diff options
author | Lorenzo Colitti <lorenzo@google.com> | 2014-05-20 16:58:34 -0700 |
---|---|---|
committer | Lorenzo Colitti <lorenzo@google.com> | 2014-05-21 19:53:04 -0700 |
commit | 20c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0 (patch) | |
tree | ec9404a13ea29b089f98eaa45e366a2a9f98c9b0 | |
parent | e7a7ef99f94206a42388b5bf42a4c0e9f61a718e (diff) | |
download | ethernet-20c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0.tar.gz |
Initial EthernetService implementation.
Bug: 14981801
Bug: 14993642
Change-Id: If392ef7063e096854ef830f4fe3b038439a1d307
-rw-r--r-- | Android.mk | 30 | ||||
-rw-r--r-- | java/com/android/server/ethernet/EthernetConfigStore.java | 63 | ||||
-rw-r--r-- | java/com/android/server/ethernet/EthernetNetworkFactory.java | 398 | ||||
-rw-r--r-- | java/com/android/server/ethernet/EthernetService.java | 45 | ||||
-rw-r--r-- | java/com/android/server/ethernet/EthernetServiceImpl.java | 177 |
5 files changed, 713 insertions, 0 deletions
diff --git a/Android.mk b/Android.mk new file mode 100644 index 0000000..99559ac --- /dev/null +++ b/Android.mk @@ -0,0 +1,30 @@ +# 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) + +# Build the java code +# ============================================================ + +include $(CLEAR_VARS) + +LOCAL_AIDL_INCLUDES := $(LOCAL_PATH)/java +LOCAL_SRC_FILES := $(call all-java-files-under, java) \ + $(call all-Iaidl-files-under, java) \ + $(call all-logtags-files-under, java) + +LOCAL_JAVA_LIBRARIES := services +LOCAL_MODULE := ethernet-service + +include $(BUILD_JAVA_LIBRARY) diff --git a/java/com/android/server/ethernet/EthernetConfigStore.java b/java/com/android/server/ethernet/EthernetConfigStore.java new file mode 100644 index 0000000..7a428a8 --- /dev/null +++ b/java/com/android/server/ethernet/EthernetConfigStore.java @@ -0,0 +1,63 @@ +/* + * 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. + */ + +package com.android.server.ethernet; + +import android.net.IpConfiguration; +import android.net.IpConfiguration.IpAssignment; +import android.net.IpConfiguration.ProxySettings; +import android.net.LinkProperties; +import android.os.Environment; +import android.util.Log; +import android.util.SparseArray; + +import com.android.server.net.IpConfigStore; + + +/** + * This class provides an API to store and manage Ethernet network configuration. + */ +public class EthernetConfigStore extends IpConfigStore { + private static final String TAG = "EthernetConfigStore"; + + private static final String ipConfigFile = Environment.getDataDirectory() + + "/misc/ethernet/ipconfig.txt"; + + public EthernetConfigStore() { + } + + public IpConfiguration readIpAndProxyConfigurations() { + SparseArray<IpConfiguration> networks = readIpAndProxyConfigurations(ipConfigFile); + + if (networks.size() == 0) { + Log.w(TAG, "No Ethernet configuration found. Using default."); + return new IpConfiguration(IpAssignment.DHCP, ProxySettings.NONE, new LinkProperties()); + } + + if (networks.size() > 1) { + // Currently we only support a single Ethernet interface. + Log.w(TAG, "Multiple Ethernet configurations detected. Only reading first one."); + } + + return networks.valueAt(0); + } + + public void writeIpAndProxyConfigurations(IpConfiguration config) { + SparseArray<IpConfiguration> networks = new SparseArray<IpConfiguration>(); + networks.put(0, config); + writeIpAndProxyConfigurations(ipConfigFile, networks); + } +} diff --git a/java/com/android/server/ethernet/EthernetNetworkFactory.java b/java/com/android/server/ethernet/EthernetNetworkFactory.java new file mode 100644 index 0000000..588913b --- /dev/null +++ b/java/com/android/server/ethernet/EthernetNetworkFactory.java @@ -0,0 +1,398 @@ +/* + * 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. + */ + +package com.android.server.ethernet; + +import android.content.Context; +import android.net.ConnectivityManager; +import android.net.ConnectivityServiceProtocol.NetworkFactoryProtocol; +import android.net.DhcpResults; +import android.net.InterfaceConfiguration; +import android.net.NetworkUtils; +import android.net.IpConfiguration; +import android.net.IpConfiguration.IpAssignment; +import android.net.IpConfiguration.ProxySettings; +import android.net.LinkAddress; +import android.net.LinkProperties; +import android.net.NetworkAgent; +import android.net.NetworkCapabilities; +import android.net.NetworkInfo; +import android.net.NetworkInfo.DetailedState; +import android.net.NetworkRequest; +import android.net.EthernetManager; +import android.os.Handler; +import android.os.IBinder; +import android.os.INetworkManagementService; +import android.os.Looper; +import android.os.Message; +import android.os.Messenger; +import android.os.RemoteException; +import android.os.ServiceManager; +import android.text.TextUtils; +import android.util.Log; + +import com.android.server.net.BaseNetworkObserver; + +import java.net.Inet4Address; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; + + +class NetworkFactory extends Handler { + public interface Callback { + public void onRequestNetwork(NetworkRequest request, int currentScore); + public void onCancelRequest(NetworkRequest request); + } + + private String mName; + private Callback mCallback; + private ConnectivityManager mCM; + + NetworkFactory(String name, Context context, Looper looper, Callback callback) { + super(looper); + mCallback = callback; + mName = name; + mCM = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); + } + + public void register() { + logi("Registering network factory"); + mCM.registerNetworkFactory(new Messenger(this), mName); + } + + @Override + public void handleMessage(Message message) { + switch(message.what) { + case NetworkFactoryProtocol.CMD_REQUEST_NETWORK: + mCallback.onRequestNetwork((NetworkRequest) message.obj, message.arg1); + break; + case NetworkFactoryProtocol.CMD_CANCEL_REQUEST: + mCallback.onCancelRequest((NetworkRequest) message.obj); + break; + default: + loge("Unhandled message " + message.what); + } + } + + private void logi(String s) { + Log.i("NetworkFactory" + mName, s); + } + + private void loge(String s) { + Log.e("NetworkFactory" + mName, s); + } +} + +/** + * This class tracks the data connection associated with Ethernet. + * @hide + */ +class EthernetNetworkFactory implements NetworkFactory.Callback { + private static final String NETWORK_TYPE = "ETHERNET"; + private static final String TAG = "EthernetNetworkFactory"; + private static final int NETWORK_SCORE = 70; + private static final boolean DBG = true; + + /** Tracks interface changes. Called from the NetworkManagementService thread. */ + private InterfaceObserver mInterfaceObserver; + + /** For static IP configuration */ + private EthernetManager mEthernetManager; + + /** To set link state and configure IP addresses. */ + private INetworkManagementService mNMService; + + /* To communicate with ConnectivityManager */ + private NetworkCapabilities mNetworkCapabilities; + private NetworkAgent mNetworkAgent; + private NetworkFactory mFactory; + + /** Product-dependent regular expression of interface names we want to track. */ + private static String mIfaceMatch = ""; + + /** Data members. All accesses must be synchronized(this). */ + private static String mIface = ""; + private String mHwAddr; + private static boolean mLinkUp; + private NetworkInfo mNetworkInfo; + private LinkProperties mLinkProperties; + + EthernetNetworkFactory() { + mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_ETHERNET, 0, NETWORK_TYPE, ""); + mLinkProperties = new LinkProperties(); + initNetworkCapabilities(); + } + + private void updateInterfaceState(String iface, boolean up) { + if (!mIface.equals(iface)) { + // We only support one interface. + return; + } + Log.d(TAG, "updateInterface: " + iface + " link " + (up ? "up" : "down")); + + synchronized(this) { + mLinkUp = up; + mNetworkInfo.setIsAvailable(up); + DetailedState state = up ? DetailedState.CONNECTED: DetailedState.DISCONNECTED; + mNetworkInfo.setDetailedState(state, null, mHwAddr); + mNetworkAgent.sendNetworkScore(mLinkUp? NETWORK_SCORE : 0); + updateAgent(); + } + } + + private class InterfaceObserver extends BaseNetworkObserver { + @Override + public void interfaceLinkStateChanged(String iface, boolean up) { + updateInterfaceState(iface, up); + } + + @Override + public void interfaceAdded(String iface) { + maybeTrackInterface(iface); + } + + @Override + public void interfaceRemoved(String iface) { + stopTrackingInterface(iface); + } + } + + private void setInterfaceUp(String iface) { + // Bring up the interface so we get link status indications. + try { + mNMService.setInterfaceUp(iface); + String hwAddr = null; + InterfaceConfiguration config = mNMService.getInterfaceConfig(iface); + + if (config == null) { + Log.e(TAG, "Null iterface config for " + iface + ". Bailing out."); + return; + } + + synchronized (this) { + if (mIface.isEmpty()) { + mIface = iface; + mHwAddr = config.getHardwareAddress(); + mNetworkInfo.setIsAvailable(true); + mNetworkInfo.setExtraInfo(mHwAddr); + } else { + Log.e(TAG, "Interface unexpectedly changed from " + iface + " to " + mIface); + mNMService.setInterfaceDown(iface); + } + } + } catch (RemoteException e) { + Log.e(TAG, "Error upping interface " + mIface + ": " + e); + } + } + + private boolean maybeTrackInterface(String iface) { + // If we don't already have an interface, and if this interface matches + // our regex, start tracking it. + if (!iface.matches(mIfaceMatch) || !mIface.isEmpty()) + return false; + + Log.d(TAG, "Started tracking interface " + iface); + setInterfaceUp(iface); + return true; + } + + private void stopTrackingInterface(String iface) { + if (!iface.equals(mIface)) + return; + + Log.d(TAG, "Stopped tracking interface " + iface); + disconnect(); + synchronized (this) { + mIface = ""; + mHwAddr = null; + mNetworkInfo.setExtraInfo(null); + } + } + + private void setStaticIpAddress(LinkProperties linkProperties) { + Log.i(TAG, "Applying static IPv4 configuration to " + mIface + ": " + mLinkProperties); + try { + InterfaceConfiguration config = mNMService.getInterfaceConfig(mIface); + for (LinkAddress address: linkProperties.getLinkAddresses()) { + // IPv6 uses autoconfiguration. + if (address.getAddress() instanceof Inet4Address) { + config.setLinkAddress(address); + // This API only supports one IPv4 address. + mNMService.setInterfaceConfig(mIface, config); + break; + } + } + } catch(RemoteException e) { + Log.e(TAG, "Setting static IP address failed: " + e.getMessage()); + } catch(IllegalStateException e) { + Log.e(TAG, "Setting static IP address failed: " + e.getMessage()); + } + } + + public void updateAgent() { + if (DBG) { + Log.i(TAG, "Updating mNetworkAgent with: " + + mNetworkCapabilities + ", " + + mNetworkInfo + ", " + + mLinkProperties); + } + mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities); + mNetworkAgent.sendNetworkInfo(mNetworkInfo); + mNetworkAgent.sendLinkProperties(mLinkProperties); + } + + /* Called by the NetworkAgent on the handler thread. */ + public void connect() { + // TODO: Handle DHCP renew. + Thread dhcpThread = new Thread(new Runnable() { + public void run() { + if (DBG) Log.i(TAG, "dhcpThread: mNetworkInfo=" + mNetworkInfo); + mNetworkInfo.setDetailedState(DetailedState.OBTAINING_IPADDR, null, mHwAddr); + LinkProperties linkProperties; + + IpConfiguration config = mEthernetManager.getConfiguration(); + + if (config.ipAssignment == IpAssignment.STATIC) { + linkProperties = config.linkProperties; + linkProperties.setInterfaceName(mIface); + setStaticIpAddress(linkProperties); + } else { + DhcpResults dhcpResults = new DhcpResults(); + // TODO: support more than one DHCP client. + if (!NetworkUtils.runDhcp(mIface, dhcpResults)) { + Log.e(TAG, "DHCP request error:" + NetworkUtils.getDhcpError()); + mNetworkAgent.sendNetworkScore(0); + return; + } + linkProperties = dhcpResults.linkProperties; + } + if (config.proxySettings == ProxySettings.STATIC) { + linkProperties.setHttpProxy(config.linkProperties.getHttpProxy()); + } + + synchronized(EthernetNetworkFactory.this) { + mLinkProperties = linkProperties; + mNetworkInfo.setIsAvailable(true); + mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, mHwAddr); + updateAgent(); + } + } + }); + dhcpThread.start(); + } + + public void disconnect() { + NetworkUtils.stopDhcp(mIface); + + synchronized(this) { + mLinkProperties.clear(); + mNetworkInfo.setIsAvailable(false); + mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null, mHwAddr); + updateAgent(); + } + + try { + mNMService.clearInterfaceAddresses(mIface); + } catch (Exception e) { + Log.e(TAG, "Failed to clear addresses or disable ipv6" + e); + } + } + + /** + * Begin monitoring connectivity + */ + public synchronized void start(Context context, Handler target) { + // The services we use. + IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE); + mNMService = INetworkManagementService.Stub.asInterface(b); + mEthernetManager = (EthernetManager) context.getSystemService(Context.ETHERNET_SERVICE); + + // Interface match regex. + mIfaceMatch = context.getResources().getString( + com.android.internal.R.string.config_ethernet_iface_regex); + + // Create our NetworkAgent. + mNetworkAgent = new NetworkAgent(target.getLooper(), context, NETWORK_TYPE) { + public synchronized void sendNetworkScore(int score) { + Log.i(TAG, "sendNetworkScore(" + score + ")"); + super.sendNetworkScore(score); + } + public void connect() { + EthernetNetworkFactory.this.connect(); + }; + public void disconnect() { + EthernetNetworkFactory.this.disconnect(); + }; + }; + mNetworkAgent.sendNetworkScore(0); + + // Create and register our NetworkFactory. + mFactory = new NetworkFactory(NETWORK_TYPE, context, target.getLooper(), this); + mFactory.register(); + + // Start tracking interface change events. + mInterfaceObserver = new InterfaceObserver(); + try { + mNMService.registerObserver(mInterfaceObserver); + } catch (RemoteException e) { + Log.e(TAG, "Could not register InterfaceObserver " + e); + } + + // If an Ethernet interface is already connected, start tracking that. + // Otherwise, the first Ethernet interface to appear will be tracked. + try { + final String[] ifaces = mNMService.listInterfaces(); + for (String iface : ifaces) { + if (maybeTrackInterface(iface)) { + break; + } + } + } catch (RemoteException e) { + Log.e(TAG, "Could not get list of interfaces " + e); + } + } + + public synchronized void stop() { + disconnect(); + mIface = ""; + mHwAddr = null; + mLinkUp = false; + mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_ETHERNET, 0, NETWORK_TYPE, ""); + mLinkProperties = new LinkProperties(); + } + + public void onRequestNetwork(NetworkRequest request, int currentScore) { + Log.i(TAG, "onRequestNetwork: (" + currentScore + "): " + request); + // TODO check that the transport is compatible. + mNetworkAgent.addNetworkRequest(request, currentScore); + } + + public void onCancelRequest(NetworkRequest request) { + Log.i(TAG, "onCancelRequest: " + request); + mNetworkAgent.removeNetworkRequest(request); + } + + private void initNetworkCapabilities() { + mNetworkCapabilities = new NetworkCapabilities(); + mNetworkCapabilities.addTransportType(NetworkCapabilities.TRANSPORT_ETHERNET); + mNetworkCapabilities.addNetworkCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET); + mNetworkCapabilities.addNetworkCapability( + NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED); + // We have no useful data on bandwidth. Say 100M up and 100M down. :-( + mNetworkCapabilities.setLinkUpstreamBandwidthKbps(100 * 1000); + mNetworkCapabilities.setLinkDownstreamBandwidthKbps(100 * 1000); + } +} diff --git a/java/com/android/server/ethernet/EthernetService.java b/java/com/android/server/ethernet/EthernetService.java new file mode 100644 index 0000000..2448146 --- /dev/null +++ b/java/com/android/server/ethernet/EthernetService.java @@ -0,0 +1,45 @@ +/* + * 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. + */ + +package com.android.server.ethernet; + +import android.content.Context; +import android.util.Log; +import com.android.server.SystemService; + +public final class EthernetService extends SystemService { + + private static final String TAG = "EthernetService"; + final EthernetServiceImpl mImpl; + + public EthernetService(Context context) { + super(context); + mImpl = new EthernetServiceImpl(context); + } + + @Override + public void onStart() { + Log.i(TAG, "Registering service " + Context.ETHERNET_SERVICE); + publishBinderService(Context.ETHERNET_SERVICE, mImpl); + } + + @Override + public void onBootPhase(int phase) { + if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) { + mImpl.start(); + } + } +} diff --git a/java/com/android/server/ethernet/EthernetServiceImpl.java b/java/com/android/server/ethernet/EthernetServiceImpl.java new file mode 100644 index 0000000..08a2e9a --- /dev/null +++ b/java/com/android/server/ethernet/EthernetServiceImpl.java @@ -0,0 +1,177 @@ +/* + * 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. + */ + +package com.android.server.ethernet; + +import android.content.Context; +import android.content.pm.PackageManager; +import com.android.internal.util.IndentingPrintWriter; +import android.net.ConnectivityManager; +import android.net.IEthernetManager; +import android.net.IpConfiguration; +import android.net.IpConfiguration.IpAssignment; +import android.net.IpConfiguration.ProxySettings; +import android.net.LinkAddress; +import android.net.LinkProperties; +import android.net.NetworkAgent; +import android.net.NetworkInfo; +import android.net.NetworkRequest; +import android.net.RouteInfo; +import android.os.Binder; +import android.os.IBinder; +import android.os.Handler; +import android.os.HandlerThread; +import android.os.Looper; +import android.os.Message; +import android.os.Messenger; +import android.os.INetworkManagementService; +import android.os.RemoteException; +import android.os.ServiceManager; +import android.text.TextUtils; +import android.util.Log; +import android.util.PrintWriterPrinter; + +import java.io.FileDescriptor; +import java.io.PrintWriter; +import java.util.concurrent.atomic.AtomicBoolean; + + +/** + * EthernetServiceImpl handles remote Ethernet operation requests by implementing + * the IEthernetManager interface. + * + * @hide + */ +public class EthernetServiceImpl extends IEthernetManager.Stub { + private static final String TAG = "EthernetServiceImpl"; + + private final Context mContext; + private final EthernetConfigStore mEthernetConfigStore; + private final INetworkManagementService mNMService; + private final AtomicBoolean mStarted = new AtomicBoolean(false); + private IpConfiguration mIpConfiguration; + private ConnectivityManager mCM; + + private Handler mHandler; + private NetworkInfo mNetworkInfo; + private EthernetNetworkFactory mTracker; + + public EthernetServiceImpl(Context context) { + mContext = context; + Log.i(TAG, "Creating EthernetConfigStore"); + mEthernetConfigStore = new EthernetConfigStore(); + mIpConfiguration = mEthernetConfigStore.readIpAndProxyConfigurations(); + + Log.i(TAG, "Read stored IP configuration: " + mIpConfiguration); + + IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE); + mNMService = INetworkManagementService.Stub.asInterface(b); + + mTracker = new EthernetNetworkFactory(); + } + + private void enforceAccessPermission() { + mContext.enforceCallingOrSelfPermission( + android.Manifest.permission.ACCESS_NETWORK_STATE, + "EthernetService"); + } + + private void enforceChangePermission() { + mContext.enforceCallingOrSelfPermission( + android.Manifest.permission.CHANGE_NETWORK_STATE, + "EthernetService"); + } + + private void enforceConnectivityInternalPermission() { + mContext.enforceCallingOrSelfPermission( + android.Manifest.permission.CONNECTIVITY_INTERNAL, + "ConnectivityService"); + } + + public void start() { + Log.i(TAG, "Starting Ethernet service"); + mCM = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE); + + HandlerThread handlerThread = new HandlerThread("EthernetServiceThread"); + handlerThread.start(); + mHandler = new Handler(handlerThread.getLooper()); + + mTracker.start(mContext, mHandler); + + mStarted.set(true); + } + + /** + * Get Ethernet configuration + * @return the Ethernet Configuration, contained in {@link IpConfiguration}. + */ + public IpConfiguration getConfiguration() { + enforceAccessPermission(); + + synchronized (mIpConfiguration) { + return new IpConfiguration(mIpConfiguration); + } + } + + /** + * Set Ethernet configuration + */ + public void setConfiguration(IpConfiguration config) { + if (!mStarted.get()) { + Log.w(TAG, "System isn't ready enough to change ethernet configuration"); + } + + enforceChangePermission(); + enforceConnectivityInternalPermission(); + + synchronized (mIpConfiguration) { + mEthernetConfigStore.writeIpAndProxyConfigurations(config); + + // TODO: this does not check proxy settings, gateways, etc. + // Fix this by making IpConfiguration a complete representation of static configuration. + if (!config.equals(mIpConfiguration)) { + mIpConfiguration.ipAssignment = config.ipAssignment; + mIpConfiguration.proxySettings = config.proxySettings; + mIpConfiguration.linkProperties = new LinkProperties(config.linkProperties); + + mTracker.stop(); + mTracker.start(mContext, mHandler); + } + } + } + + @Override + protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) { + final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " "); + if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) + != PackageManager.PERMISSION_GRANTED) { + pw.println("Permission Denial: can't dump EthernetService from pid=" + + Binder.getCallingPid() + + ", uid=" + Binder.getCallingUid()); + return; + } + pw.println("Stored Ethernet configuration: "); + + pw.increaseIndent(); + pw.println(mIpConfiguration); + pw.decreaseIndent(); + + pw.println("Handler:"); + pw.increaseIndent(); + mHandler.dump(new PrintWriterPrinter(pw), "EthernetServiceImpl"); + pw.decreaseIndent(); + } +} |