引言

  通过前面的篇章Android以太网框架情景分析之NetworkManagementService和netd交互深入分析一和Android以太网框架情景分析之NetworkManagementService和netd交互深入分析二,我想小伙伴们对NetworkManagementService和Netd的交互已经很熟悉了,而上述二者之间提供的交互能力的使用者是谁呢?使用者有各种的的网络服务,譬如WIFI,Ethernet,Phone等!而我们这个系列篇章的核心是以太网框架,所以我们这里会以以太网服务为例说明怎么通过上述二者监听网络状态变化,以及设置网络状态的。

  本篇章演示的源码是在Android 7.1 msm8953平台上,其中涉及的源码路径如下所示:

frameworks/base/services/core/java/com/android/server/NetworkManagementService.java
frameworks/opt/net/ethernet/java/com/android/server/ethernet/EthernetNetworkFactory.java
frameworks/opt/net/ethernet/java/com/android/server/ethernet/EthernetService.java
frameworks/opt/net/ethernet/java/com/android/server/ethernet/EthernetServiceImpl.java
frameworks/opt/net/ethernet/java/com/android/server/ethernet/EthernetConfigStore.java
frameworks/base/core/java/android/net/INetworkManagementEventObserver.aidl
frameworks//base/core/java/com/android/server/net/BaseNetworkObserver.java

本篇章会以如下的两个点为核心来进行相关的分析(同时为了后续方便表述统一将NetworkManagementService简化为NMService):

  • 其一就是以太网如何监听NetworkManagementService传递过来的网络状态变化,当然我们从前面的篇章知道这里的NetworkManagementService也是一个二把手,其消息的最初来源于内核上报通过Netd传递给NetworkManagementService
  • 其二就是以太网如何利用中介二把手NetworkManagementService来传递控制消息到Netd,从而来改变网络状态

关于上述两个核心点之间涉及的进程通信架构图如下所示:

Android eth0路由表 安卓ethernet_Ethernet




一. EthernetServiceImpl通过NetworkManagementService监听网络状态的变化

  通过前面的篇章Android以太网框架情景分析之EthernetNetworkFactory深入分析可知EthernetNetworkFactory类是Ethernet的核心管理类,几乎包含了Ethernet所有的网络管理操作,这其中就包括了通过NetworkManagementService监听网络状态的变化,那么我们这个章节也就从这里开始了。


1.1 EthernetNetworkFactory.start

  还是熟悉的味道,还是原来的配方。这里兜兜转转还是回到了EthernetNetworkFactory的start方法中,而在这个方法中EthernetNetworkFactory会以观察者的身份注册到NetworkManagementService中从而监听敌情,探知网络状态的变化进而做出抉择(这不是谍战片)!

//EthernetNetworkFactory.java
class EthernetNetworkFactory {
    
    public synchronized void start(Context context, Handler target) {
        IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
        mNMService = INetworkManagementService.Stub.asInterface(b);//获取NetworkManagementService服务端代理,在前期知识储备中我们有讲过NetworkManagementService主要用于和Netd通信
        
        mInterfaceObserver = new InterfaceObserver();//创建InterfaceObserver对象,详见章节1.2
        try {
            mNMService.registerObserver(mInterfaceObserver);//将该对象注册到NMService,详见章节1.5
        } catch (RemoteException e) {
            Log.e(TAG, "Could not register InterfaceObserver " + e);
        }
    }

  这里可以看到在start方法中实例化了InterfaceObserver对象mInterfaceObserver,然后将该对象作为观察者通过远程Binder调用registerObserver将其注册到NMService中,非常典型的观察者设计模式,而这里的我们需要重点关注的就是InterfaceObserver类了。


1.2 InterfaceObserver

//EthernetNetworkFactory.java
    private class InterfaceObserver extends BaseNetworkObserver {//章节1.3重点阐述
        @Override
        public void interfaceLinkStateChanged(String iface, boolean up) {
            updateInterfaceState(iface, up);
        }

        @Override
        public void interfaceAdded(String iface) {
            maybeTrackInterface(iface);
        }

        @Override
        public void interfaceRemoved(String iface) {
            stopTrackingInterface(iface);
        }
    }

  InterfaceObserver精简无比,继承BaseNetworkObserver 然后重写了感兴趣的几个方法,相关方法如下:

