[IT4.6] Unbundle NMS out from ConnectivityManager

ConnectivityService is no longer to update idle timer to NMS but
send to INetd directly after this change. Replace the API
implementation in ConnectivityManager to refer into
ConnectivityService instead of NetworkManagementService to remove
the dependency between CM and NMS for ConnectivityService mainline.

Bug: 170598012
Test: atest FrameworksNetTests
Change-Id: If0ac9a6427dba5a732a15b5d7ca1351b71b07b7b
This commit is contained in:
lucaslin
2021-01-21 02:04:15 +08:00
committed by Chiachang Wang
parent b961efcbbc
commit 1193a5d5f1
3 changed files with 134 additions and 42 deletions

View File

@@ -50,7 +50,6 @@ import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
import android.os.IBinder; import android.os.IBinder;
import android.os.INetworkActivityListener; import android.os.INetworkActivityListener;
import android.os.INetworkManagementService;
import android.os.Looper; import android.os.Looper;
import android.os.Message; import android.os.Message;
import android.os.Messenger; import android.os.Messenger;
@@ -835,7 +834,6 @@ public class ConnectivityManager {
private final Context mContext; private final Context mContext;
private INetworkManagementService mNMService;
private INetworkPolicyManager mNPManager; private INetworkPolicyManager mNPManager;
private final TetheringManager mTetheringManager; private final TetheringManager mTetheringManager;
@@ -2211,17 +2209,6 @@ public class ConnectivityManager {
void onNetworkActive(); void onNetworkActive();
} }
private INetworkManagementService getNetworkManagementService() {
synchronized (this) {
if (mNMService != null) {
return mNMService;
}
IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
mNMService = INetworkManagementService.Stub.asInterface(b);
return mNMService;
}
}
private final ArrayMap<OnNetworkActiveListener, INetworkActivityListener> private final ArrayMap<OnNetworkActiveListener, INetworkActivityListener>
mNetworkActivityListeners = new ArrayMap<>(); mNetworkActivityListeners = new ArrayMap<>();
@@ -2246,7 +2233,7 @@ public class ConnectivityManager {
}; };
try { try {
getNetworkManagementService().registerNetworkActivityListener(rl); mService.registerNetworkActivityListener(rl);
mNetworkActivityListeners.put(l, rl); mNetworkActivityListeners.put(l, rl);
} catch (RemoteException e) { } catch (RemoteException e) {
throw e.rethrowFromSystemServer(); throw e.rethrowFromSystemServer();
@@ -2263,7 +2250,7 @@ public class ConnectivityManager {
INetworkActivityListener rl = mNetworkActivityListeners.get(l); INetworkActivityListener rl = mNetworkActivityListeners.get(l);
Preconditions.checkArgument(rl != null, "Listener was not registered."); Preconditions.checkArgument(rl != null, "Listener was not registered.");
try { try {
getNetworkManagementService().unregisterNetworkActivityListener(rl); mService.registerNetworkActivityListener(rl);
} catch (RemoteException e) { } catch (RemoteException e) {
throw e.rethrowFromSystemServer(); throw e.rethrowFromSystemServer();
} }
@@ -2279,7 +2266,7 @@ public class ConnectivityManager {
*/ */
public boolean isDefaultNetworkActive() { public boolean isDefaultNetworkActive() {
try { try {
return getNetworkManagementService().isNetworkActive(); return mService.isDefaultNetworkActive();
} catch (RemoteException e) { } catch (RemoteException e) {
throw e.rethrowFromSystemServer(); throw e.rethrowFromSystemServer();
} }

View File

@@ -164,6 +164,7 @@ import android.os.Parcelable;
import android.os.PersistableBundle; import android.os.PersistableBundle;
import android.os.PowerManager; import android.os.PowerManager;
import android.os.Process; import android.os.Process;
import android.os.RemoteCallbackList;
import android.os.RemoteException; import android.os.RemoteException;
import android.os.ServiceSpecificException; import android.os.ServiceSpecificException;
import android.os.SystemClock; import android.os.SystemClock;
@@ -173,6 +174,7 @@ import android.os.UserManager;
import android.provider.Settings; import android.provider.Settings;
import android.telephony.TelephonyManager; import android.telephony.TelephonyManager;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.ArraySet; import android.util.ArraySet;
import android.util.LocalLog; import android.util.LocalLog;
import android.util.Log; import android.util.Log;
@@ -559,6 +561,11 @@ public class ConnectivityService extends IConnectivityManager.Stub
*/ */
private static final int EVENT_SET_OEM_NETWORK_PREFERENCE = 48; private static final int EVENT_SET_OEM_NETWORK_PREFERENCE = 48;
/**
* Used to indicate the system default network becomes active.
*/
private static final int EVENT_REPORT_NETWORK_ACTIVITY = 49;
/** /**
* Argument for {@link #EVENT_PROVISIONING_NOTIFICATION} to indicate that the notification * Argument for {@link #EVENT_PROVISIONING_NOTIFICATION} to indicate that the notification
* should be shown. * should be shown.
@@ -1193,7 +1200,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
mUserAllContext.registerReceiver(mIntentReceiver, intentFilter, mUserAllContext.registerReceiver(mIntentReceiver, intentFilter,
null /* broadcastPermission */, mHandler); null /* broadcastPermission */, mHandler);
mNetworkActivityTracker = new LegacyNetworkActivityTracker(mContext, mNMS); mNetworkActivityTracker = new LegacyNetworkActivityTracker(mContext, mHandler, mNMS, mNetd);
mSettingsObserver = new SettingsObserver(mContext, mHandler); mSettingsObserver = new SettingsObserver(mContext, mHandler);
registerSettingsCallbacks(); registerSettingsCallbacks();
@@ -2405,7 +2412,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
*/ */
@Override @Override
public void registerNetworkActivityListener(@NonNull INetworkActivityListener l) { public void registerNetworkActivityListener(@NonNull INetworkActivityListener l) {
// TODO: Replace network activity listener registry in ConnectivityManager from NMS to here mNetworkActivityTracker.registerNetworkActivityListener(l);
} }
/** /**
@@ -2413,7 +2420,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
*/ */
@Override @Override
public void unregisterNetworkActivityListener(@NonNull INetworkActivityListener l) { public void unregisterNetworkActivityListener(@NonNull INetworkActivityListener l) {
// TODO: Replace network activity listener registry in ConnectivityManager from NMS to here mNetworkActivityTracker.unregisterNetworkActivityListener(l);
} }
/** /**
@@ -2421,8 +2428,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
*/ */
@Override @Override
public boolean isDefaultNetworkActive() { public boolean isDefaultNetworkActive() {
// TODO: Replace isNetworkActive() in NMS. return mNetworkActivityTracker.isDefaultNetworkActive();
return false;
} }
/** /**
@@ -4448,6 +4454,9 @@ public class ConnectivityService extends IConnectivityManager.Stub
loge("handleMessage.EVENT_SET_OEM_NETWORK_PREFERENCE failed", e); loge("handleMessage.EVENT_SET_OEM_NETWORK_PREFERENCE failed", e);
} }
break; break;
case EVENT_REPORT_NETWORK_ACTIVITY:
mNetworkActivityTracker.handleReportNetworkActivity();
break;
} }
} }
} }
@@ -8637,12 +8646,33 @@ public class ConnectivityService extends IConnectivityManager.Stub
private static final class LegacyNetworkActivityTracker { private static final class LegacyNetworkActivityTracker {
private static final int NO_UID = -1; private static final int NO_UID = -1;
private final Context mContext; private final Context mContext;
private final INetd mNetd;
private final INetworkManagementService mNMS; private final INetworkManagementService mNMS;
private final RemoteCallbackList<INetworkActivityListener> mNetworkActivityListeners =
new RemoteCallbackList<>();
// Indicate the current system default network activity is active or not.
@GuardedBy("mActiveIdleTimers")
private boolean mNetworkActive;
@GuardedBy("mActiveIdleTimers")
private final ArrayMap<String, IdleTimerParams> mActiveIdleTimers = new ArrayMap();
private final Handler mHandler;
LegacyNetworkActivityTracker(@NonNull Context context, private class IdleTimerParams {
@NonNull INetworkManagementService nms) { public final int timeout;
public final int transportType;
IdleTimerParams(int timeout, int transport) {
this.timeout = timeout;
this.transportType = transport;
}
}
LegacyNetworkActivityTracker(@NonNull Context context, @NonNull Handler handler,
@NonNull INetworkManagementService nms, @NonNull INetd netd) {
mContext = context; mContext = context;
mNMS = nms; mNMS = nms;
mNetd = netd;
mHandler = handler;
try { try {
mNMS.registerObserver(mDataActivityObserver); mNMS.registerObserver(mDataActivityObserver);
} catch (RemoteException e) { } catch (RemoteException e) {
@@ -8658,9 +8688,50 @@ public class ConnectivityService extends IConnectivityManager.Stub
long tsNanos, int uid) { long tsNanos, int uid) {
sendDataActivityBroadcast(transportTypeToLegacyType(transportType), active, sendDataActivityBroadcast(transportTypeToLegacyType(transportType), active,
tsNanos); tsNanos);
synchronized (mActiveIdleTimers) {
mNetworkActive = active;
// If there are no idle timers, it means that system is not monitoring
// activity, so the system default network for those default network
// unspecified apps is always considered active.
//
// TODO: If the mActiveIdleTimers is empty, netd will actually not send
// any network activity change event. Whenever this event is received,
// the mActiveIdleTimers should be always not empty. The legacy behavior
// is no-op. Remove to refer to mNetworkActive only.
if (mNetworkActive || mActiveIdleTimers.isEmpty()) {
mHandler.sendMessage(
mHandler.obtainMessage(EVENT_REPORT_NETWORK_ACTIVITY));
}
}
} }
}; };
// The network activity should only be updated from ConnectivityService handler thread
// when mActiveIdleTimers lock is held.
@GuardedBy("mActiveIdleTimers")
private void reportNetworkActive() {
final int length = mNetworkActivityListeners.beginBroadcast();
if (DDBG) log("reportNetworkActive, notify " + length + " listeners");
try {
for (int i = 0; i < length; i++) {
try {
mNetworkActivityListeners.getBroadcastItem(i).onNetworkActive();
} catch (RemoteException | RuntimeException e) {
loge("Fail to send network activie to listener " + e);
}
}
} finally {
mNetworkActivityListeners.finishBroadcast();
}
}
@GuardedBy("mActiveIdleTimers")
public void handleReportNetworkActivity() {
synchronized (mActiveIdleTimers) {
reportNetworkActive();
}
}
// This is deprecated and only to support legacy use cases. // This is deprecated and only to support legacy use cases.
private int transportTypeToLegacyType(int type) { private int transportTypeToLegacyType(int type) {
switch (type) { switch (type) {
@@ -8729,8 +8800,13 @@ public class ConnectivityService extends IConnectivityManager.Stub
if (timeout > 0 && iface != null) { if (timeout > 0 && iface != null) {
try { try {
// TODO: Access INetd directly instead of NMS synchronized (mActiveIdleTimers) {
mNMS.addIdleTimer(iface, timeout, type); // Networks start up.
mNetworkActive = true;
mActiveIdleTimers.put(iface, new IdleTimerParams(timeout, type));
mNetd.idletimerAddInterface(iface, timeout, Integer.toString(type));
reportNetworkActive();
}
} catch (Exception e) { } catch (Exception e) {
// You shall not crash! // You shall not crash!
loge("Exception in setupDataActivityTracking " + e); loge("Exception in setupDataActivityTracking " + e);
@@ -8758,9 +8834,12 @@ public class ConnectivityService extends IConnectivityManager.Stub
try { try {
updateRadioPowerState(false /* isActive */, type); updateRadioPowerState(false /* isActive */, type);
// The call fails silently if no idle timer setup for this interface. synchronized (mActiveIdleTimers) {
// TODO: Access INetd directly instead of NMS final IdleTimerParams params = mActiveIdleTimers.remove(iface);
mNMS.removeIdleTimer(iface); // The call fails silently if no idle timer setup for this interface
mNetd.idletimerRemoveInterface(iface, params.timeout,
Integer.toString(params.transportType));
}
} catch (Exception e) { } catch (Exception e) {
// You shall not crash! // You shall not crash!
loge("Exception in removeDataActivityTracking " + e); loge("Exception in removeDataActivityTracking " + e);
@@ -8793,6 +8872,26 @@ public class ConnectivityService extends IConnectivityManager.Stub
logw("Untracked transport type:" + transportType); logw("Untracked transport type:" + transportType);
} }
} }
public boolean isDefaultNetworkActive() {
synchronized (mActiveIdleTimers) {
// If there are no idle timers, it means that system is not monitoring activity,
// so the default network is always considered active.
//
// TODO : Distinguish between the cases where mActiveIdleTimers is empty because
// tracking is disabled (negative idle timer value configured), or no active default
// network. In the latter case, this reports active but it should report inactive.
return mNetworkActive || mActiveIdleTimers.isEmpty();
}
}
public void registerNetworkActivityListener(@NonNull INetworkActivityListener l) {
mNetworkActivityListeners.register(l);
}
public void unregisterNetworkActivityListener(@NonNull INetworkActivityListener l) {
mNetworkActivityListeners.unregister(l);
}
} }
/** /**

View File

@@ -8205,8 +8205,8 @@ public class ConnectivityServiceTest {
reset(mNetworkManagementService); reset(mNetworkManagementService);
mCellNetworkAgent.connect(true); mCellNetworkAgent.connect(true);
networkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); networkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
verify(mNetworkManagementService, times(1)).addIdleTimer(eq(MOBILE_IFNAME), anyInt(), verify(mMockNetd, times(1)).idletimerAddInterface(eq(MOBILE_IFNAME), anyInt(),
eq(NetworkCapabilities.TRANSPORT_CELLULAR)); eq(Integer.toString(TRANSPORT_CELLULAR)));
mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
final LinkProperties wifiLp = new LinkProperties(); final LinkProperties wifiLp = new LinkProperties();
@@ -8214,25 +8214,27 @@ public class ConnectivityServiceTest {
mWiFiNetworkAgent.sendLinkProperties(wifiLp); mWiFiNetworkAgent.sendLinkProperties(wifiLp);
// Network switch // Network switch
reset(mNetworkManagementService);
mWiFiNetworkAgent.connect(true); mWiFiNetworkAgent.connect(true);
networkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); networkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
networkCallback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent); networkCallback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
networkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent); networkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
verify(mNetworkManagementService, times(1)).addIdleTimer(eq(WIFI_IFNAME), anyInt(), verify(mMockNetd, times(1)).idletimerAddInterface(eq(WIFI_IFNAME), anyInt(),
eq(NetworkCapabilities.TRANSPORT_WIFI)); eq(Integer.toString(TRANSPORT_WIFI)));
verify(mNetworkManagementService, times(1)).removeIdleTimer(eq(MOBILE_IFNAME)); verify(mMockNetd, times(1)).idletimerRemoveInterface(eq(MOBILE_IFNAME), anyInt(),
eq(Integer.toString(TRANSPORT_CELLULAR)));
// Disconnect wifi and switch back to cell // Disconnect wifi and switch back to cell
reset(mNetworkManagementService); reset(mMockNetd);
mWiFiNetworkAgent.disconnect(); mWiFiNetworkAgent.disconnect();
networkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); networkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
assertNoCallbacks(networkCallback); assertNoCallbacks(networkCallback);
verify(mNetworkManagementService, times(1)).removeIdleTimer(eq(WIFI_IFNAME)); verify(mMockNetd, times(1)).idletimerRemoveInterface(eq(WIFI_IFNAME), anyInt(),
verify(mNetworkManagementService, times(1)).addIdleTimer(eq(MOBILE_IFNAME), anyInt(), eq(Integer.toString(TRANSPORT_WIFI)));
eq(NetworkCapabilities.TRANSPORT_CELLULAR)); verify(mMockNetd, times(1)).idletimerAddInterface(eq(MOBILE_IFNAME), anyInt(),
eq(Integer.toString(TRANSPORT_CELLULAR)));
// reconnect wifi // reconnect wifi
reset(mMockNetd);
mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
wifiLp.setInterfaceName(WIFI_IFNAME); wifiLp.setInterfaceName(WIFI_IFNAME);
mWiFiNetworkAgent.sendLinkProperties(wifiLp); mWiFiNetworkAgent.sendLinkProperties(wifiLp);
@@ -8240,9 +8242,12 @@ public class ConnectivityServiceTest {
networkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); networkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
networkCallback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent); networkCallback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
networkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent); networkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
verify(mMockNetd, times(1)).idletimerAddInterface(eq(WIFI_IFNAME), anyInt(),
eq(Integer.toString(TRANSPORT_WIFI)));
verify(mMockNetd, times(1)).idletimerRemoveInterface(eq(MOBILE_IFNAME), anyInt(),
eq(Integer.toString(TRANSPORT_CELLULAR)));
// Disconnect cell // Disconnect cell
reset(mNetworkManagementService);
reset(mMockNetd); reset(mMockNetd);
mCellNetworkAgent.disconnect(); mCellNetworkAgent.disconnect();
networkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent); networkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
@@ -8250,17 +8255,18 @@ public class ConnectivityServiceTest {
// sent as network being switched. Ensure rule removal for cell will not be triggered // sent as network being switched. Ensure rule removal for cell will not be triggered
// unexpectedly before network being removed. // unexpectedly before network being removed.
waitForIdle(); waitForIdle();
verify(mNetworkManagementService, times(0)).removeIdleTimer(eq(MOBILE_IFNAME)); verify(mMockNetd, times(0)).idletimerRemoveInterface(eq(MOBILE_IFNAME), anyInt(),
eq(Integer.toString(TRANSPORT_CELLULAR)));
verify(mMockNetd, times(1)).networkDestroy(eq(mCellNetworkAgent.getNetwork().netId)); verify(mMockNetd, times(1)).networkDestroy(eq(mCellNetworkAgent.getNetwork().netId));
verify(mMockDnsResolver, times(1)) verify(mMockDnsResolver, times(1))
.destroyNetworkCache(eq(mCellNetworkAgent.getNetwork().netId)); .destroyNetworkCache(eq(mCellNetworkAgent.getNetwork().netId));
// Disconnect wifi // Disconnect wifi
ExpectedBroadcast b = expectConnectivityAction(TYPE_WIFI, DetailedState.DISCONNECTED); ExpectedBroadcast b = expectConnectivityAction(TYPE_WIFI, DetailedState.DISCONNECTED);
reset(mNetworkManagementService);
mWiFiNetworkAgent.disconnect(); mWiFiNetworkAgent.disconnect();
b.expectBroadcast(); b.expectBroadcast();
verify(mNetworkManagementService, times(1)).removeIdleTimer(eq(WIFI_IFNAME)); verify(mMockNetd, times(1)).idletimerRemoveInterface(eq(WIFI_IFNAME), anyInt(),
eq(Integer.toString(TRANSPORT_WIFI)));
// Clean up // Clean up
mCm.unregisterNetworkCallback(networkCallback); mCm.unregisterNetworkCallback(networkCallback);