Move native netd calls to varargs.
Uses argument escaping inside NativeDaemonConnector, using varargs to separate boundaries. Also introduces Command object to help build argument lists. Bug: 5472606 Change-Id: I357979fc19bb0171a056e690064e01b5a7119501
This commit is contained in:
@@ -29,6 +29,7 @@ import com.google.android.collect.Lists;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
|
import java.nio.charset.Charsets;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.concurrent.BlockingQueue;
|
import java.util.concurrent.BlockingQueue;
|
||||||
import java.util.concurrent.LinkedBlockingQueue;
|
import java.util.concurrent.LinkedBlockingQueue;
|
||||||
@@ -122,13 +123,15 @@ final class NativeDaemonConnector implements Runnable, Handler.Callback, Watchdo
|
|||||||
|
|
||||||
for (int i = 0; i < count; i++) {
|
for (int i = 0; i < count; i++) {
|
||||||
if (buffer[i] == 0) {
|
if (buffer[i] == 0) {
|
||||||
final String rawEvent = new String(buffer, start, i - start);
|
final String rawEvent = new String(
|
||||||
|
buffer, start, i - start, Charsets.UTF_8);
|
||||||
if (LOGD) Slog.d(TAG, "RCV <- " + rawEvent);
|
if (LOGD) Slog.d(TAG, "RCV <- " + rawEvent);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
final NativeDaemonEvent event = NativeDaemonEvent.parseRawEvent(
|
final NativeDaemonEvent event = NativeDaemonEvent.parseRawEvent(
|
||||||
rawEvent);
|
rawEvent);
|
||||||
if (event.isClassUnsolicited()) {
|
if (event.isClassUnsolicited()) {
|
||||||
|
// TODO: migrate to sending NativeDaemonEvent instances
|
||||||
mCallbackHandler.sendMessage(mCallbackHandler.obtainMessage(
|
mCallbackHandler.sendMessage(mCallbackHandler.obtainMessage(
|
||||||
event.getCode(), event.getRawEvent()));
|
event.getCode(), event.getRawEvent()));
|
||||||
} else {
|
} else {
|
||||||
@@ -213,7 +216,7 @@ final class NativeDaemonConnector implements Runnable, Handler.Callback, Watchdo
|
|||||||
throw new NativeDaemonConnectorException("missing output stream");
|
throw new NativeDaemonConnectorException("missing output stream");
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
mOutputStream.write(builder.toString().getBytes());
|
mOutputStream.write(builder.toString().getBytes(Charsets.UTF_8));
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new NativeDaemonConnectorException("problem sending command", e);
|
throw new NativeDaemonConnectorException("problem sending command", e);
|
||||||
}
|
}
|
||||||
@@ -223,9 +226,62 @@ final class NativeDaemonConnector implements Runnable, Handler.Callback, Watchdo
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Issue a command to the native daemon and return the responses.
|
* Issue the given command to the native daemon and return a single expected
|
||||||
|
* response.
|
||||||
|
*
|
||||||
|
* @throws NativeDaemonConnectorException when problem communicating with
|
||||||
|
* native daemon, or if the response matches
|
||||||
|
* {@link NativeDaemonEvent#isClassClientError()} or
|
||||||
|
* {@link NativeDaemonEvent#isClassServerError()}.
|
||||||
*/
|
*/
|
||||||
public NativeDaemonEvent[] execute(String cmd, Object... args)
|
public NativeDaemonEvent execute(Command cmd) throws NativeDaemonConnectorException {
|
||||||
|
return execute(cmd.mCmd, cmd.mArguments.toArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Issue the given command to the native daemon and return a single expected
|
||||||
|
* response.
|
||||||
|
*
|
||||||
|
* @throws NativeDaemonConnectorException when problem communicating with
|
||||||
|
* native daemon, or if the response matches
|
||||||
|
* {@link NativeDaemonEvent#isClassClientError()} or
|
||||||
|
* {@link NativeDaemonEvent#isClassServerError()}.
|
||||||
|
*/
|
||||||
|
public NativeDaemonEvent execute(String cmd, Object... args)
|
||||||
|
throws NativeDaemonConnectorException {
|
||||||
|
final NativeDaemonEvent[] events = executeForList(cmd, args);
|
||||||
|
if (events.length != 1) {
|
||||||
|
throw new NativeDaemonConnectorException(
|
||||||
|
"Expected exactly one response, but received " + events.length);
|
||||||
|
}
|
||||||
|
return events[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Issue the given command to the native daemon and return any
|
||||||
|
* {@link NativeDaemonEvent#isClassContinue()} responses, including the
|
||||||
|
* final terminal response.
|
||||||
|
*
|
||||||
|
* @throws NativeDaemonConnectorException when problem communicating with
|
||||||
|
* native daemon, or if the response matches
|
||||||
|
* {@link NativeDaemonEvent#isClassClientError()} or
|
||||||
|
* {@link NativeDaemonEvent#isClassServerError()}.
|
||||||
|
*/
|
||||||
|
public NativeDaemonEvent[] executeForList(Command cmd) throws NativeDaemonConnectorException {
|
||||||
|
return executeForList(cmd.mCmd, cmd.mArguments.toArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Issue the given command to the native daemon and return any
|
||||||
|
* {@link NativeDaemonEvent#isClassContinue()} responses, including the
|
||||||
|
* final terminal response.
|
||||||
|
*
|
||||||
|
* @throws NativeDaemonConnectorException when problem communicating with
|
||||||
|
* native daemon, or if the response matches
|
||||||
|
* {@link NativeDaemonEvent#isClassClientError()} or
|
||||||
|
* {@link NativeDaemonEvent#isClassServerError()}.
|
||||||
|
*/
|
||||||
|
public NativeDaemonEvent[] executeForList(String cmd, Object... args)
|
||||||
throws NativeDaemonConnectorException {
|
throws NativeDaemonConnectorException {
|
||||||
synchronized (mDaemonLock) {
|
synchronized (mDaemonLock) {
|
||||||
return executeLocked(cmd, args);
|
return executeLocked(cmd, args);
|
||||||
@@ -270,7 +326,7 @@ final class NativeDaemonConnector implements Runnable, Handler.Callback, Watchdo
|
|||||||
@Deprecated
|
@Deprecated
|
||||||
public ArrayList<String> doCommand(String cmd) throws NativeDaemonConnectorException {
|
public ArrayList<String> doCommand(String cmd) throws NativeDaemonConnectorException {
|
||||||
final ArrayList<String> rawEvents = Lists.newArrayList();
|
final ArrayList<String> rawEvents = Lists.newArrayList();
|
||||||
final NativeDaemonEvent[] events = execute(cmd);
|
final NativeDaemonEvent[] events = executeForList(cmd);
|
||||||
for (NativeDaemonEvent event : events) {
|
for (NativeDaemonEvent event : events) {
|
||||||
rawEvents.add(event.getRawEvent());
|
rawEvents.add(event.getRawEvent());
|
||||||
}
|
}
|
||||||
@@ -281,11 +337,12 @@ final class NativeDaemonConnector implements Runnable, Handler.Callback, Watchdo
|
|||||||
* Issues a list command and returns the cooked list of all
|
* Issues a list command and returns the cooked list of all
|
||||||
* {@link NativeDaemonEvent#getMessage()} which match requested code.
|
* {@link NativeDaemonEvent#getMessage()} which match requested code.
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public String[] doListCommand(String cmd, int expectedCode)
|
public String[] doListCommand(String cmd, int expectedCode)
|
||||||
throws NativeDaemonConnectorException {
|
throws NativeDaemonConnectorException {
|
||||||
final ArrayList<String> list = Lists.newArrayList();
|
final ArrayList<String> list = Lists.newArrayList();
|
||||||
|
|
||||||
final NativeDaemonEvent[] events = execute(cmd);
|
final NativeDaemonEvent[] events = executeForList(cmd);
|
||||||
for (int i = 0; i < events.length - 1; i++) {
|
for (int i = 0; i < events.length - 1; i++) {
|
||||||
final NativeDaemonEvent event = events[i];
|
final NativeDaemonEvent event = events[i];
|
||||||
final int code = event.getCode();
|
final int code = event.getCode();
|
||||||
@@ -351,6 +408,26 @@ final class NativeDaemonConnector implements Runnable, Handler.Callback, Watchdo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Command builder that handles argument list building.
|
||||||
|
*/
|
||||||
|
public static class Command {
|
||||||
|
private String mCmd;
|
||||||
|
private ArrayList<Object> mArguments = Lists.newArrayList();
|
||||||
|
|
||||||
|
public Command(String cmd, Object... args) {
|
||||||
|
mCmd = cmd;
|
||||||
|
for (Object arg : args) {
|
||||||
|
appendArg(arg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Command appendArg(Object arg) {
|
||||||
|
mArguments.add(arg);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
/** {@inheritDoc} */
|
||||||
public void monitor() {
|
public void monitor() {
|
||||||
synchronized (mDaemonLock) { }
|
synchronized (mDaemonLock) { }
|
||||||
|
|||||||
@@ -16,6 +16,10 @@
|
|||||||
|
|
||||||
package com.android.server;
|
package com.android.server;
|
||||||
|
|
||||||
|
import com.google.android.collect.Lists;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parsed event from native side of {@link NativeDaemonConnector}.
|
* Parsed event from native side of {@link NativeDaemonConnector}.
|
||||||
*/
|
*/
|
||||||
@@ -88,6 +92,17 @@ public class NativeDaemonEvent {
|
|||||||
return mCode >= 600 && mCode < 700;
|
return mCode >= 600 && mCode < 700;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verify this event matches the given code.
|
||||||
|
*
|
||||||
|
* @throws IllegalStateException if {@link #getCode()} doesn't match.
|
||||||
|
*/
|
||||||
|
public void checkCode(int code) {
|
||||||
|
if (mCode != code) {
|
||||||
|
throw new IllegalStateException("Expected " + code + " but was: " + this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse the given raw event into {@link NativeDaemonEvent} instance.
|
* Parse the given raw event into {@link NativeDaemonEvent} instance.
|
||||||
*
|
*
|
||||||
@@ -110,4 +125,18 @@ public class NativeDaemonEvent {
|
|||||||
final String message = rawEvent.substring(splitIndex + 1);
|
final String message = rawEvent.substring(splitIndex + 1);
|
||||||
return new NativeDaemonEvent(code, message, rawEvent);
|
return new NativeDaemonEvent(code, message, rawEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filter the given {@link NativeDaemonEvent} list, returning
|
||||||
|
* {@link #getMessage()} for any events matching the requested code.
|
||||||
|
*/
|
||||||
|
public static String[] filterMessageList(NativeDaemonEvent[] events, int matchCode) {
|
||||||
|
final ArrayList<String> result = Lists.newArrayList();
|
||||||
|
for (NativeDaemonEvent event : events) {
|
||||||
|
if (event.getCode() == matchCode) {
|
||||||
|
result.add(event.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result.toArray(new String[result.size()]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user