NativeDaemonConnector: offload callbacks to another thread.

Now callbacks can communicate to the same daemon without causing a
deadlock. This also improves the latency of calls because they no
longer need to wait for the callbacks for the pending events.

Change-Id: I153fcf16bd64de79ee1c1a57d3cfdb12b354cf47
This commit is contained in:
Chia-chi Yeh
2011-08-03 14:42:11 -07:00
parent 7407e09009
commit 4ac474e88b

View File

@@ -19,6 +19,9 @@ package com.android.server;
import android.net.LocalSocketAddress; import android.net.LocalSocketAddress;
import android.net.LocalSocket; import android.net.LocalSocket;
import android.os.Environment; import android.os.Environment;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Message;
import android.os.SystemClock; import android.os.SystemClock;
import android.os.SystemProperties; import android.os.SystemProperties;
import android.util.Slog; import android.util.Slog;
@@ -39,7 +42,7 @@ import java.util.concurrent.LinkedBlockingQueue;
* daemon which uses the libsysutils FrameworkListener * daemon which uses the libsysutils FrameworkListener
* protocol. * protocol.
*/ */
final class NativeDaemonConnector implements Runnable { final class NativeDaemonConnector implements Runnable, Handler.Callback {
private static final boolean LOCAL_LOGD = false; private static final boolean LOCAL_LOGD = false;
private BlockingQueue<String> mResponseQueue; private BlockingQueue<String> mResponseQueue;
@@ -47,6 +50,7 @@ final class NativeDaemonConnector implements Runnable {
private String TAG = "NativeDaemonConnector"; private String TAG = "NativeDaemonConnector";
private String mSocket; private String mSocket;
private INativeDaemonConnectorCallbacks mCallbacks; private INativeDaemonConnectorCallbacks mCallbacks;
private Handler mCallbackHandler;
private final int BUFFER_SIZE = 4096; private final int BUFFER_SIZE = 4096;
@@ -76,7 +80,11 @@ final class NativeDaemonConnector implements Runnable {
mResponseQueue = new LinkedBlockingQueue<String>(responseQueueSize); mResponseQueue = new LinkedBlockingQueue<String>(responseQueueSize);
} }
@Override
public void run() { public void run() {
HandlerThread thread = new HandlerThread(TAG + ".CallbackHandler");
thread.start();
mCallbackHandler = new Handler(thread.getLooper(), this);
while (true) { while (true) {
try { try {
@@ -88,6 +96,21 @@ final class NativeDaemonConnector implements Runnable {
} }
} }
@Override
public boolean handleMessage(Message msg) {
String event = (String) msg.obj;
try {
if (!mCallbacks.onEvent(msg.what, event, event.split(" "))) {
Slog.w(TAG, String.format(
"Unhandled event '%s'", event));
}
} catch (Exception e) {
Slog.e(TAG, String.format(
"Error handling '%s'", event), e);
}
return true;
}
private void listenToSocket() throws IOException { private void listenToSocket() throws IOException {
LocalSocket socket = null; LocalSocket socket = null;
@@ -119,20 +142,13 @@ final class NativeDaemonConnector implements Runnable {
String event = new String(buffer, start, i - start); String event = new String(buffer, start, i - start);
if (LOCAL_LOGD) Slog.d(TAG, String.format("RCV <- {%s}", event)); if (LOCAL_LOGD) Slog.d(TAG, String.format("RCV <- {%s}", event));
String[] tokens = event.split(" "); String[] tokens = event.split(" ", 2);
try { try {
int code = Integer.parseInt(tokens[0]); int code = Integer.parseInt(tokens[0]);
if (code >= ResponseCode.UnsolicitedInformational) { if (code >= ResponseCode.UnsolicitedInformational) {
try { mCallbackHandler.sendMessage(
if (!mCallbacks.onEvent(code, event, tokens)) { mCallbackHandler.obtainMessage(code, event));
Slog.w(TAG, String.format(
"Unhandled event (%s)", event));
}
} catch (Exception ex) {
Slog.e(TAG, String.format(
"Error handling '%s'", event), ex);
}
} else { } else {
try { try {
mResponseQueue.put(event); mResponseQueue.put(event);