  • interfaceLinkStateChanged(),网络接口状态改变通知
  • interfaceAdded(),网络模块的添加,这里我们说的是以太网,那肯定是eth类型的了譬如eth0阿等
  • interfaceRemoved(),网络模块的删除,这里我们说的是以太网,那肯定是eth类型的了譬如eth0阿等


1.3 BaseNetworkObserver

//BaseNetworkObserver.java
public class BaseNetworkObserver extends INetworkManagementEventObserver.Stub {//实现了INetworkManagementEventObserver接口的Binder服务端,详见1.4
    @Override
    public void interfaceStatusChanged(String iface, boolean up) {
        // default no-op
    }

    @Override
    public void interfaceRemoved(String iface) {
        // default no-op
    }

    @Override
    public void addressUpdated(String iface, LinkAddress address) {
        // default no-op
    }

    @Override
    public void addressRemoved(String iface, LinkAddress address) {
        // default no-op
    }

    @Override
    public void interfaceLinkStateChanged(String iface, boolean up) {
        // default no-op
    }

    @Override
    public void interfaceAdded(String iface) {
        // default no-op
    }

    @Override
    public void interfaceClassDataActivityChanged(String label, boolean active, long tsNanos) {
        // default no-op
    }

    @Override
    public void interfaceMessageRecevied(String message) {
        // default no-op
    }

    @Override
    public void limitReached(String limitName, String iface) {
        // default no-op
    }

    @Override
    public void interfaceDnsServerInfo(String iface, long lifetime, String[] servers) {
        // default no-op
    }

    @Override
    public void routeUpdated(RouteInfo route) {
        // default no-op
    }

    @Override
    public void routeRemoved(RouteInfo route) {
        // default no-op
    }
}

  这里可以看到BaseNetworkObserver类的父类是INetworkManagementEventObserver.Stub,然后其接口实现都为空,这个就需要相关子类去实现了。而这些子类实现这分别为WIFI,Ethernet,Phone等然后根据自己的特点实现自己感兴趣的接口。而这里INetworkManagementEventObserver.Stub大伙一看,就应该知道这个牵涉到了aidl的Binder通信了!


1.4 INetworkManagementEventObserver

//INetworkManagementEventObserver.adil
interface INetworkManagementEventObserver {
    /**
     * Interface configuration status has changed.
     *
     * @param iface The interface.
     * @param up True if the interface has been enabled.
     */
    void interfaceStatusChanged(String iface, boolean up);

    /**
     * Interface physical-layer link state has changed.  For Ethernet,
     * this method is invoked when the cable is plugged in or unplugged.
     *
     * @param iface The interface.
     * @param up  True if the physical link-layer connection signal is valid.
     */
    void interfaceLinkStateChanged(String iface, boolean up);

    /**
     * An interface has been added to the system
     *
     * @param iface The interface.
     */
    void interfaceAdded(String iface);

    /**
     * An interface has been removed from the system
     *
     * @param iface The interface.
     */
    void interfaceRemoved(String iface);


    /**
     * An interface address has been added or updated.
     *
     * @param iface The interface.
     * @param address The address.
     */
    void addressUpdated(String iface, in LinkAddress address);

    /**
     * An interface address has been removed.
     *
     * @param iface The interface.
     * @param address The address.
     */
    void addressRemoved(String iface, in LinkAddress address);

    /**
     * A networking quota limit has been reached. The quota might not
     * be specific to an interface.
     *
     * @param limitName The name of the limit that triggered.
     * @param iface The interface on which the limit was detected.
     */
    void limitReached(String limitName, String iface);

    /**
     * Interface data activity status is changed.
     *
     * @param iface The interface.
     * @param active  True if the interface is actively transmitting data, false if it is idle.
     * @param tsNanos Elapsed realtime in nanos when the state of the network interface changed.
     */
    void interfaceClassDataActivityChanged(String label, boolean active, long tsNanos);

    /**
     * Message is received from network interface.
     *
     * @param message The message
     */
    void interfaceMessageRecevied(String message);

    /**
     * Information about available DNS servers has been received.
     *
     * @param iface The interface on which the information was received.
     * @param lifetime The time in seconds for which the DNS servers may be used.
     * @param servers The IP addresses of the DNS servers.
     */
    void interfaceDnsServerInfo(String iface, long lifetime, in String[] servers);

    /**
     * A route has been added or updated.
     */
    void routeUpdated(in RouteInfo route);

    /**
     * A route has been removed.
     */
    void routeRemoved(in RouteInfo route);

