summaryrefslogtreecommitdiff
authorZhiwei Gong <zhiwei.gong@amlogic.com>2015-01-16 08:46:43 (GMT)
committer zhiwei.gong <zhiwei.gong@amlogic.com>2015-01-19 02:04:07 (GMT)
commit7abd6089b536b9422e647fe9a13526de72497912 (patch)
tree7277b8086206579cb28ebda5bd03ab388371d18c
parent2978d264b0115244dd46de3ca93c00bce6befc7f (diff)
downloadpppoe-7abd6089b536b9422e647fe9a13526de72497912.zip
pppoe-7abd6089b536b9422e647fe9a13526de72497912.tar.gz
pppoe-7abd6089b536b9422e647fe9a13526de72497912.tar.bz2
add pppoe support
Change-Id: I9b48039d6b6a317010059119be48ce44f3e0a951
Diffstat
-rw-r--r--java/Android.mk24
-rw-r--r--java/src/com/droidlogic/pppoe/DhcpInfoInternal.java173
-rw-r--r--java/src/com/droidlogic/pppoe/IPppoeManager.java365
-rw-r--r--java/src/com/droidlogic/pppoe/PppoeDevInfo.java109
-rw-r--r--java/src/com/droidlogic/pppoe/PppoeManager.java137
-rw-r--r--java/src/com/droidlogic/pppoe/PppoeMonitor.java119
-rw-r--r--java/src/com/droidlogic/pppoe/PppoeNative.java21
-rw-r--r--java/src/com/droidlogic/pppoe/PppoeService.java274
-rw-r--r--java/src/com/droidlogic/pppoe/PppoeStateTracker.java615
-rw-r--r--java/src/com/droidlogic/pppoe/package.html3
-rw-r--r--jni/Android.mk19
-rw-r--r--jni/com_droidlogic_common.cpp551
-rw-r--r--jni/com_droidlogic_common.h64
-rw-r--r--jni/com_droidlogic_pppoe.cpp302
14 files changed, 2776 insertions, 0 deletions
diff --git a/java/Android.mk b/java/Android.mk
new file mode 100644
index 0000000..dbd7cc0
--- a/dev/null
+++ b/java/Android.mk
@@ -0,0 +1,24 @@
+# Copyright (C) 2014 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.
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := droidlogic.frameworks.pppoe
+
+LOCAL_SRC_FILES := $(call all-java-files-under,src)
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_JAVA_LIBRARY)
+
diff --git a/java/src/com/droidlogic/pppoe/DhcpInfoInternal.java b/java/src/com/droidlogic/pppoe/DhcpInfoInternal.java
new file mode 100644
index 0000000..eecaadd
--- a/dev/null
+++ b/java/src/com/droidlogic/pppoe/DhcpInfoInternal.java
@@ -0,0 +1,173 @@
+/*
+ * 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 com.droidlogic.pppoe;
+
+
+
+import android.text.TextUtils;
+import android.util.Log;
+import android.net.RouteInfo;
+import android.net.DhcpInfo;
+import android.net.LinkAddress;
+import android.net.LinkProperties;
+import android.net.NetworkUtils;
+
+import java.net.Inet4Address;
+import java.net.InetAddress;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+
+/**
+ * A simple object for retrieving the results of a DHCP request.
+ * Replaces (internally) the IPv4-only DhcpInfo class.
+ * @hide
+ */
+public class DhcpInfoInternal {
+ private final static String TAG = "DhcpInfoInternal";
+ public String ipAddress;
+ public int prefixLength;
+
+ public String dns1;
+ public String dns2;
+
+ public String serverAddress;
+ public int leaseDuration;
+
+ /**
+ * Vendor specific information (from RFC 2132).
+ */
+ public String vendorInfo;
+
+ private Collection<RouteInfo> mRoutes;
+
+ public DhcpInfoInternal() {
+ mRoutes = new ArrayList<RouteInfo>();
+ }
+
+ public void addRoute(RouteInfo routeInfo) {
+ mRoutes.add(routeInfo);
+ }
+
+ public Collection<RouteInfo> getRoutes() {
+ return Collections.unmodifiableCollection(mRoutes);
+ }
+
+ private int convertToInt(String addr) {
+ if (addr != null) {
+ try {
+ InetAddress inetAddress = NetworkUtils.numericToInetAddress(addr);
+ if (inetAddress instanceof Inet4Address) {
+ return NetworkUtils.inetAddressToInt((Inet4Address)inetAddress);
+ }
+ } catch (IllegalArgumentException e) {}
+ }
+ return 0;
+ }
+
+ public DhcpInfo makeDhcpInfo() {
+ DhcpInfo info = new DhcpInfo();
+ info.ipAddress = convertToInt(ipAddress);
+ for (RouteInfo route : mRoutes) {
+ if (route.isDefaultRoute()) {
+ info.gateway = convertToInt(route.getGateway().getHostAddress());
+ break;
+ }
+ }
+ try {
+ InetAddress inetAddress = NetworkUtils.numericToInetAddress(ipAddress);
+ info.netmask = NetworkUtils.prefixLengthToNetmaskInt(prefixLength);
+ } catch (IllegalArgumentException e) {}
+ info.dns1 = convertToInt(dns1);
+ info.dns2 = convertToInt(dns2);
+ info.serverAddress = convertToInt(serverAddress);
+ info.leaseDuration = leaseDuration;
+ return info;
+ }
+
+ public LinkAddress makeLinkAddress() {
+ if (TextUtils.isEmpty(ipAddress)) {
+ Log.e(TAG, "makeLinkAddress with empty ipAddress");
+ return null;
+ }
+ return new LinkAddress(NetworkUtils.numericToInetAddress(ipAddress), prefixLength);
+ }
+
+ public LinkProperties makeLinkProperties() {
+ LinkProperties p = new LinkProperties();
+ p.addLinkAddress(makeLinkAddress());
+ for (RouteInfo route : mRoutes) {
+ p.addRoute(route);
+ }
+ //if empty, connectivity configures default DNS
+ if (TextUtils.isEmpty(dns1) == false) {
+ p.addDnsServer(NetworkUtils.numericToInetAddress(dns1));
+ } else {
+ Log.d(TAG, "makeLinkProperties with empty dns1!");
+ }
+ if (TextUtils.isEmpty(dns2) == false) {
+ p.addDnsServer(NetworkUtils.numericToInetAddress(dns2));
+ } else {
+ Log.d(TAG, "makeLinkProperties with empty dns2!");
+ }
+ return p;
+ }
+
+ /* Updates the DHCP fields that need to be retained from
+ * original DHCP request if the DHCP renewal shows them as
+ * being empty
+ */
+ public void updateFromDhcpRequest(DhcpInfoInternal orig) {
+ if (orig == null) return;
+
+ if (TextUtils.isEmpty(dns1)) {
+ dns1 = orig.dns1;
+ }
+
+ if (TextUtils.isEmpty(dns2)) {
+ dns2 = orig.dns2;
+ }
+
+ if (mRoutes.size() == 0) {
+ for (RouteInfo route : orig.getRoutes()) {
+ addRoute(route);
+ }
+ }
+ }
+
+ /**
+ * Test if this DHCP lease includes vendor hint that network link is
+ * metered, and sensitive to heavy data transfers.
+ */
+ public boolean hasMeteredHint() {
+ if (vendorInfo != null) {
+ return vendorInfo.contains("ANDROID_METERED");
+ } else {
+ return false;
+ }
+ }
+
+ public String toString() {
+ String routeString = "";
+ for (RouteInfo route : mRoutes) routeString += route.toString() + " | ";
+ return "addr: " + ipAddress + "/" + prefixLength +
+ " mRoutes: " + routeString +
+ " dns: " + dns1 + "," + dns2 +
+ " dhcpServer: " + serverAddress +
+ " leaseDuration: " + leaseDuration;
+ }
+}
diff --git a/java/src/com/droidlogic/pppoe/IPppoeManager.java b/java/src/com/droidlogic/pppoe/IPppoeManager.java
new file mode 100644
index 0000000..5b04d04
--- a/dev/null
+++ b/java/src/com/droidlogic/pppoe/IPppoeManager.java
@@ -0,0 +1,365 @@
+/*
+ * This file is auto-generated. DO NOT MODIFY.
+ * Original file: frameworks/base/pppoe/java/android/net/pppoe/IPppoeManager.aidl
+ */
+package com.droidlogic.pppoe;
+public interface IPppoeManager extends android.os.IInterface
+{
+/** Local-side IPC implementation stub class. */
+public static abstract class Stub extends android.os.Binder implements com.droidlogic.pppoe.IPppoeManager
+{
+private static final java.lang.String DESCRIPTOR = "com.droidlogic.pppoe.IPppoeManager";
+/** Construct the stub at attach it to the interface. */
+public Stub()
+{
+this.attachInterface(this, DESCRIPTOR);
+}
+/**
+ * Cast an IBinder object into an android.net.pppoe.IPppoeManager interface,
+ * generating a proxy if needed.
+ */
+public static com.droidlogic.pppoe.IPppoeManager asInterface(android.os.IBinder obj)
+{
+if ((obj == null)) {
+return null;
+}
+android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
+if (((iin != null) && (iin instanceof com.droidlogic.pppoe.IPppoeManager))) {
+return ((com.droidlogic.pppoe.IPppoeManager)iin);
+}
+return new com.droidlogic.pppoe.IPppoeManager.Stub.Proxy(obj);
+}
+@Override public android.os.IBinder asBinder()
+{
+return this;
+}
+@Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException
+{
+switch (code)
+{
+case INTERFACE_TRANSACTION:
+{
+reply.writeString(DESCRIPTOR);
+return true;
+}
+case TRANSACTION_getDeviceNameList:
+{
+data.enforceInterface(DESCRIPTOR);
+java.lang.String[] _result = this.getDeviceNameList();
+reply.writeNoException();
+reply.writeStringArray(_result);
+return true;
+}
+case TRANSACTION_setPppoeState:
+{
+data.enforceInterface(DESCRIPTOR);
+int _arg0;
+_arg0 = data.readInt();
+this.setPppoeState(_arg0);
+reply.writeNoException();
+return true;
+}
+case TRANSACTION_getPppoeState:
+{
+data.enforceInterface(DESCRIPTOR);
+int _result = this.getPppoeState();
+reply.writeNoException();
+reply.writeInt(_result);
+return true;
+}
+case TRANSACTION_UpdatePppoeDevInfo:
+{
+data.enforceInterface(DESCRIPTOR);
+com.droidlogic.pppoe.PppoeDevInfo _arg0;
+if ((0 != data.readInt())) {
+_arg0 = com.droidlogic.pppoe.PppoeDevInfo.CREATOR.createFromParcel(data);
+}
+else {
+_arg0 = null;
+}
+this.UpdatePppoeDevInfo(_arg0);
+reply.writeNoException();
+return true;
+}
+case TRANSACTION_isPppoeConfigured:
+{
+data.enforceInterface(DESCRIPTOR);
+boolean _result = this.isPppoeConfigured();
+reply.writeNoException();
+reply.writeInt(((_result)?(1):(0)));
+return true;
+}
+case TRANSACTION_getSavedPppoeConfig:
+{
+data.enforceInterface(DESCRIPTOR);
+com.droidlogic.pppoe.PppoeDevInfo _result = this.getSavedPppoeConfig();
+reply.writeNoException();
+if ((_result != null)) {
+reply.writeInt(1);
+_result.writeToParcel(reply, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
+}
+else {
+reply.writeInt(0);
+}
+return true;
+}
+case TRANSACTION_getTotalInterface:
+{
+data.enforceInterface(DESCRIPTOR);
+int _result = this.getTotalInterface();
+reply.writeNoException();
+reply.writeInt(_result);
+return true;
+}
+case TRANSACTION_setPppoeMode:
+{
+data.enforceInterface(DESCRIPTOR);
+java.lang.String _arg0;
+_arg0 = data.readString();
+this.setPppoeMode(_arg0);
+reply.writeNoException();
+return true;
+}
+case TRANSACTION_isPppoeDeviceUp:
+{
+data.enforceInterface(DESCRIPTOR);
+boolean _result = this.isPppoeDeviceUp();
+reply.writeNoException();
+reply.writeInt(((_result)?(1):(0)));
+return true;
+}
+case TRANSACTION_getDhcpInfo:
+{
+data.enforceInterface(DESCRIPTOR);
+android.net.DhcpInfo _result = this.getDhcpInfo();
+reply.writeNoException();
+if ((_result != null)) {
+reply.writeInt(1);
+_result.writeToParcel(reply, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
+}
+else {
+reply.writeInt(0);
+}
+return true;
+}
+}
+return super.onTransact(code, data, reply, flags);
+}
+private static class Proxy implements com.droidlogic.pppoe.IPppoeManager
+{
+private android.os.IBinder mRemote;
+Proxy(android.os.IBinder remote)
+{
+mRemote = remote;
+}
+@Override public android.os.IBinder asBinder()
+{
+return mRemote;
+}
+public java.lang.String getInterfaceDescriptor()
+{
+return DESCRIPTOR;
+}
+@Override public java.lang.String[] getDeviceNameList() throws android.os.RemoteException
+{
+android.os.Parcel _data = android.os.Parcel.obtain();
+android.os.Parcel _reply = android.os.Parcel.obtain();
+java.lang.String[] _result;
+try {
+_data.writeInterfaceToken(DESCRIPTOR);
+mRemote.transact(Stub.TRANSACTION_getDeviceNameList, _data, _reply, 0);
+_reply.readException();
+_result = _reply.createStringArray();
+}
+finally {
+_reply.recycle();
+_data.recycle();
+}
+return _result;
+}
+@Override public void setPppoeState(int state) throws android.os.RemoteException
+{
+android.os.Parcel _data = android.os.Parcel.obtain();
+android.os.Parcel _reply = android.os.Parcel.obtain();
+try {
+_data.writeInterfaceToken(DESCRIPTOR);
+_data.writeInt(state);
+mRemote.transact(Stub.TRANSACTION_setPppoeState, _data, _reply, 0);
+_reply.readException();
+}
+finally {
+_reply.recycle();
+_data.recycle();
+}
+}
+@Override public int getPppoeState() throws android.os.RemoteException
+{
+android.os.Parcel _data = android.os.Parcel.obtain();
+android.os.Parcel _reply = android.os.Parcel.obtain();
+int _result;
+try {
+_data.writeInterfaceToken(DESCRIPTOR);
+mRemote.transact(Stub.TRANSACTION_getPppoeState, _data, _reply, 0);
+_reply.readException();
+_result = _reply.readInt();
+}
+finally {
+_reply.recycle();
+_data.recycle();
+}
+return _result;
+}
+@Override public void UpdatePppoeDevInfo(com.droidlogic.pppoe.PppoeDevInfo info) throws android.os.RemoteException
+{
+android.os.Parcel _data = android.os.Parcel.obtain();
+android.os.Parcel _reply = android.os.Parcel.obtain();
+try {
+_data.writeInterfaceToken(DESCRIPTOR);
+if ((info != null)) {
+_data.writeInt(1);
+info.writeToParcel(_data, 0);
+}
+else {
+_data.writeInt(0);
+}
+mRemote.transact(Stub.TRANSACTION_UpdatePppoeDevInfo, _data, _reply, 0);
+_reply.readException();
+}
+finally {
+_reply.recycle();
+_data.recycle();
+}
+}
+@Override public boolean isPppoeConfigured() throws android.os.RemoteException
+{
+android.os.Parcel _data = android.os.Parcel.obtain();
+android.os.Parcel _reply = android.os.Parcel.obtain();
+boolean _result;
+try {
+_data.writeInterfaceToken(DESCRIPTOR);
+mRemote.transact(Stub.TRANSACTION_isPppoeConfigured, _data, _reply, 0);
+_reply.readException();
+_result = (0!=_reply.readInt());
+}
+finally {
+_reply.recycle();
+_data.recycle();
+}
+return _result;
+}
+@Override public com.droidlogic.pppoe.PppoeDevInfo getSavedPppoeConfig() throws android.os.RemoteException
+{
+android.os.Parcel _data = android.os.Parcel.obtain();
+android.os.Parcel _reply = android.os.Parcel.obtain();
+com.droidlogic.pppoe.PppoeDevInfo _result;
+try {
+_data.writeInterfaceToken(DESCRIPTOR);
+mRemote.transact(Stub.TRANSACTION_getSavedPppoeConfig, _data, _reply, 0);
+_reply.readException();
+if ((0 != _reply.readInt())) {
+_result = com.droidlogic.pppoe.PppoeDevInfo.CREATOR.createFromParcel(_reply);
+}
+else {
+_result = null;
+}
+}
+finally {
+_reply.recycle();
+_data.recycle();
+}
+return _result;
+}
+@Override public int getTotalInterface() throws android.os.RemoteException
+{
+android.os.Parcel _data = android.os.Parcel.obtain();
+android.os.Parcel _reply = android.os.Parcel.obtain();
+int _result;
+try {
+_data.writeInterfaceToken(DESCRIPTOR);
+mRemote.transact(Stub.TRANSACTION_getTotalInterface, _data, _reply, 0);
+_reply.readException();
+_result = _reply.readInt();
+}
+finally {
+_reply.recycle();
+_data.recycle();
+}
+return _result;
+}
+@Override public void setPppoeMode(java.lang.String mode) throws android.os.RemoteException
+{
+android.os.Parcel _data = android.os.Parcel.obtain();
+android.os.Parcel _reply = android.os.Parcel.obtain();
+try {
+_data.writeInterfaceToken(DESCRIPTOR);
+_data.writeString(mode);
+mRemote.transact(Stub.TRANSACTION_setPppoeMode, _data, _reply, 0);
+_reply.readException();
+}
+finally {
+_reply.recycle();
+_data.recycle();
+}
+}
+@Override public boolean isPppoeDeviceUp() throws android.os.RemoteException
+{
+android.os.Parcel _data = android.os.Parcel.obtain();
+android.os.Parcel _reply = android.os.Parcel.obtain();
+boolean _result;
+try {
+_data.writeInterfaceToken(DESCRIPTOR);
+mRemote.transact(Stub.TRANSACTION_isPppoeDeviceUp, _data, _reply, 0);
+_reply.readException();
+_result = (0!=_reply.readInt());
+}
+finally {
+_reply.recycle();
+_data.recycle();
+}
+return _result;
+}
+@Override public android.net.DhcpInfo getDhcpInfo() throws android.os.RemoteException
+{
+android.os.Parcel _data = android.os.Parcel.obtain();
+android.os.Parcel _reply = android.os.Parcel.obtain();
+android.net.DhcpInfo _result;
+try {
+_data.writeInterfaceToken(DESCRIPTOR);
+mRemote.transact(Stub.TRANSACTION_getDhcpInfo, _data, _reply, 0);
+_reply.readException();
+if ((0 != _reply.readInt())) {
+_result = android.net.DhcpInfo.CREATOR.createFromParcel(_reply);
+}
+else {
+_result = null;
+}
+}
+finally {
+_reply.recycle();
+_data.recycle();
+}
+return _result;
+}
+}
+static final int TRANSACTION_getDeviceNameList = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
+static final int TRANSACTION_setPppoeState = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
+static final int TRANSACTION_getPppoeState = (android.os.IBinder.FIRST_CALL_TRANSACTION + 2);
+static final int TRANSACTION_UpdatePppoeDevInfo = (android.os.IBinder.FIRST_CALL_TRANSACTION + 3);
+static final int TRANSACTION_isPppoeConfigured = (android.os.IBinder.FIRST_CALL_TRANSACTION + 4);
+static final int TRANSACTION_getSavedPppoeConfig = (android.os.IBinder.FIRST_CALL_TRANSACTION + 5);
+static final int TRANSACTION_getTotalInterface = (android.os.IBinder.FIRST_CALL_TRANSACTION + 6);
+static final int TRANSACTION_setPppoeMode = (android.os.IBinder.FIRST_CALL_TRANSACTION + 7);
+static final int TRANSACTION_isPppoeDeviceUp = (android.os.IBinder.FIRST_CALL_TRANSACTION + 8);
+static final int TRANSACTION_getDhcpInfo = (android.os.IBinder.FIRST_CALL_TRANSACTION + 9);
+}
+public java.lang.String[] getDeviceNameList() throws android.os.RemoteException;
+public void setPppoeState(int state) throws android.os.RemoteException;
+public int getPppoeState() throws android.os.RemoteException;
+public void UpdatePppoeDevInfo(com.droidlogic.pppoe.PppoeDevInfo info) throws android.os.RemoteException;
+public boolean isPppoeConfigured() throws android.os.RemoteException;
+public com.droidlogic.pppoe.PppoeDevInfo getSavedPppoeConfig() throws android.os.RemoteException;
+public int getTotalInterface() throws android.os.RemoteException;
+public void setPppoeMode(java.lang.String mode) throws android.os.RemoteException;
+public boolean isPppoeDeviceUp() throws android.os.RemoteException;
+public android.net.DhcpInfo getDhcpInfo() throws android.os.RemoteException;
+}
diff --git a/java/src/com/droidlogic/pppoe/PppoeDevInfo.java b/java/src/com/droidlogic/pppoe/PppoeDevInfo.java
new file mode 100644
index 0000000..e70d18c
--- a/dev/null
+++ b/java/src/com/droidlogic/pppoe/PppoeDevInfo.java
@@ -0,0 +1,109 @@
+package com.droidlogic.pppoe;
+
+
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.os.Parcelable.Creator;
+
+public class PppoeDevInfo implements Parcelable {
+ private String dev_name;
+ private String ipaddr;
+ private String netmask;
+ private String route;
+ private String dns;
+ private String mode;
+ public static final String PPPOE_CONN_MODE_DHCP= "dhcp";
+ public static final String PPPOE_CONN_MODE_MANUAL = "manual";
+
+ public PppoeDevInfo () {
+ dev_name = null;
+ ipaddr = null;
+ dns = null;
+ route = null;
+ netmask = null;
+ mode = PPPOE_CONN_MODE_DHCP;
+ }
+
+ public void setIfName(String ifname) {
+ this.dev_name = ifname;
+ }
+
+ 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;
+ }
+
+ public boolean setConnectMode(String mode) {
+ if (mode.equals(PPPOE_CONN_MODE_DHCP) || mode.equals(PPPOE_CONN_MODE_MANUAL)) {
+ this.mode = mode;
+ return true;
+ }
+ return false;
+ }
+
+ public String getConnectMode() {
+ return this.mode;
+ }
+
+ public int describeContents() {
+ // TODO Auto-generated method stub
+ 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<PppoeDevInfo> CREATOR =
+ new Creator<PppoeDevInfo>() {
+ public PppoeDevInfo createFromParcel(Parcel in) {
+ PppoeDevInfo info = new PppoeDevInfo();
+ 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 PppoeDevInfo[] newArray(int size) {
+ return new PppoeDevInfo[size];
+ }
+ };
+}
diff --git a/java/src/com/droidlogic/pppoe/PppoeManager.java b/java/src/com/droidlogic/pppoe/PppoeManager.java
new file mode 100644
index 0000000..23572c6
--- a/dev/null
+++ b/java/src/com/droidlogic/pppoe/PppoeManager.java
@@ -0,0 +1,137 @@
+package com.droidlogic.pppoe;
+
+import java.util.List;
+
+import android.content.Context;
+import android.annotation.SdkConstant;
+import android.annotation.SdkConstant.SdkConstantType;
+import android.net.wifi.IWifiManager;
+import android.os.Handler;
+import android.os.RemoteException;
+import android.util.Slog;
+import android.net.DhcpInfo;
+import com.droidlogic.pppoe.PppoeDevInfo;
+import com.droidlogic.pppoe.IPppoeManager;
+import com.droidlogic.pppoe.PppoeService;
+
+public class PppoeManager {
+ public static final String TAG = "PppoeManager";
+ public static final int PPPOE_DEVICE_SCAN_RESULT_READY = 0;
+ public static final String PPPOE_STATE_CHANGED_ACTION =
+ "com.droidlogic.pppoe.PPPOE_STATE_CHANGED";
+ public static final String NETWORK_STATE_CHANGED_ACTION =
+ "com.droidlogic.pppoe.STATE_CHANGE";
+
+// public static final String ACTION_PPPOE_NETWORK = "android.net.pppoe.PPPOE_NET_CHG";
+
+
+ public static final String EXTRA_NETWORK_INFO = "networkInfo";
+ public static final String EXTRA_PPPOE_STATE = "pppoe_state";
+ public static final String EXTRA_PPPOE_ERRCODE = "pppoe_errcode";
+ public static final String PROP_VAL_PPP_NOERR = "0:0";
+ public static final String EXTRA_PREVIOUS_PPPOE_STATE = "previous_pppoe_state";
+
+ public static final int PPPOE_STATE_UNKNOWN = 0;
+ public static final int PPPOE_STATE_DISABLED = 1;
+ public static final int PPPOE_STATE_ENABLED = 2;
+
+ IPppoeManager mService;
+ private final Context mContext;
+
+
+ public PppoeManager(IPppoeManager service, Context context) {
+ Slog.i(TAG, "Init Pppoe Manager");
+ mService = service;
+ mContext = context;
+
+ }
+
+ public boolean isPppoeConfigured() {
+ try {
+ return mService.isPppoeConfigured();
+ } catch (RemoteException e) {
+ Slog.i(TAG, "Can not check pppoe config state");
+ }
+ return false;
+ }
+
+ public PppoeDevInfo getSavedPppoeConfig() {
+ try {
+ return mService.getSavedPppoeConfig();
+ } catch (RemoteException e) {
+ Slog.i(TAG, "Can not get pppoe config");
+ }
+ return null;
+ }
+
+ public void UpdatePppoeDevInfo(PppoeDevInfo info) {
+ try {
+ mService.UpdatePppoeDevInfo(info);
+ } catch (RemoteException e) {
+ Slog.i(TAG, "Can not update pppoe device info");
+ }
+ }
+
+ public String[] getDeviceNameList() {
+ try {
+ return mService.getDeviceNameList();
+ } catch (RemoteException e) {
+ return null;
+ }
+ }
+
+ public void setPppoeEnabled(boolean enable) {
+ try {
+ mService.setPppoeState(enable ? PPPOE_STATE_ENABLED:PPPOE_STATE_DISABLED);
+ } catch (RemoteException e) {
+ Slog.i(TAG,"Can not set new state");
+ }
+ }
+
+ public int getPppoeState( ) {
+ try {
+ return mService.getPppoeState();
+ } catch (RemoteException e) {
+ return 0;
+ }
+ }
+
+ public boolean pppoeConfigured() {
+ try {
+ return mService.isPppoeConfigured();
+ } catch (RemoteException e) {
+ return false;
+ }
+ }
+
+ public DhcpInfo getDhcpInfo() {
+ try {
+ return mService.getDhcpInfo();
+ } catch (RemoteException e) {
+ return null;
+ }
+ }
+
+ public int getTotalInterface() {
+ try {
+ return mService.getTotalInterface();
+ } catch (RemoteException e) {
+ return 0;
+ }
+ }
+
+ public void pppoeSetDefaultConf() {
+ try {
+ mService.setPppoeMode(PppoeDevInfo.PPPOE_CONN_MODE_DHCP);
+ } catch (RemoteException e) {
+ }
+ }
+
+ public boolean isPppoeDeviceUp() {
+ try {
+ return mService.isPppoeDeviceUp();
+ } catch (RemoteException e) {
+ return false;
+ }
+ }
+}
diff --git a/java/src/com/droidlogic/pppoe/PppoeMonitor.java b/java/src/com/droidlogic/pppoe/PppoeMonitor.java
new file mode 100644
index 0000000..9348701
--- a/dev/null
+++ b/java/src/com/droidlogic/pppoe/PppoeMonitor.java
@@ -0,0 +1,119 @@
+package com.droidlogic.pppoe;
+
+import java.util.regex.Matcher;
+
+import android.os.SystemProperties;
+import android.net.NetworkInfo;
+import android.util.Config;
+import android.util.Slog;
+import java.util.StringTokenizer;
+
+/**
+ * Listens for events for pppoe, and passes them on
+ * to the {@link PppoeStateTracker} for handling. Runs in its own thread.
+ *
+ * @hide
+ */
+public class PppoeMonitor {
+ private static final String TAG = "PppoeMonitor";
+ private static final int CONNECTED = 1;
+ private static final int INTERFACE_DOWN = 2;
+ private static final int INTERFACE_UP = 3;
+ private static final int DEV_ADDED = 4;
+ private static final int DEV_REMOVED = 5;
+ private static final String connectedEvent = "CONNECTED";
+ private static final String disconnectedEvent = "DISCONNECTED";
+
+ private static final int NEW_LINK = 16;
+ private static final int DEL_LINK = 17;
+ private static final boolean DEBUG = false;
+ private final String pppoe_running_flag = "net.pppoe.running";
+
+ private PppoeStateTracker mTracker;
+
+ public PppoeMonitor(PppoeStateTracker tracker) {
+ mTracker = tracker;
+ }
+
+ public void startMonitoring() {
+ if (DEBUG) Slog.i(TAG, "Start startMonitoring");
+ new MonitorThread().start();
+ }
+
+ class MonitorThread extends Thread {
+
+ public MonitorThread() {
+ super("PppoeMonitor");
+ }
+
+ public void run() {
+ int index;
+ int i;
+ if (DEBUG) Slog.i(TAG, "Start run");
+ for (;;) {
+ String eventName = PppoeNative.waitForEvent();
+
+ String propVal = SystemProperties.get(pppoe_running_flag);
+ if (DEBUG) Slog.i(TAG, "Start run for "+"eventName"+eventName+"propVal"+propVal);
+ int n = 0;
+ if (propVal.length() != 0) {
+ try {
+ n = Integer.parseInt(propVal);
+ } catch (NumberFormatException e) {}
+ }
+
+ if ( 0 == n) {
+ continue;
+ }
+
+ if (eventName == null) {
+ continue;
+ }
+ if (DEBUG) Slog.i(TAG, "EVENT[" + eventName+"]");
+ /*
+ * Map event name into event enum
+ */
+ String [] events = eventName.split(":");
+ index = events.length;
+ if (index < 2)
+ continue;
+ i = 0;
+ while (index != 0 && i < index-1) {
+ int event = 0;
+ if ("added".equals(events[i+1]) ) {
+ event = DEV_ADDED;
+ }
+ else if ("removed".equals(events[i+1])) {
+ event = DEV_REMOVED;
+ }
+ else {
+ int cmd =Integer.parseInt(events[i+1]);
+ if ( cmd == DEL_LINK) {
+ event = INTERFACE_DOWN;
+ handleEvent(events[i],event);
+ }
+ else if (cmd == NEW_LINK) {
+ event = INTERFACE_UP;
+ handleEvent(events[i],event);
+ }
+ }
+ i = i + 2;
+ }
+ }
+ }
+
+ void handleEvent(String ifname,int event) {
+ switch (event) {
+ case INTERFACE_DOWN:
+ mTracker.notifyStateChange(ifname,NetworkInfo.DetailedState.DISCONNECTED);
+ break;
+ case INTERFACE_UP:
+ mTracker.notifyStateChange(ifname,NetworkInfo.DetailedState.CONNECTED);
+ break;
+ default:
+ mTracker.notifyStateChange(ifname,NetworkInfo.DetailedState.FAILED);
+ }
+ }
+
+ }
+}
diff --git a/java/src/com/droidlogic/pppoe/PppoeNative.java b/java/src/com/droidlogic/pppoe/PppoeNative.java
new file mode 100644
index 0000000..030e1a3
--- a/dev/null
+++ b/java/src/com/droidlogic/pppoe/PppoeNative.java
@@ -0,0 +1,21 @@
+package com.droidlogic.pppoe;
+
+/**
+ * Native calls to pppoe interface.
+ *
+ * {@hide}
+ */
+
+public class PppoeNative {
+ static {
+ System.loadLibrary("pppoe");
+ initPppoeNative();
+ }
+
+ public native static String getInterfaceName(int i);
+ public native static int getInterfaceCnt();
+ public native static int initPppoeNative();
+ public native static String waitForEvent();
+ public native static int isInterfaceAdded(String ifname);
+
+}
diff --git a/java/src/com/droidlogic/pppoe/PppoeService.java b/java/src/com/droidlogic/pppoe/PppoeService.java
new file mode 100644
index 0000000..c333b56
--- a/dev/null
+++ b/java/src/com/droidlogic/pppoe/PppoeService.java
@@ -0,0 +1,274 @@
+/*
+ * Copyright (C) 2009 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.droidlogic.pppoe;
+
+import java.net.UnknownHostException;
+import com.droidlogic.pppoe.PppoeNative;
+import com.droidlogic.pppoe.PppoeManager;
+import com.droidlogic.pppoe.PppoeStateTracker;
+import com.droidlogic.pppoe.PppoeDevInfo;
+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 java.io.IOException;
+import java.io.FileReader;
+import java.io.BufferedReader;
+import android.net.DhcpInfo;
+
+public class PppoeService<syncronized> extends IPppoeManager.Stub{
+
+ private Context mContext;
+ private PppoeStateTracker mTracker;
+ private String[] DevName;
+ private static final String TAG = "PppoeService";
+ private int isPppoeEnabled ;
+ private int mPppoeState= PppoeManager.PPPOE_STATE_UNKNOWN;
+ /** {@hide} */
+ public static final String PPPOE_ON = "pppoe_on";
+ /** {@hide} */
+ public static final String PPPOE_IP = "pppoe_ip";
+ /** {@hide} */
+ public static final String PPPOE_MASK = "pppoe_mask";
+ /** {@hide} */
+ public static final String PPPOE_DNS = "pppoe_dns";
+ /** {@hide} */
+ public static final String PPPOE_ROUTE = "pppoe_route";
+ /** {@hide} */
+ public static final String PPPOE_CONF = "pppoe_conf";
+ /** {@hide} */
+ public static final String PPPOE_IFNAME = "pppoe_ifname";
+
+ public PppoeService(Context context, PppoeStateTracker Tracker){
+ mTracker = Tracker;
+ mContext = context;
+
+ isPppoeEnabled = getPersistedState();
+ Slog.i(TAG,"Pppoe dev enabled " + isPppoeEnabled );
+ getDeviceNameList();
+ setPppoeState(isPppoeEnabled);
+ registerForBroadcasts();
+ Slog.i(TAG, "Trigger the pppoe monitor");
+ mTracker.StartPolling();
+ }
+
+ public boolean isPppoeConfigured() {
+
+ final ContentResolver cr = mContext.getContentResolver();
+ int x = Settings.Secure.getInt(cr, PPPOE_CONF,0);
+
+ if (x == 0) {
+ Settings.Secure.putString(cr, PPPOE_IFNAME, "ppp0");
+ Settings.Secure.putString(cr, PPPOE_IP, "0.0.0.0");
+ Settings.Secure.putString(cr, PPPOE_DNS, "0.0.0.0");
+ Settings.Secure.putString(cr, PPPOE_MASK, "255.255.255.0");
+ Settings.Secure.putString(cr, PPPOE_ROUTE, "0.0.0.0");
+
+ Slog.i(TAG, "@@@@@@NO CONFIG. set default");
+ Settings.Secure.putInt(cr, PPPOE_CONF,1);
+ }
+
+ x = Settings.Secure.getInt(cr, PPPOE_CONF,0);
+
+ if (x == 1)
+ return true;
+ return false;
+ }
+
+ public synchronized PppoeDevInfo getSavedPppoeConfig() {
+
+ if (isPppoeConfigured() ) {
+ final ContentResolver cr = mContext.getContentResolver();
+ PppoeDevInfo info = new PppoeDevInfo();
+ info.setIfName(Settings.Secure.getString(cr, PPPOE_IFNAME));
+ info.setIpAddress(Settings.Secure.getString(cr, PPPOE_IP));
+ info.setDnsAddr(Settings.Secure.getString(cr, PPPOE_DNS));
+ info.setNetMask(Settings.Secure.getString(cr, PPPOE_MASK));
+ info.setRouteAddr(Settings.Secure.getString(cr, PPPOE_ROUTE));
+
+ return info;
+ }
+ return null;
+ }
+
+
+ public synchronized void setPppoeMode(String mode) {
+ final ContentResolver cr = mContext.getContentResolver();
+ Slog.i(TAG,"Set pppoe mode " + DevName + " mode " + mode);
+ if (DevName != null) {
+ Settings.Secure.putString(cr, PPPOE_IFNAME, DevName[0]);
+ Settings.Secure.putInt(cr, PPPOE_CONF,1);
+ }
+ }
+
+ public synchronized void UpdatePppoeDevInfo(PppoeDevInfo info) {
+ final ContentResolver cr = mContext.getContentResolver();
+ Settings.Secure.putInt(cr, PPPOE_CONF,1);
+ Settings.Secure.putString(cr, PPPOE_IFNAME, info.getIfName());
+ Settings.Secure.putString(cr, PPPOE_IP, info.getIpAddress());
+ Settings.Secure.putString(cr, PPPOE_DNS, info.getDnsAddr());
+ Settings.Secure.putString(cr, PPPOE_ROUTE, info.getRouteAddr());
+ Settings.Secure.putString(cr, PPPOE_MASK,info.getNetMask());
+ }
+ private void registerForBroadcasts() {
+ IntentFilter intentFilter = new IntentFilter();
+ intentFilter.addAction(Intent.ACTION_SCREEN_ON);
+ intentFilter.addAction(Intent.ACTION_SCREEN_OFF);
+ mContext.registerReceiver(mReceiver, intentFilter);
+ }
+
+ public int getTotalInterface() {
+ return PppoeNative.getInterfaceCnt();
+ }
+
+
+ private int scanPppoeDevice() {
+ int i = 0,j;
+ if ((i = PppoeNative.getInterfaceCnt()) != 0) {
+ Slog.i(TAG, "total found "+i+ " net devices");
+ DevName = new String[i];
+ }
+ else
+ return i;
+
+ for (j = 0; j < i; j++) {
+ DevName[j] = PppoeNative.getInterfaceName(j);
+ if (DevName[j] == null)
+ break;
+ Slog.i(TAG,"device " + j + " name " + DevName[j]);
+ }
+
+ return i;
+ }
+
+ public String[] getDeviceNameList() {
+ return (scanPppoeDevice() > 0 ) ? DevName : null;
+ }
+
+ private int getPersistedState() {
+ final ContentResolver cr = mContext.getContentResolver();
+ try {
+ return Settings.Secure.getInt(cr, PPPOE_ON);
+ } catch (Settings.SettingNotFoundException e) {
+ return PppoeManager.PPPOE_STATE_UNKNOWN;
+ }
+ }
+
+ private synchronized void persistPppoeEnabled(boolean enabled) {
+ final ContentResolver cr = mContext.getContentResolver();
+ Settings.Secure.putInt(cr, PPPOE_ON,
+ enabled ? PppoeManager.PPPOE_STATE_ENABLED : PppoeManager.PPPOE_STATE_DISABLED);
+ }
+
+ private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ String action = intent.getAction();
+ if (action.equals(Intent.ACTION_SCREEN_ON)) {
+ Slog.d(TAG, "ACTION_SCREEN_ON");
+ try {
+ mTracker.resetInterface();
+ } catch (UnknownHostException e) {
+ Slog.e(TAG, "Wrong pppoe configuration");
+ }
+ } else if (action.equals(Intent.ACTION_SCREEN_OFF)) {
+ Slog.d(TAG, "ACTION_SCREEN_OFF");
+ mTracker.stopInterface(false);
+ }
+ }
+ };
+
+ public synchronized void setPppoeState(int state) {
+ Slog.i(TAG, "setPppoeState from " + mPppoeState + " to "+ state);
+
+ if (mPppoeState != state) {
+ mPppoeState = state;
+ if (state == PppoeManager.PPPOE_STATE_DISABLED) {
+ persistPppoeEnabled(false);
+// mTracker.stopInterface(false);
+ new Thread("stopInterface") {
+ @Override
+ public void run() {
+ mTracker.stopInterface(false);
+ }
+ }.start();
+ } else {
+ persistPppoeEnabled(true);
+ if (!isPppoeConfigured()) {
+ // If user did not configure any interfaces yet, pick the first one
+ // and enable it.
+ setPppoeMode(PppoeDevInfo.PPPOE_CONN_MODE_DHCP);
+ }
+// try {
+// mTracker.resetInterface();
+// } catch (UnknownHostException e) {
+// Slog.e(TAG, "Wrong pppoe configuration");
+// }
+ new Thread("resetInterface") {
+ @Override
+ public void run() {
+ try {
+ mTracker.resetInterface();
+ } catch (UnknownHostException e) {
+ Slog.e(TAG, "Wrong pppoe configuration");
+ }
+ }
+ }.start();
+
+ }
+ }
+ }
+
+ public int getPppoeState( ) {
+ return mPppoeState;
+ }
+
+ public boolean isPppoeDeviceUp( ) {
+ try {
+ boolean retval = false;
+ FileReader fr = new FileReader("/sys/class/net/ppp0/operstate");
+ BufferedReader br = new BufferedReader(fr, 32);
+ String status = br.readLine();
+ if (status != null && status.equals("up")) {
+ Slog.d(TAG, "PppoeDevice status:" + status);
+ retval = true;
+ }
+ else if (status != null && status.equals("down")) {
+ Slog.d(TAG, "PppoeDevice status:" + status);
+ retval = false;
+ }
+ else {
+ retval = false;
+ }
+ br.close();
+ fr.close();
+ return retval;
+ } catch (IOException e) {
+ Slog.d(TAG, "get PppoeDevice status error");
+ return false;
+ }
+ }
+
+ public DhcpInfo getDhcpInfo( ) {
+ return mTracker.getDhcpInfo();
+ }
+}
diff --git a/java/src/com/droidlogic/pppoe/PppoeStateTracker.java b/java/src/com/droidlogic/pppoe/PppoeStateTracker.java
new file mode 100644
index 0000000..e7b90b0
--- a/dev/null
+++ b/java/src/com/droidlogic/pppoe/PppoeStateTracker.java
@@ -0,0 +1,615 @@
+package com.droidlogic.pppoe;
+
+import java.net.Inet4Address;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.Iterator;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+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.net.ConnectivityManager;
+import android.net.DhcpInfo;
+import android.net.InterfaceConfiguration;
+import android.net.NetworkInfo;
+import android.net.NetworkInfo.DetailedState;
+import android.net.RouteInfo;
+import android.net.LinkAddress;
+import android.net.NetworkCapabilities;
+import android.net.LinkProperties;
+import android.net.LinkQualityInfo;
+import android.net.NetworkStateTracker;
+import android.net.NetworkUtils;
+import android.net.NetworkInfo.DetailedState;
+import android.net.NetworkAgent;
+import android.net.Network;
+import android.net.SamplingDataTracker;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.IBinder;
+import android.os.INetworkManagementService;
+import android.os.Looper;
+import android.os.Message;
+import android.os.Messenger;
+import android.os.Parcel;
+import android.os.SystemProperties;
+import android.os.ServiceManager;
+import android.os.INetworkManagementService;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.util.*;
+import android.util.Slog;
+/**
+ * Track the state of Pppoe connectivity. All event handling is done here,
+ * and all changes in connectivity state are initiated here.
+ *
+ * @hide
+ */
+public class PppoeStateTracker implements NetworkStateTracker {
+
+ private static final String TAG="PppoeStateTracker";
+ private static final String PROP_PPP_ADDR = "dhcp.ppp0.ipaddress";
+ private static final String PROP_PPP_MASK = "dhcp.ppp0.mask";
+ private static final String PROP_PPP_DNS1 = "dhcp.ppp0.dns1";
+ private static final String PROP_PPP_DNS2 = "dhcp.ppp0.dns2";
+ private static final String PROP_PPP_GW = "dhcp.ppp0.gateway";
+ private static final String PROP_PPP_DEF_ROUTE ="net.ppp0.gw";
+
+ private static final String PROP_VAL_PPP_NOERR = "0:0";
+ private static final String PROP_NAME_PPP_ERRCODE = "net.ppp.errcode";
+
+ public static final int EVENT_CONNECTED = 3;
+ public static final int EVENT_DISCONNECTED = 4;
+ public static final int EVENT_CONNECT_FAILED = 5;
+ public static final int EVENT_DISCONNECT_FAILED = 6;
+
+ public static final String PPPOE_SERVICE = "pppoe";
+
+ private PppoeManager mEM;
+ private boolean mServiceStarted;
+ private boolean mInterfaceStopped;
+ private String mInterfaceName = "ppp0";
+ private DhcpInfoInternal mDhcpInfoInternal;
+ private PppoeMonitor mMonitor;
+
+ private AtomicBoolean mTeardownRequested = new AtomicBoolean(false);
+ private AtomicBoolean mPrivateDnsRouteSet = new AtomicBoolean(false);
+ private AtomicBoolean mDefaultRouteSet = new AtomicBoolean(false);
+ private PppoeDevInfo Info;
+ protected Network mNetwork = new Network(ConnectivityManager.NETID_UNSET);
+
+ private LinkProperties mLinkProperties;
+ private NetworkCapabilities mNetworkCapabilities;
+ private NetworkInfo mNetworkInfo;
+ private final Looper mLooper;
+ private NetworkAgent mNetworkAgent;
+ private String mNetworkName;
+ private Handler mTarget;
+ private Handler mTrackerTarget;
+ private Context mContext;
+ private static DetailedState mLastState = DetailedState.DISCONNECTED;
+
+ public PppoeStateTracker(Looper looper,int netType, String networkName) {
+ Slog.i(TAG,"Starts ...");
+ mNetworkName = networkName;
+ mNetworkInfo = new NetworkInfo(netType, 0, networkName, "");
+ mNetworkInfo.setIsAvailable(false);
+ setTeardownRequested(false);
+ mLooper=looper;
+ mLinkProperties = new LinkProperties();
+ mNetworkCapabilities = new NetworkCapabilities();
+
+ if (PppoeNative.initPppoeNative() != 0 ) {
+ Slog.e(TAG,"Can not init pppoe device layers");
+ return;
+ }
+ Slog.i(TAG,"Successed");
+
+ mServiceStarted = true;
+
+ mMonitor = new PppoeMonitor(this);
+
+
+ }
+
+ public boolean stopInterface(boolean suspend) {
+ if (mEM != null) {
+ PppoeDevInfo info = mEM.getSavedPppoeConfig();
+ if (info != null && mEM.pppoeConfigured())
+ {
+ mInterfaceStopped = true;
+ Slog.i(TAG, "stop interface");
+ String ifname = info.getIfName();
+
+ NetworkUtils.resetConnections(ifname, NetworkUtils.RESET_ALL_ADDRESSES);
+ if (!suspend)
+ NetworkUtils.disableInterface(ifname);
+ }
+ }
+
+ return true;
+ }
+
+
+ private boolean configureInterfaceStatic(String ifname, DhcpInfoInternal dhcpInfoInternal) {
+ IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
+ INetworkManagementService netd = INetworkManagementService.Stub.asInterface(b);
+ InterfaceConfiguration ifcg = new InterfaceConfiguration();
+ ifcg.setLinkAddress(dhcpInfoInternal.makeLinkAddress());
+ Slog.i(TAG, "configureInterface on dev:" + ifname);
+ try {
+ netd.setInterfaceConfig(ifname, ifcg);
+ //mLinkProperties = dhcpInfoInternal.makeLinkProperties();
+
+ //return true;
+ } catch (RemoteException re) {
+ Slog.i(TAG, "IP configuration failed: " + re);
+ return false;
+ } catch (IllegalStateException e) {
+ Slog.i(TAG, "IP configuration failed: " + e);
+ return false;
+ }
+ // Create our NetworkAgent.
+
+
+ final boolean linkChanged = !dhcpInfoInternal.makeLinkProperties().equals(mLinkProperties);
+ if (linkChanged) {
+ mLinkProperties = dhcpInfoInternal.makeLinkProperties();
+ //mLinkProperties.addLinkAddress();
+ mLinkProperties.addRoute(new RouteInfo(NetworkUtils.numericToInetAddress(Info.getRouteAddr())));
+ //mLinkProperties.addDnsServer();
+ mLinkProperties.setInterfaceName(ifname);
+ Slog.i(TAG,"Link configuration changed for netId: "
+ + " new: " + mLinkProperties + "info.getRouteAddr():" +Info.getRouteAddr());
+
+
+// }
+// if (mNetworkAgent != null) mNetworkAgent.sendLinkProperties(mLinkProperties);
+ return true;
+ }
+ return false;
+ }
+
+ private boolean configureInterface(PppoeDevInfo info) throws UnknownHostException {
+ mInterfaceStopped = false;
+ Info=info;
+ mDhcpInfoInternal = new DhcpInfoInternal();
+ mDhcpInfoInternal.ipAddress = info.getIpAddress();
+ mDhcpInfoInternal.addRoute(new RouteInfo(NetworkUtils.numericToInetAddress(info.getRouteAddr())));
+
+
+ InetAddress ia = NetworkUtils.numericToInetAddress(info.getNetMask());
+ mDhcpInfoInternal.prefixLength = NetworkUtils.netmaskIntToPrefixLength(
+ NetworkUtils.inetAddressToInt((Inet4Address)ia));
+ mDhcpInfoInternal.dns1 = info.getDnsAddr();
+
+ configureInterfaceStatic(info.getIfName(), mDhcpInfoInternal);
+ return true;
+ }
+
+
+ public boolean resetInterface() throws UnknownHostException{
+ /*
+ * This will guide us to enabled the enabled device
+ */
+ Slog.i(TAG, ">>>resetInterface");
+ if (mEM != null) {
+ Slog.i(TAG, "pppoeConfigured: " + mEM.pppoeConfigured());
+ PppoeDevInfo info = mEM.getSavedPppoeConfig();
+
+ if (info != null && mEM.pppoeConfigured()) {
+ Slog.i(TAG, "IfName:" + info.getIfName());
+ Slog.i(TAG, "IP:" + info.getIpAddress());
+ Slog.i(TAG, "Mask:" + info.getNetMask());
+ Slog.i(TAG, "DNS:" + info.getDnsAddr());
+ Slog.i(TAG, "Route:" + info.getRouteAddr());
+
+ synchronized(this) {
+ if (mInterfaceName != null) {
+ Slog.i(TAG, "reset device " + mInterfaceName);
+ NetworkUtils.resetConnections(mInterfaceName, NetworkUtils.RESET_ALL_ADDRESSES);
+ }
+
+ Slog.i(TAG, "Force the connection disconnected before configuration");
+ setPppoeState( false, EVENT_DISCONNECTED, PppoeManager.PROP_VAL_PPP_NOERR);
+
+ configureInterface(info);
+ }
+ }
+ }
+ return true;
+ }
+
+
+ @Override
+ public String getTcpBufferSizesPropName() {
+ // TODO Auto-generated method stub
+ return "net.tcp.buffersize.pppoe";
+ }
+
+ public void StartPolling() {
+ Slog.i(TAG, "start monitoring");
+ mMonitor.startMonitoring();
+ Slog.i(TAG, "end monitoring");
+ }
+ @Override
+ public boolean isAvailable() {
+ // Only say available if we have interfaces and user did not disable us.
+ return ((mEM.getTotalInterface() != 0) && (mEM.getPppoeState() != PppoeManager.PPPOE_STATE_DISABLED));
+ }
+
+ @Override
+ public boolean reconnect() {
+ Slog.i(TAG, ">>>reconnect");
+ try {
+ if (mEM.getPppoeState() != PppoeManager.PPPOE_STATE_DISABLED ) {
+ // maybe this is the first time we run, so set it to enabled
+ mEM.setPppoeEnabled(true);
+ if (!mEM.pppoeConfigured()) {
+ mEM.pppoeSetDefaultConf();
+ }
+ return resetInterface();
+ }
+ } catch (UnknownHostException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ return false;
+
+ }
+
+ @Override
+ public boolean setRadio(boolean turnOn) {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ @Override
+ public void startMonitoring(Context context, Handler target) {
+ Slog.i(TAG,"start to monitor the pppoe devices");
+ if (mServiceStarted) {
+ mContext = context;
+ IBinder b = ServiceManager.getService(PPPOE_SERVICE);
+ IPppoeManager PppoeService = IPppoeManager.Stub.asInterface(b);
+ mEM = new PppoeManager(PppoeService, context);
+ mTarget = target;
+ mTrackerTarget = new Handler(target.getLooper(), mTrackerHandlerCallback);
+ if (mEM == null) {
+ Slog.i(TAG,"failed to start startMonitoring");
+ return;
+ }
+ int state = mEM.getPppoeState();
+ if (state != mEM.PPPOE_STATE_DISABLED) {
+ if (state == mEM.PPPOE_STATE_UNKNOWN) {
+ // maybe this is the first time we run, so set it to enabled
+ mEM.setPppoeEnabled(true);
+ } else {
+ try {
+ resetInterface();
+ } catch (UnknownHostException e) {
+ Slog.e(TAG, "Wrong pppoe configuration");
+ }
+ }
+ }
+ }
+ }
+
+ @Override
+ public void setNetId(int netId) {
+ mNetwork = new Network(netId);
+ }
+
+ @Override
+ public Network getNetwork() {
+ return mNetwork;
+ }
+
+ public boolean teardown() {
+ return (mEM != null) ? stopInterface(false) : false;
+ }
+
+ public void captivePortalCheckComplete() {
+ //TODO
+ }
+ private void postNotification(int event, String errcode) {
+ final Intent intent = new Intent(PppoeManager.PPPOE_STATE_CHANGED_ACTION);
+ intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
+ intent.putExtra(PppoeManager.EXTRA_PPPOE_STATE, event);
+ intent.putExtra(PppoeManager.EXTRA_PPPOE_ERRCODE, errcode);
+ mContext.sendBroadcast(intent);
+
+ Slog.d(TAG, "Send PPPOE_STATE_CHANGED_ACTION");
+ }
+
+ private void setPppoeState(boolean state, int event, String errcode) {
+ Slog.d(TAG, "PST.setPppoeState()" + mNetworkInfo.isConnected() + " ==> " + state);
+ if (event == EVENT_CONNECT_FAILED || mNetworkInfo.isConnected() != state) {
+ mNetworkInfo.setIsAvailable(state);
+ postNotification(event, errcode);
+ }
+
+ if (mNetworkInfo.isConnected() != state) {
+ if (state) {
+ mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, null);
+
+ } else {
+ mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null, null);
+ if ( EVENT_DISCONNECTED == event ) {
+ Slog.d(TAG, "EVENT_DISCONNECTED: StopInterface");
+ stopInterface(true);
+ }
+ }
+ Message msg = mTarget.obtainMessage(EVENT_CONFIGURATION_CHANGED, mNetworkInfo);
+ msg.sendToTarget();
+
+ msg = mTarget.obtainMessage(EVENT_STATE_CHANGED, mNetworkInfo);
+ msg.sendToTarget();
+ }
+ }
+ public DhcpInfo getDhcpInfo() {
+ return mDhcpInfoInternal.makeDhcpInfo();
+ }
+
+ private Handler.Callback mTrackerHandlerCallback = new Handler.Callback() {
+ /** {@inheritDoc} */
+ public boolean handleMessage(Message msg) {
+ synchronized (this) {
+ boolean newNetworkstate = false;
+ PppoeDevInfo info = new PppoeDevInfo();
+
+ switch (msg.what) {
+ case EVENT_DISCONNECTED:
+ Slog.i(TAG, "[EVENT: PPP DOWN]");
+ Slog.i(TAG, "DO NOT clear IP Config and PPP Property");
+
+ /*
+ SystemProperties.set(PROP_PPP_ADDR, "0.0.0.0");
+ SystemProperties.set(PROP_PPP_MASK, "0.0.0.0");
+ SystemProperties.set(PROP_PPP_DNS1, "0.0.0.0");
+ SystemProperties.set(PROP_PPP_DNS2, "0.0.0.0");
+ SystemProperties.set(PROP_PPP_GW, "0.0.0.0");
+ */
+ info.setIfName(mInterfaceName);
+ info.setIpAddress("0.0.0.0");
+ info.setNetMask("0.0.0.0");
+ info.setDnsAddr("0.0.0.0");
+ info.setRouteAddr("0.0.0.0");
+ mEM.UpdatePppoeDevInfo(info);
+
+ try {
+ configureInterface(info);
+ } catch (UnknownHostException e) {
+ e.printStackTrace();
+ }
+ newNetworkstate = false;
+
+ String ppp_err = SystemProperties.get(PROP_NAME_PPP_ERRCODE, PppoeManager.PROP_VAL_PPP_NOERR);
+ Slog.i(TAG, "ppp_err:" + ppp_err);
+ if (ppp_err.equals(PROP_VAL_PPP_NOERR)) {
+ setPppoeState(newNetworkstate, EVENT_DISCONNECTED, PppoeManager.PROP_VAL_PPP_NOERR);
+ } else {
+ setPppoeState(newNetworkstate, EVENT_CONNECT_FAILED, ppp_err);
+ }
+ break;
+
+ case EVENT_CONNECTED:
+ Slog.i(TAG, "[EVENT: PPP UP]");
+ newNetworkstate = true;
+
+ int i=0;
+
+ info.setIfName(mInterfaceName);
+ String prop_val = null;
+ do {
+ prop_val = SystemProperties.get(PROP_PPP_ADDR, "0.0.0.0");
+ info.setIpAddress(prop_val);
+ Slog.i(TAG, "ip:" + prop_val);
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException ex) {
+ // Shut up!
+ }
+ i++;
+ } while(info.getIpAddress().equals("0.0.0.0") && i<10);
+
+ prop_val = SystemProperties.get(PROP_PPP_MASK, "0.0.0.0");
+ info.setNetMask(prop_val);
+ Slog.i(TAG, "mask:" + prop_val);
+
+ prop_val = SystemProperties.get(PROP_PPP_DNS1, "0.0.0.0");
+ info.setDnsAddr(prop_val);
+ Slog.i(TAG, "dns:" + prop_val);
+
+ prop_val = SystemProperties.get(PROP_PPP_GW, "0.0.0.0");
+ info.setRouteAddr(prop_val);
+ Slog.i(TAG, "gw:" + prop_val);
+
+ SystemProperties.set(PROP_PPP_DEF_ROUTE,prop_val);
+ mEM.UpdatePppoeDevInfo(info);
+ try {
+ configureInterface(info);
+ } catch (UnknownHostException e) {
+ e.printStackTrace();
+ }
+
+ setPppoeState(newNetworkstate, EVENT_CONNECTED, PppoeManager.PROP_VAL_PPP_NOERR);
+ mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, null);
+
+ mNetworkAgent = new NetworkAgent(mLooper, mContext, mNetworkName,
+ mNetworkInfo, mNetworkCapabilities,mLinkProperties,60) {
+ @Override
+ public void unwanted() {
+ // We are user controlled, not driven by NetworkRequest.
+ }
+ };
+ if (mNetworkAgent != null) {
+ mNetworkAgent.sendNetworkInfo(mNetworkInfo);
+ }
+// if (mNetworkAgent != null) mNetworkAgent.sendLinkProperties(mLinkProperties);
+ break;
+ }
+ }
+ return true;
+ }
+ };
+
+ public void notifyPppConnected(String ifname) {
+ Slog.i(TAG, "report interface is up for " + ifname + ", last status: " + mLastState);
+ mLastState = DetailedState.CONNECTED;
+ synchronized(this) {
+ mTrackerTarget.sendEmptyMessage(EVENT_CONNECTED);
+ }
+
+ }
+ public void notifyStateChange(String ifname,DetailedState state) {
+ Slog.i(TAG, "report state change:" + mLastState.toString() + "->" + state.toString() + " on dev " + ifname);
+ if (ifname.equals(mInterfaceName)) {
+ mLastState = state;
+ synchronized(this) {
+ mTrackerTarget.sendEmptyMessage(state.equals(DetailedState.CONNECTED)
+ ? EVENT_CONNECTED : EVENT_DISCONNECTED);
+ }
+ }
+ }
+
+
+ /**
+ * 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 NetworkCapabilities getNetworkCapabilities() {
+ return new NetworkCapabilities(mNetworkCapabilities);
+ }
+
+
+ public void setUserDataEnable(boolean enabled) {
+ Slog.d(TAG, "ignoring setUserDataEnable(" + enabled + ")");
+ }
+
+ public void setPolicyDataEnable(boolean enabled) {
+ Slog.d(TAG, "ignoring setPolicyDataEnable(" + enabled + ")");
+ }
+
+
+ /**
+ * Check if private DNS route is set for the network
+ */
+ public boolean isPrivateDnsRouteSet() {
+ Slog.v(TAG, "isPrivateDnsRouteSet");
+ return mPrivateDnsRouteSet.get();
+ }
+
+ /**
+ * Set a flag indicating private DNS route is set
+ */
+ public void privateDnsRouteSet(boolean enabled) {
+ Slog.v(TAG, "privateDnsRouteSet");
+ mPrivateDnsRouteSet.set(enabled);
+ }
+
+
+ /**
+ * Check if default route is set
+ */
+ public boolean isDefaultRouteSet() {
+ Slog.v(TAG, "isDefaultRouteSet");
+ return mDefaultRouteSet.get();
+ }
+
+
+ /**
+ * Set a flag indicating default route is set for the network
+ */
+ public void defaultRouteSet(boolean enabled) {
+ Slog.v(TAG, "defaultRouteSet");
+ mDefaultRouteSet.set(enabled);
+ }
+
+ public void setTeardownRequested(boolean isRequested) {
+ Slog.v(TAG, "setTeardownRequested(" + isRequested + ")");
+ mTeardownRequested.set(isRequested);
+ }
+
+ public boolean isTeardownRequested() {
+ boolean flag = mTeardownRequested.get();
+ Slog.v(TAG, "isTeardownRequested: " + flag);
+ return flag;
+ }
+
+ public void setDependencyMet(boolean met) {
+ // not supported on this network
+ }
+
+ /**
+ * Informs the state tracker that another interface is stacked on top of it.
+ **/
+ public void addStackedLink(LinkProperties link){
+ }
+
+ /**
+ * Informs the state tracker that a stacked interface has been removed.
+ **/
+ public void removeStackedLink(LinkProperties link){
+ }
+
+ /*
+ * Called once to setup async channel between this and
+ * the underlying network specific code.
+ */
+ public void supplyMessenger(Messenger messenger){
+ }
+
+ /*
+ * Network interface name that we'll lookup for sampling data
+ */
+ public String getNetworkInterfaceName(){
+ return null;
+ }
+
+ /*
+ * Save the starting sample
+ */
+ public void startSampling(SamplingDataTracker.SamplingSnapshot s){
+ }
+
+ /*
+ * Save the ending sample
+ */
+ public void stopSampling(SamplingDataTracker.SamplingSnapshot s) {
+ }
+
+ @Override
+ public void captivePortalCheckCompleted(boolean isCaptivePortal) {
+ // not implemented
+ }
+
+ /**
+ * Get interesting information about this network link
+ * @return a copy of link information, null if not available
+ */
+ public LinkQualityInfo getLinkQualityInfo(){
+ return null;
+ }
+}
diff --git a/java/src/com/droidlogic/pppoe/package.html b/java/src/com/droidlogic/pppoe/package.html
new file mode 100644
index 0000000..db6f78b
--- a/dev/null
+++ b/java/src/com/droidlogic/pppoe/package.html
@@ -0,0 +1,3 @@
+<body>
+{@hide}
+</body> \ No newline at end of file
diff --git a/jni/Android.mk b/jni/Android.mk
new file mode 100644
index 0000000..3ce7c94
--- a/dev/null
+++ b/jni/Android.mk
@@ -0,0 +1,19 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+ com_droidlogic_common.cpp \
+ com_droidlogic_pppoe.cpp\
+
+#LOCAL_C_INCLUDES := $(JNI_H_INCLUDE)
+
+LOCAL_SHARED_LIBRARIES := \
+ liblog \
+ libcutils \
+ libgui \
+ libnativehelper
+
+LOCAL_MODULE := libpppoe
+
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/jni/com_droidlogic_common.cpp b/jni/com_droidlogic_common.cpp
new file mode 100644
index 0000000..ce96878
--- a/dev/null
+++ b/jni/com_droidlogic_common.cpp
@@ -0,0 +1,551 @@
+/*
+ * Copyright 2009, 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: kejun.gao <greatgauss@gmail.com>
+ */
+
+#include "jni.h"
+#include "com_droidlogic_common.h"
+
+
+//namespace android {
+
+
+/* Same as strlen(x) for constant string literals ONLY */
+#define CONST_STRLEN(x) (sizeof(x)-1)
+
+/* Convenience macro to call has_prefix with a constant string literal */
+#define HAS_CONST_PREFIX(str,end,prefix) has_prefix((str),(end),prefix,CONST_STRLEN(prefix))
+
+
+
+static char flags_desc[512];
+
+static const char * flag_desc_tbl[32] = {
+ "UP",
+ "BC",
+ "DBG",
+ "LOOPBACK",
+
+ "PPP",
+ "NT",
+ "RUNNING",
+ "NOARP",
+
+ "PROMISC",
+ "ALLMULTI",
+ "MASTER",
+ "SLAVE",
+
+ "MC",
+ "PORTSEL",
+ "AUTOMEDIA",
+ "DYNAMIC",
+
+ "LINK_UP",
+ "DORMANT",
+ "UNDEFINED",
+ "UNDEFINED",
+
+ "UNDEFINED",
+ "UNDEFINED",
+ "UNDEFINED",
+ "UNDEFINED",
+
+ "UNDEFINED",
+ "UNDEFINED",
+ "UNDEFINED",
+ "UNDEFINED",
+ "UNDEFINED",
+ "UNDEFINED",
+ "UNDEFINED",
+ "UNDEFINED",
+};
+
+static char* if_flags_desc(int flags, char *desc) {
+ desc[0] = '\0';
+ for (int i = 18; i >= 0; i--) {
+ if (flags & (1<<i)) {
+ strcat(desc, " ");
+ strcat(desc, flag_desc_tbl[i]);
+ }
+ }
+
+ return desc;
+}
+
+
+/*
+ * Decode a RTM_NEWADDR or RTM_DELADDR message.
+ */
+static int parseIfAddrMessage
+(int type, struct ifaddrmsg *ifaddr, int rtasize, char *ifname,
+pfunc_is_interested_event pfunc_check)
+{
+ struct rtattr *rta;
+ struct ifa_cacheinfo *cacheinfo = NULL;
+ char addrstr[INET6_ADDRSTRLEN] = "";
+
+ // Sanity check.
+ if (type != RTM_NEWADDR && type != RTM_DELADDR) {
+ ALOGE("%s on incorrect message type 0x%x" , __FUNCTION__, type);
+ return -1;
+ }
+
+ // For log messages.
+ const char *msgtype = (type == RTM_NEWADDR) ? "RTM_NEWADDR" : "RTM_DELADDR";
+
+ for (rta = IFA_RTA(ifaddr); RTA_OK(rta, rtasize);
+ rta = RTA_NEXT(rta, rtasize)) {
+ if (rta->rta_type == IFA_ADDRESS) {
+ // Only look at the first address, because we only support notifying
+ // one change at a time.
+ if (*addrstr != '\0') {
+ ALOGE("Multiple IFA_ADDRESSes in %s, ignoring" , msgtype);
+ continue;
+ }
+
+ // Convert the IP address to a string.
+ if (ifaddr->ifa_family == AF_INET) {
+ struct in_addr *addr4 = (struct in_addr *) RTA_DATA(rta);
+ if (RTA_PAYLOAD(rta) < sizeof(*addr4)) {
+ ALOGE("Short IPv4 address (%d bytes) in %s" ,
+ RTA_PAYLOAD(rta), msgtype);
+ continue;
+ }
+ inet_ntop(AF_INET, addr4, addrstr, sizeof(addrstr));
+ } else if (ifaddr->ifa_family == AF_INET6) {
+ struct in6_addr *addr6 = (struct in6_addr *) RTA_DATA(rta);
+ if (RTA_PAYLOAD(rta) < sizeof(*addr6)) {
+ ALOGE("Short IPv6 address (%d bytes) in %s" ,
+ RTA_PAYLOAD(rta), msgtype);
+ continue;
+ }
+ inet_ntop(AF_INET6, addr6, addrstr, sizeof(addrstr));
+ } else {
+ ALOGE("Unknown address family %d" , ifaddr->ifa_family);
+ continue;
+ }
+
+ // Find the interface name.
+ if (!if_indextoname(ifaddr->ifa_index, ifname)) {
+ ALOGE("Unknown ifindex %d in %s" , ifaddr->ifa_index, msgtype);
+ return -1;
+ }
+
+ if (pfunc_check && !pfunc_check(ifname)) {
+ return -1;
+ }
+ ALOGI("Address %s %s/%d %s %u %u" ,
+ (type == RTM_NEWADDR) ? "updated": "removed",
+ addrstr, ifaddr->ifa_prefixlen, ifname, ifaddr->ifa_flags, ifaddr->ifa_scope );
+ } else if (rta->rta_type == IFA_CACHEINFO) {
+ // Address lifetime information.
+ if (cacheinfo) {
+ // We only support one address.
+ ALOGE("Multiple IFA_CACHEINFOs in %s, ignoring\n" , msgtype);
+ continue;
+ }
+
+ if (RTA_PAYLOAD(rta) < sizeof(*cacheinfo)) {
+ ALOGE("Short IFA_CACHEINFO (%d vs. %d bytes) in %s" ,
+ RTA_PAYLOAD(rta), sizeof(cacheinfo), msgtype);
+ continue;
+ }
+
+ cacheinfo = (struct ifa_cacheinfo *) RTA_DATA(rta);
+ }
+ }
+
+ if (addrstr[0] == '\0') {
+ ALOGE("No IFA_ADDRESS in %s" , msgtype);
+ return -1;
+ }
+
+ return 0;
+}
+
+
+static void parseBinaryNetlinkMessage
+(char *buff, int len, char *rbuf, int rbufsize, int *pguard, pfunc_is_interested_event pfunc_check)
+{
+ char *result = NULL;
+ unsigned int guard;
+ int nAttrLen;
+ struct nlmsghdr *nh;
+ struct rtattr *pstruAttr;
+ char *ifname = (char*)"UNKNOWN_NAME";
+
+ guard = *pguard;
+ result = rbuf + guard;
+
+ rbuf[0] = '\0';
+ for (nh = (struct nlmsghdr *) buff; NLMSG_OK (nh, (unsigned int)len);
+ nh = NLMSG_NEXT (nh, len))
+ {
+ if (nh->nlmsg_type == NLMSG_DONE) {
+ ALOGE("Did not find useful eth interface information");
+ return;
+ }
+
+ if (nh->nlmsg_type == NLMSG_ERROR) {
+ /* Do some error handling. */
+ ALOGE("Read device name failed");
+ return;
+ }
+
+ if (nh->nlmsg_type == RTM_DELLINK ||
+ nh->nlmsg_type == RTM_NEWLINK) {
+ struct ifinfomsg *einfo;
+ int type = nh->nlmsg_type;
+ char *desc;
+
+ einfo = (struct ifinfomsg *)NLMSG_DATA(nh);
+
+ pstruAttr = IFLA_RTA(einfo);
+ nAttrLen = NLMSG_PAYLOAD(nh, sizeof(struct ifinfomsg));
+
+ while (RTA_OK(pstruAttr, nAttrLen))
+ {
+ switch (pstruAttr->rta_type)
+ {
+ case IFLA_IFNAME:
+ ifname = (char *)RTA_DATA(pstruAttr);
+ break;
+
+ default:
+ break;
+ }
+
+ pstruAttr = RTA_NEXT(pstruAttr, nAttrLen);
+ }
+
+ if (pfunc_check && !pfunc_check(ifname)) {
+ continue;
+ }
+
+ if (type == RTM_NEWLINK &&
+ (!(einfo->ifi_flags & IFF_LOWER_UP))) {
+ type = RTM_DELLINK;
+ }
+
+ desc = (char*)((type == RTM_DELLINK) ? "DELLINK" : "NEWLINK");
+
+ ALOGI("%s: %s(%d), flags=0X%X(%s)", ifname, desc, type, einfo->ifi_flags, if_flags_desc(einfo->ifi_flags, flags_desc));
+
+ snprintf(result,rbufsize-guard, "%s:%d:",ifname,type);
+ guard += strlen(result);
+ result +=guard;
+ *pguard = guard;
+ }
+ else if (nh->nlmsg_type == RTM_DELADDR || nh->nlmsg_type == RTM_NEWADDR) {
+ int len = nh->nlmsg_len - sizeof(*nh);
+ struct ifaddrmsg *ifa;
+ char ifname[IFNAMSIZ + 1] = {0};
+
+ if (sizeof(*ifa) > (size_t) len) {
+ ALOGE("Got a short RTM_xxxADDR message\n");
+ continue;
+ }
+
+ ifa = (struct ifaddrmsg *)NLMSG_DATA(nh);
+ size_t rtasize = IFA_PAYLOAD(nh);
+ if (0 != parseIfAddrMessage(nh->nlmsg_type, ifa, rtasize, ifname, pfunc_check)) {
+ continue;
+ }
+ snprintf(result,rbufsize-guard, "%s:%d:",ifname,nh->nlmsg_type);
+ guard += strlen(result);
+ result +=guard;
+ *pguard = guard;
+ }
+
+ }
+ rbuf[guard] = '\0';
+
+ if (rbuf[0]) ALOGI("%s",rbuf);
+}
+
+
+/* If the string between 'str' and 'end' begins with 'prefixlen' characters
+ * from the 'prefix' array, then return 'str + prefixlen', otherwise return
+ * NULL.
+ */
+static const char*
+has_prefix(const char* str, const char* end, const char* prefix, size_t prefixlen)
+{
+ if ((end-str) >= (ptrdiff_t)prefixlen && !memcmp(str, prefix, prefixlen))
+ return str + prefixlen;
+ else
+ return NULL;
+}
+
+
+/*
+ * Parse an ASCII-formatted message from a NETLINK_KOBJECT_UEVENT
+ * netlink socket.
+ */
+static void parseAsciiNetlinkMessage
+(char *buff, int len, char *rbuf, int rbufsize, int *pguard, pfunc_is_interested_event pfunc_check)
+{
+ int guard;
+ char *result = NULL;
+ unsigned int left;
+ const char *s = buff;
+ const char *end;
+ int param_idx = 0;
+ int i;
+ int first = 1;
+ char *path = NULL;
+ const char *action = NULL;
+ int seq;
+ char *subsys = NULL;
+ char *pch;
+ char *net_if = NULL;
+
+ if (len == 0)
+ return;
+ guard = *pguard;
+ result = rbuf + guard;
+
+ ALOGV(">>>>>>KOBJECT_UEVENT");
+ for (pch = buff; pch < buff + len;) {
+ ALOGV("%s", pch);
+ pch = strchr(pch,'\0');
+ pch++;
+ }
+ ALOGV("<<<<<<KOBJECT_UEVENT");
+
+ /* Ensure the buff is zero-terminated, the code below depends on this */
+ buff[len-1] = '\0';
+
+ end = s + len;
+ while (s < end) {
+ if (first) {
+ const char *p;
+ /* buff is 0-terminated, no need to check p < end */
+ for (p = s; *p != '@'; p++) {
+ if (!*p) { /* no '@', should not happen */
+ return;
+ }
+ }
+ path = strdup(p+1);
+ first = 0;
+ } else {
+ const char* a;
+ if ((a = HAS_CONST_PREFIX(s, end, "ACTION=")) != NULL) {
+ if (!strcmp(a, "add"))
+ action = "added";
+ else if (!strcmp(a, "remove"))
+ action = "removed";
+ else if (!strcmp(a, "change"))
+ action = "changed";
+ } else if ((a = HAS_CONST_PREFIX(s, end, "SEQNUM=")) != NULL) {
+ seq = atoi(a);
+ } else if ((a = HAS_CONST_PREFIX(s, end, "SUBSYSTEM=")) != NULL) {
+ subsys = strdup(a);
+ } else if ((a = HAS_CONST_PREFIX(s, end, "INTERFACE=")) != NULL) {
+ net_if = strdup(a);
+ } }
+ s += strlen(s) + 1;
+ }
+
+ if (subsys && 0 == strcmp(subsys, "net") && net_if && action) {
+ if (!pfunc_check || pfunc_check(net_if)) {
+ ALOGI("%s %s", net_if, action);
+ snprintf(result, rbufsize-guard, "%s:%s:",net_if,action);
+ guard += strlen(result);
+ }
+ }
+ rbuf[guard] = '\0';
+ *pguard = guard;
+ if (rbuf[0]) ALOGI("%s",rbuf);
+ return;
+}
+
+
+static char* waitForNetInterfaceEvent
+(int nl_socket_netlink_route, int nl_socket_kobj_uevent,
+char *rbuf, int *pguard,
+pfunc_update_interface_list pfunc,
+pfunc_is_interested_event pfunc_check)
+{
+ char *buff;
+ struct iovec iov;
+ struct msghdr msg;
+ int len;
+ fd_set readable;
+ int result = -1;
+ int maxfd;
+ int old_guard;
+
+ *pguard = 0;
+ 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 = NULL;
+ msg.msg_namelen = 0;
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+ msg.msg_control = NULL;
+ msg.msg_controllen = 0;
+ msg.msg_flags = 0;
+
+ maxfd = (nl_socket_netlink_route >= nl_socket_kobj_uevent) ?
+ nl_socket_netlink_route: nl_socket_kobj_uevent;
+
+ FD_ZERO(&readable);
+ FD_SET(nl_socket_netlink_route, &readable);
+ FD_SET(nl_socket_kobj_uevent, &readable);
+
+ while (1) {
+ result = select(maxfd+1, &readable, NULL, NULL, NULL);
+ if (result >= 0 || errno != EINTR) {
+ break;
+ }
+ }
+
+ if (result < 0) {
+ goto error;
+ }
+ if (result == 0) {
+ /* Timed out */
+ goto error;
+ }
+
+ if (FD_ISSET(nl_socket_netlink_route, &readable)) {
+ old_guard = *pguard;
+ if ((len = recvmsg(nl_socket_netlink_route, &msg, 0))>= 0) {
+ parseBinaryNetlinkMessage(buff, len, rbuf, RET_STR_SZ, pguard,pfunc_check);
+ }
+
+ if (old_guard != *pguard)
+ ALOGE("netlink_route socket readable: [%s]", rbuf);
+ }
+
+ if (FD_ISSET(nl_socket_kobj_uevent, &readable)) {
+ old_guard = *pguard;
+ if ((len = recvmsg(nl_socket_kobj_uevent, &msg, 0))>= 0) {
+ parseAsciiNetlinkMessage(buff, len, rbuf, RET_STR_SZ, pguard,pfunc_check);
+ pfunc();
+ }
+ if (old_guard != *pguard)
+ ALOGE("kobject_event socket readable: [%s]", rbuf);
+ }
+
+ return rbuf;
+
+error:
+ if (buff)
+ free(buff);
+ return NULL;
+}
+
+
+static int open_NETLINK_socket(int netlinkFamily, int groups)
+{
+ struct sockaddr_nl nl_addr;
+ int ret = -1;
+ int mysocket;
+
+ memset(&nl_addr, 0, sizeof(struct sockaddr_nl));
+ nl_addr.nl_family = AF_NETLINK;
+ nl_addr.nl_pid = 0;
+ nl_addr.nl_groups = groups;
+
+ /*
+ *Create connection to netlink socket
+ */
+ mysocket = socket(AF_NETLINK,SOCK_DGRAM,netlinkFamily);
+ if (mysocket < 0) {
+ ALOGE("Can not create netlink poll socket" );
+ goto error;
+ }
+
+ errno = 0;
+ if (bind(mysocket, (struct sockaddr *)(&nl_addr),
+ sizeof(struct sockaddr_nl))) {
+ ALOGE("Can not bind to netlink poll socket,%s",strerror(errno));
+
+ goto error;
+ }
+
+ return mysocket;
+error:
+ ALOGE("%s failed" ,__FUNCTION__);
+ if (mysocket >0)
+ close(mysocket);
+ return ret;
+}
+
+
+static int find_empty_node(interface_info_t *node_table, int nr_nodes)
+{
+ int i;
+ for ( i = 0; i <nr_nodes; i++) {
+ if (node_table[i].if_index == -1)
+ return i;
+ }
+ return -1;
+}
+
+
+
+static int add_interface_node_to_list(interface_info_t *node_table, int nr_nodes, int if_index, char *if_name)
+{
+ /*
+ *Todo: Lock here!!!!
+ */
+ int i;
+
+ i = find_empty_node(node_table, nr_nodes);
+ if (i < 0)
+ return -1;
+
+ node_table[i].if_index = if_index;
+ node_table[i].name = strdup(if_name);
+
+ return 0;
+}
+
+
+static int getInterfaceName(interface_info_t *node_table, int nr_nodes,
+ int index, char *ifname)
+{
+ int i, j;
+ interface_info_t *info;
+
+ for ( i = 0, j = -1; i < nr_nodes; i++) {
+ info= node_table + i;
+ if (node_table[i].if_index != -1)
+ j++;
+ if (j == index) {
+ ALOGI("Found :%s",info->name);
+ strcpy(ifname, info->name);
+ return 0;
+ }
+ }
+
+ ifname[0]='\0';
+ return -1;
+}
+
+
+//};
+
diff --git a/jni/com_droidlogic_common.h b/jni/com_droidlogic_common.h
new file mode 100644
index 0000000..f6d44cd
--- a/dev/null
+++ b/jni/com_droidlogic_common.h
@@ -0,0 +1,64 @@
+#ifndef ANDROID_NET_COMMON_H
+#define ANDROID_NET_COMMON_H
+ #include <inttypes.h>
+#include <utils/misc.h>
+#include <android_runtime/AndroidRuntime.h>
+#include <utils/Log.h>
+#include <asm/types.h>
+
+/*
+The statement
+ typedef unsigned short sa_family_t;
+is removed from bionic/libc/kernel/common/linux/socket.h.
+To avoid compile failure, add the statement here.
+*/
+typedef unsigned short sa_family_t;
+
+#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>
+#include <arpa/inet.h>
+#include <net/if.h>
+#include <linux/rtnetlink.h> //for ifinfomsg
+#include <linux/netlink.h> //for nlmsghdr{}
+
+#define NL_SOCK_INV -1
+#define RET_STR_SZ 4096
+#define NL_POLL_MSG_SZ 8*1024
+#define SYSFS_PATH_MAX 256
+
+#define SYSFS_CLASS_NET "/sys/class/net"
+
+typedef int (*pfunc_update_interface_list)(void);
+typedef int (*pfunc_is_interested_event)(char *ifname);
+
+typedef struct _interface_info_t {
+ int if_index;
+ char *name;
+} interface_info_t;
+
+#define NR_ETHER_INTERFACES 16
+#define NR_PPP_INTERFACES 16
+
+static int open_NETLINK_socket(int netlinkFamily, int groups);
+static void parseAsciiNetlinkMessage
+(char *buff, int len, char *rbuf, int rbufsize, int *pguard, pfunc_is_interested_event pfunc_check);
+static void parseBinaryNetlinkMessage
+(char *buff, int len, char *rbuf, int rbufsize, int *pguard, pfunc_is_interested_event pfunc_check);
+
+static char* waitForNetInterfaceEvent
+(int nl_socket_netlink_route, int nl_socket_kobj_uevent,
+char *rbuf, int *pguard, pfunc_update_interface_list pfunc);
+static int find_empty_node(interface_info_t *node_table, int nr_nodes);
+static int add_interface_node_to_list(interface_info_t *node_table, int nr_nodes, int if_index, char *if_name);
+static int getInterfaceName(interface_info_t *node_table, int nr_nodes, int index, char *ifname);
+
+#endif
+
diff --git a/jni/com_droidlogic_pppoe.cpp b/jni/com_droidlogic_pppoe.cpp
new file mode 100644
index 0000000..80fed3d
--- a/dev/null
+++ b/jni/com_droidlogic_pppoe.cpp
@@ -0,0 +1,302 @@
+/*
+ * Copyright 2009, 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 "pppoe"
+
+#include "jni.h"
+#include <cutils/properties.h>
+#include "com_droidlogic_common.h"
+#include "com_droidlogic_common.cpp"
+
+#include <jni.h>
+#include <JNIHelp.h>
+
+#include <utils/Log.h>
+#include <gui/SurfaceComposerClient.h>
+
+
+#define PPPOE_PKG_NAME "com/droidlogic/pppoe/PppoeNative"
+
+namespace android {
+static struct fieldIds {
+ jclass dhcpInfoClass;
+ jmethodID constructorId;
+ jfieldID ipaddress;
+ jfieldID gateway;
+ jfieldID netmask;
+ jfieldID dns1;
+ jfieldID dns2;
+ jfieldID serverAddress;
+ jfieldID leaseDuration;
+} dhcpInfoFieldIds;
+
+
+interface_info_t pppoe_if_list[NR_PPP_INTERFACES];
+
+static int nr_pppoe_if = 0;
+static int nl_socket_netlink_route = -1;
+static int nl_socket_kobj_uevent = -1;
+
+static int netlink_init_pppoe_list(void);
+
+
+static int is_interested_event(char *ifname)
+{
+ char phy_if_name[PROP_VALUE_MAX] = {0};
+ property_get("net.pppoe.phyif", phy_if_name, "UNKNOWN_PHYIF");
+ return (0 == strncmp("ppp", ifname, 3) || 0 == strcmp(phy_if_name, ifname));
+}
+
+
+static jstring com_droidlogic_pppoe_PppoeNative_waitForEvent
+(JNIEnv *env, jobject clazz)
+{
+ char rbuf[RET_STR_SZ] = {0};
+ int guard = 0;
+
+ waitForNetInterfaceEvent(nl_socket_netlink_route, nl_socket_kobj_uevent,
+ rbuf, &guard, netlink_init_pppoe_list, is_interested_event);
+
+ return env->NewStringUTF(guard > 0 ? rbuf : NULL);
+}
+
+
+static int netlink_init_pppoe_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];
+ int i;
+
+ for ( i = 0; i < NR_ETHER_INTERFACES; i++) {
+ pppoe_if_list[i].if_index = -1;
+ pppoe_if_list[i].name = NULL;
+ nr_pppoe_if = 0;
+ }
+
+ if ((netdir = opendir(SYSFS_CLASS_NET)) != NULL) {
+ while ((de = readdir(netdir)) != NULL) {
+ if (strcmp(de->d_name,"ppp0"))
+ continue;
+
+ snprintf(path, SYSFS_PATH_MAX, "%s/%s/type", SYSFS_CLASS_NET, de->d_name);
+ FILE *typefd;
+ if ((typefd = fopen(path, "r")) != NULL) {
+ char typestr[MAX_FGETS_LEN + 1];
+ int type = 0;
+ memset(typestr, 0, MAX_FGETS_LEN + 1);
+ if (fgets(typestr, MAX_FGETS_LEN, typefd) != NULL) {
+ type = strtoimax(typestr, NULL, 10);
+ }
+ fclose(typefd);
+ if (type >= ARPHRD_TUNNEL && type < ARPHRD_IEEE802_TR)
+ 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);
+ fclose(ifidx);
+ continue;
+ }
+ fclose(ifidx);
+ } else {
+ ALOGE("Can not open %s for read",path);
+ continue;
+ }
+
+ if (0 == add_interface_node_to_list(pppoe_if_list,NR_PPP_INTERFACES,index, (char *) de->d_name)) {
+ nr_pppoe_if++;
+ }
+ }
+ closedir(netdir);
+ }
+ ret = 0;
+error:
+ return ret;
+}
+
+
+static jint com_droidlogic_pppoe_PppoeNative_initPppoeNative
+(JNIEnv *env, jobject clazz)
+{
+ int ret = -1;
+
+ ALOGI("==>%s",__FUNCTION__);
+
+ nl_socket_netlink_route = open_NETLINK_socket(NETLINK_ROUTE, RTMGRP_LINK | RTMGRP_IPV4_IFADDR);
+ if (nl_socket_netlink_route < 0) {
+ ALOGE("failed to create NETLINK socket");
+ goto error;
+ }
+
+ nl_socket_kobj_uevent = open_NETLINK_socket(NETLINK_KOBJECT_UEVENT, 0xFFFFFFFF);
+ if (nl_socket_kobj_uevent < 0) {
+ ALOGE("failed to create NETLINK socket");
+ goto error;
+ }
+
+ if ((ret = netlink_init_pppoe_list()) < 0) {
+ ALOGE("Can not collect the interface list");
+ goto error;
+ }
+ return ret;
+error:
+ ALOGE("%s exited with error",__FUNCTION__);
+ if (nl_socket_netlink_route >0)
+ close(nl_socket_netlink_route);
+ if (nl_socket_kobj_uevent >0)
+ close(nl_socket_kobj_uevent);
+ return ret;
+}
+
+
+static jstring com_droidlogic_pppoe_PppoeNative_getInterfaceName
+(JNIEnv *env, jobject clazz, jint index)
+{
+ int ret;
+ char ifname[IFNAMSIZ+1]= {0};
+ ALOGI("User ask for device name on %d, total:%d",index, nr_pppoe_if);
+
+ if (nr_pppoe_if == 0 || index >= nr_pppoe_if) {
+ ALOGI("Invalid parameters");
+ return env->NewStringUTF(NULL);
+ }
+
+ ret = getInterfaceName(pppoe_if_list, NR_PPP_INTERFACES, index, ifname);
+ if (ret != 0) {
+ ALOGI("No device name found");
+ }
+
+ return env->NewStringUTF(ret==0 ? ifname:NULL);
+}
+
+
+static jint com_droidlogic_pppoe_PppoeNative_getInterfaceCnt() {
+ return nr_pppoe_if;
+}
+
+static jint com_droidlogic_pppoe_PppoeNative_isInterfaceAdded
+(JNIEnv *env, jobject clazz, jstring ifname)
+{
+ int retval = 0;
+ const char * ppp_name = env->GetStringUTFChars(ifname, NULL);
+ if (ppp_name == NULL) {
+ ALOGE("Device name NULL!");
+ return 0;
+ }
+ while (true) {
+ ALOGE("android_net_pppoe_isInterfaceAdded undefined!");
+ }
+
+ env->ReleaseStringUTFChars(ifname, ppp_name);
+ return retval;
+}
+
+static JNINativeMethod gPppoeMethods[] = {
+ {"waitForEvent", "()Ljava/lang/String;",
+ (void *)com_droidlogic_pppoe_PppoeNative_waitForEvent},
+ {"getInterfaceName", "(I)Ljava/lang/String;",
+ (void *)com_droidlogic_pppoe_PppoeNative_getInterfaceName},
+ {"initPppoeNative", "()I",
+ (void *)com_droidlogic_pppoe_PppoeNative_initPppoeNative},
+ {"getInterfaceCnt","()I",
+ (void *)com_droidlogic_pppoe_PppoeNative_getInterfaceCnt},
+ {"isInterfaceAdded","(Ljava/lang/String;)I",
+ (void *)com_droidlogic_pppoe_PppoeNative_isInterfaceAdded}
+};
+
+
+
+
+int register_com_droidlogic_pppoe_PppoeManager(JNIEnv* env)
+{
+ jclass pppoe = env->FindClass(PPPOE_PKG_NAME);
+ ALOGI("Loading pppoe jni class");
+ LOG_FATAL_IF( pppoe == NULL, "Unable to find class " PPPOE_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,
+ // PPPOE_PKG_NAME,
+ // gPppoeMethods,
+ // NELEM(gPppoeMethods));
+ return jniRegisterNativeMethods(env, PPPOE_PKG_NAME,
+ gPppoeMethods, NELEM(gPppoeMethods));
+}
+
+extern "C" jint JNI_OnLoad(JavaVM* vm, void* reserved __unused)
+{
+
+ JNIEnv* env = NULL;
+ jint result = -1;
+
+ if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
+ ALOGE("ERROR: GetEnv failed\n");
+ goto bail;
+ }
+ assert(env != NULL);
+
+ if (register_com_droidlogic_pppoe_PppoeManager(env) < 0) {
+ ALOGE("ERROR: PppoeManager native registration failed\n");
+ goto bail;
+ }
+
+ /* success -- return valid version number */
+ result = JNI_VERSION_1_4;
+
+bail:
+ return result;
+}
+
+};