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:
Jeff Sharkey
2011-08-09 21:44:24 -07:00
parent 0c001477c2
commit 7b331c0451

View File

@@ -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) { }
}
} }