120c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti/*
220c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti * Copyright (C) 2014 The Android Open Source Project
320c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti *
420c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti * Licensed under the Apache License, Version 2.0 (the "License");
520c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti * you may not use this file except in compliance with the License.
620c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti * You may obtain a copy of the License at
720c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti *
820c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti *      http://www.apache.org/licenses/LICENSE-2.0
920c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti *
1020c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti * Unless required by applicable law or agreed to in writing, software
1120c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti * distributed under the License is distributed on an "AS IS" BASIS,
1220c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1320c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti * See the License for the specific language governing permissions and
1420c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti * limitations under the License.
1520c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti */
1620c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti
1720c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colittipackage com.android.server.ethernet;
1820c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti
1920c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colittiimport android.content.Context;
2020c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colittiimport android.content.pm.PackageManager;
2120c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colittiimport android.net.IEthernetManager;
22a3d7e61812f8d68ca109280c4e7589e4f968723aJaewan Kimimport android.net.IEthernetServiceListener;
2320c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colittiimport android.net.IpConfiguration;
2420c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colittiimport android.net.IpConfiguration.IpAssignment;
2520c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colittiimport android.net.IpConfiguration.ProxySettings;
2620c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colittiimport android.os.Binder;
2720c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colittiimport android.os.Handler;
2820c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colittiimport android.os.HandlerThread;
29a3d7e61812f8d68ca109280c4e7589e4f968723aJaewan Kimimport android.os.RemoteCallbackList;
3020c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colittiimport android.os.RemoteException;
3176502788598a85d24b9ae3e253016a9370c49a42Billy Lauimport android.provider.Settings;
3220c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colittiimport android.util.Log;
3320c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colittiimport android.util.PrintWriterPrinter;
3420c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti
35a3d7e61812f8d68ca109280c4e7589e4f968723aJaewan Kimimport com.android.internal.util.IndentingPrintWriter;
36a3d7e61812f8d68ca109280c4e7589e4f968723aJaewan Kim
3720c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colittiimport java.io.FileDescriptor;
3820c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colittiimport java.io.PrintWriter;
3920c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colittiimport java.util.concurrent.atomic.AtomicBoolean;
4020c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti
4120c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti/**
4220c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti * EthernetServiceImpl handles remote Ethernet operation requests by implementing
4320c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti * the IEthernetManager interface.
4420c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti *
4520c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti * @hide
4620c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti */
4720c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colittipublic class EthernetServiceImpl extends IEthernetManager.Stub {
4820c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti    private static final String TAG = "EthernetServiceImpl";
4920c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti
5020c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti    private final Context mContext;
5120c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti    private final EthernetConfigStore mEthernetConfigStore;
5220c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti    private final AtomicBoolean mStarted = new AtomicBoolean(false);
5320c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti    private IpConfiguration mIpConfiguration;
5420c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti
5520c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti    private Handler mHandler;
56aea43f5901e6591c390b83b10d3dd9b515a6442aLorenzo Colitti    private final EthernetNetworkFactory mTracker;
57a3d7e61812f8d68ca109280c4e7589e4f968723aJaewan Kim    private final RemoteCallbackList<IEthernetServiceListener> mListeners =
58a3d7e61812f8d68ca109280c4e7589e4f968723aJaewan Kim            new RemoteCallbackList<IEthernetServiceListener>();
5920c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti
6020c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti    public EthernetServiceImpl(Context context) {
6120c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti        mContext = context;
6220c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti        Log.i(TAG, "Creating EthernetConfigStore");
6320c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti        mEthernetConfigStore = new EthernetConfigStore();
6420c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti        mIpConfiguration = mEthernetConfigStore.readIpAndProxyConfigurations();
6520c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti
6620c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti        Log.i(TAG, "Read stored IP configuration: " + mIpConfiguration);
6720c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti
68a3d7e61812f8d68ca109280c4e7589e4f968723aJaewan Kim        mTracker = new EthernetNetworkFactory(mListeners);
6920c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti    }
7020c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti
7120c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti    private void enforceAccessPermission() {
7220c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti        mContext.enforceCallingOrSelfPermission(
7320c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti                android.Manifest.permission.ACCESS_NETWORK_STATE,
7420c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti                "EthernetService");
7520c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti    }
7620c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti
7720c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti    private void enforceChangePermission() {
7876502788598a85d24b9ae3e253016a9370c49a42Billy Lau        int uid = Binder.getCallingUid();
7976502788598a85d24b9ae3e253016a9370c49a42Billy Lau        Settings.checkAndNoteChangeNetworkStateOperation(mContext, uid, Settings
8076502788598a85d24b9ae3e253016a9370c49a42Billy Lau                .getPackageNameForUid(mContext, uid), true);
8120c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti    }
8220c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti
8320c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti    private void enforceConnectivityInternalPermission() {
8420c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti        mContext.enforceCallingOrSelfPermission(
8520c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti                android.Manifest.permission.CONNECTIVITY_INTERNAL,
8620c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti                "ConnectivityService");
8720c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti    }
8820c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti
8920c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti    public void start() {
9020c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti        Log.i(TAG, "Starting Ethernet service");
9120c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti
9220c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti        HandlerThread handlerThread = new HandlerThread("EthernetServiceThread");
9320c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti        handlerThread.start();
9420c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti        mHandler = new Handler(handlerThread.getLooper());
9520c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti
9620c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti        mTracker.start(mContext, mHandler);
9720c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti
9820c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti        mStarted.set(true);
9920c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti    }
10020c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti
10120c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti    /**
10220c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti     * Get Ethernet configuration
10320c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti     * @return the Ethernet Configuration, contained in {@link IpConfiguration}.
10420c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti     */
105a3d7e61812f8d68ca109280c4e7589e4f968723aJaewan Kim    @Override
10620c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti    public IpConfiguration getConfiguration() {
10720c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti        enforceAccessPermission();
10820c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti
10920c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti        synchronized (mIpConfiguration) {
11020c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti            return new IpConfiguration(mIpConfiguration);
11120c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti        }
11220c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti    }
11320c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti
11420c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti    /**
11520c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti     * Set Ethernet configuration
11620c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti     */
117a3d7e61812f8d68ca109280c4e7589e4f968723aJaewan Kim    @Override
11820c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti    public void setConfiguration(IpConfiguration config) {
11920c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti        if (!mStarted.get()) {
12020c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti            Log.w(TAG, "System isn't ready enough to change ethernet configuration");
12120c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti        }
12220c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti
12320c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti        enforceChangePermission();
12420c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti        enforceConnectivityInternalPermission();
12520c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti
12620c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti        synchronized (mIpConfiguration) {
12720c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti            mEthernetConfigStore.writeIpAndProxyConfigurations(config);
12820c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti
12920c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti            // TODO: this does not check proxy settings, gateways, etc.
13020c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti            // Fix this by making IpConfiguration a complete representation of static configuration.
13120c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti            if (!config.equals(mIpConfiguration)) {
13241a372f13a7d19807d91e09f2e955b8a61f02d5cLorenzo Colitti                mIpConfiguration = new IpConfiguration(config);
13320c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti                mTracker.stop();
13420c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti                mTracker.start(mContext, mHandler);
13520c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti            }
13620c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti        }
13720c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti    }
138a3d7e61812f8d68ca109280c4e7589e4f968723aJaewan Kim
139a3d7e61812f8d68ca109280c4e7589e4f968723aJaewan Kim    /**
140a3d7e61812f8d68ca109280c4e7589e4f968723aJaewan Kim     * Indicates whether the system currently has one or more
141a3d7e61812f8d68ca109280c4e7589e4f968723aJaewan Kim     * Ethernet interfaces.
142a3d7e61812f8d68ca109280c4e7589e4f968723aJaewan Kim     */
143a3d7e61812f8d68ca109280c4e7589e4f968723aJaewan Kim    @Override
144a3d7e61812f8d68ca109280c4e7589e4f968723aJaewan Kim    public boolean isAvailable() {
145a3d7e61812f8d68ca109280c4e7589e4f968723aJaewan Kim        enforceAccessPermission();
146a3d7e61812f8d68ca109280c4e7589e4f968723aJaewan Kim        return mTracker.isTrackingInterface();
147a3d7e61812f8d68ca109280c4e7589e4f968723aJaewan Kim    }
148a3d7e61812f8d68ca109280c4e7589e4f968723aJaewan Kim
149a3d7e61812f8d68ca109280c4e7589e4f968723aJaewan Kim    /**
150a3d7e61812f8d68ca109280c4e7589e4f968723aJaewan Kim     * Addes a listener.
151a3d7e61812f8d68ca109280c4e7589e4f968723aJaewan Kim     * @param listener A {@link IEthernetServiceListener} to add.
152a3d7e61812f8d68ca109280c4e7589e4f968723aJaewan Kim     */
153a3d7e61812f8d68ca109280c4e7589e4f968723aJaewan Kim    public void addListener(IEthernetServiceListener listener) {
154a3d7e61812f8d68ca109280c4e7589e4f968723aJaewan Kim        if (listener == null) {
155a3d7e61812f8d68ca109280c4e7589e4f968723aJaewan Kim            throw new IllegalArgumentException("listener must not be null");
156a3d7e61812f8d68ca109280c4e7589e4f968723aJaewan Kim        }
157a3d7e61812f8d68ca109280c4e7589e4f968723aJaewan Kim        enforceAccessPermission();
158a3d7e61812f8d68ca109280c4e7589e4f968723aJaewan Kim        mListeners.register(listener);
159a3d7e61812f8d68ca109280c4e7589e4f968723aJaewan Kim    }
160a3d7e61812f8d68ca109280c4e7589e4f968723aJaewan Kim
161a3d7e61812f8d68ca109280c4e7589e4f968723aJaewan Kim    /**
162a3d7e61812f8d68ca109280c4e7589e4f968723aJaewan Kim     * Removes a listener.
163a3d7e61812f8d68ca109280c4e7589e4f968723aJaewan Kim     * @param listener A {@link IEthernetServiceListener} to remove.
164a3d7e61812f8d68ca109280c4e7589e4f968723aJaewan Kim     */
165a3d7e61812f8d68ca109280c4e7589e4f968723aJaewan Kim    public void removeListener(IEthernetServiceListener listener) {
166a3d7e61812f8d68ca109280c4e7589e4f968723aJaewan Kim        if (listener == null) {
167a3d7e61812f8d68ca109280c4e7589e4f968723aJaewan Kim            throw new IllegalArgumentException("listener must not be null");
168a3d7e61812f8d68ca109280c4e7589e4f968723aJaewan Kim        }
169a3d7e61812f8d68ca109280c4e7589e4f968723aJaewan Kim        enforceAccessPermission();
170a3d7e61812f8d68ca109280c4e7589e4f968723aJaewan Kim        mListeners.unregister(listener);
171a3d7e61812f8d68ca109280c4e7589e4f968723aJaewan Kim    }
17220c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti
17320c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti    @Override
17420c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti    protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
17520c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti        final IndentingPrintWriter pw = new IndentingPrintWriter(writer, "  ");
17620c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
17720c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti                != PackageManager.PERMISSION_GRANTED) {
17820c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti            pw.println("Permission Denial: can't dump EthernetService from pid="
17920c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti                    + Binder.getCallingPid()
18020c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti                    + ", uid=" + Binder.getCallingUid());
18120c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti            return;
18220c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti        }
18320c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti
184aea43f5901e6591c390b83b10d3dd9b515a6442aLorenzo Colitti        pw.println("Current Ethernet state: ");
185aea43f5901e6591c390b83b10d3dd9b515a6442aLorenzo Colitti        pw.increaseIndent();
186aea43f5901e6591c390b83b10d3dd9b515a6442aLorenzo Colitti        mTracker.dump(fd, pw, args);
187aea43f5901e6591c390b83b10d3dd9b515a6442aLorenzo Colitti        pw.decreaseIndent();
188aea43f5901e6591c390b83b10d3dd9b515a6442aLorenzo Colitti
189aea43f5901e6591c390b83b10d3dd9b515a6442aLorenzo Colitti        pw.println();
190aea43f5901e6591c390b83b10d3dd9b515a6442aLorenzo Colitti        pw.println("Stored Ethernet configuration: ");
19120c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti        pw.increaseIndent();
19220c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti        pw.println(mIpConfiguration);
19320c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti        pw.decreaseIndent();
19420c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti
19520c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti        pw.println("Handler:");
19620c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti        pw.increaseIndent();
19720c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti        mHandler.dump(new PrintWriterPrinter(pw), "EthernetServiceImpl");
19820c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti        pw.decreaseIndent();
19920c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti    }
20020c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti}
201