  这里的INetworkManagementEventObserver是一个adil文件的接口类,然后在Android源码变一下生成的Java文件如下所示,而前面的BaseNetworkObserver即它服务端的实现者。

/*
 * This file is auto-generated.  DO NOT MODIFY.
 * Original file: frameworks/base/core/java/android/net/INetworkManagementEventObserver.aidl
 */
package android.net;

/**
 * Callback class for receiving events from an INetworkManagementService
 * 
 * @hide
 */
public interface INetworkManagementEventObserver extends android.os.IInterface {
    /** Local-side IPC implementation stub class. */
    public static abstract class Stub extends android.os.Binder implements
            android.net.INetworkManagementEventObserver {
        private static final java.lang.String DESCRIPTOR = "android.net.INetworkManagementEventObserver";

        /** Construct the stub at attach it to the interface. */
        public Stub() {
            this.attachInterface(this, DESCRIPTOR);
        }

        /**
         * Cast an IBinder object into an
         * android.net.INetworkManagementEventObserver interface, generating a
         * proxy if needed.
         */
        public static android.net.INetworkManagementEventObserver asInterface(
                android.os.IBinder obj) {
            if ((obj == null)) {
                return null;
            }
            android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
            if (((iin != null) && (iin instanceof android.net.INetworkManagementEventObserver))) {
                return ((android.net.INetworkManagementEventObserver) iin);
            }
            return new android.net.INetworkManagementEventObserver.Stub.Proxy(
                    obj);
        }

        @Override
        public android.os.IBinder asBinder() {
            return this;
        }

        @Override
        public boolean onTransact(int code, android.os.Parcel data,
                android.os.Parcel reply, int flags)
                throws android.os.RemoteException {
            switch (code) {
            case INTERFACE_TRANSACTION: {
                reply.writeString(DESCRIPTOR);
                return true;
            }
            case TRANSACTION_interfaceStatusChanged: {
                data.enforceInterface(DESCRIPTOR);
                java.lang.String _arg0;
                _arg0 = data.readString();
                boolean _arg1;
                _arg1 = (0 != data.readInt());
                this.interfaceStatusChanged(_arg0, _arg1);
                reply.writeNoException();
                return true;
            }
            case TRANSACTION_interfaceLinkStateChanged: {
                data.enforceInterface(DESCRIPTOR);
                java.lang.String _arg0;
                _arg0 = data.readString();
                boolean _arg1;
                _arg1 = (0 != data.readInt());
                this.interfaceLinkStateChanged(_arg0, _arg1);
                reply.writeNoException();
                return true;
            }
            case TRANSACTION_interfaceAdded: {
                data.enforceInterface(DESCRIPTOR);
                java.lang.String _arg0;
                _arg0 = data.readString();
                this.interfaceAdded(_arg0);
                reply.writeNoException();
                return true;
            }
            case TRANSACTION_interfaceRemoved: {
                data.enforceInterface(DESCRIPTOR);
                java.lang.String _arg0;
                _arg0 = data.readString();
                this.interfaceRemoved(_arg0);
                reply.writeNoException();
                return true;
            }
            case TRANSACTION_addressUpdated: {
                data.enforceInterface(DESCRIPTOR);
                java.lang.String _arg0;
                _arg0 = data.readString();
                android.net.LinkAddress _arg1;
                if ((0 != data.readInt())) {
                    _arg1 = android.net.LinkAddress.CREATOR
                            .createFromParcel(data);
                } else {
                    _arg1 = null;
                }
                this.addressUpdated(_arg0, _arg1);
                reply.writeNoException();
                return true;
            }
            case TRANSACTION_addressRemoved: {
                data.enforceInterface(DESCRIPTOR);
                java.lang.String _arg0;
                _arg0 = data.readString();
                android.net.LinkAddress _arg1;
                if ((0 != data.readInt())) {
                    _arg1 = android.net.LinkAddress.CREATOR
                            .createFromParcel(data);
                } else {
                    _arg1 = null;
                }
                this.addressRemoved(_arg0, _arg1);
                reply.writeNoException();
                return true;
            }
            case TRANSACTION_limitReached: {
                data.enforceInterface(DESCRIPTOR);
                java.lang.String _arg0;
                _arg0 = data.readString();
                java.lang.String _arg1;
                _arg1 = data.readString();
                this.limitReached(_arg0, _arg1);
                reply.writeNoException();
                return true;
            }
            case TRANSACTION_interfaceClassDataActivityChanged: {
                data.enforceInterface(DESCRIPTOR);
                java.lang.String _arg0;
                _arg0 = data.readString();
                boolean _arg1;
                _arg1 = (0 != data.readInt());
                long _arg2;
                _arg2 = data.readLong();
                this.interfaceClassDataActivityChanged(_arg0, _arg1, _arg2);
                reply.writeNoException();
                return true;
            }
            case TRANSACTION_interfaceMessageRecevied: {
                data.enforceInterface(DESCRIPTOR);
                java.lang.String _arg0;
                _arg0 = data.readString();
                this.interfaceMessageRecevied(_arg0);
                reply.writeNoException();
                return true;
            }
            case TRANSACTION_interfaceDnsServerInfo: {
                data.enforceInterface(DESCRIPTOR);
                java.lang.String _arg0;
                _arg0 = data.readString();
                long _arg1;
                _arg1 = data.readLong();
                java.lang.String[] _arg2;
                _arg2 = data.createStringArray();
                this.interfaceDnsServerInfo(_arg0, _arg1, _arg2);
                reply.writeNoException();
                return true;
            }
            case TRANSACTION_routeUpdated: {
                data.enforceInterface(DESCRIPTOR);
                android.net.RouteInfo _arg0;
                if ((0 != data.readInt())) {
                    _arg0 = android.net.RouteInfo.CREATOR
                            .createFromParcel(data);
                } else {
                    _arg0 = null;
                }
                this.routeUpdated(_arg0);
                reply.writeNoException();
                return true;
            }
            case TRANSACTION_routeRemoved: {
                data.enforceInterface(DESCRIPTOR);
                android.net.RouteInfo _arg0;
                if ((0 != data.readInt())) {
                    _arg0 = android.net.RouteInfo.CREATOR
                            .createFromParcel(data);
                } else {
                    _arg0 = null;
                }
                this.routeRemoved(_arg0);
                reply.writeNoException();
                return true;
            }
            }
            return super.onTransact(code, data, reply, flags);
        }

        private static class Proxy implements
                android.net.INetworkManagementEventObserver {
            private android.os.IBinder mRemote;

            Proxy(android.os.IBinder remote) {
                mRemote = remote;
            }

            @Override
            public android.os.IBinder asBinder() {
                return mRemote;
            }

            public java.lang.String getInterfaceDescriptor() {
                return DESCRIPTOR;
            }

            /**
             * Interface configuration status has changed.
             * 
             * @param iface
             *            The interface.
             * @param up
             *            True if the interface has been enabled.
             */
            @Override
            public void interfaceStatusChanged(java.lang.String iface,
                    boolean up) throws android.os.RemoteException {
                android.os.Parcel _data = android.os.Parcel.obtain();
                android.os.Parcel _reply = android.os.Parcel.obtain();
                try {
                    _data.writeInterfaceToken(DESCRIPTOR);
                    _data.writeString(iface);
                    _data.writeInt(((up) ? (1) : (0)));
                    mRemote.transact(Stub.TRANSACTION_interfaceStatusChanged,
                            _data, _reply, 0);
                    _reply.readException();
                } finally {
                    _reply.recycle();
                    _data.recycle();
                }
            }

            /**
             * Interface physical-layer link state has changed. For Ethernet,
             * this method is invoked when the cable is plugged in or unplugged.
             * 
             * @param iface
             *            The interface.
             * @param up
             *            True if the physical link-layer connection signal is
             *            valid.
             */
            @Override
            public void interfaceLinkStateChanged(java.lang.String iface,
                    boolean up) throws android.os.RemoteException {
                android.os.Parcel _data = android.os.Parcel.obtain();
                android.os.Parcel _reply = android.os.Parcel.obtain();
                try {
                    _data.writeInterfaceToken(DESCRIPTOR);
                    _data.writeString(iface);
                    _data.writeInt(((up) ? (1) : (0)));
                    mRemote.transact(
                            Stub.TRANSACTION_interfaceLinkStateChanged, _data,
                            _reply, 0);
                    _reply.readException();
                } finally {
                    _reply.recycle();
                    _data.recycle();
                }
            }

            /**
             * An interface has been added to the system
             * 
             * @param iface
             *            The interface.
             */
            @Override
            public void interfaceAdded(java.lang.String iface)
                    throws android.os.RemoteException {
                android.os.Parcel _data = android.os.Parcel.obtain();
                android.os.Parcel _reply = android.os.Parcel.obtain();
                try {
                    _data.writeInterfaceToken(DESCRIPTOR);
                    _data.writeString(iface);
                    mRemote.transact(Stub.TRANSACTION_interfaceAdded, _data,
                            _reply, 0);
                    _reply.readException();
                } finally {
                    _reply.recycle();
                    _data.recycle();
                }
            }

            /**
             * An interface has been removed from the system
             * 
             * @param iface
             *            The interface.
             */
            @Override
            public void interfaceRemoved(java.lang.String iface)
                    throws android.os.RemoteException {
                android.os.Parcel _data = android.os.Parcel.obtain();
                android.os.Parcel _reply = android.os.Parcel.obtain();
                try {
                    _data.writeInterfaceToken(DESCRIPTOR);
                    _data.writeString(iface);
                    mRemote.transact(Stub.TRANSACTION_interfaceRemoved, _data,
                            _reply, 0);
                    _reply.readException();
                } finally {
                    _reply.recycle();
                    _data.recycle();
                }
            }

            /**
             * An interface address has been added or updated.
             * 
             * @param iface
             *            The interface.
             * @param address
             *            The address.
             */
            @Override
            public void addressUpdated(java.lang.String iface,
                    android.net.LinkAddress address)
                    throws android.os.RemoteException {
                android.os.Parcel _data = android.os.Parcel.obtain();
                android.os.Parcel _reply = android.os.Parcel.obtain();
                try {
                    _data.writeInterfaceToken(DESCRIPTOR);
                    _data.writeString(iface);
                    if ((address != null)) {
                        _data.writeInt(1);
                        address.writeToParcel(_data, 0);
                    } else {
                        _data.writeInt(0);
                    }
                    mRemote.transact(Stub.TRANSACTION_addressUpdated, _data,
                            _reply, 0);
                    _reply.readException();
                } finally {
                    _reply.recycle();
                    _data.recycle();
                }
            }

            /**
             * An interface address has been removed.
             * 
             * @param iface
             *            The interface.
             * @param address
             *            The address.
             */
            @Override
            public void addressRemoved(java.lang.String iface,
                    android.net.LinkAddress address)
                    throws android.os.RemoteException {
                android.os.Parcel _data = android.os.Parcel.obtain();
                android.os.Parcel _reply = android.os.Parcel.obtain();
                try {
                    _data.writeInterfaceToken(DESCRIPTOR);
                    _data.writeString(iface);
                    if ((address != null)) {
                        _data.writeInt(1);
                        address.writeToParcel(_data, 0);
                    } else {
                        _data.writeInt(0);
                    }
                    mRemote.transact(Stub.TRANSACTION_addressRemoved, _data,
                            _reply, 0);
                    _reply.readException();
                } finally {
                    _reply.recycle();
                    _data.recycle();
                }
            }

            /**
             * A networking quota limit has been reached. The quota might not be
             * specific to an interface.
             * 
             * @param limitName
             *            The name of the limit that triggered.
             * @param iface
             *            The interface on which the limit was detected.
             */
            @Override
            public void limitReached(java.lang.String limitName,
                    java.lang.String iface) throws android.os.RemoteException {
                android.os.Parcel _data = android.os.Parcel.obtain();
                android.os.Parcel _reply = android.os.Parcel.obtain();
                try {
                    _data.writeInterfaceToken(DESCRIPTOR);
                    _data.writeString(limitName);
                    _data.writeString(iface);
                    mRemote.transact(Stub.TRANSACTION_limitReached, _data,
                            _reply, 0);
                    _reply.readException();
                } finally {
                    _reply.recycle();
                    _data.recycle();
                }
            }

            /**
             * Interface data activity status is changed.
             * 
             * @param iface
             *            The interface.
             * @param active
             *            True if the interface is actively transmitting data,
             *            false if it is idle.
             * @param tsNanos
             *            Elapsed realtime in nanos when the state of the
             *            network interface changed.
             */
            @Override
            public void interfaceClassDataActivityChanged(
                    java.lang.String label, boolean active, long tsNanos)
                    throws android.os.RemoteException {
                android.os.Parcel _data = android.os.Parcel.obtain();
                android.os.Parcel _reply = android.os.Parcel.obtain();
                try {
                    _data.writeInterfaceToken(DESCRIPTOR);
                    _data.writeString(label);
                    _data.writeInt(((active) ? (1) : (0)));
                    _data.writeLong(tsNanos);
                    mRemote.transact(
                            Stub.TRANSACTION_interfaceClassDataActivityChanged,
                            _data, _reply, 0);
                    _reply.readException();
                } finally {
                    _reply.recycle();
                    _data.recycle();
                }
            }

            /**
             * Message is received from network interface.
             * 
             * @param message
             *            The message
             */
            @Override
            public void interfaceMessageRecevied(java.lang.String message)
                    throws android.os.RemoteException {
                android.os.Parcel _data = android.os.Parcel.obtain();
                android.os.Parcel _reply = android.os.Parcel.obtain();
                try {
                    _data.writeInterfaceToken(DESCRIPTOR);
                    _data.writeString(message);
                    mRemote.transact(Stub.TRANSACTION_interfaceMessageRecevied,
                            _data, _reply, 0);
                    _reply.readException();
                } finally {
                    _reply.recycle();
                    _data.recycle();
                }
            }

            /**
             * Information about available DNS servers has been received.
             * 
             * @param iface
             *            The interface on which the information was received.
             * @param lifetime
             *            The time in seconds for which the DNS servers may be
             *            used.
             * @param servers
             *            The IP addresses of the DNS servers.
             */
            @Override
            public void interfaceDnsServerInfo(java.lang.String iface,
                    long lifetime, java.lang.String[] servers)
                    throws android.os.RemoteException {
                android.os.Parcel _data = android.os.Parcel.obtain();
                android.os.Parcel _reply = android.os.Parcel.obtain();
                try {
                    _data.writeInterfaceToken(DESCRIPTOR);
                    _data.writeString(iface);
                    _data.writeLong(lifetime);
                    _data.writeStringArray(servers);
                    mRemote.transact(Stub.TRANSACTION_interfaceDnsServerInfo,
                            _data, _reply, 0);
                    _reply.readException();
                } finally {
                    _reply.recycle();
                    _data.recycle();
                }
            }

            /**
             * A route has been added or updated.
             */
            @Override
            public void routeUpdated(android.net.RouteInfo route)
                    throws android.os.RemoteException {
                android.os.Parcel _data = android.os.Parcel.obtain();
                android.os.Parcel _reply = android.os.Parcel.obtain();
                try {
                    _data.writeInterfaceToken(DESCRIPTOR);
                    if ((route != null)) {
                        _data.writeInt(1);
                        route.writeToParcel(_data, 0);
                    } else {
                        _data.writeInt(0);
                    }
                    mRemote.transact(Stub.TRANSACTION_routeUpdated, _data,
                            _reply, 0);
                    _reply.readException();
                } finally {
                    _reply.recycle();
                    _data.recycle();
                }
            }

            /**
             * A route has been removed.
             */
            @Override
            public void routeRemoved(android.net.RouteInfo route)
                    throws android.os.RemoteException {
                android.os.Parcel _data = android.os.Parcel.obtain();
                android.os.Parcel _reply = android.os.Parcel.obtain();
                try {
                    _data.writeInterfaceToken(DESCRIPTOR);
                    if ((route != null)) {
                        _data.writeInt(1);
                        route.writeToParcel(_data, 0);
                    } else {
                        _data.writeInt(0);
                    }
                    mRemote.transact(Stub.TRANSACTION_routeRemoved, _data,
                            _reply, 0);
                    _reply.readException();
                } finally {
                    _reply.recycle();
                    _data.recycle();
                }
            }
        }

        static final int TRANSACTION_interfaceStatusChanged = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
        static final int TRANSACTION_interfaceLinkStateChanged = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
        static final int TRANSACTION_interfaceAdded = (android.os.IBinder.FIRST_CALL_TRANSACTION + 2);
        static final int TRANSACTION_interfaceRemoved = (android.os.IBinder.FIRST_CALL_TRANSACTION + 3);
        static final int TRANSACTION_addressUpdated = (android.os.IBinder.FIRST_CALL_TRANSACTION + 4);
        static final int TRANSACTION_addressRemoved = (android.os.IBinder.FIRST_CALL_TRANSACTION + 5);
        static final int TRANSACTION_limitReached = (android.os.IBinder.FIRST_CALL_TRANSACTION + 6);
        static final int TRANSACTION_interfaceClassDataActivityChanged = (android.os.IBinder.FIRST_CALL_TRANSACTION + 7);
        static final int TRANSACTION_interfaceMessageRecevied = (android.os.IBinder.FIRST_CALL_TRANSACTION + 8);
        static final int TRANSACTION_interfaceDnsServerInfo = (android.os.IBinder.FIRST_CALL_TRANSACTION + 9);
        static final int TRANSACTION_routeUpdated = (android.os.IBinder.FIRST_CALL_TRANSACTION + 10);
        static final int TRANSACTION_routeRemoved = (android.os.IBinder.FIRST_CALL_TRANSACTION + 11);
    }

