以太网Ethernet移植(android4.3添加Ethernet框架支持)

http://blog.163.com/a_a_2_b/blog/static/24104708120155174352430/

一、移植framework部分(+号的行代表增加的内容,-号的行代表删除的内容) 
1.1.将源路径framework/base/ethernet 复制到目标路径的framework/base/目录下
 
1.2.修改目标路径的framework/base目录下的Android.mk 

    vpn/java/android/net/vpn/IVpnService.aidl \
+    ethernet/java/android/net/ethernet/IEthernetManager.aidl \
    voip/java/android/net/sip/ISipSession.aidl \


1.3. 将源路径文件frameworks/base/services/java/com/android/server/EthernetService.java
复制到目标路径frameworks/base/services/java/com/android/server/目录下
1.4. 修改目标路径framework/base/service/java/com/android/server目录下的ConnectivityService.java文件

import android.net.wifi.WifiStateTracker;
+import android.net.ethernet.EthernetStateTracker; 
import android.net.wimax.WimaxManagerConstants; 
//------------------------------------------------------------------------
if (mNetConfigs[n.type] != null) {
loge("Error in networkAttributes - ignoring attempt to redefine type "+ n.type);
continue;
}
+      if ((n.type != ConnectivityManager.TYPE_ETHERNET) &&mRadioAttributes[n.radio] == null) {
+ loge("Error in networkAttributes - ignoring attempt to use undefined "+ "radio " + n.radio + " +in network type " + n.type);
+ continue;
+ }
mNetConfigs[n.type] = n;
//--------------------------------------------------------------------------------
case TYPE_WIMAX:
return makeWimaxStateTracker(mContext, mTrackerHandler);
+ case TYPE_ETHERNET:
+ EthernetStateTracker est = newEthernetStateTracker(targetNetworkType, config.name);
+ EthernetService ethService = new EthernetService(mContext, est);
+ ServiceManager.addService(Context.ETHERNET_SERVICE,ethService);
+ // mNetTrackers[ConnectivityManager.TYPE_ETHERNET] = est;   //注释掉,否则编译报错
+ est.startMonitoring(mContext, mTrackerHandler);
+ return est;
//---------------------------------------------------------------------
这个地方有可能会出现空指针异常:
// Update 464xlat state.
+ //Slog.d(TAG, "--------------------------netType = " + netType);
        NetworkStateTracker tracker = mNetTrackers[netType];
