android 5.1 Ethernet开发相关

android5.0以上的系统自带了ethernet service,默认开机就会启动,默认ip获取方式是动态分配。开发中,有时需要用到非公开的API,在以前,一般是通过反射去调用隐藏的API,但是这样就会存在性能隐患。首先将 framework.jar 导入到 Android Studio 中,以去掉反射。

  1. 取到系统源码的framework.jar 。路径:

     out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/classes.jar
    

改名得到framework.jar。

  1. 把 framework.jar 放到 app 模块的 libs 目录下, 依次打开 File –> Project Structure –> Modules 中找到 app ,在右边选择 Dependencies 选项卡,点击左下角的 + 按钮,选择 File dependency ,在弹出的 Select Path 窗口中选择 libs 中的 framework.jar

  2. 在新增的 Dependencies 记录的右边,将 Compile 修改为 Provided ,点击 OK 保存修改,Provided 的作用是只参与编译,但不打包到apk中

  3. 修改根目录下的build.prop文件

     allprojects {
         repositories {
             jcenter()
                    }
     //添加以下代码,使framework-base.jar包编译先于android.jar
     gradle.projectsEvaluated {
         tasks.withType(JavaCompile){
             options.compilerArgs.add('-Xbootclasspath/p:app\\libs\\framework-base.jar')
         }
        }
     }
    

以太网源码流程

frameworks/base/services/Java/com/android/server/SystemServer.java

public final class SystemServer {  
 private static final String ETHERNET_SERVICE_CLASS =  
        "com.android.server.ethernet.EthernetService";  
  public static void main(String[] args) {  
       new SystemServer().run();  
     }  
  private void run() {  
    startOtherServices();  
  }  
  private void startOtherServices() {  
    if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_ETHERNET)) {  
                mSystemServiceManager.startService(ETHERNET_SERVICE_CLASS);  
        }  
  }  
}  

frameworks/opt/net/ethernet/java/com/android/server/ethernet/EthernetService.java

public final class EthernetService extends SystemService {  
private static final String TAG = "EthernetService";  
final EthernetServiceImpl mImpl;  
public EthernetService(Context context) {  
    super(context);  
    mImpl = new EthernetServiceImpl(context);  
}  
@Override  
public void onStart() {  
    Log.i(TAG, "Registering service " + Context.ETHERNET_SERVICE);  
    publishBinderService(Context.ETHERNET_SERVICE, mImpl);  
}  
@Override  
public void onBootPhase(int phase) {  
    if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) {  
        mImpl.start();  
        }  
    }  
} 

frameworks/opt/net/ethernet/java/com/android/server/ethernet/EthernetServiceImpl.java

public class EthernetServiceImpl extends IEthernetManager.Stub {  
  public EthernetServiceImpl(Context context) {  
    mContext = context;  
    Log.i(TAG, "Creating EthernetConfigStore");  
    mEthernetConfigStore = new EthernetConfigStore();  
    mIpConfiguration = mEthernetConfigStore.readIpAndProxyConfigurations();  
    Log.i(TAG, "Read stored IP configuration: " + mIpConfiguration);  
    IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);  
    mNMService = INetworkManagementService.Stub.asInterface(b);  
    mTracker = new EthernetNetworkFactory();  
  }  
  public void start() {  
    mCM = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);  
    HandlerThread handlerThread = new HandlerThread("EthernetServiceThread");  
    handlerThread.start();  
    mHandler = new Handler(handlerThread.getLooper());  
    mEnabled = getPersistedState();  
    Log.i(TAG, "Ethernet Persisted Enabled " + mEnabled);  
    setState(mEnabled);  //重要  
  }  
  public synchronized void setState(int state) {  
    enforceChangePermission();  
    Log.i(TAG, "setState from mState=" + mState + " to state=" + state);  
    if (mState != state) {  
      mState = state;  
      if (state == EthernetManager.ETHERNET_STATE_DISABLED) {  
        setPersistedState(EthernetManager.ETHERNET_STATE_DISABLED);  
        mTracker.stopInterface();  
        mStarted.set(false);  
      } else {  
        setPersistedState(EthernetManager.ETHERNET_STATE_ENABLED);  
        mTracker.stop();  
        mTracker.start(mContext, mHandler);  
        mStarted.set(true);  
      }  
    }  
  }  
} 

frameworks/opt/net/ethernet/java/com/android/server/ethernet/EthernetNetworkFactory.java