    /**
     * Interface configuration status has changed.
     * 
     * @param iface
     *            The interface.
     * @param up
     *            True if the interface has been enabled.
     */
    public void interfaceStatusChanged(java.lang.String iface, boolean up)
            throws android.os.RemoteException;

    /**
     * Interface physical-layer link state has changed. For Ethernet, this
     * method is invoked when the cable is plugged in or unplugged.
     * 
     * @param iface
     *            The interface.
     * @param up
     *            True if the physical link-layer connection signal is valid.
     */
    public void interfaceLinkStateChanged(java.lang.String iface, boolean up)
            throws android.os.RemoteException;

    /**
     * An interface has been added to the system
     * 
     * @param iface
     *            The interface.
     */
    public void interfaceAdded(java.lang.String iface)
            throws android.os.RemoteException;

    /**
     * An interface has been removed from the system
     * 
     * @param iface
     *            The interface.
     */
    public void interfaceRemoved(java.lang.String iface)
            throws android.os.RemoteException;

    /**
     * An interface address has been added or updated.
     * 
     * @param iface
     *            The interface.
     * @param address
     *            The address.
     */
    public void addressUpdated(java.lang.String iface,
            android.net.LinkAddress address) throws android.os.RemoteException;

    /**
     * An interface address has been removed.
     * 
     * @param iface
     *            The interface.
     * @param address
     *            The address.
     */
    public void addressRemoved(java.lang.String iface,
            android.net.LinkAddress address) throws android.os.RemoteException;

