基于 AOSP master 分支,至少是 Android 12
1. Overview
2. Network Service Discovery Flow
以 discoverService 为例,介绍 Network Service Discovery 调用流程
2.1 NSD Flow in API & Framework
frameworks/base/core/java/android/net/nsd/NsdManager.java
public void discoverServices(String serviceType, int protocolType, DiscoveryListener listener) {
checkStringNotEmpty(serviceType, "Service type cannot be empty");
checkProtocol(protocolType);
NsdServiceInfo s = new NsdServiceInfo();
s.setServiceType(serviceType);
int key = putListener(listener, s);
try {
mService.discoverServices(key, s);
} catch (RemoteException e) {
e.rethrowFromSystemServer();
}
}
frameworks/base/services/core/java/com/android/server/NsdService.java
private class NsdServiceConnector extends INsdServiceConnector.Stub
implements IBinder.DeathRecipient {
@Override
public void discoverServices(int listenerKey, NsdServiceInfo serviceInfo) {
mNsdStateMachine.sendMessage(mNsdStateMachine.obtainMessage(
NsdManager.DISCOVER_SERVICES, 0, listenerKey,
new ListenerArgs(this, serviceInfo)));
}
}
class EnabledState extends State {
@Override
public boolean processMessage(Message msg) {
final ClientInfo clientInfo;
final int id;
final int clientId = msg.arg2;
final ListenerArgs args;
switch (msg.what) {
case NsdManager.DISCOVER_SERVICES:
args = (ListenerArgs) msg.obj;
clientInfo = mClients.get(args.connector);
maybeStartDaemon();
id = getUniqueId();
if (discoverServices(id, args.serviceInfo.getServiceType())) {
storeRequestMap(clientId, id, clientInfo, msg.what);
clientInfo.onDiscoverServicesStarted(clientId, args.serviceInfo);
}
break;
这里有两个重要方法:
- maybeStartDaemon()
- discoverServices()
2.1.1 maybeStartDaemon()
frameworks/base/services/core/java/com/android/server/NsdService.java
private class NsdStateMachine extends StateMachine {
private void maybeStartDaemon() {
mDaemon.maybeStart();
maybeScheduleStop();
}
}
public static class DaemonConnection {
final NativeDaemonConnector mNativeConnector;
boolean mIsStarted = false;
DaemonConnection(NativeCallbackReceiver callback) {
mNativeConnector = new NativeDaemonConnector(callback, "mdns", 10, MDNS_TAG, 25, null);
new Thread(mNativeConnector, MDNS_TAG).start();
}
public void maybeStart() {
if (mIsStarted) {
return;
}
execute("start-service");
mIsStarted = true;
}
public boolean execute(Object... args) {
try {
mNativeConnector.execute("mdnssd", args);
} catch (NativeDaemonConnectorException e) {
return false;
}
return true;
}
要执行之,首先需要执行 的初始化
// 初始化过程先不分析了,结论是作为 client 端连接一个 socket 到 server端(netd)
- 初始化过程出现了 “mdns”,在初始化过程逐步解析为 dev/socket/mdns,最终连接到它;
- 命令执行中出现了 “mdnssd”,这是 Network Service Discovery 操作的命令,其他内容作为它的参数;
- 此处执行的 “start-service” 便是以 “mdnssd” 为命令,以 “start-service” 作为参数列表
2.1.2 discoverServices()
private boolean discoverServices(int discoveryId, String serviceType) {
return mDaemon.execute("discover", discoveryId, serviceType);
}
与前文分析相同,以 “mdnssd” 为命令,以 “discover”、discoveryId、serviceType 作为参数列表
2.2 NSD Flow in Netd
int main() {
......
MDnsSdListener mdnsl;
if (mdnsl.startListener()) {
exit(1);
}
......
}
system/core/libsysutils/src/SocketListener.cpp
int SocketListener::startListener() {
return startListener(4);
}
int SocketListener::startListener(int backlog) {
......
if (pthread_create(&mThread, nullptr, SocketListener::threadStart, this)) {
return -1;
}
return 0;
}
void *SocketListener::threadStart(void *obj) {
SocketListener *me = reinterpret_cast<SocketListener *>(obj);
me->runListener();
pthread_exit(nullptr);
return nullptr;
}
void SocketListener::runListener() {
while (true) {
......
for (SocketClient* c : pending) {
if (!onDataAvailable(c)) {
release(c, false);
}
c->decRef();
}
}
}
onDataAvailable() 方法的具体实现在 SocketListener 子类 FrameworkListener 中
system/core/libsysutils/include/sysutils/FrameworkListener.h
class FrameworkListener : public SocketListener {
......
}
bool FrameworkListener::onDataAvailable(SocketClient *c) {
......
for (i = 0; i < len; i++) {
if (buffer[i] == '\0') {
if (mSkipToNextNullByte) {
mSkipToNextNullByte = false;
} else {
dispatchCommand(c, buffer + offset);
}
offset = i + 1;
}
}
return true;
}
void FrameworkListener::dispatchCommand(SocketClient *cli, char *data) {
......
for (auto* c : mCommands) {
if (!strcmp(argv[0], c->getCommand())) {
if (c->runCommand(cli, argc, argv)) {
}
goto out;
}
}
......
}
void FrameworkListener::registerCmd(FrameworkCommand *cmd) {
mCommands.push_back(cmd);
}
先确定 mCommand 集合里有什么,才能确定具体执行的 runCommand() 方法是什么
system/netd/server/MDnsSdListener.cpp
MDnsSdListener::MDnsSdListener() : FrameworkListener(SOCKET_NAME, true) {
Monitor *m = new Monitor();
registerCmd(new Handler(m, this));
}
MDnsSdListener::Handler::Handler(Monitor *m, MDnsSdListener *listener) :
NetdCommand("mdnssd") {
mMonitor = m;
mListener = listener;
}
从以上源码可知,注册的命令是 “mdnssd”,与前文的客户端匹配
具体命令的处理过程如下,前文提到了 discover 和 start-service 两个操作,这里仅分析 discover 命令
int MDnsSdListener::Handler::runCommand(SocketClient *cli,
int argc, char **argv) {
.......
if (strcmp(cmd, "discover") == 0) {
int requestId = strtol(argv[2], nullptr, 10);
char *serviceType = argv[3];
discover(cli, nullptr, serviceType, nullptr, requestId, 0);
} else if (strcmp(cmd, "start-service") == 0) {
if (mMonitor->startService()) {
cli->sendMsg(ResponseCode::CommandOkay, "Service Started", false);
} else {
cli->sendMsg(ResponseCode::ServiceStartFailed, "Service already running", false);
}
}
......
}
void MDnsSdListener::Handler::discover(SocketClient *cli,
const char *iface,
const char *regType,
const char *domain,
const int requestId,
const int requestFlags) {
......
DNSServiceErrorType result = DNSServiceBrowse(ref, nativeFlags, interfaceInt, regType,
domain, &MDnsSdListenerDiscoverCallback, context);
......
}
2.3 NSD Flow in mDNSResponder
external/mdnsresponder/mDNSShared/dnssd_clientstub.c
DNSServiceErrorType DNSSD_API DNSServiceBrowse
(
DNSServiceRef *sdRef,
DNSServiceFlags flags,
uint32_t interfaceIndex,
const char *regtype,
const char *domain,
DNSServiceBrowseReply callBack,
void *context
)
{
}
mDNSResponder Architecture.png
网友评论