一、先分析Native层:
1、C++基类SocketListener:
- class SocketListener {
- int mSock;
- const char *mSocketName;
- SocketClientCollection *mClients;
- pthread_mutex_t mClientsLock;
- bool mListen;
- int mCtrlPipe[2];
- pthread_t mThread;
- public:
- SocketListener(const char *socketNames, bool listen);
- SocketListener(int socketFd, bool listen);
- virtual ~SocketListener();
- int startListener();
- int stopListener();
- void sendBroadcast(int code, const char *msg, bool addErrno);
- void sendBroadcast(const char *msg);
- protected:
- virtual bool onDataAvailable(SocketClient *c) = 0;
- private:
- static void *threadStart(void *obj);
- void runListener();
- };
- #endif
看关键接口runListener:
- void SocketListener::runListener() {
- while(1) {
- SocketClientCollection::iterator it;
- fd_set read_fds;
- int rc = 0;
- int max = 0;
- FD_ZERO(&read_fds);
- if (mListen) {
- max = mSock;
- FD_SET(mSock, &read_fds);
- }
- FD_SET(mCtrlPipe[0], &read_fds);
- if (mCtrlPipe[0] > max)
- max = mCtrlPipe[0];
- pthread_mutex_lock(&mClientsLock);
- for (it = mClients->begin(); it != mClients->end(); ++it) {
- FD_SET((*it)->getSocket(), &read_fds);
- if ((*it)->getSocket() > max)
- max = (*it)->getSocket();
- }
- pthread_mutex_unlock(&mClientsLock);
- if ((rc = select(max + 1, &read_fds, NULL, NULL, NULL)) < 0) {
- SLOGE("select failed (%s)", strerror(errno));
- sleep(1);
- continue;
- } else if (!rc)
- continue;
- if (FD_ISSET(mCtrlPipe[0], &read_fds))
- break;
- if (mListen && FD_ISSET(mSock, &read_fds)) {
- struct sockaddr addr;
- socklen_t alen = sizeof(addr);
- int c;
- if ((c = accept(mSock, &addr, &alen)) < 0) {
- SLOGE("accept failed (%s)", strerror(errno));
- sleep(1);
- continue;
- }
- pthread_mutex_lock(&mClientsLock);
- mClients->push_back(new SocketClient(c));
- pthread_mutex_unlock(&mClientsLock);
- }
- do {
- pthread_mutex_lock(&mClientsLock);
- for (it = mClients->begin(); it != mClients->end(); ++it) {
- int fd = (*it)->getSocket();
- if (FD_ISSET(fd, &read_fds)) {
- pthread_mutex_unlock(&mClientsLock);
- if (!onDataAvailable(*it)) {//由子类实现的接口。
- close(fd);
- pthread_mutex_lock(&mClientsLock);
- delete *it;
- it = mClients->erase(it);
- pthread_mutex_unlock(&mClientsLock);
- }
- FD_CLR(fd, &read_fds);
- continue;
- }
- }
- pthread_mutex_unlock(&mClientsLock);
- } while (0);
- }
- }
2、他的第一继承者:
- #include "SocketListener.h"
- #include "FrameworkCommand.h"
- class SocketClient;
- class FrameworkListener : public SocketListener {
- public:
- static const int CMD_ARGS_MAX = 16;
- private:
- FrameworkCommandCollection *mCommands;
- public:
- FrameworkListener(const char *socketName);
- virtual ~FrameworkListener() {}
- protected:
- void registerCmd(FrameworkCommand *cmd);
- virtual bool onDataAvailable(SocketClient *c);
- private:
- void dispatchCommand(SocketClient *c, char *data);
- };
他的onDataAvailable接口实现:
- bool FrameworkListener::onDataAvailable(SocketClient *c) {
- char buffer[255];
- int len;
- if ((len = read(c->getSocket(), buffer, sizeof(buffer) -1)) < 0) {
- SLOGE("read() failed (%s)", strerror(errno));
- return errno;
- } else if (!len)
- return false;
- int offset = 0;
- int i;
- for (i = 0; i < len; i++) {
- if (buffer[i] == ' ') {
- dispatchCommand(c, buffer + offset);
- offset = i + 1;
- }
- }
- return true;
- }
3、实例:netd的CommandListener类:
- class CommandListener : public FrameworkListener {
- static TetherController *sTetherCtrl;
- static NatController *sNatCtrl;
- static PppController *sPppCtrl;
- static PanController *sPanCtrl;
- static SoftapController *sSoftapCtrl;
- static UsbController *sUsbCtrl;
- public:
- CommandListener();
- virtual ~CommandListener() {}
- private:
- static int readInterfaceCounters(const char *iface, unsigned long *rx, unsigned long *tx);
- class UsbCmd : public NetdCommand {
- public:
- UsbCmd();
- virtual ~UsbCmd() {}
- int runCommand(SocketClient *c, int argc, char ** argv);
- };
- class SoftapCmd : public NetdCommand {
- public:
- SoftapCmd();
- virtual ~SoftapCmd() {}
- int runCommand(SocketClient *c, int argc, char ** argv);
- };
- class InterfaceCmd : public NetdCommand {
- public:
- InterfaceCmd();
- virtual ~InterfaceCmd() {}
- int runCommand(SocketClient *c, int argc, char ** argv);
- };
- class IpFwdCmd : public NetdCommand {
- public:
- IpFwdCmd();
- virtual ~IpFwdCmd() {}
- int runCommand(SocketClient *c, int argc, char ** argv);
- };
- class TetherCmd : public NetdCommand {
- public:
- TetherCmd();
- virtual ~TetherCmd() {}
- int runCommand(SocketClient *c, int argc, char ** argv);
- };
- class NatCmd : public NetdCommand {
- public:
- NatCmd();
- virtual ~NatCmd() {}
- int runCommand(SocketClient *c, int argc, char ** argv);
- };
- class ListTtysCmd : public NetdCommand {
- public:
- ListTtysCmd();
- virtual ~ListTtysCmd() {}
- int runCommand(SocketClient *c, int argc, char ** argv);
- };
- class PppdCmd : public NetdCommand {
- public:
- PppdCmd();
- virtual ~PppdCmd() {}
- int runCommand(SocketClient *c, int argc, char ** argv);
- };
- class PanCmd : public NetdCommand {
- public:
- PanCmd();
- virtual ~PanCmd() {}
- int runCommand(SocketClient *c, int argc, char ** argv);
- };
- };
不能忘记NetdCommand类:
- #include <sysutils/FrameworkCommand.h>
- class NetdCommand : public FrameworkCommand {
- public:
- NetdCommand(const char *cmd);
- virtual ~NetdCommand() {}
- };
- 4、分析一个子类ListTtysCmd:
- CommandListener::ListTtysCmd::ListTtysCmd() :
- NetdCommand("list_ttys") {
- }
- int CommandListener::ListTtysCmd::runCommand(SocketClient *cli,
- int argc, char **argv) {
- TtyCollection *tlist = sPppCtrl->getTtyList();
- TtyCollection::iterator it;
- for (it = tlist->begin(); it != tlist->end(); ++it) {
- cli->sendMsg(ResponseCode::TtyListResult, *it, false);
- }
- cli->sendMsg(ResponseCode::CommandOkay, "Ttys listed.", false);
- return 0;
- }
Java层:
- private void listenToSocket() throws IOException {
- LocalSocket socket = null;
- try {
- socket = new LocalSocket();
- LocalSocketAddress address = new LocalSocketAddress(mSocket,
- LocalSocketAddress.Namespace.RESERVED);
- socket.connect(address);
- InputStream inputStream = socket.getInputStream();
- mOutputStream = socket.getOutputStream();
- mCallbacks.onDaemonConnected();
- byte[] buffer = new byte[BUFFER_SIZE];
- int start = 0;
- while (true) {
- int count = inputStream.read(buffer, start, BUFFER_SIZE - start);
- if (count < 0) break;
- // Add our starting point to the count and reset the start.
- count += start;
- start = 0;
- for (int i = 0; i < count; i++) {
- if (buffer[i] == 0) {
- String event = new String(buffer, start, i - start);
- if (LOCAL_LOGD) Slog.d(TAG, String.format("RCV <- {%s}", event));
- String[] tokens = event.split(" ", 2);
- try {
- int code = Integer.parseInt(tokens[0]);
- if (code >= ResponseCode.UnsolicitedInformational) {
- mCallbackHandler.sendMessage(
- mCallbackHandler.obtainMessage(code, event));
- } else {
- try {
- mResponseQueue.put(event);
- } catch (InterruptedException ex) {
- Slog.e(TAG, "Failed to put response onto queue", ex);
- }
- }
- } catch (NumberFormatException nfe) {
- Slog.w(TAG, String.format("Bad msg (%s)", event));
- }
- start = i + 1;
- }
- }
- // We should end at the amount we read. If not, compact then
- // buffer and read again.
- if (start != count) {
- final int remaining = BUFFER_SIZE - start;
- System.arraycopy(buffer, start, buffer, 0, remaining);
- start = remaining;
- } else {
- start = 0;
- }
- }
- } catch (IOException ex) {
- Slog.e(TAG, "Communications error", ex);
- throw ex;
- } finally {
- synchronized (mDaemonLock) {
- if (mOutputStream != null) {
- try {
- mOutputStream.close();
- } catch (IOException e) {
- Slog.w(TAG, "Failed closing output stream", e);
- }
- mOutputStream = null;
- }
- }
- try {
- if (socket != null) {
- socket.close();
- }
- } catch (IOException ex) {
- Slog.w(TAG, "Failed closing socket", ex);
- }
- }
- }
sendCommandLocked接口
- /**
- * Sends a command to the daemon with a single argument
- *
- * @param command The command to send to the daemon
- * @param argument The argument to send with the command (or null)
- */
- private void sendCommandLocked(String command, String argument)
- throws NativeDaemonConnectorException {
- if (command != null && command.indexOf(' ') >= 0) {
- throw new IllegalArgumentException("unexpected command: " + command);
- }
- if (argument != null && argument.indexOf(' ') >= 0) {
- throw new IllegalArgumentException("unexpected argument: " + argument);
- }
- 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());
- throw new NativeDaemonConnectorException("No output stream!");
- } else {
- StringBuilder builder = new StringBuilder(command);
- if (argument != null) {
- builder.append(argument);
- }
- builder.append(' ');
- try {
- mOutputStream.write(builder.toString().getBytes());
- } catch (IOException ex) {
- Slog.e(TAG, "IOException in sendCommand", ex);
- }
- }
- }