    /**
     * A networking quota limit has been reached. The quota might not be
     * specific to an interface.
     * 
     * @param limitName
     *            The name of the limit that triggered.
     * @param iface
     *            The interface on which the limit was detected.
     */
    public void limitReached(java.lang.String limitName, java.lang.String iface)
            throws android.os.RemoteException;

    /**
     * Interface data activity status is changed.
     * 
     * @param iface
     *            The interface.
     * @param active
     *            True if the interface is actively transmitting data, false if
     *            it is idle.
     * @param tsNanos
     *            Elapsed realtime in nanos when the state of the network
     *            interface changed.
     */
    public void interfaceClassDataActivityChanged(java.lang.String label,
            boolean active, long tsNanos) throws android.os.RemoteException;

    /**
     * Message is received from network interface.
     * 
     * @param message
     *            The message
     */
    public void interfaceMessageRecevied(java.lang.String message)
            throws android.os.RemoteException;

    /**
     * Information about available DNS servers has been received.
     * 
     * @param iface
     *            The interface on which the information was received.
     * @param lifetime
     *            The time in seconds for which the DNS servers may be used.
     * @param servers
     *            The IP addresses of the DNS servers.
     */
    public void interfaceDnsServerInfo(java.lang.String iface, long lifetime,
            java.lang.String[] servers) throws android.os.RemoteException;