+ //Slog.d(TAG, "--------------------------mClat = " + mClat);
+ //Slog.d(TAG, "--------------------------mNetd = " + mNetd);
解决方法:
+ if (mClat == null) {
+ mClat = new Nat464Xlat(mContext, mNetd, this,mTrackerHandler);
+ }
        if (mClat.requiresClat(netType, tracker)) {


1.5. 将源路径framework/base/core/jni/android_net_ethernet.cpp复制到目标路径framework/base/core/jni/目录下

1.6. 修改目标路径framework/base/core/jni/AndroidRuntime.cpp文件   

extern int register_android_net_wifi_WifiManager(JNIEnv* env);
+ extern int register_android_net_ethernet_EthernetManager(JNIEnv* env);
extern int register_android_security_Md5MessageDigest(JNIEnv *env);
//------------------------------------------------------------------------
REG_JNI(register_android_net_wifi_WifiManager),
+ REG_JNI(register_android_net_ethernet_EthernetManager), 
REG_JNI(register_android_nfc_NdefMessage),


1.7. 修改目标路径framework/base/core/jni/Android.mk文件,添加ethernetJNI接口文件的编译项    

android_net_wifi_Wifi.cpp \
+ android_net_ethernet.cpp \
android_nio_utils.cpp \


1.8. 修改目标路径framework/base/core/java/android/content/Context.java

public static final String WIFI_SERVICE = "wifi"; 
+ public static final String ETHERNET_SERVICE = "ethernet"; 


1.9. 修改目标路径frameworks/base/core/java/android/provider/Settings.java 

public static final String WIFI_ON = "wifi_on"; 
+ /**
+ * Ethernet related configurations
+ */
+ public static final String ETHERNET_ON = "ethernet_on";
+ public static final String ETHERNET_MODE = "ethernet_mode";
+ public static final String ETHERNET_IP = "ethernet_ip";
+ public static final String ETHERNET_MASK = "ethernet_netmask";
+ public static final String ETHERNET_DNS = "ethernet_dns";
+ public static final String ETHERNET_ROUTE = "ethernet_iproute";
+ public static final String ETHERNET_CONF = "ethernet_conf";
+ public static final String ETHERNET_IFNAME = "ethernet_ifname";


  1.10. 修改目标路径frameworks/base/core/java/android/app/ContextImpl.java   

import android.net.ethernet.IEthernetManager;
import android.net.ethernet.EthernetManager;
//----------------------------------------------------------------
registerService(ETHERNET_SERVICE, new ServiceFetcher() {
public Object createService(ContextImpl ctx) {
IBinder b = ServiceManager.getService(ETHERNET_SERVICE);
IEthernetManager service = IEthernetManager.Stub.asInterface(b);
return new EthernetManager(service,ctx.mMainThread.getHandler());
}

});


1.11. 修改目标路径frameworks/base/core/res/res/values/config.xml   

 <item><xliff:g id="id">wifi</xliff:g></item>
+ <item><xliff:g id="id">ethernet</xliff:g></item>
<item><xliff:g id="id">cdma_eri</xliff:g></item> 
//----------------------------------------------------------------------------
<item>"mobile_hipri,5,0,3"</item>
+ <item>"ethernet,9,9,1"</item> 
</string-array> 


1.12. 修改目标路径文件frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java   

import android.net.wifi.WifiManager;
+import android.net.ethernet.EthernetManager;
+import android.net.ethernet.EthernetStateTracker;
import android.os.Binder;
//-----------------------------------------------------------------------
String mContentDescriptionEthernet;
// Ethernet
boolean mEthernetEnabled, mEthernetConnected;
int mEthernetIconId = 0; // overlay arrows for wifi direction
int mEthernetActivity = EthernetManager.DATA_ACTIVITY_NONE;
private static final int[] sEthImages = {
R.drawable.connect_established,
R.drawable.connect_no,
R.drawable.connect_creating
        };
//----------------------------------------
filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
+filter.addAction(EthernetManager.ETHERNET_STATE_CHANGED_ACTION);
//----------------------------------------
 public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
if (action.equals(WifiManager.RSSI_CHANGED_ACTION)
  || action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)
  ||action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
updateWifiState(intent);
refreshViews();
} else if(action.equals(TelephonyIntents.ACTION_SIM_STATE_CHANGED)) {
updateSimState(intent);
updateDataIcon();
refreshViews();
} else if(action.equals(Telephony.Intents.SPN_STRINGS_UPDATED_ACTION)) {
updateNetworkName(intent.getBooleanExtra(
Telephony.Intents.EXTRA_SHOW_SPN,false), 
intent.getStringExtra(Telephony.Intents.EXTRA_SPN), 
intent.getBooleanExtra(Telephony.Intents.EXTRA_SHOW_PLMN,false),
intent.getStringExtra(Telephony.Intents.EXTRA_PLMN));
refreshViews();
} else if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION) ||
action.equals(ConnectivityManager.INET_CONDITION_ACTION)) {
updateConnectivity(intent); 
refreshViews();
} else if (action.equals(Intent.ACTION_CONFIGURATION_CHANGED)) {  refreshViews();
 } else if (action.equals(Intent.ACTION_AIRPLANE_MODE_CHANGED)){ updateAirplaneMode(); 
 refreshViews();
} else if(action.equals(WimaxManagerConstants.NET_4G_STATE_CHANGED_ACTION) ||
action.equals(WimaxManagerConstants.SIGNAL_LEVEL_CHANGED_ACTION) ||
action.equals(WimaxManagerConstants.WIMAX_NETWORK_STATE_CHANGED_ACTION)) {
updateWimaxState(intent);
refreshViews();
+        } else if(action.equals(EthernetManager.ETHERNET_STATE_CHANGED_ACTION)){
+            updateEth(intent);
+            refreshViews();
+        }
    }
//------------------------------------
+   private void updateEthernetIcons() {
+        if (mEthernetConnected) {
+            mEthernetIconId = sEthImages[0];
+        } else {
+            mEthernetIconId = sEthImages[1];
+        }
+    }
//-----------------------------------------------------------
+ if (mEthernetConnected) {
+            switch (mEthernetActivity) {
+                case EthernetStateTracker.EVENT_HW_CONNECTED:
+                caseEthernetStateTracker.EVENT_INTERFACE_CONFIGURATION_SUCCEEDED:
+                    mEthernetIconId = sEthImages[0];
+                    break;
+                case EthernetStateTracker.EVENT_HW_DISCONNECTED:
+                caseEthernetStateTracker.EVENT_INTERFACE_CONFIGURATION_FAILED:
+                    mEthernetIconId = sEthImages[1];
+                    return;
+                    default:
+                mEthernetIconId = sEthImages[2];
+            }
+        }

        if (mBluetoothTethered) {
            combinedLabel = mContext.getString(R.string.bluetooth_tethered);
            combinedSignalIconId = mBluetoothTetherIconId;
            mContentDescriptionCombinedSignal = mContext.getString(
                   R.string.accessibility_bluetooth_tether);
        }

+        final boolean ethernetConnected = (mConnectedNetworkType ==ConnectivityManager.TYPE_ETHERNET);
+        if (ethernetConnected) {
+            combinedLabel = context.getString(R.string.ethernet_label);
+        }
//-----------------------------------------
+ private final void updateEth(Intent intent) {
+        final int event =intent.getIntExtra(EthernetManager.EXTRA_ETHERNET_STATE,EthernetManager.ETHERNET_STATE_UNKNOWN);
+        switch (event) {
+            case EthernetStateTracker.EVENT_HW_CONNECTED:
+            caseEthernetStateTracker.EVENT_INTERFACE_CONFIGURATION_SUCCEEDED:
+                mEthernetIconId = sEthImages[0];
+                break;
+            case EthernetStateTracker.EVENT_HW_DISCONNECTED:
+            caseEthernetStateTracker.EVENT_INTERFACE_CONFIGURATION_FAILED:
+                mEthernetIconId = sEthImages[1];
+                return;
+            default:
+                mEthernetIconId = sEthImages[2];
+        }
+    }


