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

Commit fa23c5ae authored by Jeff Sharkey's avatar Jeff Sharkey
Browse files

Add NativeDaemonConnector users to watchdog.

To catch instances where NativeDaemonConnector hangs while executing
commands, add users to system_server watchdog.  Also moved qtaguid
enabler to separate thread to prevent blocking systemReady().

Bug: 5145437
Change-Id: I4c6c1dc09864a1c05f9486a31faa1b366548e911
parent 8cceb1e4
Loading
Loading
Loading
Loading
+14 −3
Original line number Diff line number Diff line
@@ -89,7 +89,8 @@ import javax.crypto.spec.PBEKeySpec;
 * @hide - Applications should use android.os.storage.StorageManager
 * to access the MountService.
 */
class MountService extends IMountService.Stub implements INativeDaemonConnectorCallbacks {
class MountService extends IMountService.Stub
        implements INativeDaemonConnectorCallbacks, Watchdog.Monitor {

    private static final boolean LOCAL_LOGD = false;
    private static final boolean DEBUG_UNMOUNT = false;
@@ -474,7 +475,8 @@ class MountService extends IMountService.Stub implements INativeDaemonConnectorC
                            // it is not safe to call vold with mVolumeStates locked
                            // so we make a copy of the paths and states and process them
                            // outside the lock
                            String[] paths, states;
                            String[] paths;
                            String[] states;
                            int count;
                            synchronized (mVolumeStates) {
                                Set<String> keys = mVolumeStates.keySet();
@@ -1179,6 +1181,9 @@ class MountService extends IMountService.Stub implements INativeDaemonConnectorC
        mReady = false;
        Thread thread = new Thread(mConnector, VOLD_TAG);
        thread.start();

        // Add ourself to the Watchdog monitors.
        Watchdog.getInstance().addMonitor(this);
    }

    /**
@@ -2379,5 +2384,11 @@ class MountService extends IMountService.Stub implements INativeDaemonConnectorC
            }
        }
    }
}

    /** {@inheritDoc} */
    public void monitor() {
        if (mConnector != null) {
            mConnector.monitor();
        }
    }
}
+38 −34
Original line number Diff line number Diff line
@@ -16,24 +16,18 @@

package com.android.server;

import android.net.LocalSocketAddress;
import android.net.LocalSocket;
import android.os.Environment;
import android.net.LocalSocketAddress;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Message;
import android.os.SystemClock;
import android.os.SystemProperties;
import android.util.Slog;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;

import java.util.List;
import java.util.ArrayList;
import java.util.ListIterator;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

@@ -42,7 +36,7 @@ import java.util.concurrent.LinkedBlockingQueue;
 * daemon which uses the libsysutils FrameworkListener
 * protocol.
 */
final class NativeDaemonConnector implements Runnable, Handler.Callback {
final class NativeDaemonConnector implements Runnable, Handler.Callback, Watchdog.Monitor {
    private static final boolean LOCAL_LOGD = false;

