Merge "Cleanup NetworkManagementService for Netd commnads binder migrartion"
am: 3af01e2f46
Change-Id: I86ca4cab29099b26f797ef6fce94dbb6f5183b90
This commit is contained in:
@@ -241,27 +241,6 @@ interface INetworkManagementService
|
||||
*/
|
||||
void tetherLimitReached(ITetheringStatsProvider provider);
|
||||
|
||||
/**
|
||||
** PPPD
|
||||
**/
|
||||
|
||||
/**
|
||||
* Returns the list of currently known TTY devices on the system
|
||||
*/
|
||||
String[] listTtys();
|
||||
|
||||
/**
|
||||
* Attaches a PPP server daemon to the specified TTY with the specified
|
||||
* local/remote addresses.
|
||||
*/
|
||||
void attachPppd(String tty, String localAddr, String remoteAddr, String dns1Addr,
|
||||
String dns2Addr);
|
||||
|
||||
/**
|
||||
* Detaches a PPP server daemon from the specified TTY.
|
||||
*/
|
||||
void detachPppd(String tty);
|
||||
|
||||
/**
|
||||
** DATA USAGE RELATED
|
||||
**/
|
||||
|
||||
@@ -39,7 +39,6 @@ import static android.net.NetworkStats.TAG_NONE;
|
||||
import static android.net.NetworkStats.UID_ALL;
|
||||
import static android.net.TrafficStats.UID_TETHERING;
|
||||
|
||||
import static com.android.server.NetworkManagementService.NetdResponseCode.TtyListResult;
|
||||
import static com.android.server.NetworkManagementSocketTagger.PROP_QTAGUID_ENABLED;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
@@ -70,7 +69,6 @@ import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.os.INetworkActivityListener;
|
||||
import android.os.INetworkManagementService;
|
||||
import android.os.PowerManager;
|
||||
import android.os.Process;
|
||||
import android.os.RemoteCallbackList;
|
||||
import android.os.RemoteException;
|
||||
@@ -111,13 +109,11 @@ import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public class NetworkManagementService extends INetworkManagementService.Stub
|
||||
implements Watchdog.Monitor {
|
||||
public class NetworkManagementService extends INetworkManagementService.Stub {
|
||||
|
||||
/**
|
||||
* Helper class that encapsulates NetworkManagementService dependencies and makes them
|
||||
@@ -137,8 +133,6 @@ public class NetworkManagementService extends INetworkManagementService.Stub
|
||||
|
||||
private static final String TAG = "NetworkManagement";
|
||||
private static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG);
|
||||
private static final String NETD_TAG = "NetdConnector";
|
||||
static final String NETD_SERVICE_NAME = "netd";
|
||||
|
||||
private static final int MAX_UID_RANGES_PER_COMMAND = 10;
|
||||
|
||||
@@ -148,44 +142,6 @@ public class NetworkManagementService extends INetworkManagementService.Stub
|
||||
*/
|
||||
public static final String LIMIT_GLOBAL_ALERT = "globalAlert";
|
||||
|
||||
static class NetdResponseCode {
|
||||
/* Keep in sync with system/netd/server/ResponseCode.h */
|
||||
public static final int InterfaceListResult = 110;
|
||||
public static final int TetherInterfaceListResult = 111;
|
||||
public static final int TetherDnsFwdTgtListResult = 112;
|
||||
public static final int TtyListResult = 113;
|
||||
public static final int TetheringStatsListResult = 114;
|
||||
|
||||
public static final int TetherStatusResult = 210;
|
||||
public static final int IpFwdStatusResult = 211;
|
||||
public static final int InterfaceGetCfgResult = 213;
|
||||
public static final int SoftapStatusResult = 214;
|
||||
public static final int InterfaceRxCounterResult = 216;
|
||||
public static final int InterfaceTxCounterResult = 217;
|
||||
public static final int QuotaCounterResult = 220;
|
||||
public static final int TetheringStatsResult = 221;
|
||||
public static final int DnsProxyQueryResult = 222;
|
||||
public static final int ClatdStatusResult = 223;
|
||||
|
||||
public static final int InterfaceChange = 600;
|
||||
public static final int BandwidthControl = 601;
|
||||
public static final int InterfaceClassActivity = 613;
|
||||
public static final int InterfaceAddressChange = 614;
|
||||
public static final int InterfaceDnsServerInfo = 615;
|
||||
public static final int RouteChange = 616;
|
||||
public static final int StrictCleartext = 617;
|
||||
}
|
||||
|
||||
/**
|
||||
* String indicating a softap command.
|
||||
*/
|
||||
static final String SOFT_AP_COMMAND = "softap";
|
||||
|
||||
/**
|
||||
* String passed back to netd connector indicating softap command success.
|
||||
*/
|
||||
static final String SOFT_AP_COMMAND_SUCCESS = "Ok";
|
||||
|
||||
static final int DAEMON_MSG_MOBILE_CONN_REAL_TIME_INFO = 1;
|
||||
|
||||
static final boolean MODIFY_OPERATION_ADD = true;
|
||||
@@ -196,12 +152,6 @@ public class NetworkManagementService extends INetworkManagementService.Stub
|
||||
*/
|
||||
private final Context mContext;
|
||||
|
||||
/**
|
||||
* connector object for communicating with netd
|
||||
*/
|
||||
private final NativeDaemonConnector mConnector;
|
||||
|
||||
private final Handler mFgHandler;
|
||||
private final Handler mDaemonHandler;
|
||||
|
||||
private final SystemServices mServices;
|
||||
@@ -212,9 +162,6 @@ public class NetworkManagementService extends INetworkManagementService.Stub
|
||||
|
||||
private IBatteryStats mBatteryStats;
|
||||
|
||||
private final Thread mThread;
|
||||
private CountDownLatch mConnectedSignal = new CountDownLatch(1);
|
||||
|
||||
private final RemoteCallbackList<INetworkManagementEventObserver> mObservers =
|
||||
new RemoteCallbackList<>();
|
||||
|
||||
@@ -306,32 +253,14 @@ public class NetworkManagementService extends INetworkManagementService.Stub
|
||||
* @param context Binder context for this service
|
||||
*/
|
||||
private NetworkManagementService(
|
||||
Context context, String socket, SystemServices services) {
|
||||
Context context, SystemServices services) {
|
||||
mContext = context;
|
||||
mServices = services;
|
||||
|
||||
// make sure this is on the same looper as our NativeDaemonConnector for sync purposes
|
||||
mFgHandler = new Handler(FgThread.get().getLooper());
|
||||
|
||||
// Don't need this wake lock, since we now have a time stamp for when
|
||||
// the network actually went inactive. (It might be nice to still do this,
|
||||
// but I don't want to do it through the power manager because that pollutes the
|
||||
// battery stats history with pointless noise.)
|
||||
//PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
|
||||
PowerManager.WakeLock wl = null; //pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, NETD_TAG);
|
||||
|
||||
mConnector = new NativeDaemonConnector(
|
||||
new NetdCallbackReceiver(), socket, 10, NETD_TAG, 160, wl,
|
||||
FgThread.get().getLooper());
|
||||
mThread = new Thread(mConnector, NETD_TAG);
|
||||
|
||||
mDaemonHandler = new Handler(FgThread.get().getLooper());
|
||||
|
||||
mNetdUnsolicitedEventListener = new NetdUnsolicitedEventListener();
|
||||
|
||||
// Add ourself to the Watchdog monitors.
|
||||
Watchdog.getInstance().addMonitor(this);
|
||||
|
||||
mServices.registerLocalService(new LocalService());
|
||||
|
||||
synchronized (mTetheringStatsProviders) {
|
||||
@@ -341,25 +270,17 @@ public class NetworkManagementService extends INetworkManagementService.Stub
|
||||
|
||||
@VisibleForTesting
|
||||
NetworkManagementService() {
|
||||
mConnector = null;
|
||||
mContext = null;
|
||||
mDaemonHandler = null;
|
||||
mFgHandler = null;
|
||||
mThread = null;
|
||||
mServices = null;
|
||||
mNetdUnsolicitedEventListener = null;
|
||||
}
|
||||
|
||||
static NetworkManagementService create(Context context, String socket, SystemServices services)
|
||||
static NetworkManagementService create(Context context, SystemServices services)
|
||||
throws InterruptedException {
|
||||
final NetworkManagementService service =
|
||||
new NetworkManagementService(context, socket, services);
|
||||
final CountDownLatch connectedSignal = service.mConnectedSignal;
|
||||
new NetworkManagementService(context, services);
|
||||
if (DBG) Slog.d(TAG, "Creating NetworkManagementService");
|
||||
service.mThread.start();
|
||||
if (DBG) Slog.d(TAG, "Awaiting socket connection");
|
||||
connectedSignal.await();
|
||||
if (DBG) Slog.d(TAG, "Connected");
|
||||
if (DBG) Slog.d(TAG, "Connecting native netd service");
|
||||
service.connectNativeNetdService();
|
||||
if (DBG) Slog.d(TAG, "Connected");
|
||||
@@ -367,7 +288,7 @@ public class NetworkManagementService extends INetworkManagementService.Stub
|
||||
}
|
||||
|
||||
public static NetworkManagementService create(Context context) throws InterruptedException {
|
||||
return create(context, NETD_SERVICE_NAME, new SystemServices());
|
||||
return create(context, new SystemServices());
|
||||
}
|
||||
|
||||
public void systemReady() {
|
||||
@@ -806,212 +727,6 @@ public class NetworkManagementService extends INetworkManagementService.Stub
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Netd Callback handling
|
||||
//
|
||||
|
||||
private class NetdCallbackReceiver implements INativeDaemonConnectorCallbacks {
|
||||
@Override
|
||||
public void onDaemonConnected() {
|
||||
Slog.i(TAG, "onDaemonConnected()");
|
||||
// event is dispatched from internal NDC thread, so we prepare the
|
||||
// daemon back on main thread.
|
||||
if (mConnectedSignal != null) {
|
||||
// The system is booting and we're connecting to netd for the first time.
|
||||
mConnectedSignal.countDown();
|
||||
mConnectedSignal = null;
|
||||
} else {
|
||||
// We're reconnecting to netd after the socket connection
|
||||
// was interrupted (e.g., if it crashed).
|
||||
mFgHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
connectNativeNetdService();
|
||||
prepareNativeDaemon();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCheckHoldWakeLock(int code) {
|
||||
return code == NetdResponseCode.InterfaceClassActivity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onEvent(int code, String raw, String[] cooked) {
|
||||
String errorMessage = String.format("Invalid event from daemon (%s)", raw);
|
||||
switch (code) {
|
||||
case NetdResponseCode.InterfaceChange:
|
||||
/*
|
||||
* a network interface change occured
|
||||
* Format: "NNN Iface added <name>"
|
||||
* "NNN Iface removed <name>"
|
||||
* "NNN Iface changed <name> <up/down>"
|
||||
* "NNN Iface linkstatus <name> <up/down>"
|
||||
*/
|
||||
if (cooked.length < 4 || !cooked[1].equals("Iface")) {
|
||||
throw new IllegalStateException(errorMessage);
|
||||
}
|
||||
if (cooked[2].equals("added")) {
|
||||
notifyInterfaceAdded(cooked[3]);
|
||||
return true;
|
||||
} else if (cooked[2].equals("removed")) {
|
||||
notifyInterfaceRemoved(cooked[3]);
|
||||
return true;
|
||||
} else if (cooked[2].equals("changed") && cooked.length == 5) {
|
||||
notifyInterfaceStatusChanged(cooked[3], cooked[4].equals("up"));
|
||||
return true;
|
||||
} else if (cooked[2].equals("linkstate") && cooked.length == 5) {
|
||||
notifyInterfaceLinkStateChanged(cooked[3], cooked[4].equals("up"));
|
||||
return true;
|
||||
}
|
||||
throw new IllegalStateException(errorMessage);
|
||||
// break;
|
||||
case NetdResponseCode.BandwidthControl:
|
||||
/*
|
||||
* Bandwidth control needs some attention
|
||||
* Format: "NNN limit alert <alertName> <ifaceName>"
|
||||
*/
|
||||
if (cooked.length < 5 || !cooked[1].equals("limit")) {
|
||||
throw new IllegalStateException(errorMessage);
|
||||
}
|
||||
if (cooked[2].equals("alert")) {
|
||||
notifyLimitReached(cooked[3], cooked[4]);
|
||||
return true;
|
||||
}
|
||||
throw new IllegalStateException(errorMessage);
|
||||
// break;
|
||||
case NetdResponseCode.InterfaceClassActivity:
|
||||
/*
|
||||
* An network interface class state changed (active/idle)
|
||||
* Format: "NNN IfaceClass <active/idle> <label>"
|
||||
*/
|
||||
if (cooked.length < 4 || !cooked[1].equals("IfaceClass")) {
|
||||
throw new IllegalStateException(errorMessage);
|
||||
}
|
||||
long timestampNanos = 0;
|
||||
int processUid = -1;
|
||||
if (cooked.length >= 5) {
|
||||
try {
|
||||
timestampNanos = Long.parseLong(cooked[4]);
|
||||
if (cooked.length == 6) {
|
||||
processUid = Integer.parseInt(cooked[5]);
|
||||
}
|
||||
} catch(NumberFormatException ne) {}
|
||||
} else {
|
||||
timestampNanos = SystemClock.elapsedRealtimeNanos();
|
||||
}
|
||||
boolean isActive = cooked[2].equals("active");
|
||||
notifyInterfaceClassActivity(Integer.parseInt(cooked[3]),
|
||||
isActive, timestampNanos, processUid, false);
|
||||
return true;
|
||||
// break;
|
||||
case NetdResponseCode.InterfaceAddressChange:
|
||||
/*
|
||||
* A network address change occurred
|
||||
* Format: "NNN Address updated <addr> <iface> <flags> <scope>"
|
||||
* "NNN Address removed <addr> <iface> <flags> <scope>"
|
||||
*/
|
||||
if (cooked.length < 7 || !cooked[1].equals("Address")) {
|
||||
throw new IllegalStateException(errorMessage);
|
||||
}
|
||||
|
||||
String iface = cooked[4];
|
||||
LinkAddress address;
|
||||
try {
|
||||
int flags = Integer.parseInt(cooked[5]);
|
||||
int scope = Integer.parseInt(cooked[6]);
|
||||
address = new LinkAddress(cooked[3], flags, scope);
|
||||
} catch(NumberFormatException e) { // Non-numeric lifetime or scope.
|
||||
throw new IllegalStateException(errorMessage, e);
|
||||
} catch(IllegalArgumentException e) { // Malformed/invalid IP address.
|
||||
throw new IllegalStateException(errorMessage, e);
|
||||
}
|
||||
|
||||
if (cooked[2].equals("updated")) {
|
||||
notifyAddressUpdated(iface, address);
|
||||
} else {
|
||||
notifyAddressRemoved(iface, address);
|
||||
}
|
||||
return true;
|
||||
// break;
|
||||
case NetdResponseCode.InterfaceDnsServerInfo:
|
||||
/*
|
||||
* Information about available DNS servers has been received.
|
||||
* Format: "NNN DnsInfo servers <interface> <lifetime> <servers>"
|
||||
*/
|
||||
long lifetime; // Actually a 32-bit unsigned integer.
|
||||
|
||||
if (cooked.length == 6 &&
|
||||
cooked[1].equals("DnsInfo") &&
|
||||
cooked[2].equals("servers")) {
|
||||
try {
|
||||
lifetime = Long.parseLong(cooked[4]);
|
||||
} catch (NumberFormatException e) {
|
||||
throw new IllegalStateException(errorMessage);
|
||||
}
|
||||
String[] servers = cooked[5].split(",");
|
||||
notifyInterfaceDnsServerInfo(cooked[3], lifetime, servers);
|
||||
}
|
||||
return true;
|
||||
// break;
|
||||
case NetdResponseCode.RouteChange:
|
||||
/*
|
||||
* A route has been updated or removed.
|
||||
* Format: "NNN Route <updated|removed> <dst> [via <gateway] [dev <iface>]"
|
||||
*/
|
||||
if (!cooked[1].equals("Route") || cooked.length < 6) {
|
||||
throw new IllegalStateException(errorMessage);
|
||||
}
|
||||
|
||||
String via = null;
|
||||
String dev = null;
|
||||
boolean valid = true;
|
||||
for (int i = 4; (i + 1) < cooked.length && valid; i += 2) {
|
||||
if (cooked[i].equals("dev")) {
|
||||
if (dev == null) {
|
||||
dev = cooked[i+1];
|
||||
} else {
|
||||
valid = false; // Duplicate interface.
|
||||
}
|
||||
} else if (cooked[i].equals("via")) {
|
||||
if (via == null) {
|
||||
via = cooked[i+1];
|
||||
} else {
|
||||
valid = false; // Duplicate gateway.
|
||||
}
|
||||
} else {
|
||||
valid = false; // Unknown syntax.
|
||||
}
|
||||
}
|
||||
if (valid) {
|
||||
try {
|
||||
// InetAddress.parseNumericAddress(null) inexplicably returns ::1.
|
||||
InetAddress gateway = null;
|
||||
if (via != null) gateway = InetAddress.parseNumericAddress(via);
|
||||
RouteInfo route = new RouteInfo(new IpPrefix(cooked[3]), gateway, dev);
|
||||
notifyRouteChange(cooked[2].equals("updated"), route);
|
||||
return true;
|
||||
} catch (IllegalArgumentException e) {}
|
||||
}
|
||||
throw new IllegalStateException(errorMessage);
|
||||
// break;
|
||||
case NetdResponseCode.StrictCleartext:
|
||||
final int uid = Integer.parseInt(cooked[1]);
|
||||
final byte[] firstPacket = HexDump.hexStringToByteArray(cooked[2]);
|
||||
try {
|
||||
ActivityManager.getService().notifyCleartextNetwork(uid, firstPacket);
|
||||
} catch (RemoteException ignored) {
|
||||
}
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// INetworkManagementService members
|
||||
//
|
||||
@@ -1433,42 +1148,6 @@ public class NetworkManagementService extends INetworkManagementService.Stub
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] listTtys() {
|
||||
mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
|
||||
try {
|
||||
return NativeDaemonEvent.filterMessageList(
|
||||
mConnector.executeForList("list_ttys"), TtyListResult);
|
||||
} catch (NativeDaemonConnectorException e) {
|
||||
throw e.rethrowAsParcelableException();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void attachPppd(
|
||||
String tty, String localAddr, String remoteAddr, String dns1Addr, String dns2Addr) {
|
||||
mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
|
||||
try {
|
||||
mConnector.execute("pppd", "attach", tty,
|
||||
NetworkUtils.numericToInetAddress(localAddr).getHostAddress(),
|
||||
NetworkUtils.numericToInetAddress(remoteAddr).getHostAddress(),
|
||||
NetworkUtils.numericToInetAddress(dns1Addr).getHostAddress(),
|
||||
NetworkUtils.numericToInetAddress(dns2Addr).getHostAddress());
|
||||
} catch (NativeDaemonConnectorException e) {
|
||||
throw e.rethrowAsParcelableException();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void detachPppd(String tty) {
|
||||
mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
|
||||
try {
|
||||
mConnector.execute("pppd", "detach", tty);
|
||||
} catch (NativeDaemonConnectorException e) {
|
||||
throw e.rethrowAsParcelableException();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addIdleTimer(String iface, int timeout, final int type) {
|
||||
mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
|
||||
@@ -2289,22 +1968,10 @@ public class NetworkManagementService extends INetworkManagementService.Stub
|
||||
}
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void monitor() {
|
||||
if (mConnector != null) {
|
||||
mConnector.monitor();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
|
||||
if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
|
||||
|
||||
pw.println("NetworkManagementService NativeDaemonConnector Log:");
|
||||
mConnector.dump(fd, pw, args);
|
||||
pw.println();
|
||||
|
||||
pw.print("mMobileActivityFromRadio="); pw.print(mMobileActivityFromRadio);
|
||||
pw.print(" mLastPowerStateFromRadio="); pw.println(mLastPowerStateFromRadio);
|
||||
pw.print("mNetworkActive="); pw.println(mNetworkActive);
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package com.android.server;
|
||||
|
||||
import static org.mockito.Mockito.doNothing;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.reset;
|
||||
@@ -23,11 +24,11 @@ import static org.mockito.Mockito.timeout;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.content.Context;
|
||||
import android.net.INetd;
|
||||
import android.net.INetdUnsolicitedEventListener;
|
||||
import android.net.LinkAddress;
|
||||
import android.net.LocalServerSocket;
|
||||
import android.net.LocalSocket;
|
||||
import android.os.BatteryStats;
|
||||
import android.os.Binder;
|
||||
import android.os.IBinder;
|
||||
@@ -43,12 +44,11 @@ import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Captor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
/**
|
||||
* Tests for {@link NetworkManagementService}.
|
||||
*/
|
||||
@@ -56,16 +56,16 @@ import java.io.OutputStream;
|
||||
@SmallTest
|
||||
public class NetworkManagementServiceTest {
|
||||
|
||||
private static final String SOCKET_NAME = "__test__NetworkManagementServiceTest";
|
||||
private NetworkManagementService mNMService;
|
||||
private LocalServerSocket mServerSocket;
|
||||
private LocalSocket mSocket;
|
||||
private OutputStream mOutputStream;
|
||||
|
||||
@Mock private Context mContext;
|
||||
@Mock private IBatteryStats.Stub mBatteryStatsService;
|
||||
@Mock private INetd.Stub mNetdService;
|
||||
|
||||
@NonNull
|
||||
@Captor
|
||||
private ArgumentCaptor<INetdUnsolicitedEventListener> mUnsolListenerCaptor;
|
||||
|
||||
private final SystemServices mServices = new SystemServices() {
|
||||
@Override
|
||||
public IBinder getService(String name) {
|
||||
@@ -88,32 +88,15 @@ public class NetworkManagementServiceTest {
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
|
||||
// Set up a sheltered test environment.
|
||||
mServerSocket = new LocalServerSocket(SOCKET_NAME);
|
||||
|
||||
doNothing().when(mNetdService)
|
||||
.registerUnsolicitedEventListener(mUnsolListenerCaptor.capture());
|
||||
// Start the service and wait until it connects to our socket.
|
||||
mNMService = NetworkManagementService.create(mContext, SOCKET_NAME, mServices);
|
||||
mSocket = mServerSocket.accept();
|
||||
mOutputStream = mSocket.getOutputStream();
|
||||
mNMService = NetworkManagementService.create(mContext, mServices);
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
mNMService.shutdown();
|
||||
// Once NetworkManagementService#shutdown() actually does something and shutdowns
|
||||
// the underlying NativeDaemonConnector, the block below should be uncommented.
|
||||
// if (mOutputStream != null) mOutputStream.close();
|
||||
// if (mSocket != null) mSocket.close();
|
||||
// if (mServerSocket != null) mServerSocket.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a message on the netd socket and gives the events some time to make it back.
|
||||
*/
|
||||
private void sendMessage(String message) throws IOException {
|
||||
// Strings are null-terminated, so add "\0" at the end.
|
||||
mOutputStream.write((message + "\0").getBytes());
|
||||
}
|
||||
|
||||
private static <T> T expectSoon(T mock) {
|
||||
@@ -131,125 +114,78 @@ public class NetworkManagementServiceTest {
|
||||
|
||||
// Forget everything that happened to the mock so far, so we can explicitly verify
|
||||
// everything that happens and does not happen to it from now on.
|
||||
reset(observer);
|
||||
|
||||
// Now send NetworkManagementService messages and ensure that the observer methods are
|
||||
// called. After every valid message we expect a callback soon after; to ensure that
|
||||
INetdUnsolicitedEventListener unsolListener = mUnsolListenerCaptor.getValue();
|
||||
reset(observer);
|
||||
// Now call unsolListener methods and ensure that the observer methods are
|
||||
// called. After every method we expect a callback soon after; to ensure that
|
||||
// invalid messages don't cause any callbacks, we call verifyNoMoreInteractions at the end.
|
||||
|
||||
/**
|
||||
* Interface changes.
|
||||
*/
|
||||
sendMessage("600 Iface added rmnet12");
|
||||
unsolListener.onInterfaceAdded("rmnet12");
|
||||
expectSoon(observer).interfaceAdded("rmnet12");
|
||||
|
||||
sendMessage("600 Iface removed eth1");
|
||||
unsolListener.onInterfaceRemoved("eth1");
|
||||
expectSoon(observer).interfaceRemoved("eth1");
|
||||
|
||||
sendMessage("607 Iface removed eth1");
|
||||
// Invalid code.
|
||||
|
||||
sendMessage("600 Iface borked lo down");
|
||||
// Invalid event.
|
||||
|
||||
sendMessage("600 Iface changed clat4 up again");
|
||||
// Extra tokens.
|
||||
|
||||
sendMessage("600 Iface changed clat4 up");
|
||||
unsolListener.onInterfaceChanged("clat4", true);
|
||||
expectSoon(observer).interfaceStatusChanged("clat4", true);
|
||||
|
||||
sendMessage("600 Iface linkstate rmnet0 down");
|
||||
unsolListener.onInterfaceLinkStateChanged("rmnet0", false);
|
||||
expectSoon(observer).interfaceLinkStateChanged("rmnet0", false);
|
||||
|
||||
sendMessage("600 IFACE linkstate clat4 up");
|
||||
// Invalid group.
|
||||
|
||||
/**
|
||||
* Bandwidth control events.
|
||||
*/
|
||||
sendMessage("601 limit alert data rmnet_usb0");
|
||||
unsolListener.onQuotaLimitReached("data", "rmnet_usb0");
|
||||
expectSoon(observer).limitReached("data", "rmnet_usb0");
|
||||
|
||||
sendMessage("601 invalid alert data rmnet0");
|
||||
// Invalid group.
|
||||
|
||||
sendMessage("601 limit increased data rmnet0");
|
||||
// Invalid event.
|
||||
|
||||
|
||||
/**
|
||||
* Interface class activity.
|
||||
*/
|
||||
|
||||
sendMessage("613 IfaceClass active 1 1234 10012");
|
||||
unsolListener.onInterfaceClassActivityChanged(true, 1, 1234, 0);
|
||||
expectSoon(observer).interfaceClassDataActivityChanged("1", true, 1234);
|
||||
|
||||
sendMessage("613 IfaceClass idle 9 5678");
|
||||
unsolListener.onInterfaceClassActivityChanged(false, 9, 5678, 0);
|
||||
expectSoon(observer).interfaceClassDataActivityChanged("9", false, 5678);
|
||||
|
||||
sendMessage("613 IfaceClass reallyactive 9 4321");
|
||||
unsolListener.onInterfaceClassActivityChanged(false, 9, 4321, 0);
|
||||
expectSoon(observer).interfaceClassDataActivityChanged("9", false, 4321);
|
||||
|
||||
sendMessage("613 InterfaceClass reallyactive 1");
|
||||
// Invalid group.
|
||||
|
||||
|
||||
/**
|
||||
* IP address changes.
|
||||
*/
|
||||
sendMessage("614 Address updated fe80::1/64 wlan0 128 253");
|
||||
unsolListener.onInterfaceAddressUpdated("fe80::1/64", "wlan0", 128, 253);
|
||||
expectSoon(observer).addressUpdated("wlan0", new LinkAddress("fe80::1/64", 128, 253));
|
||||
|
||||
// There is no "added", so we take this as "removed".
|
||||
sendMessage("614 Address added fe80::1/64 wlan0 128 253");
|
||||
unsolListener.onInterfaceAddressRemoved("fe80::1/64", "wlan0", 128, 253);
|
||||
expectSoon(observer).addressRemoved("wlan0", new LinkAddress("fe80::1/64", 128, 253));
|
||||
|
||||
sendMessage("614 Address removed 2001:db8::1/64 wlan0 1 0");
|
||||
unsolListener.onInterfaceAddressRemoved("2001:db8::1/64", "wlan0", 1, 0);
|
||||
expectSoon(observer).addressRemoved("wlan0", new LinkAddress("2001:db8::1/64", 1, 0));
|
||||
|
||||
sendMessage("614 Address removed 2001:db8::1/64 wlan0 1");
|
||||
// Not enough arguments.
|
||||
|
||||
sendMessage("666 Address removed 2001:db8::1/64 wlan0 1 0");
|
||||
// Invalid code.
|
||||
|
||||
|
||||
/**
|
||||
* DNS information broadcasts.
|
||||
*/
|
||||
sendMessage("615 DnsInfo servers rmnet_usb0 3600 2001:db8::1");
|
||||
unsolListener.onInterfaceDnsServerInfo("rmnet_usb0", 3600, new String[]{"2001:db8::1"});
|
||||
expectSoon(observer).interfaceDnsServerInfo("rmnet_usb0", 3600,
|
||||
new String[]{"2001:db8::1"});
|
||||
|
||||
sendMessage("615 DnsInfo servers wlan0 14400 2001:db8::1,2001:db8::2");
|
||||
unsolListener.onInterfaceDnsServerInfo("wlan0", 14400,
|
||||
new String[]{"2001:db8::1", "2001:db8::2"});
|
||||
expectSoon(observer).interfaceDnsServerInfo("wlan0", 14400,
|
||||
new String[]{"2001:db8::1", "2001:db8::2"});
|
||||
|
||||
// We don't check for negative lifetimes, only for parse errors.
|
||||
sendMessage("615 DnsInfo servers wlan0 -3600 ::1");
|
||||
unsolListener.onInterfaceDnsServerInfo("wlan0", -3600, new String[]{"::1"});
|
||||
expectSoon(observer).interfaceDnsServerInfo("wlan0", -3600,
|
||||
new String[]{"::1"});
|
||||
|
||||
sendMessage("615 DnsInfo servers wlan0 SIXHUNDRED ::1");
|
||||
// Non-numeric lifetime.
|
||||
|
||||
sendMessage("615 DnsInfo servers wlan0 2001:db8::1");
|
||||
// Missing lifetime.
|
||||
|
||||
sendMessage("615 DnsInfo servers wlan0 3600");
|
||||
// No servers.
|
||||
|
||||
sendMessage("615 DnsInfo servers 3600 wlan0 2001:db8::1,2001:db8::2");
|
||||
// Non-numeric lifetime.
|
||||
|
||||
sendMessage("615 DnsInfo wlan0 7200 2001:db8::1,2001:db8::2");
|
||||
// Invalid tokens.
|
||||
|
||||
sendMessage("666 DnsInfo servers wlan0 5400 2001:db8::1");
|
||||
// Invalid code.
|
||||
|
||||
// No syntax checking on the addresses.
|
||||
sendMessage("615 DnsInfo servers wlan0 600 ,::,,foo,::1,");
|
||||
unsolListener.onInterfaceDnsServerInfo("wlan0", 600,
|
||||
new String[]{"", "::", "", "foo", "::1"});
|
||||
expectSoon(observer).interfaceDnsServerInfo("wlan0", 600,
|
||||
new String[]{"", "::", "", "foo", "::1"});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user