Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e5750a34 authored by Chia-chi Yeh's avatar Chia-chi Yeh
Browse files

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
parent 85de77a1
Loading
Loading
Loading
Loading
+27 −11
Original line number Diff line number Diff line
@@ -19,6 +19,9 @@ package com.android.server;
import android.net.LocalSocketAddress;
import android.net.LocalSocket;
import android.os.Environment;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Message;
import android.os.SystemClock;
import android.os.SystemProperties;
import android.util.Slog;
@@ -39,7 +42,7 @@ import java.util.concurrent.LinkedBlockingQueue;
 * daemon which uses the libsysutils FrameworkListener
 * protocol.
 */
final class NativeDaemonConnector implements Runnable {
final class NativeDaemonConnector implements Runnable, Handler.Callback {
    private static final boolean LOCAL_LOGD = false;

    private BlockingQueue<String> mResponseQueue;
@@ -47,6 +50,7 @@ final class NativeDaemonConnector implements Runnable {
    private String                TAG = "NativeDaemonConnector";
    private String                mSocket;
    private INativeDaemonConnectorCallbacks mCallbacks;
    private Handler               mCallbackHandler;

    private final int BUFFER_SIZE = 4096;

@@ -76,7 +80,11 @@ final class NativeDaemonConnector implements Runnable {
        mResponseQueue = new LinkedBlockingQueue<String>(responseQueueSize);
    }

    @Override
    public void run() {
        HandlerThread thread = new HandlerThread(TAG + ".CallbackHandler");
        thread.start();
        mCallbackHandler = new Handler(thread.getLooper(), this);

        while (true) {
            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 {
        LocalSocket socket = null;

@@ -119,20 +142,13 @@ final class NativeDaemonConnector implements Runnable {
                        String event = new String(buffer, start, i - start);
                        if (LOCAL_LOGD) Slog.d(TAG, String.format("RCV <- {%s}", event));

                        String[] tokens = event.split(" ");
                        String[] tokens = event.split(" ", 2);
                        try {
                            int code = Integer.parseInt(tokens[0]);

                            if (code >= ResponseCode.UnsolicitedInformational) {
                                try {
                                    if (!mCallbacks.onEvent(code, event, tokens)) {
                                        Slog.w(TAG, String.format(
                                                "Unhandled event (%s)", event));
                                    }
                                } catch (Exception ex) {
                                    Slog.e(TAG, String.format(
                                            "Error handling '%s'", event), ex);
                                }
                                mCallbackHandler.sendMessage(
                                        mCallbackHandler.obtainMessage(code, event));
                            } else {
                                try {
                                    mResponseQueue.put(event);