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.net.ConnectivityManager;
|
||||
import android.net.INetd;
|
||||
import android.net.INetdUnsolicitedEventListener;
|
||||
import android.net.INetworkManagementEventObserver;
|
||||
import android.net.ITetheringStatsProvider;
|
||||
import android.net.InetAddresses;
|
||||
import android.net.InterfaceConfiguration;
|
||||
import android.net.InterfaceConfigurationParcel;
|
||||
import android.net.IpPrefix;
|
||||
@@ -61,7 +63,6 @@ import android.net.RouteInfo;
|
||||
import android.net.TetherStatsParcel;
|
||||
import android.net.UidRange;
|
||||
import android.net.shared.NetdService;
|
||||
import android.net.shared.NetworkObserverRegistry;
|
||||
import android.os.BatteryStats;
|
||||
import android.os.Binder;
|
||||
import android.os.Handler;
|
||||
@@ -205,13 +206,16 @@ public class NetworkManagementService extends INetworkManagementService.Stub
|
||||
|
||||
private INetd mNetdService;
|
||||
|
||||
private NMSNetworkObserverRegistry mNetworkObserverRegistry;
|
||||
private final NetdUnsolicitedEventListener mNetdUnsolicitedEventListener;
|
||||
|
||||
private IBatteryStats mBatteryStats;
|
||||
|
||||
private final Thread mThread;
|
||||
private CountDownLatch mConnectedSignal = new CountDownLatch(1);
|
||||
|
||||
private final RemoteCallbackList<INetworkManagementEventObserver> mObservers =
|
||||
new RemoteCallbackList<>();
|
||||
|
||||
private final NetworkStatsFactory mStatsFactory = new NetworkStatsFactory();
|
||||
|
||||
@GuardedBy("mTetheringStatsProviders")
|
||||
@@ -321,6 +325,8 @@ public class NetworkManagementService extends INetworkManagementService.Stub
|
||||
|
||||
mDaemonHandler = new Handler(FgThread.get().getLooper());
|
||||
|
||||
mNetdUnsolicitedEventListener = new NetdUnsolicitedEventListener();
|
||||
|
||||
// Add ourself to the Watchdog monitors.
|
||||
Watchdog.getInstance().addMonitor(this);
|
||||
|
||||
@@ -339,7 +345,7 @@ public class NetworkManagementService extends INetworkManagementService.Stub
|
||||
mFgHandler = null;
|
||||
mThread = null;
|
||||
mServices = null;
|
||||
mNetworkObserverRegistry = null;
|
||||
mNetdUnsolicitedEventListener = null;
|
||||
}
|
||||
|
||||
static NetworkManagementService create(Context context, String socket, SystemServices services)
|
||||
@@ -387,12 +393,14 @@ public class NetworkManagementService extends INetworkManagementService.Stub
|
||||
|
||||
@Override
|
||||
public void registerObserver(INetworkManagementEventObserver observer) {
|
||||
mNetworkObserverRegistry.registerObserver(observer);
|
||||
mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
|
||||
mObservers.register(observer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unregisterObserver(INetworkManagementEventObserver observer) {
|
||||
mNetworkObserverRegistry.unregisterObserver(observer);
|
||||
mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
|
||||
mObservers.unregister(observer);
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
@@ -400,97 +408,123 @@ public class NetworkManagementService extends INetworkManagementService.Stub
|
||||
public void sendCallback(INetworkManagementEventObserver o) throws RemoteException;
|
||||
}
|
||||
|
||||
private class NMSNetworkObserverRegistry extends NetworkObserverRegistry {
|
||||
NMSNetworkObserverRegistry(Context context, Handler handler, INetd netd)
|
||||
throws RemoteException {
|
||||
super(context, handler, netd);
|
||||
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
|
||||
*/
|
||||
@Override
|
||||
public 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;
|
||||
/**
|
||||
* Notify our observers of an interface status change
|
||||
*/
|
||||
private void notifyInterfaceStatusChanged(String iface, boolean up) {
|
||||
invokeForAllObservers(o -> o.interfaceStatusChanged(iface, up));
|
||||
}
|
||||
|
||||
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) {
|
||||
mLastPowerStateFromRadio = powerState;
|
||||
try {
|
||||
getBatteryStats().noteMobileRadioPowerState(powerState, tsNanos, uid);
|
||||
} catch (RemoteException e) {
|
||||
}
|
||||
/**
|
||||
* Notify our observers of an interface link state change
|
||||
* (typically, an Ethernet cable has been plugged-in or unplugged).
|
||||
*/
|
||||
private void notifyInterfaceLinkStateChanged(String iface, boolean up) {
|
||||
invokeForAllObservers(o -> o.interfaceLinkStateChanged(iface, up));
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify our observers of an interface addition.
|
||||
*/
|
||||
private void notifyInterfaceAdded(String iface) {
|
||||
invokeForAllObservers(o -> o.interfaceAdded(iface));
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 (ConnectivityManager.isNetworkTypeWifi(type)) {
|
||||
if (mLastPowerStateFromWifi != powerState) {
|
||||
mLastPowerStateFromWifi = powerState;
|
||||
try {
|
||||
getBatteryStats().noteWifiRadioPowerState(powerState, tsNanos, uid);
|
||||
} catch (RemoteException e) {
|
||||
}
|
||||
if (mLastPowerStateFromRadio != powerState) {
|
||||
mLastPowerStateFromRadio = powerState;
|
||||
try {
|
||||
getBatteryStats().noteMobileRadioPowerState(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();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify our observers of an interface removal.
|
||||
*/
|
||||
@Override
|
||||
public 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);
|
||||
super.notifyInterfaceRemoved(iface);
|
||||
if (ConnectivityManager.isNetworkTypeWifi(type)) {
|
||||
if (mLastPowerStateFromWifi != powerState) {
|
||||
mLastPowerStateFromWifi = powerState;
|
||||
try {
|
||||
getBatteryStats().noteWifiRadioPowerState(powerState, tsNanos, uid);
|
||||
} catch (RemoteException e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@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));
|
||||
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;
|
||||
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;
|
||||
}
|
||||
// No current code examines the interface parameter in a global alert. Just pass null.
|
||||
mDaemonHandler.post(() -> mNetworkObserverRegistry.notifyLimitReached(
|
||||
LIMIT_GLOBAL_ALERT, null));
|
||||
mDaemonHandler.post(() -> notifyLimitReached(LIMIT_GLOBAL_ALERT, null));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -552,11 +585,10 @@ public class NetworkManagementService extends INetworkManagementService.Stub
|
||||
private void connectNativeNetdService() {
|
||||
mNetdService = mServices.getNetd();
|
||||
try {
|
||||
mNetworkObserverRegistry = new NMSNetworkObserverRegistry(
|
||||
mContext, mDaemonHandler, mNetdService);
|
||||
if (DBG) Slog.d(TAG, "Registered NetworkObserverRegistry");
|
||||
mNetdService.registerUnsolicitedEventListener(mNetdUnsolicitedEventListener);
|
||||
if (DBG) Slog.d(TAG, "Register unsolicited event listener");
|
||||
} 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
|
||||
//
|
||||
@@ -708,18 +852,16 @@ public class NetworkManagementService extends INetworkManagementService.Stub
|
||||
throw new IllegalStateException(errorMessage);
|
||||
}
|
||||
if (cooked[2].equals("added")) {
|
||||
mNetworkObserverRegistry.notifyInterfaceAdded(cooked[3]);
|
||||
notifyInterfaceAdded(cooked[3]);
|
||||
return true;
|
||||
} else if (cooked[2].equals("removed")) {
|
||||
mNetworkObserverRegistry.notifyInterfaceRemoved(cooked[3]);
|
||||
notifyInterfaceRemoved(cooked[3]);
|
||||
return true;
|
||||
} else if (cooked[2].equals("changed") && cooked.length == 5) {
|
||||
mNetworkObserverRegistry.notifyInterfaceStatusChanged(
|
||||
cooked[3], cooked[4].equals("up"));
|
||||
notifyInterfaceStatusChanged(cooked[3], cooked[4].equals("up"));
|
||||
return true;
|
||||
} else if (cooked[2].equals("linkstate") && cooked.length == 5) {
|
||||
mNetworkObserverRegistry.notifyInterfaceLinkStateChanged(
|
||||
cooked[3], cooked[4].equals("up"));
|
||||
notifyInterfaceLinkStateChanged(cooked[3], cooked[4].equals("up"));
|
||||
return true;
|
||||
}
|
||||
throw new IllegalStateException(errorMessage);
|
||||
@@ -733,7 +875,7 @@ public class NetworkManagementService extends INetworkManagementService.Stub
|
||||
throw new IllegalStateException(errorMessage);
|
||||
}
|
||||
if (cooked[2].equals("alert")) {
|
||||
mNetworkObserverRegistry.notifyLimitReached(cooked[3], cooked[4]);
|
||||
notifyLimitReached(cooked[3], cooked[4]);
|
||||
return true;
|
||||
}
|
||||
throw new IllegalStateException(errorMessage);
|
||||
@@ -759,9 +901,8 @@ public class NetworkManagementService extends INetworkManagementService.Stub
|
||||
timestampNanos = SystemClock.elapsedRealtimeNanos();
|
||||
}
|
||||
boolean isActive = cooked[2].equals("active");
|
||||
mNetworkObserverRegistry.notifyInterfaceClassActivity(
|
||||
Integer.parseInt(cooked[3]), isActive,
|
||||
timestampNanos, processUid, false);
|
||||
notifyInterfaceClassActivity(Integer.parseInt(cooked[3]),
|
||||
isActive, timestampNanos, processUid, false);
|
||||
return true;
|
||||
// break;
|
||||
case NetdResponseCode.InterfaceAddressChange:
|
||||
@@ -787,9 +928,9 @@ public class NetworkManagementService extends INetworkManagementService.Stub
|
||||
}
|
||||
|
||||
if (cooked[2].equals("updated")) {
|
||||
mNetworkObserverRegistry.notifyAddressUpdated(iface, address);
|
||||
notifyAddressUpdated(iface, address);
|
||||
} else {
|
||||
mNetworkObserverRegistry.notifyAddressRemoved(iface, address);
|
||||
notifyAddressRemoved(iface, address);
|
||||
}
|
||||
return true;
|
||||
// break;
|
||||
@@ -809,8 +950,7 @@ public class NetworkManagementService extends INetworkManagementService.Stub
|
||||
throw new IllegalStateException(errorMessage);
|
||||
}
|
||||
String[] servers = cooked[5].split(",");
|
||||
mNetworkObserverRegistry.notifyInterfaceDnsServerInfo(
|
||||
cooked[3], lifetime, servers);
|
||||
notifyInterfaceDnsServerInfo(cooked[3], lifetime, servers);
|
||||
}
|
||||
return true;
|
||||
// break;
|
||||
@@ -849,8 +989,7 @@ public class NetworkManagementService extends INetworkManagementService.Stub
|
||||
InetAddress gateway = null;
|
||||
if (via != null) gateway = InetAddress.parseNumericAddress(via);
|
||||
RouteInfo route = new RouteInfo(new IpPrefix(cooked[3]), gateway, dev);
|
||||
mNetworkObserverRegistry.notifyRouteChange(
|
||||
cooked[2].equals("updated"), route);
|
||||
notifyRouteChange(cooked[2].equals("updated"), route);
|
||||
return true;
|
||||
} catch (IllegalArgumentException e) {}
|
||||
}
|
||||
@@ -1313,8 +1452,8 @@ public class NetworkManagementService extends INetworkManagementService.Stub
|
||||
if (ConnectivityManager.isNetworkTypeMobile(type)) {
|
||||
mNetworkActive = false;
|
||||
}
|
||||
mDaemonHandler.post(() -> mNetworkObserverRegistry.notifyInterfaceClassActivity(
|
||||
type, true /* isActive */, SystemClock.elapsedRealtimeNanos(), -1, false));
|
||||
mDaemonHandler.post(() -> notifyInterfaceClassActivity(type, true,
|
||||
SystemClock.elapsedRealtimeNanos(), -1, false));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1337,9 +1476,8 @@ public class NetworkManagementService extends INetworkManagementService.Stub
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
mActiveIdleTimers.remove(iface);
|
||||
mDaemonHandler.post(() -> mNetworkObserverRegistry.notifyInterfaceClassActivity(
|
||||
params.type, false /* isActive */, SystemClock.elapsedRealtimeNanos(), -1,
|
||||
false));
|
||||
mDaemonHandler.post(() -> notifyInterfaceClassActivity(params.type, false,
|
||||
SystemClock.elapsedRealtimeNanos(), -1, 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