131c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey/* 231c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey * Copyright (C) 2011 The Android Open Source Project 331c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey * 431c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey * Licensed under the Apache License, Version 2.0 (the "License"); 531c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey * you may not use this file except in compliance with the License. 631c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey * You may obtain a copy of the License at 731c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey * 831c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey * http://www.apache.org/licenses/LICENSE-2.0 931c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey * 1031c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey * Unless required by applicable law or agreed to in writing, software 1131c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey * distributed under the License is distributed on an "AS IS" BASIS, 1231c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1331c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey * See the License for the specific language governing permissions and 1431c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey * limitations under the License. 1531c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey */ 1631c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey 1731c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkeypackage com.android.server; 1831c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey 192d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwaltimport android.util.Slog; 20ba2896e939f359e5857149f1a27212db71be012bJeff Sharkeyimport com.google.android.collect.Lists; 21ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey 22ba2896e939f359e5857149f1a27212db71be012bJeff Sharkeyimport java.util.ArrayList; 23ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey 2431c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey/** 2531c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey * Parsed event from native side of {@link NativeDaemonConnector}. 2631c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey */ 2731c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkeypublic class NativeDaemonEvent { 2831c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey 2931c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey // TODO: keep class ranges in sync with ResponseCode.h 3031c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey // TODO: swap client and server error ranges to roughly mirror HTTP spec 3131c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey 32470007f69a258ccebb7c04927210a091dbcbe181Robert Greenwalt private final int mCmdNumber; 3331c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey private final int mCode; 3431c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey private final String mMessage; 3531c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey private final String mRawEvent; 36c38182ff3b1ecaf5e7a7270074bbab7f37819d3dPaul Lawrence private final String mLogMessage; 372d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt private String[] mParsed; 3831c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey 39c38182ff3b1ecaf5e7a7270074bbab7f37819d3dPaul Lawrence private NativeDaemonEvent(int cmdNumber, int code, String message, 40c38182ff3b1ecaf5e7a7270074bbab7f37819d3dPaul Lawrence String rawEvent, String logMessage) { 41470007f69a258ccebb7c04927210a091dbcbe181Robert Greenwalt mCmdNumber = cmdNumber; 4231c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey mCode = code; 4331c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey mMessage = message; 4431c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey mRawEvent = rawEvent; 45c38182ff3b1ecaf5e7a7270074bbab7f37819d3dPaul Lawrence mLogMessage = logMessage; 462d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt mParsed = null; 4731c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey } 4831c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey 49c38182ff3b1ecaf5e7a7270074bbab7f37819d3dPaul Lawrence static public final String SENSITIVE_MARKER = "{{sensitive}}"; 50c38182ff3b1ecaf5e7a7270074bbab7f37819d3dPaul Lawrence 51470007f69a258ccebb7c04927210a091dbcbe181Robert Greenwalt public int getCmdNumber() { 52470007f69a258ccebb7c04927210a091dbcbe181Robert Greenwalt return mCmdNumber; 53470007f69a258ccebb7c04927210a091dbcbe181Robert Greenwalt } 54470007f69a258ccebb7c04927210a091dbcbe181Robert Greenwalt 5531c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey public int getCode() { 5631c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey return mCode; 5731c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey } 5831c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey 5931c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey public String getMessage() { 6031c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey return mMessage; 6131c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey } 6231c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey 6331c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey @Deprecated 6431c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey public String getRawEvent() { 6531c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey return mRawEvent; 6631c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey } 6731c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey 6831c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey @Override 6931c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey public String toString() { 70c38182ff3b1ecaf5e7a7270074bbab7f37819d3dPaul Lawrence return mLogMessage; 7131c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey } 7231c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey 7331c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey /** 7431c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey * Test if event represents a partial response which is continued in 7531c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey * additional subsequent events. 7631c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey */ 7731c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey public boolean isClassContinue() { 7831c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey return mCode >= 100 && mCode < 200; 7931c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey } 8031c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey 8131c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey /** 8231c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey * Test if event represents a command success. 8331c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey */ 8431c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey public boolean isClassOk() { 8531c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey return mCode >= 200 && mCode < 300; 8631c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey } 8731c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey 8831c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey /** 8931c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey * Test if event represents a remote native daemon error. 9031c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey */ 9131c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey public boolean isClassServerError() { 9231c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey return mCode >= 400 && mCode < 500; 9331c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey } 9431c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey 9531c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey /** 9631c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey * Test if event represents a command syntax or argument error. 9731c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey */ 9831c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey public boolean isClassClientError() { 9931c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey return mCode >= 500 && mCode < 600; 10031c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey } 10131c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey 10231c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey /** 10331c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey * Test if event represents an unsolicited event from native daemon. 10431c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey */ 10531c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey public boolean isClassUnsolicited() { 106470007f69a258ccebb7c04927210a091dbcbe181Robert Greenwalt return isClassUnsolicited(mCode); 107470007f69a258ccebb7c04927210a091dbcbe181Robert Greenwalt } 108470007f69a258ccebb7c04927210a091dbcbe181Robert Greenwalt 109470007f69a258ccebb7c04927210a091dbcbe181Robert Greenwalt private static boolean isClassUnsolicited(int code) { 110470007f69a258ccebb7c04927210a091dbcbe181Robert Greenwalt return code >= 600 && code < 700; 11131c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey } 11231c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey 11331c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey /** 114ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey * Verify this event matches the given code. 115ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey * 116ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey * @throws IllegalStateException if {@link #getCode()} doesn't match. 117ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey */ 118ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey public void checkCode(int code) { 119ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey if (mCode != code) { 120ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey throw new IllegalStateException("Expected " + code + " but was: " + this); 121ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey } 122ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey } 123ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey 124ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey /** 12531c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey * Parse the given raw event into {@link NativeDaemonEvent} instance. 12631c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey * 12731c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey * @throws IllegalArgumentException when line doesn't match format expected 12831c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey * from native side. 12931c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey */ 13031c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey public static NativeDaemonEvent parseRawEvent(String rawEvent) { 131470007f69a258ccebb7c04927210a091dbcbe181Robert Greenwalt final String[] parsed = rawEvent.split(" "); 132470007f69a258ccebb7c04927210a091dbcbe181Robert Greenwalt if (parsed.length < 2) { 133470007f69a258ccebb7c04927210a091dbcbe181Robert Greenwalt throw new IllegalArgumentException("Insufficient arguments"); 13431c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey } 13531c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey 136470007f69a258ccebb7c04927210a091dbcbe181Robert Greenwalt int skiplength = 0; 137470007f69a258ccebb7c04927210a091dbcbe181Robert Greenwalt 13831c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey final int code; 13931c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey try { 140470007f69a258ccebb7c04927210a091dbcbe181Robert Greenwalt code = Integer.parseInt(parsed[0]); 141470007f69a258ccebb7c04927210a091dbcbe181Robert Greenwalt skiplength = parsed[0].length() + 1; 14231c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey } catch (NumberFormatException e) { 14331c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey throw new IllegalArgumentException("problem parsing code", e); 14431c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey } 14531c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey 146470007f69a258ccebb7c04927210a091dbcbe181Robert Greenwalt int cmdNumber = -1; 147470007f69a258ccebb7c04927210a091dbcbe181Robert Greenwalt if (isClassUnsolicited(code) == false) { 148470007f69a258ccebb7c04927210a091dbcbe181Robert Greenwalt if (parsed.length < 3) { 149470007f69a258ccebb7c04927210a091dbcbe181Robert Greenwalt throw new IllegalArgumentException("Insufficient arguemnts"); 150470007f69a258ccebb7c04927210a091dbcbe181Robert Greenwalt } 151470007f69a258ccebb7c04927210a091dbcbe181Robert Greenwalt try { 152470007f69a258ccebb7c04927210a091dbcbe181Robert Greenwalt cmdNumber = Integer.parseInt(parsed[1]); 153470007f69a258ccebb7c04927210a091dbcbe181Robert Greenwalt skiplength += parsed[1].length() + 1; 154470007f69a258ccebb7c04927210a091dbcbe181Robert Greenwalt } catch (NumberFormatException e) { 155470007f69a258ccebb7c04927210a091dbcbe181Robert Greenwalt throw new IllegalArgumentException("problem parsing cmdNumber", e); 156470007f69a258ccebb7c04927210a091dbcbe181Robert Greenwalt } 157470007f69a258ccebb7c04927210a091dbcbe181Robert Greenwalt } 158470007f69a258ccebb7c04927210a091dbcbe181Robert Greenwalt 159c38182ff3b1ecaf5e7a7270074bbab7f37819d3dPaul Lawrence String logMessage = rawEvent; 160c38182ff3b1ecaf5e7a7270074bbab7f37819d3dPaul Lawrence if (parsed.length > 2 && parsed[2].equals(SENSITIVE_MARKER)) { 161c38182ff3b1ecaf5e7a7270074bbab7f37819d3dPaul Lawrence skiplength += parsed[2].length() + 1; 162c38182ff3b1ecaf5e7a7270074bbab7f37819d3dPaul Lawrence logMessage = parsed[0] + " " + parsed[1] + " {}"; 163c38182ff3b1ecaf5e7a7270074bbab7f37819d3dPaul Lawrence } 164c38182ff3b1ecaf5e7a7270074bbab7f37819d3dPaul Lawrence 165470007f69a258ccebb7c04927210a091dbcbe181Robert Greenwalt final String message = rawEvent.substring(skiplength); 166470007f69a258ccebb7c04927210a091dbcbe181Robert Greenwalt 167c38182ff3b1ecaf5e7a7270074bbab7f37819d3dPaul Lawrence return new NativeDaemonEvent(cmdNumber, code, message, rawEvent, logMessage); 16831c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey } 169ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey 170ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey /** 171ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey * Filter the given {@link NativeDaemonEvent} list, returning 172ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey * {@link #getMessage()} for any events matching the requested code. 173ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey */ 174ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey public static String[] filterMessageList(NativeDaemonEvent[] events, int matchCode) { 175ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey final ArrayList<String> result = Lists.newArrayList(); 176ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey for (NativeDaemonEvent event : events) { 177ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey if (event.getCode() == matchCode) { 178ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey result.add(event.getMessage()); 179ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey } 180ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey } 181ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey return result.toArray(new String[result.size()]); 182ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey } 1832d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt 1842d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt /** 1852d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt * Find the Nth field of the event. 1862d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt * 1872d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt * This ignores and code or cmdNum, the first return value is given for N=0. 1882d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt * Also understands "\"quoted\" multiword responses" and tries them as a single field 1892d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt */ 1902d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt public String getField(int n) { 1912d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt if (mParsed == null) { 1922d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt mParsed = unescapeArgs(mRawEvent); 1932d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt } 1942d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt n += 2; // skip code and command# 1952d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt if (n > mParsed.length) return null; 1962d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt return mParsed[n]; 1972d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt } 1982d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt 1992d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt public static String[] unescapeArgs(String rawEvent) { 2002d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt final boolean DEBUG_ROUTINE = false; 2012d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt final String LOGTAG = "unescapeArgs"; 2022d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt final ArrayList<String> parsed = new ArrayList<String>(); 2032d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt final int length = rawEvent.length(); 2042d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt int current = 0; 2052d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt int wordEnd = -1; 2062d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt boolean quoted = false; 2072d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt 2082d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt if (DEBUG_ROUTINE) Slog.e(LOGTAG, "parsing '" + rawEvent + "'"); 2092d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt if (rawEvent.charAt(current) == '\"') { 2102d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt quoted = true; 2112d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt current++; 2122d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt } 2132d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt while (current < length) { 2142d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt // find the end of the word 215ef12884da7c8844f8dd27cbc9c9980f685b73a2cSreeram Ramachandran char terminator = quoted ? '\"' : ' '; 216ef12884da7c8844f8dd27cbc9c9980f685b73a2cSreeram Ramachandran wordEnd = current; 217ef12884da7c8844f8dd27cbc9c9980f685b73a2cSreeram Ramachandran while (wordEnd < length && rawEvent.charAt(wordEnd) != terminator) { 218ef12884da7c8844f8dd27cbc9c9980f685b73a2cSreeram Ramachandran if (rawEvent.charAt(wordEnd) == '\\') { 219ef12884da7c8844f8dd27cbc9c9980f685b73a2cSreeram Ramachandran // skip the escaped char 220ef12884da7c8844f8dd27cbc9c9980f685b73a2cSreeram Ramachandran ++wordEnd; 2212d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt } 222ef12884da7c8844f8dd27cbc9c9980f685b73a2cSreeram Ramachandran ++wordEnd; 2232d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt } 224ef12884da7c8844f8dd27cbc9c9980f685b73a2cSreeram Ramachandran if (wordEnd > length) wordEnd = length; 2252d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt String word = rawEvent.substring(current, wordEnd); 2262d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt current += word.length(); 2272d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt if (!quoted) { 2282d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt word = word.trim(); 2292d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt } else { 2302d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt current++; // skip the trailing quote 2312d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt } 2322d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt // unescape stuff within the word 233d7663955d0e00ddc7e93e1cc70559857c3fdb2ebYou Kim word = word.replace("\\\\", "\\"); 234d7663955d0e00ddc7e93e1cc70559857c3fdb2ebYou Kim word = word.replace("\\\"", "\""); 2352d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt 2362d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt if (DEBUG_ROUTINE) Slog.e(LOGTAG, "found '" + word + "'"); 2372d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt parsed.add(word); 2382d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt 2392d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt // find the beginning of the next word - either of these options 2402d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt int nextSpace = rawEvent.indexOf(' ', current); 2412d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt int nextQuote = rawEvent.indexOf(" \"", current); 2422d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt if (DEBUG_ROUTINE) { 2432d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt Slog.e(LOGTAG, "nextSpace=" + nextSpace + ", nextQuote=" + nextQuote); 2442d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt } 2452d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt if (nextQuote > -1 && nextQuote <= nextSpace) { 2462d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt quoted = true; 2472d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt current = nextQuote + 2; 2482d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt } else { 2492d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt quoted = false; 2502d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt if (nextSpace > -1) { 2512d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt current = nextSpace + 1; 2522d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt } 2532d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt } // else we just start the next word after the current and read til the end 2542d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt if (DEBUG_ROUTINE) { 2552d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt Slog.e(LOGTAG, "next loop - current=" + current + 2562d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt ", length=" + length + ", quoted=" + quoted); 2572d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt } 2582d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt } 2592d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt return parsed.toArray(new String[parsed.size()]); 2602d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt } 26131c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey} 262