PPPOE流程分析2 --PPPoEService系统应用

来源:互联网 发布:国外设计app软件 编辑:程序博客网 时间:2024/05/22 20:47
1. PPPoEService相关文件
核心代码在android/device/softwinner/common/packages/PPPoEService中, 文件也只有Loader.java/PPPoEService.java/IPppoeBinder.aidl/Android.mk/AndroidManifest.xml
1.1 Android.mk
此文件定义了最终编译出的应用名称PPPoESerivce
1.2 AndroidManifest.xml
此文件定义了一个Android的Service, 对应的就是PPPoEService
  <service android:name="PPPoEService">
            <intent-filter>
                <action android:name="com.softwinner.pppoe.START_PPPOE" />
            </intent-filter>
        </service>
还定义了一个Receiver, 对应的就是Loader.java文件, 从中可以看出此Receiver监听了5个Intent
  <receiver android:name="Loader">
            <intent-filter>
                <action android:name="com.softwinner.pppoe.ACTION_STATE_CHANGE"/>   // 这个Intent就是在TvdSetting中修改了是否使能PPPoE时发出的
            </intent-filter>
            <intent-filter>
                <action android:name="android.net.wifi.STATE_CHANGED"/>
            </intent-filter>
            <intent-filter>
                <action android:name="android.net.ethernet.LINKED_ACTION"/>
            </intent-filter>
            <intent-filter>
                <action android:name="android.net.ethernet.DISLINKED_ACTION"/>
            </intent-filter>
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED"/>
            </intent-filter>
        </receiver>
1.3 Loader.java 
是个Receiver, 接受事件, 判断是否开启PPPoEService
1.4 PPPoEService.java
PPP拨号Android应用层控制核心, 执行pppoe拨号连接与断开操作.
1.5 PppoeBindler.aidl
是Android Binder机制服务端与client端通信的接口.

2. Loader.java
此类只是个Receiver, 通过AndroidManifest.xml中定义想要接受哪些Intent, 目前接受5中Intent, 下面分别是接受不同Intent时的操作, 在Receiver开始处会先获取在TvdSetting的PPPoE设置界面修改的几个值, 一个是自动连接, 一个是使能, 一个是PPPoE使用的网卡接口
 boolean autoConn = Settings.Secure.getInt(context.getContentResolver(),
    Settings.Secure.PPPOE_AUTO_CONN, 0) != 0 ? true : false;
  boolean enable = Settings.Secure.getInt(context.getContentResolver(),
    Settings.Secure.PPPOE_ENABLE, 0) != 0 ? true : false;
String iface = Settings.Secure.getString(context.getContentResolver(),
    Settings.Secure.PPPOE_INTERFACE);
2.1 接收到 public static final String ACTION_STATE_CHANGE = "com.softwinner.pppoe.ACTION_STATE_CHANGE";
这个Action是在TvdSetting应用中使能PPPoE时发出, 当设置当前是使能PPPoE, 会开启PPPoEService, 否则, 判断PPPoEService当前是否为running状态, 如果是, 这stop.
if (ACTION_STATE_CHANGE.equals(action)) {
   if (enable) {
    Intent startIntent = new Intent(PPPoEService.ACTION_START_PPPOE);
    context.startService(startIntent);
   } else if (PPPoEService.isConnect()) {
    PPPoEService.stop();
   }
  }

2.2 接收到Intent.ACTION_BOOT_COMPLETED
这个Action是相关Android服务都已经开启成功后发出, 表明Android启动完成, 这时会判断autoConn和enable, 如果都为true, 这开启PPPoEService
if (Intent.ACTION_BOOT_COMPLETED.equals(action) && autoConn && enable) {
   Intent startIntent = new Intent(PPPoEService.ACTION_START_PPPOE);   // 要开启某个服务, 需要一个Intent和对应服务监听的Action, PPPoEService在AndroidManifest.xml中设置了监听此Action
   context.startService(startIntent);
  }

2.3 接收到WifiManager.WIFI_STATE_CHANGED_ACTION
Wifi的状态改变, 从代码中分析, 如果enable/autoConn都为true, 且PPPoE连接设置使用的网卡是ethx类别的, 且当前wifi处于连接状态, 则开启PPPoEService, 也就是尝试拨号.

