NetworkManagementService介绍

本文为《深入理解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等。

ServerThread 中和 NMService 相关的重要知识点仅 create 和 systemReady 两个函数:
android-5.1/frameworks/base/services/core/java/com/android/server/NetworkManagementService.java

    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 线程完成初始化工作。下面来看构造函数:
android-5.1/frameworks/base/services/core/java/com/android/server/NetworkManagementService.java

    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 :
android-5.1/frameworks/base/services/core/java/com/android/server/NetworkManagementService.java

    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 函数详解:
android-5.1/frameworks/base/services/core/java/com/android/server/NetworkManagementService.java

    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();
        }
    }

你可能感兴趣的:(wifi)