class EthernetNetworkFactory {
  EthernetNetworkFactory() {
    mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_ETHERNET, 0, NETWORK_TYPE, "");
    mLinkProperties = new LinkProperties();
    initNetworkCapabilities();
  }
  public synchronized void start(Context context, Handler target) {
    IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
    mNMService = INetworkManagementService.Stub.asInterface(b);
    mEthernetManager = (EthernetManager) context.getSystemService(Context.ETHERNET_SERVICE);
    mFactory = new LocalNetworkFactory(NETWORK_TYPE, context, target.getLooper());
    mFactory.setCapabilityFilter(mNetworkCapabilities);
    mFactory.setScoreFilter(-1); // this set high when we have an iface
    mFactory.register();
    /*
    public void register() { 
      if (DBG) log("Registering NetworkFactory"); 
      if (mMessenger == null) { 
        mMessenger = new Messenger(this); 
    ConnectivityManager.from(mContext).registerNetworkFactory(mMessenger, LOG_TAG); 
      } 
    } 
    frameworks/base/services/core/java/com/android/server/ConnectivityService.java 
    public void registerNetworkFactory(Messenger messenger, String name) { 
      NetworkFactoryInfo nfi = new NetworkFactoryInfo(name, messenger, new AsyncChannel()); 
      mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_FACTORY, nfi)); 
    } 
    private class InternalHandler extends Handler { 
      public void handleMessage(Message msg) { 
        case EVENT_REGISTER_NETWORK_FACTORY: { 
          handleRegisterNetworkFactory((NetworkFactoryInfo)msg.obj); 
          break; 
        } 
      } 
    } 
private void handleRegisterNetworkFactory(NetworkFactoryInfo nfi) { 
      if (DBG) log("Got NetworkFactory Messenger for " + nfi.name); 
      mNetworkFactoryInfos.put(nfi.messenger, nfi); 
      nfi.asyncChannel.connect(mContext, mTrackerHandler, nfi.messenger); 
    }
    */
    mInterfaceObserver = new InterfaceObserver();
    try {
      mNMService.registerObserver(mInterfaceObserver);
    } catch (RemoteException e) {
      Log.e(TAG, "Could not register InterfaceObserver " + e);
    }
    updateInterfaceState(iface, true); //注册
  }
  private void updateInterfaceState(String iface, boolean up) {
    updateAgent();
    mFactory.setScoreFilter(up ? NETWORK_SCORE : -1); //设置scroe值;这个是网络优先级判断依据
  }
  public void updateAgent() {
    mNetworkAgent.sendNetworkInfo(mNetworkInfo);
  }
}

ETHERNET监听NETD进程的socket

init.rc

service netd /system/bin/netd
class main
socket netd stream 0660 root system
socket dnsproxyd stream 0660 root inet
socket mdns stream 0660 root system
socket fwmarkd stream 0660 root inet

frameworks/base/services/core/java/com/android/server/NetworkManagementService.java

public static NetworkManagementService create(Context context) throws InterruptedException {
  return create(context, NETD_SOCKET_NAME);
  /*
  private static final String NETD_SOCKET_NAME = "netd";
  */
}

private NetworkManagementService(Context context, String socket) {
  mConnector = new NativeDaemonConnector(
                new NetdCallbackReceiver(), socket, 10, NETD_TAG, 160, wl,
                FgThread.get().getLooper());
  /*
  frameworks/base/services/core/java/com/android/server/NativeDaemonConnector.java
  public void run() {
    mCallbackHandler = new Handler(mLooper, this);
    while (true) {
      try {
        listenToSocket();
      } catch (Exception e) {
        loge("Error in NativeDaemonConnector: " + e);
        SystemClock.sleep(5000);
      }
    }
  }
  private void listenToSocket() throws IOException {
    LocalSocketAddress address = determineSocketAddress();
    mCallbackHandler.sendMessage();
  }
  public boolean handleMessage(Message msg) {
    mCallbacks.onEvent
  }
  */
}

private class NetdCallbackReceiver implements INativeDaemonConnectorCallbacks {
  public boolean onEvent(int code, String raw, String[] cooked) {
    notifyInterfaceAdded(cooked[3]);
    ......
    notifyInterfaceRemoved(cooked[3]);
    ......
    notifyInterfaceStatusChanged(cooked[3], cooked[4].equals("up"));
    ......
    notifyInterfaceLinkStateChanged(cooked[3], cooked[4].equals("up"));
  }
  private void notifyInterfaceLinkStateChanged(String iface, boolean up) {
    mObservers.getBroadcastItem(i).interfaceLinkStateChanged(iface, up);
  }
}

frameworks/opt/net/ethernet/java/com/android/server/ethernet/EthernetNetworkFactory.java

private class InterfaceObserver extends BaseNetworkObserver {  
  public void interfaceLinkStateChanged(String iface, boolean up) {  
    updateInterfaceState(iface, up);  
  }  
}     
private void updateInterfaceState(String iface, boolean up) {  
 mFactory.setScoreFilter(up ? NETWORK_SCORE : -1);  
}  

frameworks/base/core/java/android/net/NetworkFactory.java

public void setScoreFilter(int score) {
  sendMessage(obtainMessage(CMD_SET_SCORE, score, 0));
}

public void handleMessage(Message msg) {
  case CMD_SET_SCORE: {
    handleSetScore(msg.arg1);
    break;
  }
}

private void handleSetScore(int score) {
  mScore = score;
  evalRequests();
}