2.4 接收到EthernetManager.ETHERNET_LINKED_ACTION
网线连接上事件, 这时如果没有PPPoE的话, 一般系统会进行dhcpd, 执行获取IP操作, 而Loader接收到此Action后, 会判断autoConn和enable是否同时为true, 如果是, 这时PPPoEService会处于running状态,  接下来会读取拨号的用户名与密码, 通过PPPoEService.connect(interface, username)来执行ppp拨号.

2.5 但接收到EthernetManager.ETHERNET_DISLINKED_ACTION
以太网线断开的Action时, 会通过PPPoEService.stop()函数, 执行ppp断开操作.
 

3. PPPoEService.java
核心, 执行pppoe connect/disconnect操作.
在此服务中会开启一个线程, 移植监听PPP拨号的状态, 如果状态未改变, 则休眠一段时间, 如果状态有改变, 这根据状态执行不同逻辑,
Thread.sleep(CONN_TRY_TIME_OUT); // 5 * 1000, 也就是5s
PPP的状态主要有6种,
 private static final int STATE_STOPED = 0;
 private static final int STATE_STARTING = 1;
 private static final int STATE_STARTED = 2;
 private static final int STATE_RETRY = 3;
 private static final int STATE_EXIT = 4;
 private static final int STATE_UNKWON = 5;

3.1 状态转换到STATE_STOPED
PPPoE_Service中有一个retry次数, 重新尝试connect, 当retry次数减为0, 停止尝试连接, 并发送EthernetManager.PPPOE_STATE_CHANGED_ACTION广播, 这个广播会被EthernetDataTrcker.java接收到, 
Intent intent = new Intent(EthernetManager.PPPOE_STATE_CHANGED_ACTION);
      intent.putExtra(EthernetManager.EXTRA_PPPOE_STATE, EthernetManager.PPPOE_STATE_DISABLED);
      sendBroadcast(intent);

3.2 状态转换到STATE_STARTING
正在连接, 休眠CONN_TRY_TIME_OUT后, 线程继续执行监听状态.

3.3 状态转换到STATE_RETRY
重新尝试, 不做操作. 跳到起点, 继续监听状态

3.4 状态转换到STATE_STARTED
PPPOE连接成功, 发送广播, 告诉EthernetDataTracker.java pppoe连接成功, 同时会更新Notification状态栏.
Intent intent = new Intent(EthernetManager.PPPOE_STATE_CHANGED_ACTION);
     intent.putExtra(EthernetManager.EXTRA_PPPOE_STATE, EthernetManager.PPPOE_STATE_ENABLED);
     sendBroadcast(intent);

3.5 状态转换到STATE_EXIT
pppoe程序执行失败, 退出, 这里会打印error number的, 会发送广播, 同样会被EthernetDataTracker.java接收, 并间发送message给ConnectivityService.java来更新网络信息. 同时会更新Notification状态栏信息.
 Intent intent = new Intent(EthernetManager.PPPOE_STATE_CHANGED_ACTION);
 intent.putExtra(EthernetManager.EXTRA_PPPOE_STATE, EthernetManager.PPPOE_STATE_DISABLED);

3.6 连接操作
此操作比较简单, 只是设置system property中对应值, code如下,
 private static final String SVC_STATE_CMD_PREFIX = "init.svc.";
 private static final String SVC_START_CMD = "ctl.start";
 private static final String SVC_STOP_CMD = "ctl.stop";
private static final String PPPOE_PROTOCOL = "pppoe";
 public static void connect(String iface,String username) throws InterruptedException{
  SystemProperties.set(SVC_START_CMD, PPPOE_PROTOCOL +
    ":" + iface + " " + username);         // ctl.start, pppoe:eth0 username
  if(DEBUG) Log.d(TAG,"SystemProperties.set" + PPPOE_PROTOCOL +
    ":" + iface + " " + username);
 }

3.7 关闭操作
关闭操作是直接调用su, 开启一种终端, 来执行pppoe-disconnect脚本来完成.
 public static boolean stop(){
  //SystemProperties.set(SVC_STOP_CMD, PPPOE_PROTOCOL);      // 目前不清楚为何将此种关闭方式注释掉了?
  execCmd("pppoe-disconnect");
  return isStoped();
 }

shanxiaoxi@allwinnertech.com: 以前写在有道云笔记中, 在这里分享出来.
原创粉丝点击