summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBernhard Rosenkraenzer <Bernhard.Rosenkranzer@linaro.org>2012-11-16 23:31:13 +0100
committerBernhard Rosenkraenzer <Bernhard.Rosenkranzer@linaro.org>2012-11-19 09:20:15 +0100
commit9f3e8c686a2965c459922e89c220343058bd10c1 (patch)
treef915526cb49a0e4ed2c7ca517193c0773cf2be02
parent3333b4d3c64b2534255fea4e44d53ec5df146a6f (diff)
downloadbase-linaro_android_4.2.tar.gz
frameworks/base: Bring back Ethernet Connection Managerlinaro_android_4.2
Change-Id: I2b9a3c005481c9330e6b68ba403b327a0edd32a5 Signed-off-by: Bernhard Rosenkraenzer <Bernhard.Rosenkranzer@linaro.org>
-rw-r--r--Android.mk1
-rw-r--r--api/current.txt179
-rw-r--r--core/java/android/app/ContextImpl.java9
-rw-r--r--core/java/android/content/Context.java10
-rw-r--r--core/java/android/net/NetworkUtils.java12
-rw-r--r--core/java/android/provider/Settings.java21
-rw-r--r--core/jni/Android.mk1
-rw-r--r--core/jni/AndroidRuntime.cpp2
-rw-r--r--core/jni/android_net_NetUtils.cpp31
-rw-r--r--core/jni/android_net_ethernet.cpp419
-rwxr-xr-xcore/res/res/values/config.xml3
-rw-r--r--ethernet/java/android/net/ethernet/EthernetDevInfo.aidl19
-rw-r--r--ethernet/java/android/net/ethernet/EthernetDevInfo.java152
-rw-r--r--ethernet/java/android/net/ethernet/EthernetManager.java192
-rw-r--r--ethernet/java/android/net/ethernet/EthernetMonitor.java134
-rw-r--r--ethernet/java/android/net/ethernet/EthernetNative.java30
-rw-r--r--ethernet/java/android/net/ethernet/EthernetStateMachine.java472
-rw-r--r--ethernet/java/android/net/ethernet/EthernetStateTracker.java558
-rw-r--r--ethernet/java/android/net/ethernet/IEthernetManager.aidl33
-rw-r--r--packages/SystemUI/res/drawable-hdpi/connect_creating.pngbin0 -> 429 bytes
-rw-r--r--packages/SystemUI/res/drawable-hdpi/connect_established.pngbin0 -> 5009 bytes
-rw-r--r--packages/SystemUI/res/drawable-hdpi/connect_no.pngbin0 -> 438 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/connect_creating.pngbin0 -> 476 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/connect_established.pngbin0 -> 876 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/connect_no.pngbin0 -> 373 bytes
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java56
-rw-r--r--services/java/com/android/server/ConnectivityService.java5
-rw-r--r--services/java/com/android/server/EthernetService.java241
-rw-r--r--services/java/com/android/server/SystemServer.java12
29 files changed, 2583 insertions, 9 deletions
diff --git a/Android.mk b/Android.mk
index d38150f0bf2a..c738c9cd997e 100644
--- a/Android.mk
+++ b/Android.mk
@@ -221,6 +221,7 @@ LOCAL_SRC_FILES += \
telephony/java/com/android/internal/telephony/IExtendedNetworkService.aidl \
wifi/java/android/net/wifi/IWifiManager.aidl \
wifi/java/android/net/wifi/p2p/IWifiP2pManager.aidl \
+ ethernet/java/android/net/ethernet/IEthernetManager.aidl \
voip/java/android/net/sip/ISipSession.aidl \
voip/java/android/net/sip/ISipSessionListener.aidl \
voip/java/android/net/sip/ISipService.aidl
diff --git a/api/current.txt b/api/current.txt
index 6b893d52372e..c9e1019cf8bb 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -5438,6 +5438,7 @@ package android.content {
field public static final java.lang.String DISPLAY_SERVICE = "display";
field public static final java.lang.String DOWNLOAD_SERVICE = "download";
field public static final java.lang.String DROPBOX_SERVICE = "dropbox";
+ field public static final java.lang.String ETHERNET_SERVICE = "ethernet";
field public static final java.lang.String INPUT_METHOD_SERVICE = "input_method";
field public static final java.lang.String INPUT_SERVICE = "input";
field public static final java.lang.String KEYGUARD_SERVICE = "keyguard";
@@ -12933,6 +12934,98 @@ package android.net {
}
+package android.net.ethernet {
+
+ public class EthernetDevInfo implements android.os.Parcelable {
+ ctor public EthernetDevInfo();
+ method public int describeContents();
+ method public java.lang.String getConnectMode();
+ method public java.lang.String getDnsAddr();
+ method public java.lang.String getIfName();
+ method public java.lang.String getIpAddress();
+ method public java.lang.String getNetMask();
+ method public java.lang.String getRouteAddr();
+ method public boolean setConnectMode(java.lang.String);
+ method public void setDnsAddr(java.lang.String);
+ method public void setIfName(java.lang.String);
+ method public void setIpAddress(java.lang.String);
+ method public void setNetMask(java.lang.String);
+ method public void setRouteAddr(java.lang.String);
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final java.lang.String ETHERNET_CONN_MODE_DHCP = "dhcp";
+ field public static final java.lang.String ETHERNET_CONN_MODE_MANUAL = "manual";
+ }
+
+ public class EthernetManager {
+ ctor public EthernetManager(android.net.ethernet.IEthernetManager, android.os.Handler);
+ method public java.lang.String[] getDeviceNameList();
+ method public android.net.ethernet.EthernetDevInfo getSavedConfig();
+ method public int getState();
+ method public int getTotalInterface();
+ method public boolean isConfigured();
+ method public boolean reconnect();
+ method public boolean startEthernet();
+ method public boolean stopEthernet();
+ method public void updateDevInfo(android.net.ethernet.EthernetDevInfo);
+ field public static final int DATA_ACTIVITY_IN = 1; // 0x1
+ field public static final int DATA_ACTIVITY_INOUT = 3; // 0x3
+ field public static final int DATA_ACTIVITY_NONE = 0; // 0x0
+ field public static final int DATA_ACTIVITY_OUT = 2; // 0x2
+ field public static final int ETHERNET_DEVICE_SCAN_RESULT_READY = 0; // 0x0
+ field public static final java.lang.String ETHERNET_STATE_CHANGED_ACTION = "android.net.ethernet.ETHERNET_STATE_CHANGED";
+ field public static final int ETHERNET_STATE_DISABLED = 1; // 0x1
+ field public static final int ETHERNET_STATE_ENABLED = 2; // 0x2
+ field public static final int ETHERNET_STATE_UNKNOWN = 0; // 0x0
+ field public static final java.lang.String EXTRA_ETHERNET_STATE = "ETHERNET_state";
+ field public static final java.lang.String EXTRA_NETWORK_INFO = "networkInfo";
+ field public static final java.lang.String EXTRA_PREVIOUS_ETHERNET_STATE = "previous_ETHERNET_state";
+ field public static final java.lang.String LINK_CONFIGURATION_CHANGED_ACTION = "android.net.ethernet.LINK_CONFIGURATION_CHANGED";
+ field public static final java.lang.String NETWORK_STATE_CHANGED_ACTION = "android.net.ethernet.STATE_CHANGE";
+ field public static final java.lang.String TAG = "EthernetManager";
+ }
+
+ public class EthernetStateMachine extends com.android.internal.util.StateMachine {
+ ctor public EthernetStateMachine(android.content.Context, java.lang.String);
+ method public void handleMessage(android.os.Message);
+ method public void reconnectCommand();
+ method public boolean resetInterface() throws java.net.UnknownHostException;
+ method public void setEthernetEnabled(boolean);
+ method public void startMonitoring(android.content.Context);
+ method public boolean stopInterface(boolean);
+ method public android.net.DhcpInfo syncGetDhcpInfo();
+ method public int syncGetEthernetState();
+ method public java.lang.String syncGetEthernetStateByName();
+ field public static final int EVENT_DHCP_START = 0; // 0x0
+ field public static final int EVENT_HW_CONNECTED = 3; // 0x3
+ field public static final int EVENT_HW_DISCONNECTED = 4; // 0x4
+ field public static final int EVENT_HW_PHYCONNECTED = 5; // 0x5
+ field public static final int EVENT_INTERFACE_CONFIGURATION_FAILED = 2; // 0x2
+ field public static final int EVENT_INTERFACE_CONFIGURATION_SUCCEEDED = 1; // 0x1
+ }
+
+ public abstract interface IEthernetManager implements android.os.IInterface {
+ method public abstract java.lang.String[] getDeviceNameList() throws android.os.RemoteException;
+ method public abstract android.net.ethernet.EthernetDevInfo getSavedConfig() throws android.os.RemoteException;
+ method public abstract int getState() throws android.os.RemoteException;
+ method public abstract int getTotalInterface() throws android.os.RemoteException;
+ method public abstract boolean isConfigured() throws android.os.RemoteException;
+ method public abstract void reconnect() throws android.os.RemoteException;
+ method public abstract void setMode(java.lang.String) throws android.os.RemoteException;
+ method public abstract void setState(int) throws android.os.RemoteException;
+ method public abstract void startEthernet() throws android.os.RemoteException;
+ method public abstract void stopEthernet() throws android.os.RemoteException;
+ method public abstract void updateDevInfo(android.net.ethernet.EthernetDevInfo) throws android.os.RemoteException;
+ }
+
+ public static abstract class IEthernetManager.Stub extends android.os.Binder implements android.net.ethernet.IEthernetManager {
+ ctor public IEthernetManager.Stub();
+ method public android.os.IBinder asBinder();
+ method public static android.net.ethernet.IEthernetManager asInterface(android.os.IBinder);
+ method public boolean onTransact(int, android.os.Parcel, android.os.Parcel, int) throws android.os.RemoteException;
+ }
+
+}
+
package android.net.http {
public final class AndroidHttpClient implements org.apache.http.client.HttpClient {
@@ -18869,6 +18962,14 @@ package android.provider {
field public static final deprecated java.lang.String DEVICE_PROVISIONED = "device_provisioned";
field public static final java.lang.String ENABLED_ACCESSIBILITY_SERVICES = "enabled_accessibility_services";
field public static final java.lang.String ENABLED_INPUT_METHODS = "enabled_input_methods";
+ field public static final java.lang.String ETHERNET_CONF = "ethernet_conf";
+ field public static final java.lang.String ETHERNET_DNS = "ethernet_dns";
+ field public static final java.lang.String ETHERNET_IFNAME = "ethernet_ifname";
+ field public static final java.lang.String ETHERNET_IP = "ethernet_ip";
+ field public static final java.lang.String ETHERNET_MASK = "ethernet_netmask";
+ field public static final java.lang.String ETHERNET_MODE = "ethernet_mode";
+ field public static final java.lang.String ETHERNET_ON = "ethernet_on";
+ field public static final java.lang.String ETHERNET_ROUTE = "ethernet_iproute";
field public static final deprecated java.lang.String HTTP_PROXY = "http_proxy";
field public static final java.lang.String INPUT_METHOD_SELECTOR_VISIBILITY = "input_method_selector_visibility";
field public static final deprecated java.lang.String INSTALL_NON_MARKET_APPS = "install_non_market_apps";
@@ -29884,10 +29985,88 @@ package android.widget {
package com.android.internal.util {
+ public abstract interface IState {
+ method public abstract void enter();
+ method public abstract void exit();
+ method public abstract java.lang.String getName();
+ method public abstract boolean processMessage(android.os.Message);
+ field public static final boolean HANDLED = true;
+ field public static final boolean NOT_HANDLED = false;
+ }
+
public abstract interface Predicate {
method public abstract boolean apply(T);
}
+ public class State implements com.android.internal.util.IState {
+ ctor protected State();
+ method public void enter();
+ method public void exit();
+ method public java.lang.String getName();
+ method public boolean processMessage(android.os.Message);
+ }
+
+ public class StateMachine {
+ ctor protected StateMachine(java.lang.String);
+ ctor protected StateMachine(java.lang.String, android.os.Looper);
+ method protected void addLogRec(java.lang.String);
+ method protected void addLogRec(java.lang.String, com.android.internal.util.State);
+ method protected final void addState(com.android.internal.util.State, com.android.internal.util.State);
+ method protected final void addState(com.android.internal.util.State);
+ method protected final void deferMessage(android.os.Message);
+ method public void dump(java.io.FileDescriptor, java.io.PrintWriter, java.lang.String[]);
+ method protected final android.os.Message getCurrentMessage();
+ method protected final com.android.internal.util.IState getCurrentState();
+ method public final android.os.Handler getHandler();
+ method public final com.android.internal.util.StateMachine.LogRec getLogRec(int);
+ method public final int getLogRecCount();
+ method public final int getLogRecSize();
+ method protected java.lang.String getLogRecString(android.os.Message);
+ method public final java.lang.String getName();
+ method protected java.lang.String getWhatToString(int);
+ method protected void haltedProcessMessage(android.os.Message);
+ method public boolean isDbg();
+ method public final android.os.Message obtainMessage();
+ method public final android.os.Message obtainMessage(int);
+ method public final android.os.Message obtainMessage(int, java.lang.Object);
+ method public final android.os.Message obtainMessage(int, int, int);
+ method public final android.os.Message obtainMessage(int, int, int, java.lang.Object);
+ method protected void onHalting();
+ method protected void onQuitting();
+ method protected final void quit();
+ method protected final void quitNow();
+ method protected boolean recordLogRec(android.os.Message);
+ method protected final void removeMessages(int);
+ method public final void sendMessage(int);
+ method public final void sendMessage(int, java.lang.Object);
+ method public final void sendMessage(android.os.Message);
+ method protected final void sendMessageAtFrontOfQueue(int, java.lang.Object);
+ method protected final void sendMessageAtFrontOfQueue(int);
+ method protected final void sendMessageAtFrontOfQueue(android.os.Message);
+ method public final void sendMessageDelayed(int, long);
+ method public final void sendMessageDelayed(int, java.lang.Object, long);
+ method public final void sendMessageDelayed(android.os.Message, long);
+ method public void setDbg(boolean);
+ method protected final void setInitialState(com.android.internal.util.State);
+ method public final void setLogRecSize(int);
+ method public void start();
+ method protected final void transitionTo(com.android.internal.util.IState);
+ method protected final void transitionToHaltingState();
+ method protected void unhandledMessage(android.os.Message);
+ field public static final boolean HANDLED = true;
+ field public static final boolean NOT_HANDLED = false;
+ }
+
+ public static class StateMachine.LogRec {
+ method public java.lang.String getInfo();
+ method public com.android.internal.util.State getOriginalState();
+ method public com.android.internal.util.State getState();
+ method public long getTime();
+ method public long getWhat();
+ method public java.lang.String toString(com.android.internal.util.StateMachine);
+ method public void update(android.os.Message, java.lang.String, com.android.internal.util.State, com.android.internal.util.State);
+ }
+
}
package dalvik.annotation {
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 95b6bed3dfb8..8e51c58a3d43 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -74,6 +74,8 @@ import android.net.wifi.IWifiManager;
import android.net.wifi.WifiManager;
import android.net.wifi.p2p.IWifiP2pManager;
import android.net.wifi.p2p.WifiP2pManager;
+import android.net.ethernet.IEthernetManager;
+import android.net.ethernet.EthernetManager;
import android.nfc.NfcManager;
import android.os.Binder;
import android.os.Bundle;
@@ -518,6 +520,13 @@ class ContextImpl extends Context {
return new WifiP2pManager(service);
}});
+ 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());
+ }});
+
registerService(WINDOW_SERVICE, new ServiceFetcher() {
public Object getService(ContextImpl ctx) {
Display display = ctx.mDisplay;
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 7aa2507975dc..064280798df4 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -1838,6 +1838,16 @@ public abstract class Context {
*/
public static final String WINDOW_SERVICE = "window";
+ /**
+ * Use with {@link #getSystemService} to retrieve a {@link
+ * android.net.ethernet.EthernetManager} for handling management of
+ * Ethernet access.
+ *
+ * @see #getSystemService
+ * @see android.net.ethernet.EthernetManager
+ */
+ public static final String ETHERNET_SERVICE = "ethernet";
+
/**
* Use with {@link #getSystemService} to retrieve a
* {@link android.view.LayoutInflater} for inflating layout resources in this
diff --git a/core/java/android/net/NetworkUtils.java b/core/java/android/net/NetworkUtils.java
index d39e741efddc..daa8d3574cce 100644
--- a/core/java/android/net/NetworkUtils.java
+++ b/core/java/android/net/NetworkUtils.java
@@ -102,6 +102,18 @@ public class NetworkUtils {
*/
public native static String getDhcpError();
+ 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, int dns1, int dns2);
+
/**
* Convert a IPv4 address from an integer to an InetAddress.
* @param hostAddress an int corresponding to the IPv4 address in network byte order
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index b94f0b91b5e5..ae49580fe43d 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -3668,13 +3668,20 @@ public final class Settings {
Global.WIFI_MOBILE_DATA_TRANSITION_WAKELOCK_TIMEOUT_MS;
/**
- * Whether background data usage is allowed.
- *
- * @deprecated As of {@link VERSION_CODES#ICE_CREAM_SANDWICH},
- * availability of background data depends on several
- * combined factors. When background data is unavailable,
- * {@link ConnectivityManager#getActiveNetworkInfo()} will
- * now appear disconnected.
+ * 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";
+
+ /**
+ * Whether background data usage is allowed by the user. See
+ * ConnectivityManager for more info.
*/
@Deprecated
public static final String BACKGROUND_DATA = "background_data";
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index 3142141f5045..9e3bea3ff919 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -77,6 +77,7 @@ LOCAL_SRC_FILES:= \
android_net_NetUtils.cpp \
android_net_TrafficStats.cpp \
android_net_wifi_Wifi.cpp \
+ android_net_ethernet.cpp \
android_nio_utils.cpp \
android_text_format_Time.cpp \
android_util_AssetManager.cpp \
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 9820e60545d1..6bac598930c4 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -146,6 +146,7 @@ extern int register_android_net_LocalSocketImpl(JNIEnv* env);
extern int register_android_net_NetworkUtils(JNIEnv* env);
extern int register_android_net_TrafficStats(JNIEnv* env);
extern int register_android_net_wifi_WifiManager(JNIEnv* env);
+extern int register_android_net_ethernet_EthernetManager(JNIEnv* env);
extern int register_android_text_AndroidCharacter(JNIEnv *env);
extern int register_android_text_AndroidBidi(JNIEnv *env);
extern int register_android_opengl_classes(JNIEnv *env);
@@ -1174,6 +1175,7 @@ static const RegJNIRec gRegJNI[] = {
REG_JNI(register_android_net_NetworkUtils),
REG_JNI(register_android_net_TrafficStats),
REG_JNI(register_android_net_wifi_WifiManager),
+ REG_JNI(register_android_net_ethernet_EthernetManager),
REG_JNI(register_android_os_MemoryFile),
REG_JNI(register_com_android_internal_os_ZygoteInit),
REG_JNI(register_android_hardware_Camera),
diff --git a/core/jni/android_net_NetUtils.cpp b/core/jni/android_net_NetUtils.cpp
index 1f2b1ae0e51b..6447eb75d667 100644
--- a/core/jni/android_net_NetUtils.cpp
+++ b/core/jni/android_net_NetUtils.cpp
@@ -26,7 +26,9 @@
extern "C" {
int ifc_enable(const char *ifname);
int ifc_disable(const char *ifname);
+int ifc_remove_default_route(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 *ifname,
const char *ipaddr,
@@ -93,6 +95,16 @@ static jint android_net_utils_disableInterface(JNIEnv* env, jobject clazz, jstri
return (jint)result;
}
+static jint android_net_utils_removeDefaultRoute(JNIEnv* env, jobject clazz, jstring ifname)
+{
+ int result;
+
+ const char *nameStr = env->GetStringUTFChars(ifname, NULL);
+ result = ::ifc_remove_default_route(nameStr);
+ env->ReleaseStringUTFChars(ifname, nameStr);
+ return (jint)result;
+}
+
static jint android_net_utils_resetConnections(JNIEnv* env, jobject clazz,
jstring ifname, jint mask)
{
@@ -170,6 +182,24 @@ static jboolean android_net_utils_runDhcpCommon(JNIEnv* env, jobject clazz, jstr
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 jboolean android_net_utils_runDhcp(JNIEnv* env, jobject clazz, jstring ifname, jobject info)
{
return android_net_utils_runDhcpCommon(env, clazz, ifname, info, false);
@@ -222,6 +252,7 @@ static JNINativeMethod gNetworkUtilMethods[] = {
{ "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 },
+ { "configureNative", "(Ljava/lang/String;IIIII)Z", (void *)android_net_utils_configureInterface },
};
int register_android_net_NetworkUtils(JNIEnv* env)
diff --git a/core/jni/android_net_ethernet.cpp b/core/jni/android_net_ethernet.cpp
new file mode 100644
index 000000000000..78f0643417ed
--- /dev/null
+++ b/core/jni/android_net_ethernet.cpp
@@ -0,0 +1,419 @@
+/*
+ * Copyright 2010, The Android-x86 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.
+ *
+ * Author: Yi Sun <beyounn@gmail.com>
+ */
+
+#define LOG_TAG "ethernet"
+
+#include "jni.h"
+#include <inttypes.h>
+#include <utils/misc.h>
+#include <android_runtime/AndroidRuntime.h>
+#include <utils/Log.h>
+#include <asm/types.h>
+#include <sys/un.h>
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <poll.h>
+#include <net/if_arp.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+#include <dirent.h>
+
+
+#define ETH_PKG_NAME "android/net/ethernet/EthernetNative"
+#define NL_SOCK_INV -1
+#define RET_STR_SZ 4096
+#define NL_POLL_MSG_SZ 8*1024
+#define SYSFS_PATH_MAX 256
+
+namespace android {
+ static struct fieldIds {
+ jclass dhcpInfoClass;
+ jmethodID constructorId;
+ jfieldID ipaddress;
+ jfieldID gateway;
+ jfieldID netmask;
+ jfieldID dns1;
+ jfieldID dns2;
+ jfieldID serverAddress;
+ jfieldID leaseDuration;
+ } dhcpInfoFieldIds;
+
+ struct interface_info_t {
+ unsigned int i; /* interface index */
+ char *name; /* name (eth0, eth1, ...) */
+ struct interface_info_t *next;
+ };
+
+ interface_info_t *interfaces = NULL;
+ int total_int = 0;
+ static const char SYSFS_CLASS_NET[] = "/sys/class/net";
+ static int nl_socket_msg = NL_SOCK_INV;
+ static struct sockaddr_nl addr_msg;
+ static int nl_socket_poll = NL_SOCK_INV;
+ static struct sockaddr_nl addr_poll;
+ static int getinterfacename(int index, char *name, size_t len);
+
+ static interface_info_t *find_info_by_index(unsigned int index)
+ {
+ interface_info_t *info = interfaces;
+ while (info) {
+ if (info->i == index)
+ break;
+ info = info->next;
+ }
+ return info;
+ }
+
+ static jstring android_net_ethernet_waitForEvent(JNIEnv *env, jobject clazz)
+ {
+ char *buff;
+ struct nlmsghdr *nh;
+ struct ifinfomsg *einfo;
+ struct iovec iov;
+ struct msghdr msg;
+ char *result = NULL;
+ char rbuf[4096];
+ unsigned int left;
+ interface_info_t *info;
+ int len;
+
+ ALOGV("Poll events from ethernet devices");
+ /*
+ *wait on uevent netlink socket for the ethernet device
+ */
+ buff = (char *)malloc(NL_POLL_MSG_SZ);
+ if (!buff) {
+ ALOGE("Allocate poll buffer failed");
+ goto error;
+ }
+
+ iov.iov_base = buff;
+ iov.iov_len = NL_POLL_MSG_SZ;
+ msg.msg_name = (void *)&addr_msg;
+ msg.msg_namelen = sizeof(addr_msg);
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+ msg.msg_control = NULL;
+ msg.msg_controllen = 0;
+ msg.msg_flags = 0;
+
+ if ((len = recvmsg(nl_socket_poll, &msg, 0)) >= 0) {
+ ALOGV("recvmsg get data");
+ result = rbuf;
+ left = 4096;
+ rbuf[0] = '\0';
+ for (nh = (struct nlmsghdr *) buff; NLMSG_OK (nh, len);
+ nh = NLMSG_NEXT (nh, len)) {
+
+ if (nh->nlmsg_type == NLMSG_DONE) {
+ ALOGE("Did not find useful eth interface information");
+ goto error;
+ }
+
+ if (nh->nlmsg_type == NLMSG_ERROR) {
+ /* Do some error handling. */
+ ALOGE("Read device name failed");
+ goto error;
+ }
+
+ ALOGV(" event :%d found", nh->nlmsg_type);
+ einfo = (struct ifinfomsg *)NLMSG_DATA(nh);
+ ALOGV("the device flag :%X", einfo->ifi_flags);
+ if (nh->nlmsg_type == RTM_DELLINK ||
+ nh->nlmsg_type == RTM_NEWLINK ||
+ nh->nlmsg_type == RTM_DELADDR ||
+ nh->nlmsg_type == RTM_NEWADDR) {
+ int type = nh->nlmsg_type;
+ if (type == RTM_NEWLINK &&
+ (!(einfo->ifi_flags & IFF_LOWER_UP))) {
+ type = RTM_DELLINK;
+ }
+ if ((info = find_info_by_index
+ (((struct ifinfomsg*) NLMSG_DATA(nh))->ifi_index)) != NULL)
+ snprintf(result,left, "%s:%d:",info->name,type);
+ left = left - strlen(result);
+ result =(char *)(result+ strlen(result));
+ }
+
+ }
+ ALOGV("Done parsing");
+ rbuf[4096 - left] = '\0';
+ ALOGV("poll state :%s, left:%d", rbuf, left);
+ }
+
+
+ error:
+ free(buff);
+ return env->NewStringUTF(rbuf);
+ }
+
+ static int netlink_send_dump_request(int sock, int type, int family)
+ {
+ int ret;
+ char buf[4096];
+ struct sockaddr_nl snl;
+ struct nlmsghdr *nlh;
+ struct rtgenmsg *g;
+
+ memset(&snl, 0, sizeof(snl));
+ snl.nl_family = AF_NETLINK;
+
+ memset(buf, 0, sizeof(buf));
+ nlh = (struct nlmsghdr *)buf;
+ g = (struct rtgenmsg *)(buf + sizeof(struct nlmsghdr));
+
+ nlh->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtgenmsg));
+ nlh->nlmsg_flags = NLM_F_REQUEST|NLM_F_DUMP;
+ nlh->nlmsg_type = type;
+ g->rtgen_family = family;
+
+ ret = sendto(sock, buf, nlh->nlmsg_len, 0, (struct sockaddr *)&snl,
+ sizeof(snl));
+ if (ret < 0) {
+ perror("netlink_send_dump_request sendto");
+ return -1;
+ }
+
+ return ret;
+ }
+
+ static void free_int_list()
+ {
+ interface_info_t *tmp = interfaces;
+ while (tmp) {
+ if (tmp->name)
+ free(tmp->name);
+ interfaces = tmp->next;
+ free(tmp);
+ tmp = interfaces;
+ total_int--;
+ }
+ if (total_int) {
+ ALOGE("Wrong interface count found");
+ total_int = 0;
+ }
+ }
+
+ static void add_int_to_list(interface_info_t *node)
+ {
+ /* Todo: Lock here!!!! */
+ node->next = interfaces;
+ interfaces = node;
+ total_int++;
+ }
+
+ static int netlink_init_interfaces_list(void)
+ {
+ int ret = -1;
+ DIR *netdir;
+ struct dirent *de;
+ char path[SYSFS_PATH_MAX];
+ interface_info_t *intfinfo;
+ int index;
+ FILE *ifidx;
+ #define MAX_FGETS_LEN 4
+ char idx[MAX_FGETS_LEN+1];
+
+ if ((netdir = opendir(SYSFS_CLASS_NET)) != NULL) {
+ while ((de = readdir(netdir))) {
+ if ((de->d_name[0] == '.') || (!strcmp(de->d_name, "lo")) ||
+ (!strcmp(de->d_name, "wmaster0")) || (!strcmp(de->d_name, "pan0")))
+ continue;
+ snprintf(path, SYSFS_PATH_MAX,"%s/%s/phy80211", SYSFS_CLASS_NET, de->d_name);
+ if (!access(path, F_OK))
+ continue;
+ snprintf(path, SYSFS_PATH_MAX,"%s/%s/wireless", SYSFS_CLASS_NET, de->d_name);
+ if (!access(path, F_OK))
+ continue;
+
+ snprintf(path, SYSFS_PATH_MAX,"%s/%s/ifindex", SYSFS_CLASS_NET, de->d_name);
+ if ((ifidx = fopen(path, "r")) != NULL) {
+ memset(idx, 0, MAX_FGETS_LEN + 1);
+ if (fgets(idx,MAX_FGETS_LEN, ifidx) != NULL) {
+ index = strtoimax(idx, NULL, 10);
+ } else {
+ ALOGE("Can not read %s", path);
+ continue;
+ }
+ } else {
+ ALOGE("Can not open %s for read", path);
+ continue;
+ }
+ /* make some room! */
+ intfinfo = (interface_info_t *)malloc(sizeof(interface_info_t));
+ if (intfinfo == NULL) {
+ ALOGE("malloc in netlink_init_interfaces_table");
+ goto error;
+ }
+ /* copy the interface name (eth0, eth1, ...) */
+ intfinfo->name = strndup((char *) de->d_name, SYSFS_PATH_MAX);
+ intfinfo->i = index;
+ ALOGI("interface %s:%d found", intfinfo->name, intfinfo->i);
+ add_int_to_list(intfinfo);
+ }
+ closedir(netdir);
+ }
+ ret = 0;
+
+ error:
+ return ret;
+ }
+
+ /*
+ * The netlink socket
+ */
+
+ static jint android_net_ethernet_initEthernetNative(JNIEnv *env,
+ jobject clazz)
+ {
+ int ret = -1;
+
+ memset(&addr_msg, 0, sizeof(sockaddr_nl));
+ addr_msg.nl_family = AF_NETLINK;
+ memset(&addr_poll, 0, sizeof(sockaddr_nl));
+ addr_poll.nl_family = AF_NETLINK;
+ addr_poll.nl_pid = 0;//getpid();
+ addr_poll.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_IFADDR;
+
+ /*
+ *Create connection to netlink socket
+ */
+ nl_socket_msg = socket(AF_NETLINK,SOCK_RAW,NETLINK_ROUTE);
+ if (nl_socket_msg <= 0) {
+ ALOGE("Can not create netlink msg socket");
+ goto error;
+ }
+ if (bind(nl_socket_msg, (struct sockaddr *)(&addr_msg),
+ sizeof(struct sockaddr_nl))) {
+ ALOGE("Can not bind to netlink msg socket");
+ goto error;
+ }
+
+ nl_socket_poll = socket(AF_NETLINK,SOCK_RAW,NETLINK_ROUTE);
+ if (nl_socket_poll <= 0) {
+ ALOGE("Can not create netlink poll socket");
+ goto error;
+ }
+
+ errno = 0;
+ if (bind(nl_socket_poll, (struct sockaddr *)(&addr_poll),
+ sizeof(struct sockaddr_nl))) {
+ ALOGE("Can not bind to netlink poll socket,%s", strerror(errno));
+
+ goto error;
+ }
+
+ if ((ret = netlink_init_interfaces_list()) < 0) {
+ ALOGE("Can not collect the interface list");
+ goto error;
+ }
+ ALOGE("%s exited with success", __FUNCTION__);
+ return ret;
+
+ error:
+ ALOGE("%s exited with error", __FUNCTION__);
+ if (nl_socket_msg > 0)
+ close(nl_socket_msg);
+ if (nl_socket_poll > 0)
+ close(nl_socket_poll);
+ return ret;
+ }
+
+ static jstring android_net_ethernet_getInterfaceName(JNIEnv *env,
+ jobject clazz,
+ jint index)
+ {
+ int i = 0;
+ interface_info_t *info;
+ ALOGI("User ask for device name on %d, list:%X, total:%d",
+ index, (unsigned int)interfaces, total_int);
+ info = interfaces;
+ if (total_int != 0 && index <= (total_int - 1)) {
+ while (info) {
+ if (index == i) {
+ ALOGV("Found: %s", info->name);
+ return env->NewStringUTF(info->name);
+ }
+ info = info->next;
+ i++;
+ }
+ }
+ ALOGI("No device name found");
+ return env->NewStringUTF(NULL);
+ }
+
+
+ static jint android_net_ethernet_getInterfaceCnt()
+ {
+ return total_int;
+ }
+
+ static JNINativeMethod gEthernetMethods[] = {
+ {"waitForEvent", "()Ljava/lang/String;",
+ (void *)android_net_ethernet_waitForEvent},
+ {"getInterfaceName", "(I)Ljava/lang/String;",
+ (void *)android_net_ethernet_getInterfaceName},
+ {"initEthernetNative", "()I",
+ (void *)android_net_ethernet_initEthernetNative},
+ {"getInterfaceCnt","()I",
+ (void *)android_net_ethernet_getInterfaceCnt}
+ };
+
+ int register_android_net_ethernet_EthernetManager(JNIEnv* env)
+ {
+ jclass eth = env->FindClass(ETH_PKG_NAME);
+ ALOGI("Loading ethernet jni class");
+ LOG_FATAL_IF(eth == NULL, "Unable to find class " ETH_PKG_NAME);
+ dhcpInfoFieldIds.dhcpInfoClass =
+ env->FindClass("android/net/DhcpInfo");
+
+ if (dhcpInfoFieldIds.dhcpInfoClass != NULL) {
+ dhcpInfoFieldIds.constructorId =
+ env->GetMethodID(dhcpInfoFieldIds.dhcpInfoClass,
+ "<init>", "()V");
+ dhcpInfoFieldIds.ipaddress =
+ env->GetFieldID(dhcpInfoFieldIds.dhcpInfoClass,
+ "ipAddress", "I");
+ dhcpInfoFieldIds.gateway =
+ env->GetFieldID(dhcpInfoFieldIds.dhcpInfoClass,
+ "gateway", "I");
+ dhcpInfoFieldIds.netmask =
+ env->GetFieldID(dhcpInfoFieldIds.dhcpInfoClass,
+ "netmask", "I");
+ dhcpInfoFieldIds.dns1 =
+ env->GetFieldID(dhcpInfoFieldIds.dhcpInfoClass, "dns1", "I");
+ dhcpInfoFieldIds.dns2 =
+ env->GetFieldID(dhcpInfoFieldIds.dhcpInfoClass, "dns2", "I");
+ dhcpInfoFieldIds.serverAddress =
+ env->GetFieldID(dhcpInfoFieldIds.dhcpInfoClass,
+ "serverAddress", "I");
+ dhcpInfoFieldIds.leaseDuration =
+ env->GetFieldID(dhcpInfoFieldIds.dhcpInfoClass,
+ "leaseDuration", "I");
+ }
+
+ return AndroidRuntime::registerNativeMethods(env,
+ ETH_PKG_NAME,
+ gEthernetMethods,
+ NELEM(gEthernetMethods));
+ }
+
+}
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 3b7d73a44cbc..dbf7bffc513f 100755
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -34,6 +34,7 @@
<item><xliff:g id="id">mute</xliff:g></item>
<item><xliff:g id="id">volume</xliff:g></item>
<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><xliff:g id="id">data_connection</xliff:g></item>
<item><xliff:g id="id">phone_evdo_signal</xliff:g></item>
@@ -145,6 +146,7 @@
<item>"mobile_mms,2,0,2,60000,true"</item>
<item>"mobile_supl,3,0,2,60000,true"</item>
<item>"mobile_hipri,5,0,3,60000,true"</item>
+ <item>"ethernet,9,9,1,-1,ture"</item>
<item>"mobile_fota,10,0,2,60000,true"</item>
<item>"mobile_ims,11,0,2,60000,true"</item>
<item>"mobile_cbs,12,0,2,60000,true"</item>
@@ -167,6 +169,7 @@
<string-array translatable="false" name="radioAttributes">
<item>"1,1"</item>
<item>"0,1"</item>
+ <item>"9,1"</item>
</string-array>
<!-- Set of NetworkInfo.getType() that reflect data usage. -->
diff --git a/ethernet/java/android/net/ethernet/EthernetDevInfo.aidl b/ethernet/java/android/net/ethernet/EthernetDevInfo.aidl
new file mode 100644
index 000000000000..0f2c965bcbdf
--- /dev/null
+++ b/ethernet/java/android/net/ethernet/EthernetDevInfo.aidl
@@ -0,0 +1,19 @@
+/**
+ * Copyright (c) 2010, The Android-x86 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.ethernet;
+
+parcelable EthernetDevInfo;
diff --git a/ethernet/java/android/net/ethernet/EthernetDevInfo.java b/ethernet/java/android/net/ethernet/EthernetDevInfo.java
new file mode 100644
index 000000000000..058eb822c613
--- /dev/null
+++ b/ethernet/java/android/net/ethernet/EthernetDevInfo.java
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2010 The Android-X86 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.
+ *
+ * Author: Yi Sun <beyounn@gmail.com>
+ */
+
+
+package android.net.ethernet;
+
+import android.net.ethernet.EthernetDevInfo;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.os.Parcelable.Creator;
+
+/**
+ * Describes the state of any Ethernet connection that is active or
+ * is in the process of being set up.
+ */
+
+public class EthernetDevInfo implements Parcelable {
+ /**
+ * The ethernet interface is configured by dhcp
+ */
+ public static final String ETHERNET_CONN_MODE_DHCP= "dhcp";
+ /**
+ * The ethernet interface is configured manually
+ */
+ public static final String ETHERNET_CONN_MODE_MANUAL = "manual";
+
+ private String dev_name;
+ private String ipaddr;
+ private String netmask;
+ private String route;
+ private String dns;
+ private String mode;
+
+ public EthernetDevInfo () {
+ dev_name = null;
+ ipaddr = null;
+ dns = null;
+ route = null;
+ netmask = null;
+ mode = ETHERNET_CONN_MODE_DHCP;
+ }
+
+ /**
+ * save interface name into the configuration
+ */
+ public void setIfName(String ifname) {
+ this.dev_name = ifname;
+ }
+
+ /**
+ * Returns the interface name from the saved configuration
+ * @return interface name
+ */
+ public String getIfName() {
+ return this.dev_name;
+ }
+
+ public void setIpAddress(String ip) {
+ this.ipaddr = ip;
+ }
+
+ public String getIpAddress( ) {
+ return this.ipaddr;
+ }
+
+ public void setNetMask(String ip) {
+ this.netmask = ip;
+ }
+
+ public String getNetMask( ) {
+ return this.netmask;
+ }
+
+ public void setRouteAddr(String route) {
+ this.route = route;
+ }
+
+ public String getRouteAddr() {
+ return this.route;
+ }
+
+ public void setDnsAddr(String dns) {
+ this.dns = dns;
+ }
+
+ public String getDnsAddr( ) {
+ return this.dns;
+ }
+
+ /**
+ * Set ethernet configuration mode
+ * @param mode {@code ETHERNET_CONN_MODE_DHCP} for dhcp {@code ETHERNET_CONN_MODE_MANUAL} for manual configure
+ * @return
+ */
+ public boolean setConnectMode(String mode) {
+ if (mode.equals(ETHERNET_CONN_MODE_DHCP) || mode.equals(ETHERNET_CONN_MODE_MANUAL)) {
+ this.mode = mode;
+ return true;
+ }
+ return false;
+ }
+
+ public String getConnectMode() {
+ return this.mode;
+ }
+
+ public int describeContents() {
+ return 0;
+ }
+
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeString(this.dev_name);
+ dest.writeString(this.ipaddr);
+ dest.writeString(this.netmask);
+ dest.writeString(this.route);
+ dest.writeString(this.dns);
+ dest.writeString(this.mode);
+ }
+
+ /** Implement the Parcelable interface {@hide} */
+ public static final Creator<EthernetDevInfo> CREATOR = new Creator<EthernetDevInfo>() {
+ public EthernetDevInfo createFromParcel(Parcel in) {
+ EthernetDevInfo info = new EthernetDevInfo();
+ info.setIfName(in.readString());
+ info.setIpAddress(in.readString());
+ info.setNetMask(in.readString());
+ info.setRouteAddr(in.readString());
+ info.setDnsAddr(in.readString());
+ info.setConnectMode(in.readString());
+ return info;
+ }
+
+ public EthernetDevInfo[] newArray(int size) {
+ return new EthernetDevInfo[size];
+ }
+ };
+}
diff --git a/ethernet/java/android/net/ethernet/EthernetManager.java b/ethernet/java/android/net/ethernet/EthernetManager.java
new file mode 100644
index 000000000000..ac480c236586
--- /dev/null
+++ b/ethernet/java/android/net/ethernet/EthernetManager.java
@@ -0,0 +1,192 @@
+/*
+ * Copyright (C) 2010 The Android-X86 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.
+ *
+ * Author: Yi Sun <beyounn@gmail.com>
+ */
+
+package android.net.ethernet;
+
+import java.util.List;
+import android.annotation.SdkConstant;
+import android.annotation.SdkConstant.SdkConstantType;
+import android.os.Handler;
+import android.os.RemoteException;
+import android.util.Slog;
+
+/**
+ * This class provides the primary API for managing all aspects of Ethernet
+ * connectivity. Get an instance of this class by calling
+ * {@link android.content.Context#getSystemService(String) Context.getSystemService(Context.ETHERNET_SERVICE)}.
+ *
+ * This is the API to use when performing Ethernet specific operations. To
+ * perform operations that pertain to network connectivity at an abstract
+ * level, use {@link android.net.ConnectivityManager}.
+ */
+public class EthernetManager {
+ public static final String TAG = "EthernetManager";
+ public static final int ETHERNET_DEVICE_SCAN_RESULT_READY = 0;
+ public static final String ETHERNET_STATE_CHANGED_ACTION =
+ "android.net.ethernet.ETHERNET_STATE_CHANGED";
+ public static final String NETWORK_STATE_CHANGED_ACTION =
+ "android.net.ethernet.STATE_CHANGE";
+ public static final String LINK_CONFIGURATION_CHANGED_ACTION =
+ "android.net.ethernet.LINK_CONFIGURATION_CHANGED";
+
+ public static final String EXTRA_NETWORK_INFO = "networkInfo";
+ public static final String EXTRA_ETHERNET_STATE = "ETHERNET_state";
+ public static final String EXTRA_PREVIOUS_ETHERNET_STATE = "previous_ETHERNET_state";
+
+ public static final int ETHERNET_STATE_UNKNOWN = 0;
+ public static final int ETHERNET_STATE_DISABLED = 1;
+ public static final int ETHERNET_STATE_ENABLED = 2;
+
+ public static final int DATA_ACTIVITY_NONE = 0x00;
+ public static final int DATA_ACTIVITY_IN = 0x01;
+ public static final int DATA_ACTIVITY_OUT = 0x02;
+ public static final int DATA_ACTIVITY_INOUT = 0x03;
+
+ IEthernetManager mService;
+ Handler mHandler;
+
+ public EthernetManager(IEthernetManager service, Handler handler) {
+ Slog.i(TAG, "Init Ethernet Manager, service: " +service);
+ mService = service;
+ mHandler = handler;
+ }
+
+ /**
+ * check if the ethernet service has been configured.
+ * @return {@code true} if configured {@code false} otherwise
+ */
+ public boolean isConfigured() {
+ try {
+ return mService.isConfigured();
+ } catch (RemoteException e) {
+ Slog.i(TAG, "Can not check eth config state");
+ }
+ return false;
+ }
+
+ /**
+ * Return the saved ethernet configuration
+ * @return ethernet interface configuration on success, {@code null} on failure
+ */
+ public EthernetDevInfo getSavedConfig() {
+ try {
+ return mService.getSavedConfig();
+ } catch (RemoteException e) {
+ Slog.i(TAG, "Can not get eth config");
+ }
+ return null;
+ }
+
+ /**
+ * update a ethernet interface information
+ * @param info the interface infomation
+ */
+ public void updateDevInfo(EthernetDevInfo info) {
+ try {
+ mService.updateDevInfo(info);
+ } catch (RemoteException e) {
+ Slog.i(TAG, "Can not update ethernet device info");
+ }
+ }
+
+ /**
+ * get all the ethernet device names
+ * @return interface name list on success, {@code null} on failure
+ */
+ public String[] getDeviceNameList() {
+ try {
+ return mService.getDeviceNameList();
+ } catch (RemoteException e) {
+ return null;
+ }
+ }
+ /**
+ * Enable or Disable a ethernet service
+ * @param enable {@code true} to enable, {@code false} to disable
+ * @hide
+ */
+ public void setEnabled(boolean enable) {
+ try {
+ mService.setState(enable ? ETHERNET_STATE_ENABLED:ETHERNET_STATE_DISABLED);
+ } catch (RemoteException e) {
+ Slog.i(TAG,"Can not set new state");
+ }
+ }
+
+ /**
+ * Get ethernet service state
+ * @return the state of the ethernet service
+ */
+ public int getState( ) {
+ try {
+ return mService.getState();
+ } catch (RemoteException e) {
+ return 0;
+ }
+ }
+
+ /**
+ * get the number of ethernet interfaces in the system
+ * @return the number of ethernet interfaces
+ */
+ public int getTotalInterface() {
+ try {
+ return mService.getTotalInterface();
+ } catch (RemoteException e) {
+ return 0;
+ }
+ }
+
+ /**
+ * @hide
+ */
+ public void setDefaultConf() {
+ try {
+ mService.setMode(EthernetDevInfo.ETHERNET_CONN_MODE_DHCP);
+ } catch (RemoteException e) {
+ }
+ }
+
+ public boolean startEthernet() {
+ try {
+ mService.startEthernet();
+ return true;
+ } catch (RemoteException e) {
+ return false;
+ }
+ }
+
+ public boolean stopEthernet() {
+ try {
+ mService.stopEthernet();
+ return true;
+ } catch (RemoteException e) {
+ return false;
+ }
+ }
+
+ public boolean reconnect() {
+ try {
+ mService.reconnect();
+ return true;
+ } catch (RemoteException e) {
+ return false;
+ }
+ }
+
+}
diff --git a/ethernet/java/android/net/ethernet/EthernetMonitor.java b/ethernet/java/android/net/ethernet/EthernetMonitor.java
new file mode 100644
index 000000000000..a5c7d6297d8a
--- /dev/null
+++ b/ethernet/java/android/net/ethernet/EthernetMonitor.java
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2010 The Android-X86 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.
+ *
+ * Author: Yi Sun <beyounn@gmail.com>
+ */
+
+package android.net.ethernet;
+
+import java.util.regex.Matcher;
+
+import android.net.NetworkInfo;
+import android.util.Config;
+import android.util.Slog;
+import java.util.StringTokenizer;
+
+/**
+ * Listens for events from kernel, and passes them on
+ * to the {@link EtherentStateTracker} for handling. Runs in its own thread.
+ *
+ * @hide
+ */
+public class EthernetMonitor {
+ private static final String TAG = "EthernetMonitor";
+ private static final int CONNECTED = 1;
+ private static final int DISCONNECTED = 2;
+ private static final int PHYUP = 3;
+ private static final String connectedEvent = "CONNECTED";
+ private static final String disconnectedEvent = "DISCONNECTED";
+ private static final int ADD_ADDR = 20;
+ private static final int RM_ADDR = 21;
+ private static final int NEW_LINK = 16;
+ private static final int DEL_LINK = 17;
+ private static final boolean localLOGV = false;
+
+ private EthernetStateTracker mEthernetStateTracker;
+
+ public EthernetMonitor(EthernetStateTracker tracker) {
+ mEthernetStateTracker = tracker;
+ }
+
+ public void startMonitoring() {
+ new MonitorThread().start();
+ }
+
+ class MonitorThread extends Thread {
+ public MonitorThread() {
+ super("EthMonitor");
+ }
+
+ public void run() {
+ //noinspection InfiniteLoopStatement
+ for (;;) {
+ int index;
+ int i;
+ int cmd;
+ String dev;
+
+ if (localLOGV) Slog.v(TAG, "go poll events");
+
+ String eventName = EthernetNative.waitForEvent();
+
+ if (eventName == null) {
+ continue;
+ }
+
+ if (localLOGV) Slog.v(TAG, "get event " + eventName);
+
+ /*
+ * Map event name into event enum
+ */
+ i = 0;
+ while (i < eventName.length()) {
+ index = eventName.substring(i).indexOf(":");
+ if (index == -1)
+ break;
+ dev = eventName.substring(i, index);
+ i += index + 1;
+ index = eventName.substring(i).indexOf(":");
+ if (index == -1)
+ break;
+ cmd = Integer.parseInt(eventName.substring(i, i+index));
+ i += index + 1;
+ if (localLOGV) Slog.v(TAG, "dev: " + dev + " ev " + cmd);
+ switch (cmd) {
+ case DEL_LINK:
+ handleEvent(dev, DISCONNECTED);
+ break;
+ case ADD_ADDR:
+ handleEvent(dev, CONNECTED);
+ break;
+ case NEW_LINK:
+ handleEvent(dev, PHYUP);
+ break;
+ }
+ }
+ }
+ }
+
+ /**
+ * Handle all supplicant events except STATE-CHANGE
+ * @param event the event type
+ * @param remainder the rest of the string following the
+ * event name and &quot;&#8195;&#8212;&#8195;&quot;
+ */
+ void handleEvent(String ifname,int event) {
+ switch (event) {
+ case DISCONNECTED:
+ mEthernetStateTracker.notifyStateChange(ifname,NetworkInfo.DetailedState.DISCONNECTED);
+ break;
+ case CONNECTED:
+ mEthernetStateTracker.notifyStateChange(ifname,NetworkInfo.DetailedState.CONNECTED);
+ break;
+ case PHYUP:
+ mEthernetStateTracker.notifyPhyConnected(ifname);
+ break;
+ default:
+ mEthernetStateTracker.notifyStateChange(ifname,NetworkInfo.DetailedState.FAILED);
+ break;
+ }
+ }
+ }
+}
diff --git a/ethernet/java/android/net/ethernet/EthernetNative.java b/ethernet/java/android/net/ethernet/EthernetNative.java
new file mode 100644
index 000000000000..7f3a083e89be
--- /dev/null
+++ b/ethernet/java/android/net/ethernet/EthernetNative.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2010 The Android-X86 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.
+ *
+ * Author: Yi Sun <beyounn@gmail.com>
+ */
+
+package android.net.ethernet;
+
+/**
+ * Native calls for sending requests to the kernel,
+ * {@hide}
+ */
+public class EthernetNative {
+ public native static String getInterfaceName(int i);
+ public native static int getInterfaceCnt();
+ public native static int initEthernetNative();
+ public native static String waitForEvent();
+}
diff --git a/ethernet/java/android/net/ethernet/EthernetStateMachine.java b/ethernet/java/android/net/ethernet/EthernetStateMachine.java
new file mode 100644
index 000000000000..da6370e9fd8f
--- /dev/null
+++ b/ethernet/java/android/net/ethernet/EthernetStateMachine.java
@@ -0,0 +1,472 @@
+/*
+ * Copyright (C) 2010 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.ethernet;
+
+import java.net.UnknownHostException;
+
+import static android.net.ethernet.EthernetManager.ETHERNET_STATE_DISABLED;
+import static android.net.ethernet.EthernetManager.ETHERNET_STATE_ENABLED;
+import static android.net.ethernet.EthernetManager.ETHERNET_STATE_UNKNOWN;
+
+import android.os.IBinder;
+import android.os.INetworkManagementService;
+import android.os.ServiceManager;
+import android.os.WorkSource;
+
+import android.R;
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.net.ConnectivityManager;
+import android.net.NetworkStateTracker;
+import android.net.NetworkUtils;
+import android.net.ProxyProperties;
+import android.net.RouteInfo;
+import android.net.LinkAddress;
+import android.net.DhcpInfo;
+import android.net.DhcpInfoInternal;
+import android.net.DhcpStateMachine;
+import android.net.LinkCapabilities;
+import android.net.LinkProperties;
+import android.net.NetworkInfo;
+import android.net.NetworkInfo.DetailedState;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.Looper;
+import android.os.Message;
+import android.os.Parcel;
+import android.os.SystemProperties;
+import android.util.*;
+import java.util.Iterator;
+
+import com.android.internal.util.Protocol;
+import com.android.internal.util.State;
+import com.android.internal.util.StateMachine;
+
+import android.net.DnsPinger;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import java.net.InetAddress;
+import java.util.ArrayList;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.regex.Pattern;
+
+public class EthernetStateMachine extends StateMachine {
+
+ private static final String TAG = "EthernetStateMachine";
+ private static final String NETWORKTYPE = "ETHERNET";
+ private static final boolean DBG = true;
+
+ public static final int EVENT_DHCP_START = 0;
+ public static final int EVENT_INTERFACE_CONFIGURATION_SUCCEEDED = 1;
+ public static final int EVENT_INTERFACE_CONFIGURATION_FAILED = 2;
+ public static final int EVENT_HW_CONNECTED = 3;
+ public static final int EVENT_HW_DISCONNECTED = 4;
+ public static final int EVENT_HW_PHYCONNECTED = 5;
+ private static final int NOTIFY_ID = 6;
+ private static final boolean localLOGV = true;
+
+
+ private EthernetManager mEthernetManager;
+
+ private INetworkManagementService mNwService;
+ private ConnectivityManager mCm;
+
+ private DhcpHandler mDhcpTarget;
+ private Handler mTrackerTarget;
+ private String mInterfaceName;
+
+ private LinkCapabilities mLinkCapabilities;
+
+ private Context mContext;
+
+ private DhcpInfo mDhcpInfo;
+ private DhcpInfoInternal mDhcpInfoInternal;
+ private String[] sDnsPropNames;
+ private NetworkInfo mNetworkInfo;
+ private DhcpStateMachine mDhcpStateMachine;
+
+ private boolean mStackConnected;
+ private boolean mHWConnected;
+ private boolean mInterfaceStopped;
+ private boolean mStartingDhcp;
+
+ private static final int DEFAULT_MAX_DHCP_RETRIES = 9;
+
+
+ /**
+ * One of {@link EthernetManager#ETHERNET_STATE_DISABLED},
+ * {@link EthernetManager#ETHERNET_STATE_ENABLED},
+ * {@link EthernetManager#ETHERNET_STATE_UNKNOWN}
+ *
+ */
+ private final AtomicInteger mEthernetState = new AtomicInteger(ETHERNET_STATE_DISABLED);
+
+ /**
+ * Keep track of whether ETHERNET is running.
+ */
+ private boolean mIsRunning = false;
+
+ /**
+ * Keep track of whether we last told the battery stats we had started.
+ */
+ private boolean mReportedRunning = false;
+
+ /**
+ * Most recently set source of starting ETHERNET.
+ */
+ private final WorkSource mRunningEthernetUids = new WorkSource();
+
+ /**
+ * The last reported UIDs that were responsible for starting ETHERNET.
+ */
+ private final WorkSource mLastRunningEthernetUids = new WorkSource();
+
+ private boolean mNextEthernetActionExplicit = false;
+ private int mLastExplicitNetworkId;
+ private long mLastNetworkChoiceTime;
+ private static final long EXPLICIT_CONNECT_ALLOWED_DELAY_MS = 2 * 60 * 1000;
+
+
+ public EthernetStateMachine(Context context, String ethInterface) {
+ super(TAG);
+
+ mDhcpInfo = new DhcpInfo();
+
+ mContext = context;
+ mInterfaceName = ethInterface;
+
+ mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_ETHERNET, 0, NETWORKTYPE, "");
+
+ IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
+ mNwService = INetworkManagementService.Stub.asInterface(b);
+
+ HandlerThread dhcpThread = new HandlerThread("DHCP Handler Thread");
+ dhcpThread.start();
+ mDhcpTarget = new DhcpHandler(dhcpThread.getLooper());
+
+ mNetworkInfo.setIsAvailable(false);
+
+ if (DBG) setDbg(true);
+
+ //start the state machine
+// start();
+ }
+
+
+ public void setEthernetEnabled(boolean enable) {
+ }
+
+ public int syncGetEthernetState() {
+ return mEthernetState.get();
+ }
+
+ public String syncGetEthernetStateByName() {
+ switch (mEthernetState.get()) {
+ case ETHERNET_STATE_DISABLED:
+ return "disabled";
+ case ETHERNET_STATE_ENABLED:
+ return "enabled";
+ case ETHERNET_STATE_UNKNOWN:
+ return "unknown state";
+ default:
+ return "[invalid state]";
+ }
+ }
+
+ public DhcpInfo syncGetDhcpInfo() {
+ synchronized (mDhcpInfoInternal) {
+ return mDhcpInfoInternal.makeDhcpInfo();
+ }
+ }
+
+
+ /*********************************************************
+ * Internal private functions
+ ********************************************************/
+
+ private void checkAndSetConnectivityInstance() {
+ if (mCm == null) {
+ mCm = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
+ }
+ }
+
+
+ /**
+ * Fetch LinkProperties for the network
+ */
+ public void startMonitoring(Context context) {
+ mContext = context;
+
+ Slog.v(TAG,"start to monitor the ethernet devices");
+ mEthernetManager = (EthernetManager)mContext.getSystemService(Context.ETHERNET_SERVICE);
+ int state = mEthernetManager.getState();
+ if (state != mEthernetManager.ETHERNET_STATE_DISABLED) {
+ if (state == mEthernetManager.ETHERNET_STATE_UNKNOWN) {
+ // maybe this is the first time we run, enable it if ethernet devices exist
+ mEthernetManager.setEnabled(mEthernetManager.getDeviceNameList() != null);
+ } else {
+ try {
+ Slog.e(TAG, "startMonitoring resetInterface()");
+ resetInterface();
+ } catch (UnknownHostException e) {
+ Slog.e(TAG, "Wrong ethernet configuration");
+ }
+ }
+ }
+
+ IntentFilter filter = new IntentFilter();
+ filter.addAction(EthernetManager.NETWORK_STATE_CHANGED_ACTION);
+ }
+
+ private boolean configureInterface(EthernetDevInfo info) throws UnknownHostException {
+
+ LinkProperties linkProperties = getLinkProperties();
+
+ mStackConnected = false;
+ mHWConnected = false;
+ mInterfaceStopped = false;
+ mStartingDhcp = true;
+ if (info.getConnectMode().equals(EthernetDevInfo.ETHERNET_CONN_MODE_DHCP)) {
+ if (localLOGV) Slog.i(TAG, "trigger dhcp for device " + info.getIfName());
+ sDnsPropNames = new String[] {
+ "dhcp." + mInterfaceName + ".dns1",
+ "dhcp." + mInterfaceName + ".dns2"
+ };
+
+ mDhcpTarget.sendEmptyMessage(EVENT_DHCP_START);
+ } else {
+ int event;
+ sDnsPropNames = new String[] {
+ "net." + mInterfaceName + ".dns1",
+ "net." + mInterfaceName + ".dns2"
+ };
+
+ mDhcpInfo.ipAddress = lookupHost(info.getIpAddress());
+ mDhcpInfo.gateway = lookupHost(info.getRouteAddr());
+ mDhcpInfo.netmask = lookupHost(info.getNetMask());
+ mDhcpInfo.dns1 = lookupHost(info.getDnsAddr());
+ mDhcpInfo.dns2 = 0;
+
+ NetworkUtils.resetConnections(info.getIfName(), NetworkUtils.RESET_ALL_ADDRESSES);
+
+ if (NetworkUtils.configureInterface(info.getIfName(), mDhcpInfo)) {
+ event = EVENT_INTERFACE_CONFIGURATION_SUCCEEDED;
+ SystemProperties.set("net.dns1", info.getDnsAddr());
+ SystemProperties.set("net." + info.getIfName() + ".dns1", info.getDnsAddr());
+ SystemProperties.set("net." + info.getIfName() + ".dns2", "0.0.0.0");
+ if (localLOGV) Slog.v(TAG, "Static IP configuration succeeded");
+ } else {
+ event = EVENT_INTERFACE_CONFIGURATION_FAILED;
+ if (localLOGV) Slog.w(TAG, "Static IP configuration failed");
+ }
+// sendMessage(event);
+ }
+ return true;
+ }
+
+
+ /**
+ * reset ethernet interface
+ * @return true
+ * @throws UnknownHostException
+ */
+ public boolean resetInterface() throws UnknownHostException {
+ /*
+ * This will guide us to enabled the enabled device
+ */
+ if (mEthernetManager != null) {
+ EthernetDevInfo info = mEthernetManager.getSavedConfig();
+ if (info != null && mEthernetManager.isConfigured()) {
+ synchronized (this) {
+ mInterfaceName = info.getIfName();
+ Slog.i(TAG, "reset device " + mInterfaceName);
+ NetworkUtils.resetConnections(mInterfaceName, NetworkUtils.RESET_ALL_ADDRESSES);
+
+ // Stop DHCP
+ if (mDhcpTarget != null) {
+ mDhcpTarget.removeMessages(EVENT_DHCP_START);
+ }
+
+ if (!NetworkUtils.stopDhcp(mInterfaceName)) {
+ Slog.w(TAG, "Could not stop DHCP");
+ }
+ configureInterface(info);
+ }
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Stop etherent interface
+ * @param suspend {@code false} disable the interface {@code true} only reset the connection without disable the interface
+ * @return true
+ */
+ public boolean stopInterface(boolean suspend) {
+ if (mEthernetManager != null) {
+ EthernetDevInfo info = mEthernetManager.getSavedConfig();
+ if (info != null && mEthernetManager.isConfigured()) {
+ synchronized (mDhcpTarget) {
+ mInterfaceStopped = true;
+ Slog.i(TAG, "stop dhcp and interface");
+ mDhcpTarget.removeMessages(EVENT_DHCP_START);
+ String ifname = info.getIfName();
+
+ if (!NetworkUtils.stopDhcp(ifname)) {
+ Slog.w(TAG, "Could not stop DHCP");
+ }
+ NetworkUtils.resetConnections(ifname, NetworkUtils.RESET_ALL_ADDRESSES);
+ if (!suspend)
+ NetworkUtils.disableInterface(ifname);
+ }
+ }
+ }
+ return true;
+ }
+
+
+ private void postNotification(int event) {
+ String ns = Context.NOTIFICATION_SERVICE;
+ Intent intent = new Intent(EthernetManager.ETHERNET_STATE_CHANGED_ACTION);
+ intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
+ intent.putExtra(EthernetManager.EXTRA_ETHERNET_STATE, event);
+ mContext.sendStickyBroadcast(intent);
+ }
+
+ private void setState(boolean state, int event) {
+ if (mNetworkInfo.isConnected() != state) {
+ if (state) {
+ mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, null);
+ } else {
+ mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null, null);
+ stopInterface(true);
+ }
+ mNetworkInfo.setIsAvailable(state);
+ postNotification(event);
+ }
+ }
+
+ public void handleMessage(Message msg) {
+
+ synchronized (this) {
+ switch (msg.what) {
+ case EVENT_INTERFACE_CONFIGURATION_SUCCEEDED:
+ if (localLOGV) Slog.i(TAG, "received configured succeeded, stack=" + mStackConnected + " HW=" + mHWConnected);
+ mStackConnected = true;
+ if (mHWConnected)
+ setState(true, msg.what);
+ break;
+ case EVENT_INTERFACE_CONFIGURATION_FAILED:
+ mStackConnected = false;
+ //start to retry ?
+ break;
+ case EVENT_HW_CONNECTED:
+ if (localLOGV) Slog.i(TAG, "received HW connected, stack=" + mStackConnected + " HW=" + mHWConnected);
+ mHWConnected = true;
+ if (mStackConnected)
+ setState(true, msg.what);
+ break;
+ case EVENT_HW_DISCONNECTED:
+ if (localLOGV) Slog.i(TAG, "received disconnected events, stack=" + mStackConnected + " HW=" + mHWConnected);
+ setState(mHWConnected = false, msg.what);
+ break;
+ case EVENT_HW_PHYCONNECTED:
+ if (localLOGV) Slog.i(TAG, "interface up event, kick off connection request");
+ if (!mStartingDhcp) {
+ int state = mEthernetManager.getState();
+ if (state != mEthernetManager.ETHERNET_STATE_DISABLED) {
+ EthernetDevInfo info = mEthernetManager.getSavedConfig();
+ if (info != null && mEthernetManager.isConfigured()) {
+ try {
+ configureInterface(info);
+ } catch (UnknownHostException e) {
+ // TODO Auto-generated catch block
+ //e.printStackTrace();
+ Slog.e(TAG, "Cannot configure interface");
+ }
+ }
+ }
+ }
+ break;
+ }
+ }
+ }
+
+ private class DhcpHandler extends Handler {
+ public DhcpHandler(Looper looper) {
+ super(looper);
+ }
+
+ public void handleMessage(Message msg) {
+ int event;
+
+ switch (msg.what) {
+ case EVENT_DHCP_START:
+ synchronized (mDhcpTarget) {
+ if (!mInterfaceStopped) {
+ Slog.d(TAG, "DhcpHandler: DHCP request started");
+ DhcpInfoInternal dhcpInfoInternal = new DhcpInfoInternal();
+ if (NetworkUtils.runDhcp(mInterfaceName, dhcpInfoInternal)) {
+ SystemProperties.set("net.dns1", dhcpInfoInternal.dns1);
+ event = EVENT_INTERFACE_CONFIGURATION_SUCCEEDED;
+ Slog.d(TAG, "DhcpHandler: DHCP request succeeded: " + dhcpInfoInternal.toString());
+ } else {
+ event = EVENT_INTERFACE_CONFIGURATION_FAILED;
+ Slog.e(TAG, "DhcpHandler: DHCP request failed: " + NetworkUtils.getDhcpError());
+ }
+ // sendMessage(event);
+ } else {
+ mInterfaceStopped = false;
+ }
+ mStartingDhcp = false;
+ }
+ break;
+ }
+ }
+ }
+
+ static LinkProperties getLinkProperties() {
+ return new LinkProperties();
+ }
+
+ public void reconnectCommand() {
+// sendMessage(CMD_RECONNECT);
+ }
+
+ private static int lookupHost(String hostname) {
+ InetAddress inetAddress;
+ try {
+ inetAddress = InetAddress.getByName(hostname);
+ } catch (UnknownHostException e) {
+ return -1;
+ }
+ byte[] addrBytes;
+ int addr;
+ addrBytes = inetAddress.getAddress();
+ addr = ((addrBytes[3] & 0xff) << 24)
+ | ((addrBytes[2] & 0xff) << 16)
+ | ((addrBytes[1] & 0xff) << 8)
+ | (addrBytes[0] & 0xff);
+ return addr;
+ }
+}
+
diff --git a/ethernet/java/android/net/ethernet/EthernetStateTracker.java b/ethernet/java/android/net/ethernet/EthernetStateTracker.java
new file mode 100644
index 000000000000..5894aa7765d2
--- /dev/null
+++ b/ethernet/java/android/net/ethernet/EthernetStateTracker.java
@@ -0,0 +1,558 @@
+/*
+ * Copyright (C) 2010 The Android-X86 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.
+ *
+ * Author: Yi Sun <beyounn@gmail.com>
+ */
+
+package android.net.ethernet;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
+import android.R;
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.bluetooth.BluetoothHeadset;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.net.ConnectivityManager;
+import android.net.NetworkStateTracker;
+import android.net.NetworkUtils;
+import android.net.ProxyProperties;
+import android.net.RouteInfo;
+import android.net.LinkAddress;
+import android.net.DhcpInfoInternal;
+import android.net.LinkCapabilities;
+import android.net.LinkProperties;
+import android.net.NetworkInfo;
+import android.net.NetworkInfo.DetailedState;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.Looper;
+import android.os.Message;
+import android.os.Parcel;
+import android.os.SystemProperties;
+import android.util.*;
+import java.util.Iterator;
+
+import android.net.DnsPinger;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+/**
+ * Track the state of Ethernet connectivity. All event handling is done here,
+ * and all changes in connectivity state are initiated here.
+ *
+ * @hide
+ */
+
+public class EthernetStateTracker implements NetworkStateTracker {
+ private static final String NETWORKTYPE = "ETHERNET";
+ private static final String TAG = "EthernetStateTracker";
+
+ private static final boolean localLOGV = true;
+
+ public static final int EVENT_DHCP_START = 0;
+ public static final int EVENT_INTERFACE_CONFIGURATION_SUCCEEDED = 1;
+ public static final int EVENT_INTERFACE_CONFIGURATION_FAILED = 2;
+ public static final int EVENT_HW_CONNECTED = 3;
+ public static final int EVENT_HW_DISCONNECTED = 4;
+ public static final int EVENT_HW_PHYCONNECTED = 5;
+ private static final int NOTIFY_ID = 6;
+
+ private EthernetManager mEthernetManager;
+
+ private AtomicBoolean mTeardownRequested = new AtomicBoolean(false);
+ private AtomicBoolean mPrivateDnsRouteSet = new AtomicBoolean(false);
+ private AtomicBoolean mDefaultRouteSet = new AtomicBoolean(false);
+
+ private LinkProperties mLinkProperties;
+ private LinkCapabilities mLinkCapabilities;
+ private NetworkInfo mNetworkInfo;
+
+ private DnsPinger mDnsPinger;
+
+ private boolean mStackConnected;
+ private boolean mHWConnected;
+ private boolean mInterfaceStopped;
+ private DhcpHandler mDhcpTarget;
+ private String mInterfaceName ;
+ private DhcpInfoInternal mDhcpInfoInternal;
+ private EthernetMonitor mMonitor;
+ private String[] sDnsPropNames;
+ private boolean mStartingDhcp;
+ private NotificationManager mNotificationManager;
+ private Notification mNotification;
+
+ private Handler mTrackerTarget;
+ public static EthernetStateTracker sInstance;
+
+ /* For sending events to connectivity service handler */
+ private Handler mCsHandler;
+ private Context mContext;
+
+ public EthernetStateTracker(int netType, String networkName) {
+ if (localLOGV) Slog.v(TAG, "Starts...");
+
+ if (EthernetNative.initEthernetNative() != 0) {
+ Slog.e(TAG,"Can not init ethernet device layers");
+ return;
+ }
+
+ if (localLOGV) Slog.v(TAG,"Successed");
+ HandlerThread dhcpThread = new HandlerThread("DHCP Handler Thread");
+ dhcpThread.start();
+// mDhcpTarget = new DhcpHandler(dhcpThread.getLooper(), this);
+ mMonitor = new EthernetMonitor(this);
+
+ mNetworkInfo = new NetworkInfo(netType, 0, networkName, "");
+ mLinkProperties = new LinkProperties();
+ mLinkCapabilities = new LinkCapabilities();
+
+ mNetworkInfo.setIsAvailable(false);
+ setTeardownRequested(false);
+
+ }
+
+ public void setTeardownRequested(boolean isRequested) {
+ mTeardownRequested.set(isRequested);
+ }
+
+ public void captivePortalCheckComplete() {
+ }
+
+ public boolean isTeardownRequested() {
+ return mTeardownRequested.get();
+ }
+
+ public void startMonitoring(Context context, Handler target) {
+ mCsHandler = target;
+ mContext = context;
+
+ if (localLOGV) Slog.v(TAG,"start to monitor the ethernet devices");
+ mEthernetManager = (EthernetManager) mContext.getSystemService(Context.ETHERNET_SERVICE);
+
+ int state = mEthernetManager.getState();
+ if (state != mEthernetManager.ETHERNET_STATE_DISABLED) {
+ if (state == mEthernetManager.ETHERNET_STATE_UNKNOWN) {
+ // maybe this is the first time we run, enable it if ethernet devices exist
+ mEthernetManager.setEnabled(mEthernetManager.getDeviceNameList() != null);
+ } else {
+ try {
+ resetInterface();
+ } catch (UnknownHostException e) {
+ Slog.e(TAG, "Wrong ethernet configuration");
+ }
+ }
+ }
+ IntentFilter filter = new IntentFilter();
+ filter.addAction(EthernetManager.NETWORK_STATE_CHANGED_ACTION);
+ }
+
+ /**
+ * Disable connectivity to a network
+ * TODO: do away with return value after making MobileDataStateTracker async
+ */
+ public boolean teardown() {
+ mTeardownRequested.set(true);
+ mEthernetManager.stopEthernet();
+ return true;
+ }
+
+ /**
+ * Re-enable connectivity to a network after a {@link #teardown()}.
+ */
+ public boolean reconnect() {
+ mTeardownRequested.set(false);
+ mEthernetManager.startEthernet();
+ return true;
+ }
+
+
+ /**
+ * Stop etherent interface
+ * @param suspend {@code false} disable the interface {@code true} only reset the connection without disable the interface
+ * @return true
+ */
+ public boolean stopInterface(boolean suspend) {
+ if (mEthernetManager != null) {
+ EthernetDevInfo info = mEthernetManager.getSavedConfig();
+ if (info != null && mEthernetManager.isConfigured()) {
+/* synchronized (mDhcpTarget) {
+ mInterfaceStopped = true;
+ if (localLOGV) Slog.i(TAG, "stop dhcp and interface");
+ mDhcpTarget.removeMessages(EVENT_DHCP_START);
+ String ifname = info.getIfName();
+
+ if (!NetworkUtils.stopDhcp(ifname)) {
+ if (localLOGV) Slog.w(TAG, "Could not stop DHCP");
+ }
+ NetworkUtils.resetConnections(ifname, NetworkUtils.RESET_ALL_ADDRESSES);
+ if (!suspend)
+ NetworkUtils.disableInterface(ifname);
+ }
+*/
+ }
+ }
+ return true;
+ }
+
+ private boolean configureInterface(EthernetDevInfo info) throws UnknownHostException {
+
+ mStackConnected = false;
+ mHWConnected = false;
+ mInterfaceStopped = false;
+ mStartingDhcp = true;
+
+ DhcpInfoInternal mDhcpInfoInternal = new DhcpInfoInternal();
+ LinkProperties linkProperties = getLinkProperties();
+
+ if (info.getConnectMode().equals(EthernetDevInfo.ETHERNET_CONN_MODE_DHCP)) {
+ if (localLOGV) Slog.i(TAG, "trigger dhcp for device " + info.getIfName());
+ sDnsPropNames = new String[] {
+ "dhcp." + mInterfaceName + ".dns1",
+ "dhcp." + mInterfaceName + ".dns2"
+ };
+
+ mDhcpTarget.sendEmptyMessage(EVENT_DHCP_START);
+ } else {
+ int event;
+ sDnsPropNames = new String[] {
+ "net." + mInterfaceName + ".dns1",
+ "net." + mInterfaceName + ".dns2"
+ };
+
+ if (linkProperties != null) {
+ Iterator<LinkAddress> iter = linkProperties.getLinkAddresses().iterator();
+ if (iter.hasNext()) {
+ LinkAddress linkAddress = iter.next();
+ mDhcpInfoInternal.ipAddress = linkAddress.getAddress().getHostAddress();
+ for (RouteInfo route : linkProperties.getRoutes()) {
+ mDhcpInfoInternal.addRoute(route);
+ }
+
+ mDhcpInfoInternal.prefixLength = linkAddress.getNetworkPrefixLength();
+ Iterator<InetAddress> dnsIterator = linkProperties.getDnses().iterator();
+ mDhcpInfoInternal.dns1 = dnsIterator.next().getHostAddress();
+
+ if (dnsIterator.hasNext()) {
+ mDhcpInfoInternal.dns2 = dnsIterator.next().getHostAddress();
+ }
+ }
+ }
+
+
+ if (localLOGV) Slog.i(TAG, "set ip manually " + mDhcpInfoInternal.toString());
+ NetworkUtils.resetConnections(info.getIfName(), NetworkUtils.RESET_ALL_ADDRESSES);
+
+ if (NetworkUtils.runDhcp(info.getIfName(), mDhcpInfoInternal)) {
+ event = EVENT_INTERFACE_CONFIGURATION_SUCCEEDED;
+ SystemProperties.set("net.dns1", info.getDnsAddr());
+ SystemProperties.set("net." + info.getIfName() + ".dns1", info.getDnsAddr());
+ SystemProperties.set("net." + info.getIfName() + ".dns2", "0.0.0.0");
+ if (localLOGV) Slog.v(TAG, "Static IP configuration succeeded");
+ } else {
+ event = EVENT_INTERFACE_CONFIGURATION_FAILED;
+ if (localLOGV) Slog.w(TAG, "Static IP configuration failed");
+ }
+// this.sendEmptyMessage(event);
+ }
+ return true;
+ }
+
+ /**
+ * reset ethernet interface
+ * @return true
+ * @throws UnknownHostException
+ */
+ public boolean resetInterface() throws UnknownHostException{
+ /*
+ * This will guide us to enabled the enabled device
+ */
+ if (mEthernetManager != null) {
+ EthernetDevInfo info = mEthernetManager.getSavedConfig();
+ if (info != null && mEthernetManager.isConfigured()) {
+ synchronized (this) {
+ mInterfaceName = info.getIfName();
+ if (localLOGV) Slog.i(TAG, "reset device " + mInterfaceName);
+ NetworkUtils.resetConnections(mInterfaceName, NetworkUtils.RESET_ALL_ADDRESSES);
+ // Stop DHCP
+// if (mDhcpTarget != null) {
+// mDhcpTarget.removeMessages(EVENT_DHCP_START);
+// }
+ if (!NetworkUtils.stopDhcp(mInterfaceName)) {
+ if (localLOGV) Slog.w(TAG, "Could not stop DHCP");
+ }
+ configureInterface(info);
+ }
+ }
+ }
+ return true;
+ }
+
+ public void StartPolling() {
+ mMonitor.startMonitoring();
+ }
+
+ public synchronized boolean isAvailable() {
+ // Only say available if we have interfaces and user did not disable us.
+ return ((mEthernetManager.getTotalInterface() != 0) && (mEthernetManager.getState() != EthernetManager.ETHERNET_STATE_DISABLED));
+ }
+
+// @Override
+ public void setUserDataEnable(boolean enabled) {
+ Slog.w(TAG, "ignoring setUserDataEnable(" + enabled + ")");
+ }
+
+// @Override
+ public void setPolicyDataEnable(boolean enabled) {
+ Slog.w(TAG, "ignoring setPolicyDataEnable(" + enabled + ")");
+ }
+
+/* @Override
+ public boolean reconnect() {
+ try {
+ synchronized (this) {
+ if (mHWConnected && mStackConnected)
+ return true;
+ }
+ if (mEthernetManager.getState() != EthernetManager.ETHERNET_STATE_DISABLED) {
+ // maybe this is the first time we run, so set it to enabled
+ mEthernetManager.setEnabled(true);
+ if (!mEthernetManager.isConfigured()) {
+ mEthernetManager.setDefaultConf();
+ }
+ return resetInterface();
+ }
+ } catch (UnknownHostException e) {
+ e.printStackTrace();
+ }
+ return false;
+
+ }
+*/
+// @Override
+ public boolean setRadio(boolean turnOn) {
+ return false;
+ }
+
+/*
+ public boolean teardown() {
+ return (mEthernetManager != null) ? stopInterface(false) : false;
+ }
+*/
+ private void postNotification(int event) {
+ String ns = Context.NOTIFICATION_SERVICE;
+ Intent intent = new Intent(EthernetManager.ETHERNET_STATE_CHANGED_ACTION);
+ intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
+ intent.putExtra(EthernetManager.EXTRA_ETHERNET_STATE, event);
+ mContext.sendStickyBroadcast(intent);
+ }
+
+ private void setState(boolean state, int event) {
+ if (mNetworkInfo.isConnected() != state) {
+ if (state) {
+ mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, null);
+ } else {
+ mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, null);
+ mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null, null);
+ stopInterface(true);
+ }
+ mNetworkInfo.setIsAvailable(state);
+ postNotification(event);
+ }
+ }
+
+ public void handleMessage(Message msg) {
+
+ synchronized (this) {
+ switch (msg.what) {
+ case EVENT_INTERFACE_CONFIGURATION_SUCCEEDED:
+ if (localLOGV) Slog.i(TAG, "received configured succeeded, stack=" + mStackConnected + " HW=" + mHWConnected);
+ mStackConnected = true;
+ if (mHWConnected)
+ setState(true, msg.what);
+ break;
+ case EVENT_INTERFACE_CONFIGURATION_FAILED:
+ mStackConnected = false;
+ //start to retry ?
+ break;
+ case EVENT_HW_CONNECTED:
+ if (localLOGV) Slog.i(TAG, "received HW connected, stack=" + mStackConnected + " HW=" + mHWConnected);
+ mHWConnected = true;
+ if (mStackConnected)
+ setState(true, msg.what);
+ break;
+ case EVENT_HW_DISCONNECTED:
+ if (localLOGV) Slog.i(TAG, "received disconnected events, stack=" + mStackConnected + " HW=" + mHWConnected);
+ setState(mHWConnected = false, msg.what);
+ break;
+ case EVENT_HW_PHYCONNECTED:
+ if (localLOGV) Slog.i(TAG, "interface up event, kick off connection request");
+ if (!mStartingDhcp) {
+ int state = mEthernetManager.getState();
+ if (state != mEthernetManager.ETHERNET_STATE_DISABLED) {
+ EthernetDevInfo info = mEthernetManager.getSavedConfig();
+ if (info != null && mEthernetManager.isConfigured()) {
+ try {
+ configureInterface(info);
+ } catch (UnknownHostException e) {
+ // TODO Auto-generated catch block
+ //e.printStackTrace();
+ Slog.e(TAG, "Cannot configure interface");
+ }
+ }
+ }
+ }
+ break;
+ }
+ }
+ }
+
+ private class DhcpHandler extends Handler {
+ public DhcpHandler(Looper looper, Handler target) {
+ super(looper);
+ mTrackerTarget = target;
+ }
+
+ public void handleMessage(Message msg) {
+ int event;
+
+ switch (msg.what) {
+ case EVENT_DHCP_START:
+ if (!mInterfaceStopped) {
+ if (localLOGV) Slog.d(TAG, "DhcpHandler: DHCP request started");
+
+ DhcpInfoInternal dhcpInfoInternal = new DhcpInfoInternal();
+ if (NetworkUtils.runDhcp(mInterfaceName, dhcpInfoInternal)) {
+ event = EVENT_INTERFACE_CONFIGURATION_SUCCEEDED;
+ if (localLOGV) Slog.d(TAG, "DhcpHandler: DHCP request succeeded: " + mDhcpInfoInternal.toString());
+ } else {
+ event = EVENT_INTERFACE_CONFIGURATION_FAILED;
+ Slog.e(TAG, "DhcpHandler: DHCP request failed: " + NetworkUtils.getDhcpError());
+ }
+ } else {
+ mInterfaceStopped = false;
+ }
+ mStartingDhcp = false;
+ break;
+ }
+ }
+ }
+
+ public void notifyPhyConnected(String ifname) {
+ if (localLOGV) Slog.v(TAG, "report interface is up for " + ifname);
+ synchronized(this) {
+// this.sendEmptyMessage(EVENT_HW_PHYCONNECTED);
+ }
+
+ }
+
+ public void notifyStateChange(String ifname,DetailedState state) {
+ if (localLOGV) Slog.i(TAG, "report new state " + state.toString() + " on dev " + ifname);
+ if (ifname.equals(mInterfaceName)) {
+ if (localLOGV) Slog.v(TAG, "update network state tracker");
+ synchronized(this) {
+ // this.sendEmptyMessage(state.equals(DetailedState.CONNECTED, null, null)
+ // ? EVENT_HW_CONNECTED : EVENT_HW_DISCONNECTED);
+
+ }
+ }
+ }
+
+
+ private static int lookupHost(String hostname) {
+ InetAddress inetAddress;
+ try {
+ inetAddress = InetAddress.getByName(hostname);
+ } catch (UnknownHostException e) {
+ return -1;
+ }
+ byte[] addrBytes;
+ int addr;
+ addrBytes = inetAddress.getAddress();
+ addr = ((addrBytes[3] & 0xff) << 24)
+ | ((addrBytes[2] & 0xff) << 16)
+ | ((addrBytes[1] & 0xff) << 8)
+ | (addrBytes[0] & 0xff);
+ return addr;
+ }
+
+ public void setDependencyMet(boolean met) {
+ // not supported on this network
+ }
+
+ /**
+ * Check if private DNS route is set for the network
+ */
+ public boolean isPrivateDnsRouteSet() {
+ return mPrivateDnsRouteSet.get();
+ }
+
+ /**
+ * Set a flag indicating private DNS route is set
+ */
+ public void privateDnsRouteSet(boolean enabled) {
+ mPrivateDnsRouteSet.set(enabled);
+ }
+
+ /**
+ * Fetch NetworkInfo for the network
+ */
+ public NetworkInfo getNetworkInfo() {
+ return new NetworkInfo(mNetworkInfo);
+ }
+
+ /**
+ * Fetch LinkProperties for the network
+ */
+ public LinkProperties getLinkProperties() {
+ return new LinkProperties(mLinkProperties);
+ }
+
+ /**
+ * A capability is an Integer/String pair, the capabilities
+ * are defined in the class LinkSocket#Key.
+ *
+ * @return a copy of this connections capabilities, may be empty but never null.
+ */
+ public LinkCapabilities getLinkCapabilities() {
+ return new LinkCapabilities(mLinkCapabilities);
+ }
+
+ /**
+ * Check if default route is set
+ */
+ public boolean isDefaultRouteSet() {
+ return mDefaultRouteSet.get();
+ }
+
+ /**
+ * Set a flag indicating default route is set for the network
+ */
+ public void defaultRouteSet(boolean enabled) {
+ mDefaultRouteSet.set(enabled);
+ }
+
+ /**
+ * Return the system properties name associated with the tcp buffer sizes
+ * for this network.
+ */
+ public String getTcpBufferSizesPropName() {
+ return "net.tcp.buffersize.default";
+ }
+
+}
diff --git a/ethernet/java/android/net/ethernet/IEthernetManager.aidl b/ethernet/java/android/net/ethernet/IEthernetManager.aidl
new file mode 100644
index 000000000000..df81e636c40a
--- /dev/null
+++ b/ethernet/java/android/net/ethernet/IEthernetManager.aidl
@@ -0,0 +1,33 @@
+/**
+ * Copyright (c) 2010, The Android-x86 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.ethernet;
+import android.net.ethernet.EthernetDevInfo;
+
+interface IEthernetManager
+{
+ String[] getDeviceNameList();
+ void setState(int state);
+ int getState( );
+ void updateDevInfo(in EthernetDevInfo info);
+ boolean isConfigured();
+ EthernetDevInfo getSavedConfig();
+ int getTotalInterface();
+ void setMode(String mode);
+ void reconnect();
+ void startEthernet();
+ void stopEthernet();
+}
diff --git a/packages/SystemUI/res/drawable-hdpi/connect_creating.png b/packages/SystemUI/res/drawable-hdpi/connect_creating.png
new file mode 100644
index 000000000000..a70572ccb3fb
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/connect_creating.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/connect_established.png b/packages/SystemUI/res/drawable-hdpi/connect_established.png
new file mode 100644
index 000000000000..cd8c435ab140
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/connect_established.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/connect_no.png b/packages/SystemUI/res/drawable-hdpi/connect_no.png
new file mode 100644
index 000000000000..ea63cdd589b1
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/connect_no.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/connect_creating.png b/packages/SystemUI/res/drawable-mdpi/connect_creating.png
new file mode 100644
index 000000000000..cb507da3f119
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/connect_creating.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/connect_established.png b/packages/SystemUI/res/drawable-mdpi/connect_established.png
new file mode 100644
index 000000000000..6c511cbfb01f
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/connect_established.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/connect_no.png b/packages/SystemUI/res/drawable-mdpi/connect_no.png
new file mode 100644
index 000000000000..6f56da11d07c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/connect_no.png
Binary files differ
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
index bbb90c8aa9d1..b578f9f18efc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
@@ -27,6 +27,8 @@ import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.net.wimax.WimaxManagerConstants;
+import android.net.ethernet.EthernetManager;
+import android.net.ethernet.EthernetStateTracker;
import android.os.Binder;
import android.os.Handler;
import android.os.Message;
@@ -92,6 +94,7 @@ public class NetworkController extends BroadcastReceiver {
String mContentDescriptionPhoneSignal;
String mContentDescriptionWifi;
+ String mContentDescriptionEthernet;
String mContentDescriptionWimax;
String mContentDescriptionCombinedSignal;
String mContentDescriptionDataType;
@@ -122,6 +125,16 @@ public class NetworkController extends BroadcastReceiver {
private int mWimaxState = 0;
private int mWimaxExtraState = 0;
+ // 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
+ };
+
// data connectivity (regardless of state, can we access the internet?)
// state of inet connection - 0 not connected, 100 connected
private boolean mConnected = false;
@@ -231,6 +244,7 @@ public class NetworkController extends BroadcastReceiver {
filter.addAction(WifiManager.RSSI_CHANGED_ACTION);
filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
+ filter.addAction(EthernetManager.ETHERNET_STATE_CHANGED_ACTION);
filter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
filter.addAction(TelephonyIntents.SPN_STRINGS_UPDATED_ACTION);
filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
@@ -407,6 +421,9 @@ public class NetworkController extends BroadcastReceiver {
action.equals(WimaxManagerConstants.WIMAX_NETWORK_STATE_CHANGED_ACTION)) {
updateWimaxState(intent);
refreshViews();
+ } else if (action.equals(EthernetManager.ETHERNET_STATE_CHANGED_ACTION)) {
+ updateEth(intent);
+ refreshViews();
}
}
@@ -885,6 +902,14 @@ public class NetworkController extends BroadcastReceiver {
}
}
+ private void updateEthernetIcons() {
+ if (mEthernetConnected) {
+ mEthernetIconId = sEthImages[0];
+ } else {
+ mEthernetIconId = sEthImages[1];
+ }
+ }
+
private String huntForSsid(WifiInfo info) {
String ssid = info.getSSID();
if (ssid != null) {
@@ -1094,6 +1119,21 @@ public class NetworkController extends BroadcastReceiver {
}
}
+ if (mEthernetConnected) {
+ switch (mEthernetActivity) {
+ case EthernetStateTracker.EVENT_HW_CONNECTED:
+ case EthernetStateTracker.EVENT_INTERFACE_CONFIGURATION_SUCCEEDED:
+ mEthernetIconId = sEthImages[0];
+ break;
+ case EthernetStateTracker.EVENT_HW_DISCONNECTED:
+ case EthernetStateTracker.EVENT_INTERFACE_CONFIGURATION_FAILED:
+ mEthernetIconId = sEthImages[1];
+ return;
+ default:
+ mEthernetIconId = sEthImages[2];
+ }
+ }
+
if (mBluetoothTethered) {
combinedLabel = mContext.getString(R.string.bluetooth_tethered);
combinedSignalIconId = mBluetoothTetherIconId;
@@ -1354,6 +1394,22 @@ public class NetworkController extends BroadcastReceiver {
}
}
+ 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:
+ case EthernetStateTracker.EVENT_INTERFACE_CONFIGURATION_SUCCEEDED:
+ mEthernetIconId = sEthImages[0];
+ break;
+ case EthernetStateTracker.EVENT_HW_DISCONNECTED:
+ case EthernetStateTracker.EVENT_INTERFACE_CONFIGURATION_FAILED:
+ mEthernetIconId = sEthImages[1];
+ return;
+ default:
+ mEthernetIconId = sEthImages[2];
+ }
+ }
+
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
pw.println("NetworkController state:");
pw.println(String.format(" %s network type %d (%s)",
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java
index ad1dfb279961..f687c6aabe49 100644
--- a/services/java/com/android/server/ConnectivityService.java
+++ b/services/java/com/android/server/ConnectivityService.java
@@ -67,6 +67,7 @@ import android.net.Proxy;
import android.net.ProxyProperties;
import android.net.RouteInfo;
import android.net.wifi.WifiStateTracker;
+import android.net.ethernet.EthernetStateTracker;
import android.net.wimax.WimaxManagerConstants;
import android.os.Binder;
import android.os.FileUtils;
@@ -449,7 +450,7 @@ public class ConnectivityService extends IConnectivityManager.Stub {
n.type);
continue;
}
- if (mRadioAttributes[n.radio] == null) {
+ 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;
@@ -584,7 +585,7 @@ public class ConnectivityService extends IConnectivityManager.Stub {
case TYPE_WIMAX:
return makeWimaxStateTracker(mContext, mTrackerHandler);
case TYPE_ETHERNET:
- return EthernetDataTracker.getInstance();
+ return new EthernetStateTracker(targetNetworkType, config.name); //EthernetDataTracker.getInstance();
default:
throw new IllegalArgumentException(
"Trying to create a NetworkStateTracker for an unknown radio type: "
diff --git a/services/java/com/android/server/EthernetService.java b/services/java/com/android/server/EthernetService.java
new file mode 100644
index 000000000000..5ab66cde1ed5
--- /dev/null
+++ b/services/java/com/android/server/EthernetService.java
@@ -0,0 +1,241 @@
+/*
+ * Copyright (C) 2010 The Android-x86 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.
+ *
+ * Author: Yi Sun <beyounn@gmail.com>
+ */
+
+package com.android.server;
+
+import java.net.UnknownHostException;
+import android.net.ethernet.EthernetNative;
+import android.net.ethernet.IEthernetManager;
+import android.net.ethernet.EthernetManager;
+import android.net.ethernet.EthernetStateTracker;
+import android.net.ethernet.EthernetDevInfo;
+import android.net.ethernet.EthernetStateMachine;
+import android.provider.Settings;
+import android.util.Slog;
+import android.content.BroadcastReceiver;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.SystemProperties;
+
+/**
+ * EthernetService handles remote Ethernet operation requests by implementing
+ * the IEthernetManager interface. It also creates a EtherentMonitor to listen
+ * for Etherent-related events.
+ *
+ * @hide
+ */
+public class EthernetService<syncronized> extends IEthernetManager.Stub {
+ private static final String TAG = "EthernetService";
+ private static final int ETHERNET_HAS_CONFIG = 1;
+ private static final boolean localLOGV = true;
+
+ private final EthernetStateMachine mEthernetStateMachine;
+
+ private int mEthState= EthernetManager.ETHERNET_STATE_UNKNOWN;
+ private Context mContext;
+ private String[] DevName;
+ private int isEnabled ;
+ private String mInterfaceName;
+
+ public EthernetService(Context context) {
+ mContext = context;
+ mInterfaceName = SystemProperties.get("ethernet.interface", "eth0");
+ mEthernetStateMachine = new EthernetStateMachine(mContext, mInterfaceName);
+ }
+
+ /**
+ * Check if Wi-Fi needs to be enabled and start
+ * if needed
+ *
+ * This function is used only at boot time
+ */
+ public void checkAndStartEthernet() {
+ isEnabled = getPersistedState();
+ if (localLOGV == true) Slog.i(TAG, "Ethernet dev enabled " + isEnabled);
+ getDeviceNameList();
+ setState(isEnabled);
+
+ mEthernetStateMachine.startMonitoring(mContext);
+
+ }
+
+
+ /**
+ * check if the ethernet service has been configured.
+ * @return {@code true} if configured {@code false} otherwise
+ */
+ public boolean isConfigured() {
+ final ContentResolver cr = mContext.getContentResolver();
+ return (Settings.Secure.getInt(cr, Settings.Secure.ETHERNET_CONF, 0) == ETHERNET_HAS_CONFIG);
+
+ }
+
+ /**
+ * Return the saved ethernet configuration
+ * @return ethernet interface configuration on success, {@code null} on failure
+ */
+ public synchronized EthernetDevInfo getSavedConfig() {
+ if (!isConfigured())
+ return null;
+
+ final ContentResolver cr = mContext.getContentResolver();
+ EthernetDevInfo info = new EthernetDevInfo();
+ info.setConnectMode(Settings.Secure.getString(cr, Settings.Secure.ETHERNET_MODE));
+ info.setIfName(Settings.Secure.getString(cr, Settings.Secure.ETHERNET_IFNAME));
+ info.setIpAddress(Settings.Secure.getString(cr, Settings.Secure.ETHERNET_IP));
+ info.setDnsAddr(Settings.Secure.getString(cr, Settings.Secure.ETHERNET_DNS));
+ info.setNetMask(Settings.Secure.getString(cr, Settings.Secure.ETHERNET_MASK));
+ info.setRouteAddr(Settings.Secure.getString(cr, Settings.Secure.ETHERNET_ROUTE));
+
+ return info;
+ }
+
+ /**
+ * Set the ethernet interface configuration mode
+ * @param mode {@code ETHERNET_CONN_MODE_DHCP} for dhcp {@code ETHERNET_CONN_MODE_MANUAL} for manual configure
+ */
+ public synchronized void setMode(String mode) {
+ final ContentResolver cr = mContext.getContentResolver();
+ if (DevName != null) {
+ Settings.Secure.putString(cr, Settings.Secure.ETHERNET_IFNAME, DevName[0]);
+ Settings.Secure.putInt(cr, Settings.Secure.ETHERNET_CONF, 1);
+ Settings.Secure.putString(cr, Settings.Secure.ETHERNET_MODE, mode);
+ }
+ }
+
+ /**
+ * update a ethernet interface information
+ * @param info the interface infomation
+ */
+ public synchronized void updateDevInfo(EthernetDevInfo info) {
+ final ContentResolver cr = mContext.getContentResolver();
+ Settings.Secure.putInt(cr, Settings.Secure.ETHERNET_CONF, 1);
+ Settings.Secure.putString(cr, Settings.Secure.ETHERNET_IFNAME, info.getIfName());
+ Settings.Secure.putString(cr, Settings.Secure.ETHERNET_IP, info.getIpAddress());
+ Settings.Secure.putString(cr, Settings.Secure.ETHERNET_MODE, info.getConnectMode());
+ Settings.Secure.putString(cr, Settings.Secure.ETHERNET_DNS, info.getDnsAddr());
+ Settings.Secure.putString(cr, Settings.Secure.ETHERNET_ROUTE, info.getRouteAddr());
+ Settings.Secure.putString(cr, Settings.Secure.ETHERNET_MASK, info.getNetMask());
+ if (mEthState == EthernetManager.ETHERNET_STATE_ENABLED) {
+ try {
+ mEthernetStateMachine.resetInterface();
+ } catch (UnknownHostException e) {
+ Slog.e(TAG, "Wrong ethernet configuration");
+ }
+ }
+ }
+
+ /**
+ * get the number of ethernet interfaces in the system
+ * @return the number of ethernet interfaces
+ */
+ public int getTotalInterface() {
+ return EthernetNative.getInterfaceCnt();
+ }
+
+
+ private int scanDevice() {
+ int i, j;
+ if ((i = EthernetNative.getInterfaceCnt()) == 0)
+ return 0;
+
+ DevName = new String[i];
+
+ for (j = 0; j < i; j++) {
+ DevName[j] = EthernetNative.getInterfaceName(j);
+ if (DevName[j] == null)
+ break;
+ if (localLOGV) Slog.v(TAG, "device " + j + " name " + DevName[j]);
+ }
+
+ return i;
+ }
+
+ /**
+ * get all the ethernet device names
+ * @return interface name list on success, {@code null} on failure
+ */
+ public String[] getDeviceNameList() {
+ return (scanDevice() > 0) ? DevName : null;
+ }
+
+ private int getPersistedState() {
+ final ContentResolver cr = mContext.getContentResolver();
+ try {
+ return Settings.Secure.getInt(cr, Settings.Secure.ETHERNET_ON);
+ } catch (Settings.SettingNotFoundException e) {
+ return EthernetManager.ETHERNET_STATE_UNKNOWN;
+ }
+ }
+
+ private synchronized void persistEnabled(boolean enabled) {
+ final ContentResolver cr = mContext.getContentResolver();
+ Settings.Secure.putInt(cr, Settings.Secure.ETHERNET_ON, enabled ? EthernetManager.ETHERNET_STATE_ENABLED : EthernetManager.ETHERNET_STATE_DISABLED);
+ }
+
+ /**
+ * Enable or Disable a ethernet service
+ * @param enable {@code true} to enable, {@code false} to disable
+ */
+ public synchronized void setState(int state) {
+
+ if (mEthState != state) {
+ mEthState = state;
+ if (state == EthernetManager.ETHERNET_STATE_DISABLED) {
+ Slog.e(TAG, "EthernetManager.ETHERNET_STATE_DISABLED");
+ persistEnabled(false);
+ mEthernetStateMachine.stopInterface(false);
+ } else {
+ Slog.e(TAG, "EthernetManager.ETHERNET_STATE_ENABLED");
+ persistEnabled(true);
+ if (!isConfigured()) {
+ // If user did not configure any interfaces yet, pick the first one
+ // and enable it.
+ setMode(EthernetDevInfo.ETHERNET_CONN_MODE_DHCP);
+ }
+ try {
+ mEthernetStateMachine.resetInterface();
+ } catch (UnknownHostException e) {
+ Slog.e(TAG, "Wrong ethernet configuration");
+ }
+ }
+ }
+ }
+
+ public void reconnect() {
+ mEthernetStateMachine.reconnectCommand();
+ }
+
+ /**
+ * Get ethernet service state
+ * @return the state of the ethernet service
+ */
+ public int getState( ) {
+ return mEthState;
+ }
+
+
+ public void startEthernet() {
+ }
+
+ public void stopEthernet() {
+ }
+
+}
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 894c4d02e794..c42b54775578 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -30,6 +30,8 @@ import android.media.AudioService;
import android.net.wifi.p2p.WifiP2pService;
import android.os.Handler;
import android.os.HandlerThread;
+import android.net.ethernet.EthernetManager;
+import android.net.ethernet.EthernetStateTracker;
import android.os.Looper;
import android.os.RemoteException;
import android.os.SchedulingPolicyService;
@@ -136,6 +138,7 @@ class ServerThread extends Thread {
ConnectivityService connectivity = null;
WifiP2pService wifiP2p = null;
WifiService wifi = null;
+ EthernetService ethernet = null;
NsdService serviceDiscovery= null;
IPackageManager pm = null;
Context context = null;
@@ -490,6 +493,14 @@ class ServerThread extends Thread {
reportWtf("starting Wi-Fi Service", e);
}
+ try {
+ Slog.i(TAG, "Ethernet Service");
+ ethernet = new EthernetService(context);
+ ServiceManager.addService(Context.ETHERNET_SERVICE, ethernet);
+ } catch (Throwable e) {
+ reportWtf("starting Ethernt Service", e);
+ }
+
try {
Slog.i(TAG, "Connectivity Service");
connectivity = new ConnectivityService(
@@ -499,6 +510,7 @@ class ServerThread extends Thread {
networkPolicy.bindConnectivityManager(connectivity);
wifi.checkAndStartWifi();
wifiP2p.connectivityServiceReady();
+ ethernet.checkAndStartEthernet();
} catch (Throwable e) {
reportWtf("starting Connectivity Service", e);
}