private void evalRequests() {
  for (int i = 0; i < mNetworkRequests.size(); i++) {
    NetworkRequestInfo n = mNetworkRequests.valueAt(i);
    evalRequest(n);
  }
}

private void evalRequest(NetworkRequestInfo n) {
  needNetworkFor(n.request, n.score);
}

protected void needNetworkFor(NetworkRequest networkRequest, int score) {
  if (++mRefCount == 1) startNetwork();
}

frameworks/opt/net/ethernet/java/com/android/server/ethernet/EthernetNetworkFactory.java

private class LocalNetworkFactory extends NetworkFactory {
  LocalNetworkFactory(String name, Context context, Looper looper) {
    super(looper, context, name, new NetworkCapabilities());
  }
  protected void startNetwork() {
    onRequestNetwork();
  }
  protected void stopNetwork() {
  }
}

public void onRequestNetwork() {
  Thread dhcpThread = new Thread(new Runnable() {
    public void run() {
      DhcpResults dhcpResults = new DhcpResults(); //DHCP相关
      if (!NetworkUtils.runDhcp(mIface, dhcpResults)) {
        /*
        frameworks/base/core/java/android/net/NetworkUtils.java
        public native static boolean runDhcp(String interfaceName, DhcpResults dhcpResults);
        frameworks/base/core/jni/android_net_NetUtils.cp
        static jboolean android_net_utils_runDhcp(JNIEnv* env, jobject clazz, jstring ifname, jobject info)
        {
      return android_net_utils_runDhcpCommon(env, clazz, ifname, info, false);
    }
    static jboolean android_net_utils_runDhcpCommon(JNIEnv* env, jobject clazz, jstring ifname,
    jobject dhcpResults, bool renew)
    {
      if (renew) {
        result = ::dhcp_do_request_renew(nameStr, ipaddr, gateway, &prefixLength,
            dns, server, &lease, vendorInfo, domains, mtu);
      } else {
         result = ::dhcp_do_request(nameStr, ipaddr, gateway, &prefixLength,
            dns, server, &lease, vendorInfo, domains, mtu);
      }
    }
    system/core/libnetutils/dhcp_utils.c
    DHCP Client和DHCP server(system/bin/dhcpd进程)通过property_get/set 共享内存来共享信息
    */
    Log.e(TAG, "DHCP request error:" + NetworkUtils.getDhcpError());
    // set our score lower than any network could go
    // so we get dropped.
    mFactory.setScoreFilter(-1);
    return;
  }
  mNetworkAgent = new NetworkAgent(mFactory.getLooper(), mContext,
                        NETWORK_TYPE, mNetworkInfo, mNetworkCapabilities, mLinkProperties,
                        NETWORK_SCORE)
}
  });
  dhcpThread.start();
}

配置完成以后ConnectivityService向EthernetManager发送CONNECTIVITY_ACTION_IMMEDIATE的广播;EthernetManager接收到该广播以后向应用程序发送ETHERNET_INTERFACE_CONF_CHANGED广播。否则;应用程序将TIMEOUT。

public static final String EXTRA_ETHERNET_STATE = "ETHERNET_state";
public static final String ETHERNET_INTERFACE_CONF_CHANGED =
                            "android.net.ethernet.ETHERNET_INTERFACE_CONF_CHANGED"; //add by tank
private void sendEthBroadcast(String action, boolean state) {  
  String bootStr = SystemProperties.get("sys.boot_completed");
  Log.d(TAG, "sendEthBroadcast -->: " + bootStr);
  if(bootStr.equals("1")) { //boot complete
    Intent intent = new Intent(action);
    intent.putExtra(EXTRA_ETHERNET_STATE, state);

    Log.d(TAG, "sendEthBroadcast --> action= " + action + " state=" + state);
    mContext.sendBroadcast(intent);
  }
}
//连接成功调用如下:
sendEthBroadcast(ETHERNET_INTERFACE_CONF_CHANGED, true);
//连接失败调用如下:
sendEthBroadcast(ETHERNET_INTERFACE_CONF_CHANGED, false);

android5.1 增加ethernet设置(DHCP与Static ip)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,390评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,821评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,632评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,170评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,033评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,098评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,511评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,204评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,479评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,572评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,341评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,213评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,576评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,893评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,171评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,486评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,676评论 2 335

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,050评论 25 707
  • afinalAfinal是一个android的ioc,orm框架 https://github.com/yangf...
    passiontim阅读 15,360评论 2 44
  • /Library/Java/JavaVirtualMachines/jdk-9.jdk/Contents/Home...
    光剑书架上的书阅读 3,828评论 2 8
  • 感激生活的赐予 而不贪心 画一棵暴力树 分身体和精神 让爱融入生活 让尊重 理解 欣赏 感激 慈悲和友情 并非自私...
    yuanxuduan阅读 402评论 0 1
  • 现在的年纪,只有年轻的躯体,年轻的皮肤,可是,没有钱。 上学的时候,老师说过:钱不是万能的,没钱是万万不能的。在这...
    湖水漪阅读 223评论 1 1