Initial EthernetService implementation.
Bug: 14981801 Bug: 14993642 Change-Id: If392ef7063e096854ef830f4fe3b038439a1d307
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user