    /**
     * A route has been added or updated.
     */
    public void routeUpdated(android.net.RouteInfo route)
            throws android.os.RemoteException;

    /**
     * A route has been removed.
     */
    public void routeRemoved(android.net.RouteInfo route)
            throws android.os.RemoteException;
}


1.5 NetworkManagementService.registerObserver

  让我们重返章节1.1,继续分析以太网观察者注册流程如下:

//EthernetNetworkFactory.java
        mInterfaceObserver = new InterfaceObserver();
        try {
            mNMService.registerObserver(mInterfaceObserver);
        } catch (RemoteException e) {
            Log.e(TAG, "Could not register InterfaceObserver " + e);
        }

  这里我们可以看到该流程将会通过Binder通信远程调用NMService的方法registerObserver,至于Binder间的传输流程这里就分析了,感兴趣的可以找找相关的Binder博客自行学习,或者参阅Android Binder深入分析,总之会调用到NMService的registerObserver方法中,该方法的实现如下:

//NetworkManagementService.java
    public void registerObserver(INetworkManagementEventObserver observer) {
        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
        mObservers.register(observer);
    }
    private void notifyInterfaceAdded(String iface) {
        final int length = mObservers.beginBroadcast();
        try {
            for (int i = 0; i < length; i++) {
                try {
                    mObservers.getBroadcastItem(i).interfaceAdded(iface);
                } catch (RemoteException | RuntimeException e) {
                }
            }
        } finally {
            mObservers.finishBroadcast();
        }
    }

