NetworkManagementService介绍

来源:互联网 发布:国外大数据产业园 编辑:程序博客网 时间:2024/05/08 07:20

本文为《深入理解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 <name>"                     *         "NNN Iface removed <name>"                     *         "NNN Iface changed <name> <up/down>"                     *         "NNN Iface linkstatus <name> <up/down>"                     */                    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 <alertName> <ifaceName>"                     */                    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 <active/idle> <label>"                     */                    if (cooked.length < 4 || !cooked[1].equals("IfaceClass")) {                        throw new IllegalStateException(errorMessage);                    }                    long timestampNanos = 0;                    if (cooked.length == 5) {                        try {                            timestampNanos = Long.parseLong(cooked[4]);                        } catch(NumberFormatException ne) {}                    } else {                        timestampNanos = SystemClock.elapsedRealtimeNanos();                    }                    boolean isActive = cooked[2].equals("active");                    notifyInterfaceClassActivity(Integer.parseInt(cooked[3]),                            isActive ? DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH                            : DataConnectionRealTimeInfo.DC_POWER_STATE_LOW, timestampNanos, false);                    return true;                    // break;            case NetdResponseCode.InterfaceAddressChange:                    /*                     * A network address change occurred                     * Format: "NNN Address updated <addr> <iface> <flags> <scope>"                     *         "NNN Address removed <addr> <iface> <flags> <scope>"                     */                    if (cooked.length < 7 || !cooked[1].equals("Address")) {                        throw new IllegalStateException(errorMessage);                    }                    String iface = cooked[4];                    LinkAddress address;                    try {                        int flags = Integer.parseInt(cooked[5]);                        int scope = Integer.parseInt(cooked[6]);                        address = new LinkAddress(cooked[3], flags, scope);                    } catch(NumberFormatException e) {     // Non-numeric lifetime or scope.                        throw new IllegalStateException(errorMessage, e);                    } catch(IllegalArgumentException e) {  // Malformed/invalid IP address.                        throw new IllegalStateException(errorMessage, e);                    }                    if (cooked[2].equals("updated")) {                        notifyAddressUpdated(iface, address);                    } else {                        notifyAddressRemoved(iface, address);                    }                    return true;                    // break;            case NetdResponseCode.InterfaceDnsServerInfo:                    /*                     * Information about available DNS servers has been received.                     * Format: "NNN DnsInfo servers <interface> <lifetime> <servers>"                     */                    long lifetime;  // Actually a 32-bit unsigned integer.                    if (cooked.length == 6 &&                        cooked[1].equals("DnsInfo") &&                        cooked[2].equals("servers")) {                        try {                            lifetime = Long.parseLong(cooked[4]);                        } catch (NumberFormatException e) {                            throw new IllegalStateException(errorMessage);                        }                        String[] servers = cooked[5].split(",");                        notifyInterfaceDnsServerInfo(cooked[3], lifetime, servers);                    }                    return true;                    // break;            case NetdResponseCode.RouteChange:                    /*                     * A route has been updated or removed.                     * Format: "NNN Route <updated|removed> <dst> [via <gateway] [dev <iface>]"                     */                    if (!cooked[1].equals("Route") || cooked.length < 6) {                        throw new IllegalStateException(errorMessage);                    }                    String via = null;                    String dev = null;                    boolean valid = true;                    for (int i = 4; (i + 1) < cooked.length && valid; i += 2) {                        if (cooked[i].equals("dev")) {                            if (dev == null) {                                dev = cooked[i+1];                            } else {                                valid = false;  // Duplicate interface.                            }                        } else if (cooked[i].equals("via")) {                            if (via == null) {                                via = cooked[i+1];                            } else {                                valid = false;  // Duplicate gateway.                            }                        } else {                            valid = false;      // Unknown syntax.                        }                    }                    if (valid) {                        try {                            // InetAddress.parseNumericAddress(null) inexplicably returns ::1.                            InetAddress gateway = null;                            if (via != null) gateway = InetAddress.parseNumericAddress(via);                            RouteInfo route = new RouteInfo(new IpPrefix(cooked[3]), gateway, dev);                            notifyRouteChange(cooked[2], route);                            return true;                        } catch (IllegalArgumentException e) {}                    }                    throw new IllegalStateException(errorMessage);                    // break;            default: break;            }            return false;        }    }
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<String, Long> activeQuotas = mActiveQuotas;                mActiveQuotas = Maps.newHashMap();                for (Map.Entry<String, Long> entry : activeQuotas.entrySet()) {                    setInterfaceQuota(entry.getKey(), entry.getValue());                }            }            size = mActiveAlerts.size();            if (size > 0) {                Slog.d(TAG, "pushing " + size + " active alert rules");                final HashMap<String, Long> activeAlerts = mActiveAlerts;                mActiveAlerts = Maps.newHashMap();                for (Map.Entry<String, Long> 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();        }    }

0 1
原创粉丝点击