1.14. 修改目标路径文件frameworks/base/core/jni/android_net_NetUtils.cpp   

+  int ifc_configure(const char *ifname, in_addr_t ipaddr, uint32_tprefixLength, in_addr_t gateway, in_addr_t dns1, in_addr_t dns2);
//--------------------------------------------------------------------------------
{ "configureNative", "(Ljava/lang/String;IIIII)Z",  (void*)android_net_utils_configureInterface },
//-----------------------------------------------------------------------------------
static jboolean android_net_utils_configureInterface(JNIEnv* env,
        jobject clazz,
        jstring ifname,
        jint ipaddr,
        jint prefixLength,
        jint gateway,
        jint dns1,
        jint dns2)
{
    int result;
    uint32_t lease;

    const char *nameStr = env->GetStringUTFChars(ifname, NULL);
    result = ::ifc_configure(nameStr, ipaddr, prefixLength, gateway, dns1, dns2);
    env->ReleaseStringUTFChars(ifname, nameStr);
    return (jboolean)(result == 0);
}


要注意如果只有{ "runDhcp", "(Ljava/lang/String;Landroid/net/DhcpResults;)Z",  (void *)android_net_utils_runDhcp },
{ "runDhcpRenew", "(Ljava/lang/String;Landroid/net/DhcpResults;)Z",  (void *)android_net_utils_runDhcpRenew },
这两行,没有{ "runDhcp", "(Ljava/lang/String;Landroid/net/DhcpInfoInternal;)Z",  (void *)android_net_utils_runDhcp },
    { "runDhcpRenew", "(Ljava/lang/String;Landroid/net/DhcpInfoInternal;)Z",  (void *)android_net_utils_runDhcpRenew },
这两行,则,保留前者,去后者,并且将DhcpInfoInternal.java合并到DhcpResults.java中去。
然后在android_net_NetUtils.cpp中添加一些内容。
android_net_NetUtils.cpp和DhcpResults.java这两个文件具体改成什么样,见最后内容。

1.15. 修改目标路径文件frameworks/base/core/java/android/net/NetworkUtils.java   

public static boolean configureInterface(String interfaceName, DhcpInfo ipInfo){
        return configureNative(interfaceName,
            ipInfo.ipAddress,
            netmaskIntToPrefixLength(ipInfo.netmask),
            ipInfo.gateway,
            ipInfo.dns1,
            ipInfo.dns2);
    }

    private native static boolean configureNative(
        String interfaceName, int ipAddress, int prefixLength, int gateway, intdns1, int dns2);


二、移植packages部分
2.1.复制源路径packages/apps/Settings/src/com/android/settings/ethernet
目录到目标路径packages/apps/Settings/src/com/android/settings/目录下;

2.3.复制源路径packages/apps/Settings/res/drawable-hdpi/ic_settings_ethernet.png
到目标路径packages/apps/Settings/res/drawable-hdpi/目录下

2.4.复制源路径packages/apps/Settings/res/drawable-mdpi/ic_settings_ethernet.png
到目标路径packages/apps/Settings/res/drawable-mdpi/目录下

2.5.复制源路径packages/apps/Settings/res/layout/eth_configure.xml
到目标路径packages/apps/Settings/res/layout/目录下

2.6.复制源路径packages/apps/Settings/res/xml/ethernet_settings.xml
到目标路径packages/apps/Settings/res/xml/目录下

2.7. 修改目标路径文件packages/apps/Settings/res/values/strings.xml    

<string name="sound_category_feedback_title">Feedback</string>
+<!-- Ethernet configuration dialog -->
+<string name="eth_config_title">Configure Ethernet device</string>
+<string name="eth_setting">Ethernet setting</string>
+<string name="eth_dev_list">Ethernet Devices:</string>
+<string name="eth_con_type">Connection Type</string>
+<string name="eth_con_type_dhcp">DHCP</string>
+<string name="eth_con_type_manual">Static IP</string>
+<string name="eth_dns">DNS address</string>
+<string name="eth_gw">Default Gateway</string>
+<string name="eth_ipaddr">IP address</string>
+<string name="eth_quick_toggle_title">Ethernet</string>
+<string name="eth_quick_toggle_summary">Turn on Ethernet</string>
+<string name="eth_radio_ctrl_title">Ethernet configuration</string>
+<string name="eth_conf_perf_title">Ethernet configuration</string>
+<string name="eth_conf_summary">Configure Ethernet devices</string>
+<string name="eth_mask">Netmask</string>
+<string name="eth_toggle_summary_off">Turn off Ethernet</string>
+<string name="eth_toggle_summary_on">Turn on Ethernet</string>