  到这里小伙伴们应该非常熟悉了吗,NMService接收到Netd传递过来的消息,然后通过注册的观察者将相关信息广播出去,当然这里的观察者也包括我们的以太网络。这里有一点需要注意的是通过远程Binder传递过来的INetworkManagementEventObserver是的Biner代理端,所以在NMService接收到消息后然后可以通过该代理端将消息端传递到以太网服务端。

  这里小伙伴们有没有一个疑问,EthernetServiceImpl和NetworkManagementService都是system_server同一个进程中,注册观察者接口为啥搞得这么复杂还要牵涉到aidl的远程调用呢?是的EthernetServiceImpl和NetworkManagementService是在同一个进程者,但是其它的网络实现者Phone等都是在其它的进程中,所以必须设计一种可以跨进程通信的观察者接口。各位小伙伴应该能理解清楚了!


1.6 EthernetServiceImpl通过NetworkManagementService监听网络状态的变化小结

  关于EthernetServiceImpl通过NetworkManagementService监听网络状态到这里就分析完毕了,如果小伙伴们还有什么疑问或者其中牵涉的过程有不清楚的,建议参考下述的时序图重新撸一遍,如下:

Android eth0路由表 安卓ethernet_android_02



二. EthernetServiceImpl通过NetworkManagementService修改网络状态

