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; 362d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt private String[] mParsed; 3731c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey 38470007f69a258ccebb7c04927210a091dbcbe181Robert Greenwalt private NativeDaemonEvent(int cmdNumber, int code, String message, String rawEvent) { 39470007f69a258ccebb7c04927210a091dbcbe181Robert Greenwalt mCmdNumber = cmdNumber; 4031c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey mCode = code; 4131c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey mMessage = message; 4231c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey mRawEvent = rawEvent; 432d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt mParsed = null; 4431c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey } 4531c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey 46470007f69a258ccebb7c04927210a091dbcbe181Robert Greenwalt public int getCmdNumber() { 47470007f69a258ccebb7c04927210a091dbcbe181Robert Greenwalt return mCmdNumber; 48470007f69a258ccebb7c04927210a091dbcbe181Robert Greenwalt } 49470007f69a258ccebb7c04927210a091dbcbe181Robert Greenwalt 5031c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey public int getCode() { 5131c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey return mCode; 5231c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey } 5331c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey 5431c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey public String getMessage() { 5531c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey return mMessage; 5631c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey } 5731c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey 5831c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey @Deprecated 5931c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey public String getRawEvent() { 6031c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey return mRawEvent; 6131c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey } 6231c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey 6331c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey @Override 6431c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey public String toString() { 6531c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey return mRawEvent; 6631c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey } 6731c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey 6831c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey /** 6931c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey * Test if event represents a partial response which is continued in 7031c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey * additional subsequent events. 7131c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey */ 7231c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey public boolean isClassContinue() { 7331c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey return mCode >= 100 && mCode < 200; 7431c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey } 7531c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey 7631c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey /** 7731c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey * Test if event represents a command success. 7831c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey */ 7931c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey public boolean isClassOk() { 8031c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey return mCode >= 200 && mCode < 300; 8131c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey } 8231c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey 8331c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey /** 8431c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey * Test if event represents a remote native daemon error. 8531c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey */ 8631c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey public boolean isClassServerError() { 8731c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey return mCode >= 400 && mCode < 500; 8831c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey } 8931c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey 9031c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey /** 9131c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey * Test if event represents a command syntax or argument error. 9231c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey */ 9331c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey public boolean isClassClientError() { 9431c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey return mCode >= 500 && mCode < 600; 9531c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey } 9631c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey 9731c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey /** 9831c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey * Test if event represents an unsolicited event from native daemon. 9931c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey */ 10031c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey public boolean isClassUnsolicited() { 101470007f69a258ccebb7c04927210a091dbcbe181Robert Greenwalt return isClassUnsolicited(mCode); 102470007f69a258ccebb7c04927210a091dbcbe181Robert Greenwalt } 103470007f69a258ccebb7c04927210a091dbcbe181Robert Greenwalt 104470007f69a258ccebb7c04927210a091dbcbe181Robert Greenwalt private static boolean isClassUnsolicited(int code) { 105470007f69a258ccebb7c04927210a091dbcbe181Robert Greenwalt return code >= 600 && code < 700; 10631c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey } 10731c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey 10831c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey /** 109ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey * Verify this event matches the given code. 110ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey * 111ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey * @throws IllegalStateException if {@link #getCode()} doesn't match. 112ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey */ 113ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey public void checkCode(int code) { 114ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey if (mCode != code) { 115ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey throw new IllegalStateException("Expected " + code + " but was: " + this); 116ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey } 117ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey } 118ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey 119ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey /** 12031c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey * Parse the given raw event into {@link NativeDaemonEvent} instance. 12131c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey * 12231c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey * @throws IllegalArgumentException when line doesn't match format expected 12331c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey * from native side. 12431c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey */ 12531c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey public static NativeDaemonEvent parseRawEvent(String rawEvent) { 126470007f69a258ccebb7c04927210a091dbcbe181Robert Greenwalt final String[] parsed = rawEvent.split(" "); 127470007f69a258ccebb7c04927210a091dbcbe181Robert Greenwalt if (parsed.length < 2) { 128470007f69a258ccebb7c04927210a091dbcbe181Robert Greenwalt throw new IllegalArgumentException("Insufficient arguments"); 12931c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey } 13031c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey 131470007f69a258ccebb7c04927210a091dbcbe181Robert Greenwalt int skiplength = 0; 132470007f69a258ccebb7c04927210a091dbcbe181Robert Greenwalt 13331c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey final int code; 13431c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey try { 135470007f69a258ccebb7c04927210a091dbcbe181Robert Greenwalt code = Integer.parseInt(parsed[0]); 136470007f69a258ccebb7c04927210a091dbcbe181Robert Greenwalt skiplength = parsed[0].length() + 1; 13731c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey } catch (NumberFormatException e) { 13831c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey throw new IllegalArgumentException("problem parsing code", e); 13931c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey } 14031c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey 141470007f69a258ccebb7c04927210a091dbcbe181Robert Greenwalt int cmdNumber = -1; 142470007f69a258ccebb7c04927210a091dbcbe181Robert Greenwalt if (isClassUnsolicited(code) == false) { 143470007f69a258ccebb7c04927210a091dbcbe181Robert Greenwalt if (parsed.length < 3) { 144470007f69a258ccebb7c04927210a091dbcbe181Robert Greenwalt throw new IllegalArgumentException("Insufficient arguemnts"); 145470007f69a258ccebb7c04927210a091dbcbe181Robert Greenwalt } 146470007f69a258ccebb7c04927210a091dbcbe181Robert Greenwalt try { 147470007f69a258ccebb7c04927210a091dbcbe181Robert Greenwalt cmdNumber = Integer.parseInt(parsed[1]); 148470007f69a258ccebb7c04927210a091dbcbe181Robert Greenwalt skiplength += parsed[1].length() + 1; 149470007f69a258ccebb7c04927210a091dbcbe181Robert Greenwalt } catch (NumberFormatException e) { 150470007f69a258ccebb7c04927210a091dbcbe181Robert Greenwalt throw new IllegalArgumentException("problem parsing cmdNumber", e); 151470007f69a258ccebb7c04927210a091dbcbe181Robert Greenwalt } 152470007f69a258ccebb7c04927210a091dbcbe181Robert Greenwalt } 153470007f69a258ccebb7c04927210a091dbcbe181Robert Greenwalt 154470007f69a258ccebb7c04927210a091dbcbe181Robert Greenwalt final String message = rawEvent.substring(skiplength); 155470007f69a258ccebb7c04927210a091dbcbe181Robert Greenwalt 156470007f69a258ccebb7c04927210a091dbcbe181Robert Greenwalt return new NativeDaemonEvent(cmdNumber, code, message, rawEvent); 15731c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey } 158ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey 159ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey /** 160ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey * Filter the given {@link NativeDaemonEvent} list, returning 161ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey * {@link #getMessage()} for any events matching the requested code. 162ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey */ 163ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey public static String[] filterMessageList(NativeDaemonEvent[] events, int matchCode) { 164ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey final ArrayList<String> result = Lists.newArrayList(); 165ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey for (NativeDaemonEvent event : events) { 166ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey if (event.getCode() == matchCode) { 167ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey result.add(event.getMessage()); 168ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey } 169ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey } 170ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey return result.toArray(new String[result.size()]); 171ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey } 1722d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt 1732d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt /** 1742d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt * Find the Nth field of the event. 1752d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt * 1762d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt * This ignores and code or cmdNum, the first return value is given for N=0. 1772d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt * Also understands "\"quoted\" multiword responses" and tries them as a single field 1782d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt */ 1792d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt public String getField(int n) { 1802d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt if (mParsed == null) { 1812d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt mParsed = unescapeArgs(mRawEvent); 1822d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt } 1832d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt n += 2; // skip code and command# 1842d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt if (n > mParsed.length) return null; 1852d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt return mParsed[n]; 1862d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt } 1872d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt 1882d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt public static String[] unescapeArgs(String rawEvent) { 1892d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt final boolean DEBUG_ROUTINE = false; 1902d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt final String LOGTAG = "unescapeArgs"; 1912d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt final ArrayList<String> parsed = new ArrayList<String>(); 1922d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt final int length = rawEvent.length(); 1932d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt int current = 0; 1942d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt int wordEnd = -1; 1952d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt boolean quoted = false; 1962d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt 1972d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt if (DEBUG_ROUTINE) Slog.e(LOGTAG, "parsing '" + rawEvent + "'"); 1982d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt if (rawEvent.charAt(current) == '\"') { 1992d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt quoted = true; 2002d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt current++; 2012d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt } 2022d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt while (current < length) { 2032d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt // find the end of the word 2042d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt if (quoted) { 2052d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt wordEnd = current; 2062d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt while ((wordEnd = rawEvent.indexOf('\"', wordEnd)) != -1) { 2072d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt if (rawEvent.charAt(wordEnd - 1) != '\\') { 2082d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt break; 2092d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt } else { 2102d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt wordEnd++; // skip this escaped quote and keep looking 2112d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt } 2122d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt } 2132d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt } else { 2142d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt wordEnd = rawEvent.indexOf(' ', current); 2152d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt } 2162d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt // if we didn't find the end-o-word token, take the rest of the string 2172d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt if (wordEnd == -1) wordEnd = length; 2182d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt String word = rawEvent.substring(current, wordEnd); 2192d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt current += word.length(); 2202d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt if (!quoted) { 2212d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt word = word.trim(); 2222d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt } else { 2232d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt current++; // skip the trailing quote 2242d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt } 2252d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt // unescape stuff within the word 2262d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt word.replace("\\\\", "\\"); 2272d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt word.replace("\\\"", "\""); 2282d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt 2292d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt if (DEBUG_ROUTINE) Slog.e(LOGTAG, "found '" + word + "'"); 2302d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt parsed.add(word); 2312d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt 2322d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt // find the beginning of the next word - either of these options 2332d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt int nextSpace = rawEvent.indexOf(' ', current); 2342d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt int nextQuote = rawEvent.indexOf(" \"", current); 2352d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt if (DEBUG_ROUTINE) { 2362d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt Slog.e(LOGTAG, "nextSpace=" + nextSpace + ", nextQuote=" + nextQuote); 2372d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt } 2382d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt if (nextQuote > -1 && nextQuote <= nextSpace) { 2392d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt quoted = true; 2402d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt current = nextQuote + 2; 2412d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt } else { 2422d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt quoted = false; 2432d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt if (nextSpace > -1) { 2442d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt current = nextSpace + 1; 2452d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt } 2462d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt } // else we just start the next word after the current and read til the end 2472d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt if (DEBUG_ROUTINE) { 2482d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt Slog.e(LOGTAG, "next loop - current=" + current + 2492d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt ", length=" + length + ", quoted=" + quoted); 2502d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt } 2512d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt } 2522d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt return parsed.toArray(new String[parsed.size()]); 2532d34b4a88531e51982b030c43d672ec2cc3d8f36Robert Greenwalt } 25431c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey} 255