Merge "Revert "Extract network observer code from NetworkManagementService.""
am: 9fdc6d2963
Change-Id: Ib4a7b32a143b3c8f029ccd92191494cd9579e8bd
This commit is contained in:
@@ -47,8 +47,10 @@ import android.app.ActivityManager;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.net.ConnectivityManager;
|
import android.net.ConnectivityManager;
|
||||||
import android.net.INetd;
|
import android.net.INetd;
|
||||||
|
import android.net.INetdUnsolicitedEventListener;
|
||||||
import android.net.INetworkManagementEventObserver;
|
import android.net.INetworkManagementEventObserver;
|
||||||
import android.net.ITetheringStatsProvider;
|
import android.net.ITetheringStatsProvider;
|
||||||
|
import android.net.InetAddresses;
|
||||||
import android.net.InterfaceConfiguration;
|
import android.net.InterfaceConfiguration;
|
||||||
import android.net.InterfaceConfigurationParcel;
|
import android.net.InterfaceConfigurationParcel;
|
||||||
import android.net.IpPrefix;
|
import android.net.IpPrefix;
|
||||||
@@ -61,7 +63,6 @@ import android.net.RouteInfo;
|
|||||||
import android.net.TetherStatsParcel;
|
import android.net.TetherStatsParcel;
|
||||||
import android.net.UidRange;
|
import android.net.UidRange;
|
||||||
import android.net.shared.NetdService;
|
import android.net.shared.NetdService;
|
||||||
import android.net.shared.NetworkObserverRegistry;
|
|
||||||
import android.os.BatteryStats;
|
import android.os.BatteryStats;
|
||||||
import android.os.Binder;
|
import android.os.Binder;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
@@ -205,13 +206,16 @@ public class NetworkManagementService extends INetworkManagementService.Stub
|
|||||||
|
|
||||||
private INetd mNetdService;
|
private INetd mNetdService;
|
||||||
|
|
||||||
private NMSNetworkObserverRegistry mNetworkObserverRegistry;
|
private final NetdUnsolicitedEventListener mNetdUnsolicitedEventListener;
|
||||||
|
|
||||||
private IBatteryStats mBatteryStats;
|
private IBatteryStats mBatteryStats;
|
||||||
|
|
||||||
private final Thread mThread;
|
private final Thread mThread;
|
||||||
private CountDownLatch mConnectedSignal = new CountDownLatch(1);
|
private CountDownLatch mConnectedSignal = new CountDownLatch(1);
|
||||||
|
|
||||||
|
private final RemoteCallbackList<INetworkManagementEventObserver> mObservers =
|
||||||
|
new RemoteCallbackList<>();
|
||||||
|
|
||||||
private final NetworkStatsFactory mStatsFactory = new NetworkStatsFactory();
|
private final NetworkStatsFactory mStatsFactory = new NetworkStatsFactory();
|
||||||
|
|
||||||
@GuardedBy("mTetheringStatsProviders")
|
@GuardedBy("mTetheringStatsProviders")
|
||||||
@@ -321,6 +325,8 @@ public class NetworkManagementService extends INetworkManagementService.Stub
|
|||||||
|
|
||||||
mDaemonHandler = new Handler(FgThread.get().getLooper());
|
mDaemonHandler = new Handler(FgThread.get().getLooper());
|
||||||
|
|
||||||
|
mNetdUnsolicitedEventListener = new NetdUnsolicitedEventListener();
|
||||||
|
|
||||||
// Add ourself to the Watchdog monitors.
|
// Add ourself to the Watchdog monitors.
|
||||||
Watchdog.getInstance().addMonitor(this);
|
Watchdog.getInstance().addMonitor(this);
|
||||||
|
|
||||||
@@ -339,7 +345,7 @@ public class NetworkManagementService extends INetworkManagementService.Stub
|
|||||||
mFgHandler = null;
|
mFgHandler = null;
|
||||||
mThread = null;
|
mThread = null;
|
||||||
mServices = null;
|
mServices = null;
|
||||||
mNetworkObserverRegistry = null;
|
mNetdUnsolicitedEventListener = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
static NetworkManagementService create(Context context, String socket, SystemServices services)
|
static NetworkManagementService create(Context context, String socket, SystemServices services)
|
||||||
@@ -387,12 +393,14 @@ public class NetworkManagementService extends INetworkManagementService.Stub
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void registerObserver(INetworkManagementEventObserver observer) {
|
public void registerObserver(INetworkManagementEventObserver observer) {
|
||||||
mNetworkObserverRegistry.registerObserver(observer);
|
mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
|
||||||
|
mObservers.register(observer);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void unregisterObserver(INetworkManagementEventObserver observer) {
|
public void unregisterObserver(INetworkManagementEventObserver observer) {
|
||||||
mNetworkObserverRegistry.unregisterObserver(observer);
|
mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
|
||||||
|
mObservers.unregister(observer);
|
||||||
}
|
}
|
||||||
|
|
||||||
@FunctionalInterface
|
@FunctionalInterface
|
||||||
@@ -400,97 +408,123 @@ public class NetworkManagementService extends INetworkManagementService.Stub
|
|||||||
public void sendCallback(INetworkManagementEventObserver o) throws RemoteException;
|
public void sendCallback(INetworkManagementEventObserver o) throws RemoteException;
|
||||||
}
|
}
|
||||||
|
|
||||||
private class NMSNetworkObserverRegistry extends NetworkObserverRegistry {
|
private void invokeForAllObservers(NetworkManagementEventCallback eventCallback) {
|
||||||
NMSNetworkObserverRegistry(Context context, Handler handler, INetd netd)
|
final int length = mObservers.beginBroadcast();
|
||||||
throws RemoteException {
|
try {
|
||||||
super(context, handler, netd);
|
for (int i = 0; i < length; i++) {
|
||||||
|
try {
|
||||||
|
eventCallback.sendCallback(mObservers.getBroadcastItem(i));
|
||||||
|
} catch (RemoteException | RuntimeException e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
mObservers.finishBroadcast();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Notify our observers of a change in the data activity state of the interface
|
* Notify our observers of an interface status change
|
||||||
*/
|
*/
|
||||||
@Override
|
private void notifyInterfaceStatusChanged(String iface, boolean up) {
|
||||||
public void notifyInterfaceClassActivity(int type, boolean isActive, long tsNanos,
|
invokeForAllObservers(o -> o.interfaceStatusChanged(iface, up));
|
||||||
int uid, boolean fromRadio) {
|
}
|
||||||
final boolean isMobile = ConnectivityManager.isNetworkTypeMobile(type);
|
|
||||||
int powerState = isActive
|
|
||||||
? DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH
|
|
||||||
: DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
|
|
||||||
|
|
||||||
if (isMobile) {
|
/**
|
||||||
if (!fromRadio) {
|
* Notify our observers of an interface link state change
|
||||||
if (mMobileActivityFromRadio) {
|
* (typically, an Ethernet cable has been plugged-in or unplugged).
|
||||||
// If this call is not coming from a report from the radio itself, but we
|
*/
|
||||||
// have previously received reports from the radio, then we will take the
|
private void notifyInterfaceLinkStateChanged(String iface, boolean up) {
|
||||||
// power state to just be whatever the radio last reported.
|
invokeForAllObservers(o -> o.interfaceLinkStateChanged(iface, up));
|
||||||
powerState = mLastPowerStateFromRadio;
|
}
|
||||||
}
|
|
||||||
} else {
|
/**
|
||||||
mMobileActivityFromRadio = true;
|
* Notify our observers of an interface addition.
|
||||||
}
|
*/
|
||||||
if (mLastPowerStateFromRadio != powerState) {
|
private void notifyInterfaceAdded(String iface) {
|
||||||
mLastPowerStateFromRadio = powerState;
|
invokeForAllObservers(o -> o.interfaceAdded(iface));
|
||||||
try {
|
}
|
||||||
getBatteryStats().noteMobileRadioPowerState(powerState, tsNanos, uid);
|
|
||||||
} catch (RemoteException e) {
|
/**
|
||||||
}
|
* Notify our observers of an interface removal.
|
||||||
|
*/
|
||||||
|
private void notifyInterfaceRemoved(String iface) {
|
||||||
|
// netd already clears out quota and alerts for removed ifaces; update
|
||||||
|
// our sanity-checking state.
|
||||||
|
mActiveAlerts.remove(iface);
|
||||||
|
mActiveQuotas.remove(iface);
|
||||||
|
invokeForAllObservers(o -> o.interfaceRemoved(iface));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notify our observers of a limit reached.
|
||||||
|
*/
|
||||||
|
private void notifyLimitReached(String limitName, String iface) {
|
||||||
|
invokeForAllObservers(o -> o.limitReached(limitName, iface));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notify our observers of a change in the data activity state of the interface
|
||||||
|
*/
|
||||||
|
private void notifyInterfaceClassActivity(int type, boolean isActive, long tsNanos,
|
||||||
|
int uid, boolean fromRadio) {
|
||||||
|
final boolean isMobile = ConnectivityManager.isNetworkTypeMobile(type);
|
||||||
|
int powerState = isActive
|
||||||
|
? DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH
|
||||||
|
: DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
|
||||||
|
if (isMobile) {
|
||||||
|
if (!fromRadio) {
|
||||||
|
if (mMobileActivityFromRadio) {
|
||||||
|
// If this call is not coming from a report from the radio itself, but we
|
||||||
|
// have previously received reports from the radio, then we will take the
|
||||||
|
// power state to just be whatever the radio last reported.
|
||||||
|
powerState = mLastPowerStateFromRadio;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
mMobileActivityFromRadio = true;
|
||||||
}
|
}
|
||||||
|
if (mLastPowerStateFromRadio != powerState) {
|
||||||
if (ConnectivityManager.isNetworkTypeWifi(type)) {
|
mLastPowerStateFromRadio = powerState;
|
||||||
if (mLastPowerStateFromWifi != powerState) {
|
try {
|
||||||
mLastPowerStateFromWifi = powerState;
|
getBatteryStats().noteMobileRadioPowerState(powerState, tsNanos, uid);
|
||||||
try {
|
} catch (RemoteException e) {
|
||||||
getBatteryStats().noteWifiRadioPowerState(powerState, tsNanos, uid);
|
|
||||||
} catch (RemoteException e) {
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isMobile || fromRadio || !mMobileActivityFromRadio) {
|
|
||||||
// Report the change in data activity. We don't do this if this is a change
|
|
||||||
// on the mobile network, that is not coming from the radio itself, and we
|
|
||||||
// have previously seen change reports from the radio. In that case only
|
|
||||||
// the radio is the authority for the current state.
|
|
||||||
final boolean active = isActive;
|
|
||||||
super.notifyInterfaceClassActivity(type, isActive, tsNanos, uid, fromRadio);
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean report = false;
|
|
||||||
synchronized (mIdleTimerLock) {
|
|
||||||
if (mActiveIdleTimers.isEmpty()) {
|
|
||||||
// If there are no idle timers, we are not monitoring activity, so we
|
|
||||||
// are always considered active.
|
|
||||||
isActive = true;
|
|
||||||
}
|
|
||||||
if (mNetworkActive != isActive) {
|
|
||||||
mNetworkActive = isActive;
|
|
||||||
report = isActive;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (report) {
|
|
||||||
reportNetworkActive();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
if (ConnectivityManager.isNetworkTypeWifi(type)) {
|
||||||
* Notify our observers of an interface removal.
|
if (mLastPowerStateFromWifi != powerState) {
|
||||||
*/
|
mLastPowerStateFromWifi = powerState;
|
||||||
@Override
|
try {
|
||||||
public void notifyInterfaceRemoved(String iface) {
|
getBatteryStats().noteWifiRadioPowerState(powerState, tsNanos, uid);
|
||||||
// netd already clears out quota and alerts for removed ifaces; update
|
} catch (RemoteException e) {
|
||||||
// our sanity-checking state.
|
}
|
||||||
mActiveAlerts.remove(iface);
|
}
|
||||||
mActiveQuotas.remove(iface);
|
|
||||||
super.notifyInterfaceRemoved(iface);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
if (!isMobile || fromRadio || !mMobileActivityFromRadio) {
|
||||||
public void onStrictCleartextDetected(int uid, String hex) throws RemoteException {
|
// Report the change in data activity. We don't do this if this is a change
|
||||||
// Don't need to post to mDaemonHandler because the only thing
|
// on the mobile network, that is not coming from the radio itself, and we
|
||||||
// that notifyCleartextNetwork does is post to a handler
|
// have previously seen change reports from the radio. In that case only
|
||||||
ActivityManager.getService().notifyCleartextNetwork(uid,
|
// the radio is the authority for the current state.
|
||||||
HexDump.hexStringToByteArray(hex));
|
final boolean active = isActive;
|
||||||
|
invokeForAllObservers(o -> o.interfaceClassDataActivityChanged(
|
||||||
|
Integer.toString(type), active, tsNanos));
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean report = false;
|
||||||
|
synchronized (mIdleTimerLock) {
|
||||||
|
if (mActiveIdleTimers.isEmpty()) {
|
||||||
|
// If there are no idle timers, we are not monitoring activity, so we
|
||||||
|
// are always considered active.
|
||||||
|
isActive = true;
|
||||||
|
}
|
||||||
|
if (mNetworkActive != isActive) {
|
||||||
|
mNetworkActive = isActive;
|
||||||
|
report = isActive;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (report) {
|
||||||
|
reportNetworkActive();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -519,8 +553,7 @@ public class NetworkManagementService extends INetworkManagementService.Stub
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// No current code examines the interface parameter in a global alert. Just pass null.
|
// No current code examines the interface parameter in a global alert. Just pass null.
|
||||||
mDaemonHandler.post(() -> mNetworkObserverRegistry.notifyLimitReached(
|
mDaemonHandler.post(() -> notifyLimitReached(LIMIT_GLOBAL_ALERT, null));
|
||||||
LIMIT_GLOBAL_ALERT, null));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -552,11 +585,10 @@ public class NetworkManagementService extends INetworkManagementService.Stub
|
|||||||
private void connectNativeNetdService() {
|
private void connectNativeNetdService() {
|
||||||
mNetdService = mServices.getNetd();
|
mNetdService = mServices.getNetd();
|
||||||
try {
|
try {
|
||||||
mNetworkObserverRegistry = new NMSNetworkObserverRegistry(
|
mNetdService.registerUnsolicitedEventListener(mNetdUnsolicitedEventListener);
|
||||||
mContext, mDaemonHandler, mNetdService);
|
if (DBG) Slog.d(TAG, "Register unsolicited event listener");
|
||||||
if (DBG) Slog.d(TAG, "Registered NetworkObserverRegistry");
|
|
||||||
} catch (RemoteException | ServiceSpecificException e) {
|
} catch (RemoteException | ServiceSpecificException e) {
|
||||||
Slog.wtf(TAG, "Failed to register NetworkObserverRegistry: " + e);
|
Slog.e(TAG, "Failed to set Netd unsolicited event listener " + e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -660,6 +692,118 @@ public class NetworkManagementService extends INetworkManagementService.Stub
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notify our observers of a new or updated interface address.
|
||||||
|
*/
|
||||||
|
private void notifyAddressUpdated(String iface, LinkAddress address) {
|
||||||
|
invokeForAllObservers(o -> o.addressUpdated(iface, address));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notify our observers of a deleted interface address.
|
||||||
|
*/
|
||||||
|
private void notifyAddressRemoved(String iface, LinkAddress address) {
|
||||||
|
invokeForAllObservers(o -> o.addressRemoved(iface, address));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notify our observers of DNS server information received.
|
||||||
|
*/
|
||||||
|
private void notifyInterfaceDnsServerInfo(String iface, long lifetime, String[] addresses) {
|
||||||
|
invokeForAllObservers(o -> o.interfaceDnsServerInfo(iface, lifetime, addresses));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notify our observers of a route change.
|
||||||
|
*/
|
||||||
|
private void notifyRouteChange(boolean updated, RouteInfo route) {
|
||||||
|
if (updated) {
|
||||||
|
invokeForAllObservers(o -> o.routeUpdated(route));
|
||||||
|
} else {
|
||||||
|
invokeForAllObservers(o -> o.routeRemoved(route));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class NetdUnsolicitedEventListener extends INetdUnsolicitedEventListener.Stub {
|
||||||
|
@Override
|
||||||
|
public void onInterfaceClassActivityChanged(boolean isActive,
|
||||||
|
int label, long timestamp, int uid) throws RemoteException {
|
||||||
|
final long timestampNanos;
|
||||||
|
if (timestamp <= 0) {
|
||||||
|
timestampNanos = SystemClock.elapsedRealtimeNanos();
|
||||||
|
} else {
|
||||||
|
timestampNanos = timestamp;
|
||||||
|
}
|
||||||
|
mDaemonHandler.post(() ->
|
||||||
|
notifyInterfaceClassActivity(label, isActive, timestampNanos, uid, false));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onQuotaLimitReached(String alertName, String ifName)
|
||||||
|
throws RemoteException {
|
||||||
|
mDaemonHandler.post(() -> notifyLimitReached(alertName, ifName));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onInterfaceDnsServerInfo(String ifName,
|
||||||
|
long lifetime, String[] servers) throws RemoteException {
|
||||||
|
mDaemonHandler.post(() -> notifyInterfaceDnsServerInfo(ifName, lifetime, servers));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onInterfaceAddressUpdated(String addr,
|
||||||
|
String ifName, int flags, int scope) throws RemoteException {
|
||||||
|
final LinkAddress address = new LinkAddress(addr, flags, scope);
|
||||||
|
mDaemonHandler.post(() -> notifyAddressUpdated(ifName, address));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onInterfaceAddressRemoved(String addr,
|
||||||
|
String ifName, int flags, int scope) throws RemoteException {
|
||||||
|
final LinkAddress address = new LinkAddress(addr, flags, scope);
|
||||||
|
mDaemonHandler.post(() -> notifyAddressRemoved(ifName, address));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onInterfaceAdded(String ifName) throws RemoteException {
|
||||||
|
mDaemonHandler.post(() -> notifyInterfaceAdded(ifName));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onInterfaceRemoved(String ifName) throws RemoteException {
|
||||||
|
mDaemonHandler.post(() -> notifyInterfaceRemoved(ifName));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onInterfaceChanged(String ifName, boolean up)
|
||||||
|
throws RemoteException {
|
||||||
|
mDaemonHandler.post(() -> notifyInterfaceStatusChanged(ifName, up));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onInterfaceLinkStateChanged(String ifName, boolean up)
|
||||||
|
throws RemoteException {
|
||||||
|
mDaemonHandler.post(() -> notifyInterfaceLinkStateChanged(ifName, up));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onRouteChanged(boolean updated,
|
||||||
|
String route, String gateway, String ifName) throws RemoteException {
|
||||||
|
final RouteInfo processRoute = new RouteInfo(new IpPrefix(route),
|
||||||
|
("".equals(gateway)) ? null : InetAddresses.parseNumericAddress(gateway),
|
||||||
|
ifName);
|
||||||
|
mDaemonHandler.post(() -> notifyRouteChange(updated, processRoute));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onStrictCleartextDetected(int uid, String hex) throws RemoteException {
|
||||||
|
// Don't need to post to mDaemonHandler because the only thing
|
||||||
|
// that notifyCleartextNetwork does is post to a handler
|
||||||
|
ActivityManager.getService().notifyCleartextNetwork(uid,
|
||||||
|
HexDump.hexStringToByteArray(hex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Netd Callback handling
|
// Netd Callback handling
|
||||||
//
|
//
|
||||||
@@ -708,18 +852,16 @@ public class NetworkManagementService extends INetworkManagementService.Stub
|
|||||||
throw new IllegalStateException(errorMessage);
|
throw new IllegalStateException(errorMessage);
|
||||||
}
|
}
|
||||||
if (cooked[2].equals("added")) {
|
if (cooked[2].equals("added")) {
|
||||||
mNetworkObserverRegistry.notifyInterfaceAdded(cooked[3]);
|
notifyInterfaceAdded(cooked[3]);
|
||||||
return true;
|
return true;
|
||||||
} else if (cooked[2].equals("removed")) {
|
} else if (cooked[2].equals("removed")) {
|
||||||
mNetworkObserverRegistry.notifyInterfaceRemoved(cooked[3]);
|
notifyInterfaceRemoved(cooked[3]);
|
||||||
return true;
|
return true;
|
||||||
} else if (cooked[2].equals("changed") && cooked.length == 5) {
|
} else if (cooked[2].equals("changed") && cooked.length == 5) {
|
||||||
mNetworkObserverRegistry.notifyInterfaceStatusChanged(
|
notifyInterfaceStatusChanged(cooked[3], cooked[4].equals("up"));
|
||||||
cooked[3], cooked[4].equals("up"));
|
|
||||||
return true;
|
return true;
|
||||||
} else if (cooked[2].equals("linkstate") && cooked.length == 5) {
|
} else if (cooked[2].equals("linkstate") && cooked.length == 5) {
|
||||||
mNetworkObserverRegistry.notifyInterfaceLinkStateChanged(
|
notifyInterfaceLinkStateChanged(cooked[3], cooked[4].equals("up"));
|
||||||
cooked[3], cooked[4].equals("up"));
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
throw new IllegalStateException(errorMessage);
|
throw new IllegalStateException(errorMessage);
|
||||||
@@ -733,7 +875,7 @@ public class NetworkManagementService extends INetworkManagementService.Stub
|
|||||||
throw new IllegalStateException(errorMessage);
|
throw new IllegalStateException(errorMessage);
|
||||||
}
|
}
|
||||||
if (cooked[2].equals("alert")) {
|
if (cooked[2].equals("alert")) {
|
||||||
mNetworkObserverRegistry.notifyLimitReached(cooked[3], cooked[4]);
|
notifyLimitReached(cooked[3], cooked[4]);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
throw new IllegalStateException(errorMessage);
|
throw new IllegalStateException(errorMessage);
|
||||||
@@ -759,9 +901,8 @@ public class NetworkManagementService extends INetworkManagementService.Stub
|
|||||||
timestampNanos = SystemClock.elapsedRealtimeNanos();
|
timestampNanos = SystemClock.elapsedRealtimeNanos();
|
||||||
}
|
}
|
||||||
boolean isActive = cooked[2].equals("active");
|
boolean isActive = cooked[2].equals("active");
|
||||||
mNetworkObserverRegistry.notifyInterfaceClassActivity(
|
notifyInterfaceClassActivity(Integer.parseInt(cooked[3]),
|
||||||
Integer.parseInt(cooked[3]), isActive,
|
isActive, timestampNanos, processUid, false);
|
||||||
timestampNanos, processUid, false);
|
|
||||||
return true;
|
return true;
|
||||||
// break;
|
// break;
|
||||||
case NetdResponseCode.InterfaceAddressChange:
|
case NetdResponseCode.InterfaceAddressChange:
|
||||||
@@ -787,9 +928,9 @@ public class NetworkManagementService extends INetworkManagementService.Stub
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (cooked[2].equals("updated")) {
|
if (cooked[2].equals("updated")) {
|
||||||
mNetworkObserverRegistry.notifyAddressUpdated(iface, address);
|
notifyAddressUpdated(iface, address);
|
||||||
} else {
|
} else {
|
||||||
mNetworkObserverRegistry.notifyAddressRemoved(iface, address);
|
notifyAddressRemoved(iface, address);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
// break;
|
// break;
|
||||||
@@ -809,8 +950,7 @@ public class NetworkManagementService extends INetworkManagementService.Stub
|
|||||||
throw new IllegalStateException(errorMessage);
|
throw new IllegalStateException(errorMessage);
|
||||||
}
|
}
|
||||||
String[] servers = cooked[5].split(",");
|
String[] servers = cooked[5].split(",");
|
||||||
mNetworkObserverRegistry.notifyInterfaceDnsServerInfo(
|
notifyInterfaceDnsServerInfo(cooked[3], lifetime, servers);
|
||||||
cooked[3], lifetime, servers);
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
// break;
|
// break;
|
||||||
@@ -849,8 +989,7 @@ public class NetworkManagementService extends INetworkManagementService.Stub
|
|||||||
InetAddress gateway = null;
|
InetAddress gateway = null;
|
||||||
if (via != null) gateway = InetAddress.parseNumericAddress(via);
|
if (via != null) gateway = InetAddress.parseNumericAddress(via);
|
||||||
RouteInfo route = new RouteInfo(new IpPrefix(cooked[3]), gateway, dev);
|
RouteInfo route = new RouteInfo(new IpPrefix(cooked[3]), gateway, dev);
|
||||||
mNetworkObserverRegistry.notifyRouteChange(
|
notifyRouteChange(cooked[2].equals("updated"), route);
|
||||||
cooked[2].equals("updated"), route);
|
|
||||||
return true;
|
return true;
|
||||||
} catch (IllegalArgumentException e) {}
|
} catch (IllegalArgumentException e) {}
|
||||||
}
|
}
|
||||||
@@ -1313,8 +1452,8 @@ public class NetworkManagementService extends INetworkManagementService.Stub
|
|||||||
if (ConnectivityManager.isNetworkTypeMobile(type)) {
|
if (ConnectivityManager.isNetworkTypeMobile(type)) {
|
||||||
mNetworkActive = false;
|
mNetworkActive = false;
|
||||||
}
|
}
|
||||||
mDaemonHandler.post(() -> mNetworkObserverRegistry.notifyInterfaceClassActivity(
|
mDaemonHandler.post(() -> notifyInterfaceClassActivity(type, true,
|
||||||
type, true /* isActive */, SystemClock.elapsedRealtimeNanos(), -1, false));
|
SystemClock.elapsedRealtimeNanos(), -1, false));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1337,9 +1476,8 @@ public class NetworkManagementService extends INetworkManagementService.Stub
|
|||||||
throw new IllegalStateException(e);
|
throw new IllegalStateException(e);
|
||||||
}
|
}
|
||||||
mActiveIdleTimers.remove(iface);
|
mActiveIdleTimers.remove(iface);
|
||||||
mDaemonHandler.post(() -> mNetworkObserverRegistry.notifyInterfaceClassActivity(
|
mDaemonHandler.post(() -> notifyInterfaceClassActivity(params.type, false,
|
||||||
params.type, false /* isActive */, SystemClock.elapsedRealtimeNanos(), -1,
|
SystemClock.elapsedRealtimeNanos(), -1, false));
|
||||||
false));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,255 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2019 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 android.net.shared;
|
|
||||||
|
|
||||||
import static android.Manifest.permission.NETWORK_STACK;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.net.INetd;
|
|
||||||
import android.net.INetdUnsolicitedEventListener;
|
|
||||||
import android.net.INetworkManagementEventObserver;
|
|
||||||
import android.net.InetAddresses;
|
|
||||||
import android.net.IpPrefix;
|
|
||||||
import android.net.LinkAddress;
|
|
||||||
import android.net.RouteInfo;
|
|
||||||
import android.os.Handler;
|
|
||||||
import android.os.RemoteCallbackList;
|
|
||||||
import android.os.RemoteException;
|
|
||||||
import android.os.SystemClock;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A class for reporting network events to clients.
|
|
||||||
*
|
|
||||||
* Implements INetdUnsolicitedEventListener and registers with netd, and relays those events to
|
|
||||||
* all INetworkManagementEventObserver objects that have registered with it.
|
|
||||||
*
|
|
||||||
* TODO: Make the notifyXyz methods protected once subclasses (e.g., the NetworkManagementService
|
|
||||||
* subclass) no longer call them directly.
|
|
||||||
*
|
|
||||||
* TODO: change from RemoteCallbackList to direct in-process callbacks.
|
|
||||||
*/
|
|
||||||
public class NetworkObserverRegistry extends INetdUnsolicitedEventListener.Stub {
|
|
||||||
|
|
||||||
private final Context mContext;
|
|
||||||
private final Handler mDaemonHandler;
|
|
||||||
private static final String TAG = "NetworkObserverRegistry";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs a new instance and registers it with netd.
|
|
||||||
* This method should only be called once since netd will reject multiple registrations from
|
|
||||||
* the same process.
|
|
||||||
*/
|
|
||||||
public NetworkObserverRegistry(Context context, Handler handler, INetd netd)
|
|
||||||
throws RemoteException {
|
|
||||||
mContext = context;
|
|
||||||
mDaemonHandler = handler;
|
|
||||||
netd.registerUnsolicitedEventListener(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
private final RemoteCallbackList<INetworkManagementEventObserver> mObservers =
|
|
||||||
new RemoteCallbackList<>();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Registers the specified observer and start sending callbacks to it.
|
|
||||||
* This method may be called on any thread.
|
|
||||||
*/
|
|
||||||
public void registerObserver(INetworkManagementEventObserver observer) {
|
|
||||||
mContext.enforceCallingOrSelfPermission(NETWORK_STACK, TAG);
|
|
||||||
mObservers.register(observer);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Unregisters the specified observer and stop sending callbacks to it.
|
|
||||||
* This method may be called on any thread.
|
|
||||||
*/
|
|
||||||
public void unregisterObserver(INetworkManagementEventObserver observer) {
|
|
||||||
mContext.enforceCallingOrSelfPermission(NETWORK_STACK, TAG);
|
|
||||||
mObservers.unregister(observer);
|
|
||||||
}
|
|
||||||
|
|
||||||
@FunctionalInterface
|
|
||||||
private interface NetworkManagementEventCallback {
|
|
||||||
void sendCallback(INetworkManagementEventObserver o) throws RemoteException;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void invokeForAllObservers(NetworkManagementEventCallback eventCallback) {
|
|
||||||
final int length = mObservers.beginBroadcast();
|
|
||||||
try {
|
|
||||||
for (int i = 0; i < length; i++) {
|
|
||||||
try {
|
|
||||||
eventCallback.sendCallback(mObservers.getBroadcastItem(i));
|
|
||||||
} catch (RemoteException | RuntimeException e) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
mObservers.finishBroadcast();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Notify our observers of a change in the data activity state of the interface
|
|
||||||
*/
|
|
||||||
public void notifyInterfaceClassActivity(int type, boolean isActive, long tsNanos,
|
|
||||||
int uid, boolean fromRadio) {
|
|
||||||
invokeForAllObservers(o -> o.interfaceClassDataActivityChanged(
|
|
||||||
Integer.toString(type), isActive, tsNanos));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onInterfaceClassActivityChanged(boolean isActive,
|
|
||||||
int label, long timestamp, int uid) throws RemoteException {
|
|
||||||
final long timestampNanos;
|
|
||||||
if (timestamp <= 0) {
|
|
||||||
timestampNanos = SystemClock.elapsedRealtimeNanos();
|
|
||||||
} else {
|
|
||||||
timestampNanos = timestamp;
|
|
||||||
}
|
|
||||||
mDaemonHandler.post(() -> notifyInterfaceClassActivity(label, isActive,
|
|
||||||
timestampNanos, uid, false));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Notify our observers of a limit reached.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void onQuotaLimitReached(String alertName, String ifName) throws RemoteException {
|
|
||||||
mDaemonHandler.post(() -> notifyLimitReached(alertName, ifName));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Notify our observers of a limit reached.
|
|
||||||
*/
|
|
||||||
public void notifyLimitReached(String limitName, String iface) {
|
|
||||||
invokeForAllObservers(o -> o.limitReached(limitName, iface));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onInterfaceDnsServerInfo(String ifName,
|
|
||||||
long lifetime, String[] servers) throws RemoteException {
|
|
||||||
mDaemonHandler.post(() -> notifyInterfaceDnsServerInfo(ifName, lifetime, servers));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Notify our observers of DNS server information received.
|
|
||||||
*/
|
|
||||||
public void notifyInterfaceDnsServerInfo(String iface, long lifetime, String[] addresses) {
|
|
||||||
invokeForAllObservers(o -> o.interfaceDnsServerInfo(iface, lifetime, addresses));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onInterfaceAddressUpdated(String addr,
|
|
||||||
String ifName, int flags, int scope) throws RemoteException {
|
|
||||||
final LinkAddress address = new LinkAddress(addr, flags, scope);
|
|
||||||
mDaemonHandler.post(() -> notifyAddressUpdated(ifName, address));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Notify our observers of a new or updated interface address.
|
|
||||||
*/
|
|
||||||
public void notifyAddressUpdated(String iface, LinkAddress address) {
|
|
||||||
invokeForAllObservers(o -> o.addressUpdated(iface, address));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onInterfaceAddressRemoved(String addr,
|
|
||||||
String ifName, int flags, int scope) throws RemoteException {
|
|
||||||
final LinkAddress address = new LinkAddress(addr, flags, scope);
|
|
||||||
mDaemonHandler.post(() -> notifyAddressRemoved(ifName, address));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Notify our observers of a deleted interface address.
|
|
||||||
*/
|
|
||||||
public void notifyAddressRemoved(String iface, LinkAddress address) {
|
|
||||||
invokeForAllObservers(o -> o.addressRemoved(iface, address));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onInterfaceAdded(String ifName) throws RemoteException {
|
|
||||||
mDaemonHandler.post(() -> notifyInterfaceAdded(ifName));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Notify our observers of an interface addition.
|
|
||||||
*/
|
|
||||||
public void notifyInterfaceAdded(String iface) {
|
|
||||||
invokeForAllObservers(o -> o.interfaceAdded(iface));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onInterfaceRemoved(String ifName) throws RemoteException {
|
|
||||||
mDaemonHandler.post(() -> notifyInterfaceRemoved(ifName));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Notify our observers of an interface removal.
|
|
||||||
*/
|
|
||||||
public void notifyInterfaceRemoved(String iface) {
|
|
||||||
invokeForAllObservers(o -> o.interfaceRemoved(iface));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onInterfaceChanged(String ifName, boolean up) throws RemoteException {
|
|
||||||
mDaemonHandler.post(() -> notifyInterfaceStatusChanged(ifName, up));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Notify our observers of an interface status change
|
|
||||||
*/
|
|
||||||
public void notifyInterfaceStatusChanged(String iface, boolean up) {
|
|
||||||
invokeForAllObservers(o -> o.interfaceStatusChanged(iface, up));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onInterfaceLinkStateChanged(String ifName, boolean up) throws RemoteException {
|
|
||||||
mDaemonHandler.post(() -> notifyInterfaceLinkStateChanged(ifName, up));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Notify our observers of an interface link state change
|
|
||||||
* (typically, an Ethernet cable has been plugged-in or unplugged).
|
|
||||||
*/
|
|
||||||
public void notifyInterfaceLinkStateChanged(String iface, boolean up) {
|
|
||||||
invokeForAllObservers(o -> o.interfaceLinkStateChanged(iface, up));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onRouteChanged(boolean updated,
|
|
||||||
String route, String gateway, String ifName) throws RemoteException {
|
|
||||||
final RouteInfo processRoute = new RouteInfo(new IpPrefix(route),
|
|
||||||
("".equals(gateway)) ? null : InetAddresses.parseNumericAddress(gateway),
|
|
||||||
ifName);
|
|
||||||
mDaemonHandler.post(() -> notifyRouteChange(updated, processRoute));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Notify our observers of a route change.
|
|
||||||
*/
|
|
||||||
public void notifyRouteChange(boolean updated, RouteInfo route) {
|
|
||||||
if (updated) {
|
|
||||||
invokeForAllObservers(o -> o.routeUpdated(route));
|
|
||||||
} else {
|
|
||||||
invokeForAllObservers(o -> o.routeRemoved(route));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onStrictCleartextDetected(int uid, String hex) throws RemoteException {
|
|
||||||
// Don't do anything here because this is not a method of INetworkManagementEventObserver.
|
|
||||||
// Only the NMS subclass will implement this.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user