本文为《深入理解Android Wi-Fi、NFC和GPS卷》读书笔记,Android源码为Android 5.1
NetworkManagementService(以后简称 NMService)将通过 netd socket 和 Netd 交互:
android-5.1/frameworks/base/services/java/com/android/server/SystemServer.java
private void startOtherServices() {
.....//其他Service 的创建及相关处理
if (!disableNetwork) {
try {
Slog.i(TAG, "NetworkManagement Service");
networkManagement = NetworkManagementService.create(context);
ServiceManager.addService(Context.NETWORKMANAGEMENT_SERVICE, networkManagement);
} catch (Throwable e) {
reportWtf("starting NetworkManagement Service", e);
}
}
......
try {
if (networkManagementF != null) networkManagementF.systemReady();
} catch (Throwable e) {
reportWtf("making Network Managment Service ready", e);
}
......
}
ServerThread是Android Java Framework 的中枢,绝大部分重要 Service 都在该线程中创建,例如 ActivityManagerService、 WindowManagerService、 PackageManagerService 以及本书要介绍的 WiFiService、 WifiP2pService等。
static NetworkManagementService create(Context context,
String socket) throws InterruptedException {
//创建一个 NMService 对象
final NetworkManagementService service = new NetworkManagementService(context, socket);
final CountDownLatch connectedSignal = service.mConnectedSignal;
if (DBG) Slog.d(TAG, "Creating NetworkManagementService");
service.mThread.start(); //启动 NMService 中的一个线程
if (DBG) Slog.d(TAG, "Awaiting socket connection");
//connectedSignal 用于等待某个事情的发生。此处是等待 mThread 完成初始化工作
connectedSignal.await();
if (DBG) Slog.d(TAG, "Connected");
return service;
}
create 函数主要工作是创建一个 NMService 对象并启动其中一个线程。 create 返回前需要确保 mThread 线程完成初始化工作。下面来看构造函数:
private NetworkManagementService(Context context, String socket) {
mContext = context;
// make sure this is on the same looper as our NativeDaemonConnector for sync purposes
mFgHandler = new Handler(FgThread.get().getLooper());
//对模拟器的处理
if ("simulator".equals(SystemProperties.get("ro.product.device"))) {
mConnector = null;
mThread = null;
mDaemonHandler = null;
mPhoneStateListener = null;
return;
}
// Don't need this wake lock, since we now have a time stamp for when
// the network actually went inactive. (It might be nice to still do this,
// but I don't want to do it through the power manager because that pollutes the
// battery stats history with pointless noise.)
//PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wl = null; //pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, NETD_TAG);
//NativeDaemonConnector 是Java Framework 中一个特别的类,它用于连接指定的 socket,并发送和接收 socket 数据。
//netd 参数代表目标 socket。 NetdCallbackReceiver 为具体的 socket 连接及消息处理对象。
//1.当Netd连接成功后, NetdCallbackReceiver 的 onDaemonConnected 函数将被调用。
//2.当收到来自 Netd 的数据后, NetdCallbackReceiver 的 onEvent 函数将被调用。
mConnector = new NativeDaemonConnector(
new NetdCallbackReceiver(), socket, 10, NETD_TAG, 160, wl,
FgThread.get().getLooper());
//创建一个线程,其runnable对象就是 mConnector
mThread = new Thread(mConnector, NETD_TAG);
mDaemonHandler = new Handler(FgThread.get().getLooper());
mPhoneStateListener = new PhoneStateListener(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID,
mDaemonHandler.getLooper()) {
@Override
public void onDataConnectionRealTimeInfoChanged(
DataConnectionRealTimeInfo dcRtInfo) {
if (DBG) Slog.d(TAG, "onDataConnectionRealTimeInfoChanged: " + dcRtInfo);
notifyInterfaceClassActivity(ConnectivityManager.TYPE_MOBILE,
dcRtInfo.getDcPowerState(), dcRtInfo.getTime(), true);
}
};
TelephonyManager tm = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
if (tm != null) {
tm.listen(mPhoneStateListener,
PhoneStateListener.LISTEN_DATA_CONNECTION_REAL_TIME_INFO);
}
// Add ourself to the Watchdog monitors.
//把自己添加到watchdog中的监控队列中。这样 NMService 将受到 watchdog 的监控, 一旦 NMService 出现异常, watchdog 将自杀以重启 Android Java World。
Watchdog.getInstance().addMonitor(this);
}
上述代码最重要的是 NetdCallbackReceiver :
private class NetdCallbackReceiver implements INativeDaemonConnectorCallbacks {
@Override
public void onDaemonConnected() {
// event is dispatched from internal NDC thread, so we prepare the
// daemon back on main thread.
if (mConnectedSignal != null) {
//通知 NMService 构造函数中的 connectedSignal.await() 返回
mConnectedSignal.countDown();
mConnectedSignal = null;
} else {
mFgHandler.post(new Runnable() {
@Override
public void run() {
prepareNativeDaemon();
}
});
}
}
@Override
public boolean onCheckHoldWakeLock(int code) {
return code == NetdResponseCode.InterfaceClassActivity;
}
@Override
//处理来自 Netd 的消息
public boolean onEvent(int code, String raw, String[] cooked) {
String errorMessage = String.format("Invalid event from daemon (%s)", raw);
switch (code) {
case NetdResponseCode.InterfaceChange: //对应 InterfaceCmd
/*
* a network interface change occured
* Format: "NNN Iface added "
* "NNN Iface removed "
* "NNN Iface changed "
* "NNN Iface linkstatus "
*/
if (cooked.length < 4 || !cooked[1].equals("Iface")) {
throw new IllegalStateException(errorMessage);
}
if (cooked[2].equals("added")) {
notifyInterfaceAdded(cooked[3]);
return true;
} else if (cooked[2].equals("removed")) {
notifyInterfaceRemoved(cooked[3]);
return true;
} else if (cooked[2].equals("changed") && cooked.length == 5) {
notifyInterfaceStatusChanged(cooked[3], cooked[4].equals("up"));
return true;
} else if (cooked[2].equals("linkstate") && cooked.length == 5) {
notifyInterfaceLinkStateChanged(cooked[3], cooked[4].equals("up"));
return true;
}
throw new IllegalStateException(errorMessage);
// break;
case NetdResponseCode.BandwidthControl: //对应 BandwidthControlCmd
/*
* Bandwidth control needs some attention
* Format: "NNN limit alert "
*/
if (cooked.length < 5 || !cooked[1].equals("limit")) {
throw new IllegalStateException(errorMessage);
}
if (cooked[2].equals("alert")) {
notifyLimitReached(cooked[3], cooked[4]);
return true;
}
throw new IllegalStateException(errorMessage);
// break;
case NetdResponseCode.InterfaceClassActivity: //和IdletimerCmd有关
/*
* An network interface class state changed (active/idle)
* Format: "NNN IfaceClass
systemReady 函数详解:
public void systemReady() {
prepareNativeDaemon();
if (DBG) Slog.d(TAG, "Prepared");
}
prepareNativeDaemon 用于将系统中一些与带宽控制、防火墙相关的规则发送给 Netd 去执行:
android-5.1/frameworks/base/services/core/java/com/android/server/NetworkManagementService.java
private void prepareNativeDaemon() {
mBandwidthControlEnabled = false;
// only enable bandwidth control when support exists
//判断 kernel 是否支持 bandwidthcontrol
final boolean hasKernelSupport = new File("/proc/net/xt_qtaguid/ctrl").exists();
if (hasKernelSupport) {
Slog.d(TAG, "enabling bandwidth control");
try {
mConnector.execute("bandwidth", "enable"); //使能 bandwidth 功能
mBandwidthControlEnabled = true;
} catch (NativeDaemonConnectorException e) {
Log.wtf(TAG, "problem enabling bandwidth controls", e);
}
} else {
Slog.d(TAG, "not enabling bandwidth control");
}
//设置 Android 系统属性 net.qtaguid_enabled
SystemProperties.set(PROP_QTAGUID_ENABLED, mBandwidthControlEnabled ? "1" : "0");
if (mBandwidthControlEnabled) {
try {
getBatteryStats().noteNetworkStatsEnabled();
} catch (RemoteException e) {
}
}
// push any existing quota or UID rules
//设置 Bandwidth 规则
synchronized (mQuotaLock) {
int size = mActiveQuotas.size();
if (size > 0) {
Slog.d(TAG, "ushing " + size + " active quota rules");
//mActiveQuotas 保存了每个 Interface 的配额设置
final HashMap activeQuotas = mActiveQuotas;
mActiveQuotas = Maps.newHashMap();
for (Map.Entry entry : activeQuotas.entrySet()) {
setInterfaceQuota(entry.getKey(), entry.getValue());
}
}
size = mActiveAlerts.size();
if (size > 0) {
Slog.d(TAG, "pushing " + size + " active alert rules");
final HashMap activeAlerts = mActiveAlerts;
mActiveAlerts = Maps.newHashMap();
for (Map.Entry entry : activeAlerts.entrySet()) {
setInterfaceAlert(entry.getKey(), entry.getValue());
}
}
size = mUidRejectOnQuota.size();
if (size > 0) {
Slog.d(TAG, "pushing " + size + " active uid rules");
final SparseBooleanArray uidRejectOnQuota = mUidRejectOnQuota;
mUidRejectOnQuota = new SparseBooleanArray();
for (int i = 0; i < uidRejectOnQuota.size(); i++) {
setUidNetworkRules(uidRejectOnQuota.keyAt(i), uidRejectOnQuota.valueAt(i));
}
}
}
// TODO: Push any existing firewall state
//设置防火墙规则
setFirewallEnabled(mFirewallEnabled || LockdownVpnTracker.isEnabled());
}
@Override
public void setFirewallEnabled(boolean enabled) {
enforceSystemUid();
try {//发送firewall相关的Command给 Netd
mConnector.execute("firewall", enabled ? "enable" : "disable");
mFirewallEnabled = enabled;
} catch (NativeDaemonConnectorException e) {
throw e.rethrowAsParcelableException();
}
}