    private BlockingQueue<String> mResponseQueue;
@@ -52,6 +46,9 @@ final class NativeDaemonConnector implements Runnable, Handler.Callback {
    private INativeDaemonConnectorCallbacks mCallbacks;
    private Handler               mCallbackHandler;

    /** Lock held whenever communicating with native daemon. */
    private Object mDaemonLock = new Object();

    private final int BUFFER_SIZE = 4096;

    class ResponseCode {
@@ -177,7 +174,7 @@ final class NativeDaemonConnector implements Runnable, Handler.Callback {
            Slog.e(TAG, "Communications error", ex);
            throw ex;
        } finally {
            synchronized (this) {
            synchronized (mDaemonLock) {
                if (mOutputStream != null) {
                    try {
                        mOutputStream.close();
@@ -198,9 +195,8 @@ final class NativeDaemonConnector implements Runnable, Handler.Callback {
        }
    }

    private void sendCommand(String command)
            throws NativeDaemonConnectorException  {
        sendCommand(command, null);
    private void sendCommandLocked(String command) throws NativeDaemonConnectorException {
        sendCommandLocked(command, null);
    }

    /**
@@ -209,9 +205,8 @@ final class NativeDaemonConnector implements Runnable, Handler.Callback {
     * @param command  The command to send to the daemon
     * @param argument The argument to send with the command (or null)
     */
    private void sendCommand(String command, String argument)
    private void sendCommandLocked(String command, String argument)
            throws NativeDaemonConnectorException {
        synchronized (this) {
        if (LOCAL_LOGD) Slog.d(TAG, String.format("SND -> {%s} {%s}", command, argument));
        if (mOutputStream == null) {
            Slog.e(TAG, "No connection to daemon", new IllegalStateException());
@@ -230,15 +225,19 @@ final class NativeDaemonConnector implements Runnable, Handler.Callback {
            }
        }
    }
    }

    /**
     * Issue a command to the native daemon and return the responses
     */
    public synchronized ArrayList<String> doCommand(String cmd)
            throws NativeDaemonConnectorException  {
    public ArrayList<String> doCommand(String cmd) throws NativeDaemonConnectorException {
        synchronized (mDaemonLock) {
            return doCommandLocked(cmd);
        }
    }

    private ArrayList<String> doCommandLocked(String cmd) throws NativeDaemonConnectorException {
        mResponseQueue.clear();
        sendCommand(cmd);
        sendCommandLocked(cmd);

        ArrayList<String> response = new ArrayList<String>();
        boolean complete = false;
@@ -278,7 +277,7 @@ final class NativeDaemonConnector implements Runnable, Handler.Callback {
        return response;
    }

    /*
    /**
     * Issues a list command and returns the cooked list
     */
    public String[] doListCommand(String cmd, int expectedResponseCode)
@@ -317,4 +316,9 @@ final class NativeDaemonConnector implements Runnable, Handler.Callback {
        }
        throw new NativeDaemonConnectorException("Got an empty response");
    }

    /** {@inheritDoc} */
    public void monitor() {
        synchronized (mDaemonLock) { }
    }
}
+17 −10
Original line number Diff line number Diff line
@@ -68,7 +68,7 @@ import libcore.io.IoUtils;
/**
 * @hide
 */
class NetworkManagementService extends INetworkManagementService.Stub {
class NetworkManagementService extends INetworkManagementService.Stub implements Watchdog.Monitor {
    private static final String TAG = "NetworkManagementService";
    private static final boolean DBG = false;
    private static final String NETD_TAG = "NetdConnector";
@@ -139,7 +139,7 @@ class NetworkManagementService extends INetworkManagementService.Stub {
    /** Set of UIDs with active reject rules. */
    private SparseBooleanArray mUidRejectOnQuota = new SparseBooleanArray();

    private boolean mBandwidthControlEnabled;
    private volatile boolean mBandwidthControlEnabled;

    /**
     * Constructs a new NetworkManagementService instance
@@ -162,6 +162,9 @@ class NetworkManagementService extends INetworkManagementService.Stub {
        mConnector = new NativeDaemonConnector(
                new NetdCallbackReceiver(), "netd", 10, NETD_TAG);
        mThread = new Thread(mConnector, NETD_TAG);

        // Add ourself to the Watchdog monitors.
        Watchdog.getInstance().addMonitor(this);
    }

    public static NetworkManagementService create(Context context) throws InterruptedException {
@@ -185,14 +188,12 @@ class NetworkManagementService extends INetworkManagementService.Stub {
    }

    public void systemReady() {

        // only enable bandwidth control when support exists, and requested by
        // system setting.
        final boolean hasKernelSupport = new File("/proc/net/xt_qtaguid/ctrl").exists();
        final boolean shouldEnable =
                Settings.Secure.getInt(mContext.getContentResolver(), NETSTATS_ENABLED, 1) != 0;

        mBandwidthControlEnabled = false;
        if (hasKernelSupport && shouldEnable) {
            Slog.d(TAG, "enabling bandwidth control");
            try {
@@ -288,7 +289,7 @@ class NetworkManagementService extends INetworkManagementService.Stub {
    /**
     * Let us know the daemon is connected
     */
    protected void onConnected() {
    protected void onDaemonConnected() {
        if (DBG) Slog.d(TAG, "onConnected");
        mConnectedSignal.countDown();
    }
@@ -299,13 +300,12 @@ class NetworkManagementService extends INetworkManagementService.Stub {
    //

    class NetdCallbackReceiver implements INativeDaemonConnectorCallbacks {
        /** {@inheritDoc} */
        public void onDaemonConnected() {
            NetworkManagementService.this.onConnected();
            new Thread() {
                public void run() {
                }
            }.start();
            NetworkManagementService.this.onDaemonConnected();
        }

        /** {@inheritDoc} */
        public boolean onEvent(int code, String raw, String[] cooked) {
            switch (code) {
            case NetdResponseCode.InterfaceChange:
@@ -1520,4 +1520,11 @@ class NetworkManagementService extends INetworkManagementService.Stub {
                    "Error communicating with native daemon to flush interface " + iface, e);
        }
    }

    /** {@inheritDoc} */
    public void monitor() {
        if (mConnector != null) {
            mConnector.monitor();
        }
    }
}