Skip to content

Commit ba2896e

Browse files
committed
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
1 parent 7a1c428 commit ba2896e

File tree

4 files changed

+277
-365
lines changed

4 files changed

+277
-365
lines changed

core/java/android/net/InterfaceConfiguration.java

Lines changed: 2 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -45,24 +45,8 @@ public String toString() {
4545
return builder.toString();
4646
}
4747

48-
/**
49-
* Return flags separated by spaces.
50-
*/
51-
public String getFlags() {
52-
final int size = mFlags.size();
53-
if (size == 0) {
54-
return "";
55-
}
56-
57-
final String[] flags = mFlags.toArray(new String[size]);
58-
final StringBuilder builder = new StringBuilder();
59-
60-
builder.append(flags[0]);
61-
for (int i = 1; i < flags.length; i++) {
62-
builder.append(' ');
63-
builder.append(flags[i]);
64-
}
65-
return builder.toString();
48+
public Iterable<String> getFlags() {
49+
return mFlags;
6650
}
6751

6852
public boolean hasFlag(String flag) {

services/java/com/android/server/NativeDaemonConnector.java

Lines changed: 83 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import java.io.IOException;
3030
import java.io.InputStream;
3131
import java.io.OutputStream;
32+
import java.nio.charset.Charsets;
3233
import java.util.ArrayList;
3334
import java.util.concurrent.BlockingQueue;
3435
import java.util.concurrent.LinkedBlockingQueue;
@@ -122,13 +123,15 @@ private void listenToSocket() throws IOException {
122123

123124
for (int i = 0; i < count; i++) {
124125
if (buffer[i] == 0) {
125-
final String rawEvent = new String(buffer, start, i - start);
126+
final String rawEvent = new String(
127+
buffer, start, i - start, Charsets.UTF_8);
126128
if (LOGD) Slog.d(TAG, "RCV <- " + rawEvent);
127129

128130
try {
129131
final NativeDaemonEvent event = NativeDaemonEvent.parseRawEvent(
130132
rawEvent);
131133
if (event.isClassUnsolicited()) {
134+
// TODO: migrate to sending NativeDaemonEvent instances
132135
mCallbackHandler.sendMessage(mCallbackHandler.obtainMessage(
133136
event.getCode(), event.getRawEvent()));
134137
} else {
@@ -213,7 +216,7 @@ private String sendCommandLocked(String cmd, Object... args)
213216
throw new NativeDaemonConnectorException("missing output stream");
214217
} else {
215218
try {
216-
mOutputStream.write(builder.toString().getBytes());
219+
mOutputStream.write(builder.toString().getBytes(Charsets.UTF_8));
217220
} catch (IOException e) {
218221
throw new NativeDaemonConnectorException("problem sending command", e);
219222
}
@@ -223,9 +226,62 @@ private String sendCommandLocked(String cmd, Object... args)
223226
}
224227

225228
/**
226-
* Issue a command to the native daemon and return the responses.
229+
* Issue the given command to the native daemon and return a single expected
230+
* response.
231+
*
232+
* @throws NativeDaemonConnectorException when problem communicating with
233+
* native daemon, or if the response matches
234+
* {@link NativeDaemonEvent#isClassClientError()} or
235+
* {@link NativeDaemonEvent#isClassServerError()}.
227236
*/
228-
public NativeDaemonEvent[] execute(String cmd, Object... args)
237+
public NativeDaemonEvent execute(Command cmd) throws NativeDaemonConnectorException {
238+
return execute(cmd.mCmd, cmd.mArguments.toArray());
239+
}
240+
241+
/**
242+
* Issue the given command to the native daemon and return a single expected
243+
* response.
244+
*
245+
* @throws NativeDaemonConnectorException when problem communicating with
246+
* native daemon, or if the response matches
247+
* {@link NativeDaemonEvent#isClassClientError()} or
248+
* {@link NativeDaemonEvent#isClassServerError()}.
249+
*/
250+
public NativeDaemonEvent execute(String cmd, Object... args)
251+
throws NativeDaemonConnectorException {
252+
final NativeDaemonEvent[] events = executeForList(cmd, args);
253+
if (events.length != 1) {
254+
throw new NativeDaemonConnectorException(
255+
"Expected exactly one response, but received " + events.length);
256+
}
257+
return events[0];
258+
}
259+
260+
/**
261+
* Issue the given command to the native daemon and return any
262+
* {@link NativeDaemonEvent#isClassContinue()} responses, including the
263+
* final terminal response.
264+
*
265+
* @throws NativeDaemonConnectorException when problem communicating with
266+
* native daemon, or if the response matches
267+
* {@link NativeDaemonEvent#isClassClientError()} or
268+
* {@link NativeDaemonEvent#isClassServerError()}.
269+
*/
270+
public NativeDaemonEvent[] executeForList(Command cmd) throws NativeDaemonConnectorException {
271+
return executeForList(cmd.mCmd, cmd.mArguments.toArray());
272+
}
273+
274+
/**
275+
* Issue the given command to the native daemon and return any
276+
* {@link NativeDaemonEvent#isClassContinue()} responses, including the
277+
* final terminal response.
278+
*
279+
* @throws NativeDaemonConnectorException when problem communicating with
280+
* native daemon, or if the response matches
281+
* {@link NativeDaemonEvent#isClassClientError()} or
282+
* {@link NativeDaemonEvent#isClassServerError()}.
283+
*/
284+
public NativeDaemonEvent[] executeForList(String cmd, Object... args)
229285
throws NativeDaemonConnectorException {
230286
synchronized (mDaemonLock) {
231287
return executeLocked(cmd, args);
@@ -270,7 +326,7 @@ private NativeDaemonEvent[] executeLocked(String cmd, Object... args)
270326
@Deprecated
271327
public ArrayList<String> doCommand(String cmd) throws NativeDaemonConnectorException {
272328
final ArrayList<String> rawEvents = Lists.newArrayList();
273-
final NativeDaemonEvent[] events = execute(cmd);
329+
final NativeDaemonEvent[] events = executeForList(cmd);
274330
for (NativeDaemonEvent event : events) {
275331
rawEvents.add(event.getRawEvent());
276332
}
@@ -281,11 +337,12 @@ public ArrayList<String> doCommand(String cmd) throws NativeDaemonConnectorExcep
281337
* Issues a list command and returns the cooked list of all
282338
* {@link NativeDaemonEvent#getMessage()} which match requested code.
283339
*/
340+
@Deprecated
284341
public String[] doListCommand(String cmd, int expectedCode)
285342
throws NativeDaemonConnectorException {
286343
final ArrayList<String> list = Lists.newArrayList();
287344

288-
final NativeDaemonEvent[] events = execute(cmd);
345+
final NativeDaemonEvent[] events = executeForList(cmd);
289346
for (int i = 0; i < events.length - 1; i++) {
290347
final NativeDaemonEvent event = events[i];
291348
final int code = event.getCode();
@@ -351,6 +408,26 @@ public NativeDaemonFailureException(String command, NativeDaemonEvent event) {
351408
}
352409
}
353410

411+
/**
412+
* Command builder that handles argument list building.
413+
*/
414+
public static class Command {
415+
private String mCmd;
416+
private ArrayList<Object> mArguments = Lists.newArrayList();
417+
418+
public Command(String cmd, Object... args) {
419+
mCmd = cmd;
420+
for (Object arg : args) {
421+
appendArg(arg);
422+
}
423+
}
424+
425+
public Command appendArg(Object arg) {
426+
mArguments.add(arg);
427+
return this;
428+
}
429+
}
430+
354431
/** {@inheritDoc} */
355432
public void monitor() {
356433
synchronized (mDaemonLock) { }

services/java/com/android/server/NativeDaemonEvent.java

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@
1616

1717
package com.android.server;
1818

19+
import com.google.android.collect.Lists;
20+
21+
import java.util.ArrayList;
22+
1923
/**
2024
* Parsed event from native side of {@link NativeDaemonConnector}.
2125
*/
@@ -88,6 +92,17 @@ public boolean isClassUnsolicited() {
8892
return mCode >= 600 && mCode < 700;
8993
}
9094

95+
/**
96+
* Verify this event matches the given code.
97+
*
98+
* @throws IllegalStateException if {@link #getCode()} doesn't match.
99+
*/
100+
public void checkCode(int code) {
101+
if (mCode != code) {
102+
throw new IllegalStateException("Expected " + code + " but was: " + this);
103+
}
104+
}
105+
91106
/**
92107
* Parse the given raw event into {@link NativeDaemonEvent} instance.
93108
*
@@ -110,4 +125,18 @@ public static NativeDaemonEvent parseRawEvent(String rawEvent) {
110125
final String message = rawEvent.substring(splitIndex + 1);
111126
return new NativeDaemonEvent(code, message, rawEvent);
112127
}
128+
129+
/**
130+
* Filter the given {@link NativeDaemonEvent} list, returning
131+
* {@link #getMessage()} for any events matching the requested code.
132+
*/
133+
public static String[] filterMessageList(NativeDaemonEvent[] events, int matchCode) {
134+
final ArrayList<String> result = Lists.newArrayList();
135+
for (NativeDaemonEvent event : events) {
136+
if (event.getCode() == matchCode) {
137+
result.add(event.getMessage());
138+
}
139+
}
140+
return result.toArray(new String[result.size()]);
141+
}
113142
}

0 commit comments

Comments
 (0)