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
This commit is contained in:
@@ -16,24 +16,18 @@
|
|||||||
|
|
||||||
package com.android.server;
|
package com.android.server;
|
||||||
|
|
||||||
import android.net.LocalSocketAddress;
|
|
||||||
import android.net.LocalSocket;
|
import android.net.LocalSocket;
|
||||||
import android.os.Environment;
|
import android.net.LocalSocketAddress;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.HandlerThread;
|
import android.os.HandlerThread;
|
||||||
import android.os.Message;
|
import android.os.Message;
|
||||||
import android.os.SystemClock;
|
import android.os.SystemClock;
|
||||||
import android.os.SystemProperties;
|
|
||||||
import android.util.Slog;
|
import android.util.Slog;
|
||||||
|
|
||||||
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.net.Socket;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.ListIterator;
|
|
||||||
import java.util.concurrent.BlockingQueue;
|
import java.util.concurrent.BlockingQueue;
|
||||||
import java.util.concurrent.LinkedBlockingQueue;
|
import java.util.concurrent.LinkedBlockingQueue;
|
||||||
|
|
||||||
@@ -42,7 +36,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, Handler.Callback {
|
final class NativeDaemonConnector implements Runnable, Handler.Callback, Watchdog.Monitor {
|
||||||
private static final boolean LOCAL_LOGD = false;
|
private static final boolean LOCAL_LOGD = false;
|
||||||
|
|
||||||
private BlockingQueue<String> mResponseQueue;
|
private BlockingQueue<String> mResponseQueue;
|
||||||
@@ -52,6 +46,9 @@ final class NativeDaemonConnector implements Runnable, Handler.Callback {
|
|||||||
private INativeDaemonConnectorCallbacks mCallbacks;
|
private INativeDaemonConnectorCallbacks mCallbacks;
|
||||||
private Handler mCallbackHandler;
|
private Handler mCallbackHandler;
|
||||||
|
|
||||||
|
/** Lock held whenever communicating with native daemon. */
|
||||||
|
private Object mDaemonLock = new Object();
|
||||||
|
|
||||||
private final int BUFFER_SIZE = 4096;
|
private final int BUFFER_SIZE = 4096;
|
||||||
|
|
||||||
class ResponseCode {
|
class ResponseCode {
|
||||||
@@ -177,7 +174,7 @@ final class NativeDaemonConnector implements Runnable, Handler.Callback {
|
|||||||
Slog.e(TAG, "Communications error", ex);
|
Slog.e(TAG, "Communications error", ex);
|
||||||
throw ex;
|
throw ex;
|
||||||
} finally {
|
} finally {
|
||||||
synchronized (this) {
|
synchronized (mDaemonLock) {
|
||||||
if (mOutputStream != null) {
|
if (mOutputStream != null) {
|
||||||
try {
|
try {
|
||||||
mOutputStream.close();
|
mOutputStream.close();
|
||||||
@@ -198,9 +195,8 @@ final class NativeDaemonConnector implements Runnable, Handler.Callback {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sendCommand(String command)
|
private void sendCommandLocked(String command) throws NativeDaemonConnectorException {
|
||||||
throws NativeDaemonConnectorException {
|
sendCommandLocked(command, null);
|
||||||
sendCommand(command, null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -209,25 +205,23 @@ final class NativeDaemonConnector implements Runnable, Handler.Callback {
|
|||||||
* @param command The command to send to the daemon
|
* @param command The command to send to the daemon
|
||||||
* @param argument The argument to send with the command (or null)
|
* @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 {
|
throws NativeDaemonConnectorException {
|
||||||
synchronized (this) {
|
if (LOCAL_LOGD) Slog.d(TAG, String.format("SND -> {%s} {%s}", command, argument));
|
||||||
if (LOCAL_LOGD) Slog.d(TAG, String.format("SND -> {%s} {%s}", command, argument));
|
if (mOutputStream == null) {
|
||||||
if (mOutputStream == null) {
|
Slog.e(TAG, "No connection to daemon", new IllegalStateException());
|
||||||
Slog.e(TAG, "No connection to daemon", new IllegalStateException());
|
throw new NativeDaemonConnectorException("No output stream!");
|
||||||
throw new NativeDaemonConnectorException("No output stream!");
|
} else {
|
||||||
} else {
|
StringBuilder builder = new StringBuilder(command);
|
||||||
StringBuilder builder = new StringBuilder(command);
|
if (argument != null) {
|
||||||
if (argument != null) {
|
builder.append(argument);
|
||||||
builder.append(argument);
|
}
|
||||||
}
|
builder.append('\0');
|
||||||
builder.append('\0');
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
mOutputStream.write(builder.toString().getBytes());
|
mOutputStream.write(builder.toString().getBytes());
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
Slog.e(TAG, "IOException in sendCommand", ex);
|
Slog.e(TAG, "IOException in sendCommand", ex);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -235,10 +229,15 @@ final class NativeDaemonConnector implements Runnable, Handler.Callback {
|
|||||||
/**
|
/**
|
||||||
* Issue a command to the native daemon and return the responses
|
* Issue a command to the native daemon and return the responses
|
||||||
*/
|
*/
|
||||||
public synchronized ArrayList<String> doCommand(String cmd)
|
public ArrayList<String> doCommand(String cmd) throws NativeDaemonConnectorException {
|
||||||
throws NativeDaemonConnectorException {
|
synchronized (mDaemonLock) {
|
||||||
|
return doCommandLocked(cmd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private ArrayList<String> doCommandLocked(String cmd) throws NativeDaemonConnectorException {
|
||||||
mResponseQueue.clear();
|
mResponseQueue.clear();
|
||||||
sendCommand(cmd);
|
sendCommandLocked(cmd);
|
||||||
|
|
||||||
ArrayList<String> response = new ArrayList<String>();
|
ArrayList<String> response = new ArrayList<String>();
|
||||||
boolean complete = false;
|
boolean complete = false;
|
||||||
@@ -278,7 +277,7 @@ final class NativeDaemonConnector implements Runnable, Handler.Callback {
|
|||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* Issues a list command and returns the cooked list
|
* Issues a list command and returns the cooked list
|
||||||
*/
|
*/
|
||||||
public String[] doListCommand(String cmd, int expectedResponseCode)
|
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");
|
throw new NativeDaemonConnectorException("Got an empty response");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** {@inheritDoc} */
|
||||||
|
public void monitor() {
|
||||||
|
synchronized (mDaemonLock) { }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user