  我们知道网络间的传递通常是双向的,而我们的EthernetServiceImpl和NMService也是如此,在前面的章节中我们分析了EthernetServiceImpl怎么通过NMService监听网络状态的改变,而在这个章节我们将要分析EthernetServiceImpl怎么通过NMService来改变网络状态。这里我们以卸载以太网络模块为例。

2.1 EthernetNetworkFactory.setInterfaceDown

  通过前面的博客我们知道Android以太网框架情景分析之EthernetNetworkFactory深入分析可知EthernetServiceImpl是一个甩手掌柜,基本所有的事情都委托给了EthernetNetworkFactory来处理。所以吗,还是得EthernetNetworkFactory亲力亲为。

//EthernetNetworkFactory.java
    public boolean setInterfaceDown() {//这个方法在Android原生中是没有的,是为了管理以太网络进行添加的
        try {
            if(!TextUtils.isEmpty(mIface)) {
                mNMService.setInterfaceDown(mIface);//卸载以太网络模块,详见章节2.2
                return true;
            } else {
                Log.e(TAG,"mIface is null");
            }
        } catch (Exception e) {
            Log.e(TAG, "Error downing interface " + mIface + ": " + e);
        }
        return false;
    }

  这里非常简单主要是通过BInder远程调用NMService无法的setInterfaceDown方法,该方法类似于执行如下命令:

ifconfig eth0 down



2.2 NetworkManagementService.setInterfaceDown

//NetworkManagementService.java
    public void setInterfaceConfig(String iface, InterfaceConfiguration cfg) {
        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
        LinkAddress linkAddr = cfg.getLinkAddress();
        if (linkAddr == null || linkAddr.getAddress() == null) {
            throw new IllegalStateException("Null LinkAddress given");
        }

        final Command cmd = new Command("interface", "setcfg", iface,
                linkAddr.getAddress().getHostAddress(),
                linkAddr.getPrefixLength());
        for (String flag : cfg.getFlags()) {
            cmd.appendArg(flag);
        }

        try {
            mConnector.execute(cmd);
        } catch (NativeDaemonConnectorException e) {
            throw e.rethrowAsParcelableException();
        }
    }

    @Override
    public void setInterfaceDown(String iface) {
        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
        final InterfaceConfiguration ifcg = getInterfaceConfig(iface);
        ifcg.setInterfaceDown();
        setInterfaceConfig(iface, ifcg);
    }

  好吗,到这个地方各位小伙伴们应该又比较熟悉了,在前面的文章Android网络框架情景分析之NetworkManagementService和Netd交互深入分析二讲述到了NMService将会借助NativeDaemonConnector实现和Netd的通信,然后将控制命令传递到合适的驱动处理。

2.3 EthernetServiceImpl通过NetworkManagementService修改网络状态小结

  好吗,EthernetServiceImpl通过NetworkManagementService修改网络状态也分析over了,如果小伙伴们还有什么疑问或者其中牵涉的过程有不清楚的,建议参考下述的时序图重新撸一遍,如下:

Android eth0路由表 安卓ethernet_Ethernet_03


总结

  好了到这里Android网络框架情景分析之NetworkManagementService和Netd交互深入分析三重奏:

  • Android Net进程深入分析
  • NetworkManagementService和Netd交互深入分析
  • EthernetServiceImpl和NetworkManagementService及Netd交互深入分析