2.8. 修改目标路径文件packages/apps/Settings/res/xml/settings_headers.xml   
<!-- Ethernet -->
   <header
        android:id="@+id/ethernet_settings"
        android:title="@string/eth_radio_ctrl_title"
        android:icon="@drawable/ic_settings_ethernet"
        android:fragment="com.android.settings.ethernet.EthernetSettings"/>

2.9. 修改目标路径文件packages/apps/Settings/AndroidManifest.xml 

<!-- Ethernet controls -->
        <activity android:name="EthernetSettings"
                android:label="@string/eth_radio_ctrl_title">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <action android:name="android.settings.ETHERNET_SETTINGS"/>
                <category android:name="android.intent.category.DEFAULT" />
                <categoryandroid:name="android.intent.category.VOICE_LAUNCH" />
            </intent-filter>
        </activity>

        <activity android:name=".ethernet.EthernetEnabler"
         android:label="@string/eth_setting"
                android:clearTaskOnLaunch="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <action android:name="android.settings.ETHERNET_SETTINGS"/>
                <category android:name="android.intent.category.DEFAULT" />
                <categoryandroid:name="android.intent.category.VOICE_LAUNCH" />
                <category android:name="com.android.settings.SHORTCUT" />
            </intent-filter>
        </activity>

        <activity android:name=".ethernet.EthernetConfigure"
         android:label="@string/eth_conf_perf_title"
                android:clearTaskOnLaunch="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <action android:name="android.settings.ETHERNET_SETTINGS"/>
                <category android:name="android.intent.category.DEFAULT" />
                <categoryandroid:name="android.intent.category.VOICE_LAUNCH" />
                <category android:name="com.android.settings.SHORTCUT" />
            </intent-filter>
        </activity>


三、接下来要增加Ethernet的状态栏图标
3.1.复制源路径frameworks/base/packages/SystemUI/res/drawable-hdpi/connect_creating.png到目标路径对应目录下

3.2.复制源路径frameworks/base/packages/SystemUI/res/drawable-hdpi/connect_established.png到目标路径对应目录下

3.3.复制源路径frameworks/base/packages/SystemUI/res/drawable-hdpi/connect_no.png到目标路径对应目录下

3.4.复制源路径frameworks/base/packages/SystemUI/res/drawable-mdpi/connect_creating.png到目标路径对应目录下

3.5.复制源路径frameworks/base/packages/SystemUI/res/drawable-mdpi/connect_established.png到目标路径对应目录下

3.6.复制源路径frameworks/base/packages/SystemUI/res/drawable-mdpi/connect_no.png到目标路径对应目录下

四、修改目标路径文件build/core/pathmap.mk   

vpn \ +ethernet \ keystore \


最后记得修改init.rc,在最后增加DHCP服务 

service dhcpcd_eth0 /system/bin/dhcpcd -ABKL disabled oneshot service iprenew_eth0 /system/bin/dhcpcd -n disabled oneshot


注意:
android_net_NetUtils.cpp和DhcpResults.java的文件内容在下一篇日志里面


修改和添加完之后,要根据自己的实际情况进行调试。
参考:http://blog.csdn.net/leilu2008/article/details/8965973
android_net_NetUtils.cpp文件内容如下:

/* * Copyright 2008, The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define LOG_TAG "NetUtils" #include "jni.h" #include <utils/misc.h> #include <android_runtime/AndroidRuntime.h> #include <utils/Log.h> #include <arpa/inet.h> #include <cutils/properties.h> extern "C" { int ifc_enable(const char *ifname); int ifc_disable(const char *ifname); int ifc_reset_connections(const char *ifname, int reset_mask); int ifc_configure(const char *ifname, in_addr_t ipaddr, uint32_t prefixLength, in_addr_t gateway, in_addr_t dns1, in_addr_t dns2); int dhcp_do_request(const char * const ifname, const char *ipaddr, const char *gateway, uint32_t *prefixLength, const char *dns[], const char *server, uint32_t *lease, const char *vendorInfo, const char *domains); int dhcp_do_request_renew(const char * const ifname, const char *ipaddr, const char *gateway, uint32_t *prefixLength, const char *dns[], const char *server, uint32_t *lease, const char *vendorInfo, const char *domains); int dhcp_stop(const char *ifname); int dhcp_release_lease(const char *ifname); char *dhcp_get_errmsg(); } #define NETUTILS_PKG_NAME "android/net/NetworkUtils" namespace android { /* * The following remembers the jfieldID's of the fields * of the DhcpInfo Java object, so that we don't have * to look them up every time. */ static struct fieldIds { jmethodID clear; jmethodID setInterfaceName; jmethodID addLinkAddress; jmethodID addGateway; jmethodID addDns; jmethodID setDomains; jmethodID setServerAddress; jmethodID setLeaseDuration; jmethodID setVendorInfo; jfieldID ipaddress; jfieldID prefixLength; jfieldID dns1; jfieldID dns2; jfieldID serverAddressStr; } dhcpResultsFieldIds; static jint android_net_utils_enableInterface(JNIEnv* env, jobject clazz, jstring ifname) { int result; const char *nameStr = env->GetStringUTFChars(ifname, NULL); result = ::ifc_enable(nameStr); env->ReleaseStringUTFChars(ifname, nameStr); return (jint)result; } static jint android_net_utils_disableInterface(JNIEnv* env, jobject clazz, jstring ifname) { int result; const char *nameStr = env->GetStringUTFChars(ifname, NULL); result = ::ifc_disable(nameStr); env->ReleaseStringUTFChars(ifname, nameStr); return (jint)result; } static jint android_net_utils_resetConnections(JNIEnv* env, jobject clazz, jstring ifname, jint mask) { int result; const char *nameStr = env->GetStringUTFChars(ifname, NULL); ALOGD("android_net_utils_resetConnections in env=%p clazz=%p iface=%s mask=0x%x\n", env, clazz, nameStr, mask); result = ::ifc_reset_connections(nameStr, mask); env->ReleaseStringUTFChars(ifname, nameStr); return (jint)result; } static jboolean android_net_utils_runDhcpCommon(JNIEnv* env, jobject clazz, jstring ifname, jobject dhcpResults, bool renew) { int result; char ipaddr[PROPERTY_VALUE_MAX]; uint32_t prefixLength; char gateway[PROPERTY_VALUE_MAX]; char dns1[PROPERTY_VALUE_MAX]; char dns2[PROPERTY_VALUE_MAX]; char dns3[PROPERTY_VALUE_MAX]; char dns4[PROPERTY_VALUE_MAX]; const char *dns[5] = {dns1, dns2, dns3, dns4, NULL}; char server[PROPERTY_VALUE_MAX]; uint32_t lease; char vendorInfo[PROPERTY_VALUE_MAX]; char domains[PROPERTY_VALUE_MAX]; const char *nameStr = env->GetStringUTFChars(ifname, NULL); if (nameStr == NULL) return (jboolean)false; if (renew) { result = ::dhcp_do_request_renew(nameStr, ipaddr, gateway, &prefixLength, dns, server, &lease, vendorInfo, domains); } else { result = ::dhcp_do_request(nameStr, ipaddr, gateway, &prefixLength, dns, server, &lease, vendorInfo, domains); } if (result != 0) { ALOGD("dhcp_do_request failed"); } env->ReleaseStringUTFChars(ifname, nameStr); if (result == 0) { env->SetObjectField(dhcpResults, dhcpResultsFieldIds.ipaddress, env->NewStringUTF(ipaddr)); env->CallVoidMethod(dhcpResults, dhcpResultsFieldIds.clear); // set mIfaceName // dhcpResults->setInterfaceName(ifname) env->CallVoidMethod(dhcpResults, dhcpResultsFieldIds.setInterfaceName, ifname); // set the linkAddress // dhcpResults->addLinkAddress(inetAddress, prefixLength) result = env->CallBooleanMethod(dhcpResults, dhcpResultsFieldIds.addLinkAddress, env->NewStringUTF(ipaddr), prefixLength); env->SetIntField(dhcpResults, dhcpResultsFieldIds.prefixLength, prefixLength); env->SetObjectField(dhcpResults, dhcpResultsFieldIds.dns1, env->NewStringUTF(dns1)); env->SetObjectField(dhcpResults, dhcpResultsFieldIds.dns2, env->NewStringUTF(dns2)); env->SetObjectField(dhcpResults, dhcpResultsFieldIds.serverAddressStr, env->NewStringUTF(server)); jclass cls = env->FindClass("java/net/InetAddress"); jmethodID method = env->GetStaticMethodID(cls, "getByName", "(Ljava/lang/String;)Ljava/net/InetAddress;"); jvalue args[1]; args[0].l = env->NewStringUTF(gateway); jobject inetAddressObject = env->CallStaticObjectMethodA(cls, method, args); if (!env->ExceptionOccurred()) { cls = env->FindClass("android/net/RouteInfo"); method = env->GetMethodID(cls, "<init>", "(Ljava/net/InetAddress;)V"); args[0].l = inetAddressObject; jobject routeInfoObject = env->NewObjectA(cls, method, args); cls = env->FindClass("android/net/DhcpResults"); method = env->GetMethodID(cls, "addRoute", "(Landroid/net/RouteInfo;)V"); args[0].l = routeInfoObject; env->CallVoidMethodA(dhcpResults, method, args); } else { // if we have an exception (host not found perhaps), just don't add the route env->ExceptionClear(); } } if (result == 0) { // set the gateway // dhcpResults->addGateway(gateway) result = env->CallBooleanMethod(dhcpResults, dhcpResultsFieldIds.addGateway, env->NewStringUTF(gateway)); } if (result == 0) { // dhcpResults->addDns(new InetAddress(dns1)) result = env->CallBooleanMethod(dhcpResults, dhcpResultsFieldIds.addDns, env->NewStringUTF(dns1)); } if (result == 0) { env->CallVoidMethod(dhcpResults, dhcpResultsFieldIds.setDomains, env->NewStringUTF(domains)); result = env->CallBooleanMethod(dhcpResults, dhcpResultsFieldIds.addDns, env->NewStringUTF(dns2)); if (result == 0) { result = env->CallBooleanMethod(dhcpResults, dhcpResultsFieldIds.addDns, env->NewStringUTF(dns3)); if (result == 0) { result = env->CallBooleanMethod(dhcpResults, dhcpResultsFieldIds.addDns, env->NewStringUTF(dns4)); } } } if (result == 0) { // dhcpResults->setServerAddress(new InetAddress(server)) result = env->CallBooleanMethod(dhcpResults, dhcpResultsFieldIds.setServerAddress, env->NewStringUTF(server)); } if (result == 0) { // dhcpResults->setLeaseDuration(lease) env->CallVoidMethod(dhcpResults, dhcpResultsFieldIds.setLeaseDuration, lease); // dhcpResults->setVendorInfo(vendorInfo) env->CallVoidMethod(dhcpResults, dhcpResultsFieldIds.setVendorInfo, env->NewStringUTF(vendorInfo)); } return (jboolean)(result == 0); } 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_runDhcpRenew(JNIEnv* env, jobject clazz, jstring ifname, jobject info) { return android_net_utils_runDhcpCommon(env, clazz, ifname, info, true); } static jboolean android_net_utils_stopDhcp(JNIEnv* env, jobject clazz, jstring ifname) { int result; const char *nameStr = env->GetStringUTFChars(ifname, NULL); result = ::dhcp_stop(nameStr); env->ReleaseStringUTFChars(ifname, nameStr); return (jboolean)(result == 0); } static jboolean android_net_utils_releaseDhcpLease(JNIEnv* env, jobject clazz, jstring ifname) { int result; const char *nameStr = env->GetStringUTFChars(ifname, NULL); result = ::dhcp_release_lease(nameStr); env->ReleaseStringUTFChars(ifname, nameStr); return (jboolean)(result == 0); } static jboolean android_net_utils_configureInterface(JNIEnv* env, jobject clazz, jstring ifname, jint ipaddr, jint prefixLength, jint gateway, jint dns1, jint dns2) { int result; uint32_t lease; const char *nameStr = env->GetStringUTFChars(ifname, NULL); result = ::ifc_configure(nameStr, ipaddr, prefixLength, gateway, dns1, dns2); env->ReleaseStringUTFChars(ifname, nameStr); return (jboolean)(result == 0); } static jstring android_net_utils_getDhcpError(JNIEnv* env, jobject clazz) { return env->NewStringUTF(::dhcp_get_errmsg()); } // ---------------------------------------------------------------------------- /* * JNI registration. */ static JNINativeMethod gNetworkUtilMethods[] = { /* name, signature, funcPtr */ { "enableInterface", "(Ljava/lang/String;)I", (void *)android_net_utils_enableInterface }, { "disableInterface", "(Ljava/lang/String;)I", (void *)android_net_utils_disableInterface }, { "resetConnections", "(Ljava/lang/String;I)I", (void *)android_net_utils_resetConnections }, { "configureNative", "(Ljava/lang/String;IIIII)Z", (void *)android_net_utils_configureInterface }, { "runDhcp", "(Ljava/lang/String;Landroid/net/DhcpResults;)Z", (void *)android_net_utils_runDhcp }, { "runDhcpRenew", "(Ljava/lang/String;Landroid/net/DhcpResults;)Z", (void *)android_net_utils_runDhcpRenew }, { "stopDhcp", "(Ljava/lang/String;)Z", (void *)android_net_utils_stopDhcp }, { "releaseDhcpLease", "(Ljava/lang/String;)Z", (void *)android_net_utils_releaseDhcpLease }, { "getDhcpError", "()Ljava/lang/String;", (void*) android_net_utils_getDhcpError }, }; int register_android_net_NetworkUtils(JNIEnv* env) { jclass dhcpResultsClass = env->FindClass("android/net/DhcpResults"); LOG_FATAL_IF(dhcpResultsClass == NULL, "Unable to find class android/net/DhcpResults"); dhcpResultsFieldIds.clear = env->GetMethodID(dhcpResultsClass, "clear", "()V"); dhcpResultsFieldIds.setInterfaceName = env->GetMethodID(dhcpResultsClass, "setInterfaceName", "(Ljava/lang/String;)V"); dhcpResultsFieldIds.addLinkAddress = env->GetMethodID(dhcpResultsClass, "addLinkAddress", "(Ljava/lang/String;I)Z"); dhcpResultsFieldIds.addGateway = env->GetMethodID(dhcpResultsClass, "addGateway", "(Ljava/lang/String;)Z"); dhcpResultsFieldIds.addDns = env->GetMethodID(dhcpResultsClass, "addDns", "(Ljava/lang/String;)Z"); dhcpResultsFieldIds.setDomains = env->GetMethodID(dhcpResultsClass, "setDomains", "(Ljava/lang/String;)V"); dhcpResultsFieldIds.setServerAddress = env->GetMethodID(dhcpResultsClass, "setServerAddress", "(Ljava/lang/String;)Z"); dhcpResultsFieldIds.setLeaseDuration = env->GetMethodID(dhcpResultsClass, "setLeaseDuration", "(I)V"); dhcpResultsFieldIds.setVendorInfo = env->GetMethodID(dhcpResultsClass, "setVendorInfo", "(Ljava/lang/String;)V"); dhcpResultsFieldIds.ipaddress = env->GetFieldID(dhcpResultsClass, "ipAddress", "Ljava/lang/String;"); dhcpResultsFieldIds.prefixLength = env->GetFieldID(dhcpResultsClass, "prefixLength", "I"); dhcpResultsFieldIds.dns1 = env->GetFieldID(dhcpResultsClass, "dns1", "Ljava/lang/String;"); dhcpResultsFieldIds.dns2 = env->GetFieldID(dhcpResultsClass, "dns2", "Ljava/lang/String;"); dhcpResultsFieldIds.serverAddressStr = env->GetFieldID(dhcpResultsClass, "serverAddressStr", "Ljava/lang/String;"); return AndroidRuntime::registerNativeMethods(env, NETUTILS_PKG_NAME, gNetworkUtilMethods, NELEM(gNetworkUtilMethods)); } }; // namespace android

DhcpResult.java的内容如下:

/* * Copyright (C) 2012 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.net; import android.os.Parcelable; import android.os.Parcel; import android.text.TextUtils; import android.util.Log; import java.net.Inet4Address; import java.net.InetAddress; import java.net.UnknownHostException; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.Collections; /** * A simple object for retrieving the results of a DHCP request. * Optimized (attempted) for that jni interface * TODO - remove when DhcpInfo is deprecated. Move the remaining api to LinkProperties. * @hide */ public class DhcpResults implements Parcelable { private static final String TAG = "DhcpResults"; public final LinkProperties linkProperties; public InetAddress serverAddress; /** * Vendor specific information (from RFC 2132). */ public String vendorInfo; public int leaseDuration; public String ipAddress; public int prefixLength; public String dns1; public String dns2; public String serverAddressStr; // public int leaseDuration; // /** // * Vendor specific information (from RFC 2132). // */ // public String vendorInfo; private Collection<RouteInfo> mRoutes; public DhcpResults() { linkProperties = new LinkProperties(); mRoutes = new ArrayList<RouteInfo>(); } /** copy constructor */ public DhcpResults(DhcpResults source) { if (source != null) { linkProperties = new LinkProperties(source.linkProperties); serverAddress = source.serverAddress; leaseDuration = source.leaseDuration; vendorInfo = source.vendorInfo; } else { linkProperties = new LinkProperties(); } } public DhcpResults(LinkProperties lp) { linkProperties = new LinkProperties(lp); } public void addRoute(RouteInfo routeInfo) { mRoutes.add(routeInfo); } public Collection<RouteInfo> getRoutes() { return Collections.unmodifiableCollection(mRoutes); } private int convertToInt(String addr) { if (addr != null) { try { InetAddress inetAddress = NetworkUtils.numericToInetAddress(addr); if (inetAddress instanceof Inet4Address) { return NetworkUtils.inetAddressToInt(inetAddress); } } catch (IllegalArgumentException e) {} } return 0; } public DhcpInfo makeDhcpInfo() { DhcpInfo info = new DhcpInfo(); Log.e(TAG,"<<<<<<<<<<<ipAddress = " + ipAddress); info.ipAddress = convertToInt(ipAddress); for (RouteInfo route : mRoutes) { Log.e(TAG,"------------route.isDefaultRoute() = " + route.isDefaultRoute()); if (route.isDefaultRoute()) { info.gateway = convertToInt(route.getGateway().getHostAddress()); break; } } try { InetAddress inetAddress = NetworkUtils.numericToInetAddress(ipAddress); info.netmask = NetworkUtils.prefixLengthToNetmaskInt(prefixLength); } catch (IllegalArgumentException e) {} info.dns1 = convertToInt(dns1); info.dns2 = convertToInt(dns2); info.serverAddress = convertToInt(serverAddressStr); info.leaseDuration = leaseDuration; Log.e(TAG,"++++++++++++info = " + info); Log.e(TAG,"------------info.ipAddress = " + info.ipAddress); Log.e(TAG,"------------info.netmask = " + info.netmask); Log.e(TAG,"------------info.gateway = " + info.gateway); Log.e(TAG,"------------info.dns1 = " + info.dns1); return info; } public LinkAddress makeLinkAddress() { if (TextUtils.isEmpty(ipAddress)) { Log.e(TAG, "makeLinkAddress with empty ipAddress"); return null; } return new LinkAddress(NetworkUtils.numericToInetAddress(ipAddress), prefixLength); } public LinkProperties makeLinkProperties() { LinkProperties p = new LinkProperties(); p.addLinkAddress(makeLinkAddress()); for (RouteInfo route : mRoutes) { p.addRoute(route); } //if empty, connectivity configures default DNS if (TextUtils.isEmpty(dns1) == false) { p.addDns(NetworkUtils.numericToInetAddress(dns1)); } else { Log.d(TAG, "makeLinkProperties with empty dns1!"); } if (TextUtils.isEmpty(dns2) == false) { p.addDns(NetworkUtils.numericToInetAddress(dns2)); } else { Log.d(TAG, "makeLinkProperties with empty dns2!"); } return p; } /** * Updates the DHCP fields that need to be retained from * original DHCP request if the current renewal shows them * being empty. */ public void updateFromDhcpRequest(DhcpResults orig) { if (orig == null || orig.linkProperties == null) return; if (linkProperties.getRoutes().size() == 0) { for (RouteInfo r : orig.linkProperties.getRoutes()) linkProperties.addRoute(r); } if (linkProperties.getDnses().size() == 0) { for (InetAddress d : orig.linkProperties.getDnses()) linkProperties.addDns(d); } if (TextUtils.isEmpty(dns1)) { dns1 = orig.dns1; } if (TextUtils.isEmpty(dns2)) { dns2 = orig.dns2; } if (mRoutes.size() == 0) { for (RouteInfo route : orig.getRoutes()) { addRoute(route); } } } /** * Test if this DHCP lease includes vendor hint that network link is * metered, and sensitive to heavy data transfers. */ public boolean hasMeteredHint() { if (vendorInfo != null) { return vendorInfo.contains("ANDROID_METERED"); } else { return false; } } public void clear() { linkProperties.clear(); serverAddress = null; vendorInfo = null; leaseDuration = 0; } @Override public String toString() { StringBuffer str = new StringBuffer(linkProperties.toString()); str.append(" DHCP server ").append(serverAddress); str.append(" Vendor info ").append(vendorInfo); str.append(" lease ").append(leaseDuration).append(" seconds"); return str.toString(); } @Override public boolean equals(Object obj) { if (this == obj) return true; if (!(obj instanceof DhcpResults)) return false; DhcpResults target = (DhcpResults)obj; if (linkProperties == null) { if (target.linkProperties != null) return false; } else if (!linkProperties.equals(target.linkProperties)) return false; if (serverAddress == null) { if (target.serverAddress != null) return false; } else if (!serverAddress.equals(target.serverAddress)) return false; if (vendorInfo == null) { if (target.vendorInfo != null) return false; } else if (!vendorInfo.equals(target.vendorInfo)) return false; if (leaseDuration != target.leaseDuration) return false; return true; } /** Implement the Parcelable interface */ public int describeContents() { return 0; } /** Implement the Parcelable interface */ public void writeToParcel(Parcel dest, int flags) { linkProperties.writeToParcel(dest, flags); dest.writeInt(leaseDuration); if (serverAddress != null) { dest.writeByte((byte)1); dest.writeByteArray(serverAddress.getAddress()); } else { dest.writeByte((byte)0); } dest.writeString(vendorInfo); } /** Implement the Parcelable interface */ public static final Creator<DhcpResults> CREATOR = new Creator<DhcpResults>() { public DhcpResults createFromParcel(Parcel in) { DhcpResults prop = new DhcpResults((LinkProperties)in.readParcelable(null)); prop.leaseDuration = in.readInt(); if (in.readByte() == 1) { try { prop.serverAddress = InetAddress.getByAddress(in.createByteArray()); } catch (UnknownHostException e) {} } prop.vendorInfo = in.readString(); return prop; } public DhcpResults[] newArray(int size) { return new DhcpResults[size]; } }; // Utils for jni population - false on success public void setInterfaceName(String interfaceName) { linkProperties.setInterfaceName(interfaceName); } public boolean addLinkAddress(String addrString, int prefixLength) { InetAddress addr; try { addr = NetworkUtils.numericToInetAddress(addrString); } catch (IllegalArgumentException e) { Log.e(TAG, "addLinkAddress failed with addrString " + addrString); return true; } LinkAddress linkAddress = new LinkAddress(addr, prefixLength); linkProperties.addLinkAddress(linkAddress); RouteInfo routeInfo = new RouteInfo(linkAddress); linkProperties.addRoute(routeInfo); return false; } public boolean addGateway(String addrString) { try { linkProperties.addRoute(new RouteInfo(NetworkUtils.numericToInetAddress(addrString))); } catch (IllegalArgumentException e) { Log.e(TAG, "addGateway failed with addrString " + addrString); return true; } return false; } public boolean addDns(String addrString) { if (TextUtils.isEmpty(addrString) == false) { try { linkProperties.addDns(NetworkUtils.numericToInetAddress(addrString)); } catch (IllegalArgumentException e) { Log.e(TAG, "addDns failed with addrString " + addrString); return true; } } return false; } public boolean setServerAddress(String addrString) { try { serverAddress = NetworkUtils.numericToInetAddress(addrString); } catch (IllegalArgumentException e) { Log.e(TAG, "setServerAddress failed with addrString " + addrString); return true; } return false; } public void setLeaseDuration(int duration) { leaseDuration = duration; } public void setVendorInfo(String info) { vendorInfo = info; } public void setDomains(String domains) { linkProperties.setDomains(domains); } }



展开阅读全文

没有更多推荐了,返回首页