Snap for 6357023 from a957475923108063af3ec244042df20b74cbb4f3 to rvc-release

Change-Id: Id122ed286906bb61dbb2310805eccca8a6122c73
This commit is contained in:
android-build-team Robot
2020-04-02 02:04:43 +00:00
7 changed files with 228 additions and 40 deletions

View File

@@ -659,7 +659,8 @@ public class ConnectivityDiagnosticsManager {
public abstract static class ConnectivityDiagnosticsCallback {
/**
* Called when the platform completes a data connectivity check. This will also be invoked
* upon registration with the latest report.
* immediately upon registration for each network matching the request with the latest
* report, if a report has already been generated for that network.
*
* <p>The Network specified in the ConnectivityReport may not be active any more when this
* method is invoked.

View File

@@ -16,6 +16,8 @@
package android.net;
import static com.android.internal.annotations.VisibleForTesting.Visibility.PRIVATE;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -118,7 +120,7 @@ public final class NetworkCapabilities implements Parcelable {
mTransportInfo = nc.mTransportInfo;
mSignalStrength = nc.mSignalStrength;
setUids(nc.mUids); // Will make the defensive copy
setAdministratorUids(nc.mAdministratorUids);
setAdministratorUids(nc.getAdministratorUids());
mOwnerUid = nc.mOwnerUid;
mUnwantedNetworkCapabilities = nc.mUnwantedNetworkCapabilities;
mSSID = nc.mSSID;
@@ -919,6 +921,9 @@ public final class NetworkCapabilities implements Parcelable {
* <p>For NetworkCapability instances being sent from the System Server, this value MUST be
* empty unless the destination is 1) the System Server, or 2) Telephony. In either case, the
* receiving entity must have the ACCESS_FINE_LOCATION permission and target R+.
*
* <p>When received from an app in a NetworkRequest this is always cleared out by the system
* server. This field is never used for matching NetworkRequests to NetworkAgents.
*/
@NonNull private int[] mAdministratorUids = new int[0];
@@ -927,10 +932,11 @@ public final class NetworkCapabilities implements Parcelable {
*
* <p>UIDs included in administratorUids gain administrator privileges over this Network.
* Examples of UIDs that should be included in administratorUids are:
*
* <ul>
* <li>Carrier apps with privileges for the relevant subscription
* <li>Active VPN apps
* <li>Other application groups with a particular Network-related role
* <li>Carrier apps with privileges for the relevant subscription
* <li>Active VPN apps
* <li>Other application groups with a particular Network-related role
* </ul>
*
* <p>In general, user-supplied networks (such as WiFi networks) do not have an administrator.
@@ -938,19 +944,34 @@ public final class NetworkCapabilities implements Parcelable {
* <p>An app is granted owner privileges over Networks that it supplies. The owner UID MUST
* always be included in administratorUids.
*
* <p>The administrator UIDs are set by network agents.
*
* @param administratorUids the UIDs to be set as administrators of this Network.
* @throws IllegalArgumentException if duplicate UIDs are contained in administratorUids
* @see #mAdministratorUids
* @hide
*/
@NonNull
public NetworkCapabilities setAdministratorUids(@NonNull final int[] administratorUids) {
mAdministratorUids = Arrays.copyOf(administratorUids, administratorUids.length);
Arrays.sort(mAdministratorUids);
for (int i = 0; i < mAdministratorUids.length - 1; i++) {
if (mAdministratorUids[i] >= mAdministratorUids[i + 1]) {
throw new IllegalArgumentException("All administrator UIDs must be unique");
}
}
return this;
}
/**
* Retrieves the UIDs that are administrators of this Network.
*
* <p>This is only populated in NetworkCapabilities objects that come from network agents for
* networks that are managed by specific apps on the system, such as carrier privileged apps or
* wifi suggestion apps. This will include the network owner.
*
* @return the int[] of UIDs that are administrators of this Network
* @see #mAdministratorUids
* @hide
*/
@NonNull
@@ -960,6 +981,40 @@ public final class NetworkCapabilities implements Parcelable {
return Arrays.copyOf(mAdministratorUids, mAdministratorUids.length);
}
/**
* Tests if the set of administrator UIDs of this network is the same as that of the passed one.
*
* <p>The administrator UIDs must be in sorted order.
*
* <p>nc is assumed non-null. Else, NPE.
*
* @hide
*/
@VisibleForTesting(visibility = PRIVATE)
public boolean equalsAdministratorUids(@NonNull final NetworkCapabilities nc) {
return Arrays.equals(mAdministratorUids, nc.mAdministratorUids);
}
/**
* Combine the administrator UIDs of the capabilities.
*
* <p>This is only legal if either of the administrators lists are empty, or if they are equal.
* Combining administrator UIDs is only possible for combining non-overlapping sets of UIDs.
*
* <p>If both administrator lists are non-empty but not equal, they conflict with each other. In
* this case, it would not make sense to add them together.
*/
private void combineAdministratorUids(@NonNull final NetworkCapabilities nc) {
if (nc.mAdministratorUids.length == 0) return;
if (mAdministratorUids.length == 0) {
mAdministratorUids = Arrays.copyOf(nc.mAdministratorUids, nc.mAdministratorUids.length);
return;
}
if (!equalsAdministratorUids(nc)) {
throw new IllegalStateException("Can't combine two different administrator UID lists");
}
}
/**
* Value indicating that link bandwidth is unspecified.
* @hide
@@ -1455,6 +1510,7 @@ public final class NetworkCapabilities implements Parcelable {
combineUids(nc);
combineSSIDs(nc);
combineRequestor(nc);
combineAdministratorUids(nc);
}
/**
@@ -1568,7 +1624,8 @@ public final class NetworkCapabilities implements Parcelable {
&& equalsUids(that)
&& equalsSSID(that)
&& equalsPrivateDnsBroken(that)
&& equalsRequestor(that);
&& equalsRequestor(that)
&& equalsAdministratorUids(that);
}
@Override
@@ -1588,7 +1645,8 @@ public final class NetworkCapabilities implements Parcelable {
+ Objects.hashCode(mTransportInfo) * 41
+ Objects.hashCode(mPrivateDnsBroken) * 43
+ Objects.hashCode(mRequestorUid) * 47
+ Objects.hashCode(mRequestorPackageName) * 53;
+ Objects.hashCode(mRequestorPackageName) * 53
+ Arrays.hashCode(mAdministratorUids) * 59;
}
@Override
@@ -1609,7 +1667,7 @@ public final class NetworkCapabilities implements Parcelable {
dest.writeArraySet(mUids);
dest.writeString(mSSID);
dest.writeBoolean(mPrivateDnsBroken);
dest.writeIntArray(mAdministratorUids);
dest.writeIntArray(getAdministratorUids());
dest.writeInt(mOwnerUid);
dest.writeInt(mRequestorUid);
dest.writeString(mRequestorPackageName);

View File

@@ -653,8 +653,8 @@ public class ConnectivityService extends IConnectivityManager.Stub
final MultipathPolicyTracker mMultipathPolicyTracker;
@VisibleForTesting
final Map<IConnectivityDiagnosticsCallback, ConnectivityDiagnosticsCallbackInfo>
mConnectivityDiagnosticsCallbacks = new HashMap<>();
final Map<IBinder, ConnectivityDiagnosticsCallbackInfo> mConnectivityDiagnosticsCallbacks =
new HashMap<>();
/**
* Implements support for the legacy "one network per network type" model.
@@ -7835,11 +7835,12 @@ public class ConnectivityService extends IConnectivityManager.Stub
ensureRunningOnConnectivityServiceThread();
final IConnectivityDiagnosticsCallback cb = cbInfo.mCb;
final IBinder iCb = cb.asBinder();
final NetworkRequestInfo nri = cbInfo.mRequestInfo;
// This means that the client registered the same callback multiple times. Do
// not override the previous entry, and exit silently.
if (mConnectivityDiagnosticsCallbacks.containsKey(cb)) {
if (mConnectivityDiagnosticsCallbacks.containsKey(iCb)) {
if (VDBG) log("Diagnostics callback is already registered");
// Decrement the reference count for this NetworkRequestInfo. The reference count is
@@ -7849,40 +7850,75 @@ public class ConnectivityService extends IConnectivityManager.Stub
return;
}
mConnectivityDiagnosticsCallbacks.put(cb, cbInfo);
mConnectivityDiagnosticsCallbacks.put(iCb, cbInfo);
try {
cb.asBinder().linkToDeath(cbInfo, 0);
iCb.linkToDeath(cbInfo, 0);
} catch (RemoteException e) {
cbInfo.binderDied();
return;
}
// Once registered, provide ConnectivityReports for matching Networks
final List<NetworkAgentInfo> matchingNetworks = new ArrayList<>();
synchronized (mNetworkForNetId) {
for (int i = 0; i < mNetworkForNetId.size(); i++) {
final NetworkAgentInfo nai = mNetworkForNetId.valueAt(i);
if (nai.satisfies(nri.request)) {
matchingNetworks.add(nai);
}
}
}
for (final NetworkAgentInfo nai : matchingNetworks) {
final ConnectivityReport report = nai.getConnectivityReport();
if (report == null) {
continue;
}
if (!checkConnectivityDiagnosticsPermissions(
nri.mPid, nri.mUid, nai, cbInfo.mCallingPackageName)) {
continue;
}
try {
cb.onConnectivityReportAvailable(report);
} catch (RemoteException e) {
// Exception while sending the ConnectivityReport. Move on to the next network.
}
}
}
private void handleUnregisterConnectivityDiagnosticsCallback(
@NonNull IConnectivityDiagnosticsCallback cb, int uid) {
ensureRunningOnConnectivityServiceThread();
final IBinder iCb = cb.asBinder();
if (!mConnectivityDiagnosticsCallbacks.containsKey(cb)) {
final ConnectivityDiagnosticsCallbackInfo cbInfo =
mConnectivityDiagnosticsCallbacks.remove(iCb);
if (cbInfo == null) {
if (VDBG) log("Removing diagnostics callback that is not currently registered");
return;
}
final NetworkRequestInfo nri = mConnectivityDiagnosticsCallbacks.get(cb).mRequestInfo;
final NetworkRequestInfo nri = cbInfo.mRequestInfo;
if (uid != nri.mUid) {
if (VDBG) loge("Different uid than registrant attempting to unregister cb");
return;
}
cb.asBinder().unlinkToDeath(mConnectivityDiagnosticsCallbacks.remove(cb), 0);
// Decrement the reference count for this NetworkRequestInfo. The reference count is
// incremented when the NetworkRequestInfo is created as part of
// enforceRequestCountLimit().
decrementNetworkRequestPerUidCount(nri);
iCb.unlinkToDeath(cbInfo, 0);
}
private void handleNetworkTestedWithExtras(
@NonNull ConnectivityReportEvent reportEvent, @NonNull PersistableBundle extras) {
final NetworkAgentInfo nai = reportEvent.mNai;
final NetworkCapabilities networkCapabilities =
new NetworkCapabilities(nai.networkCapabilities);
clearNetworkCapabilitiesUids(networkCapabilities);
getNetworkCapabilitiesWithoutUids(nai.networkCapabilities);
final ConnectivityReport report =
new ConnectivityReport(
reportEvent.mNai.network,
@@ -7890,6 +7926,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
nai.linkProperties,
networkCapabilities,
extras);
nai.setConnectivityReport(report);
final List<IConnectivityDiagnosticsCallback> results =
getMatchingPermissionedCallbacks(nai);
for (final IConnectivityDiagnosticsCallback cb : results) {
@@ -7905,8 +7942,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
@NonNull NetworkAgentInfo nai, long timestampMillis, int detectionMethod,
@NonNull PersistableBundle extras) {
final NetworkCapabilities networkCapabilities =
new NetworkCapabilities(nai.networkCapabilities);
clearNetworkCapabilitiesUids(networkCapabilities);
getNetworkCapabilitiesWithoutUids(nai.networkCapabilities);
final DataStallReport report =
new DataStallReport(
nai.network,
@@ -7939,23 +7975,25 @@ public class ConnectivityService extends IConnectivityManager.Stub
}
}
private void clearNetworkCapabilitiesUids(@NonNull NetworkCapabilities nc) {
nc.setUids(null);
nc.setAdministratorUids(new int[0]);
nc.setOwnerUid(Process.INVALID_UID);
private NetworkCapabilities getNetworkCapabilitiesWithoutUids(@NonNull NetworkCapabilities nc) {
final NetworkCapabilities sanitized = new NetworkCapabilities(nc);
sanitized.setUids(null);
sanitized.setAdministratorUids(new int[0]);
sanitized.setOwnerUid(Process.INVALID_UID);
return sanitized;
}
private List<IConnectivityDiagnosticsCallback> getMatchingPermissionedCallbacks(
@NonNull NetworkAgentInfo nai) {
final List<IConnectivityDiagnosticsCallback> results = new ArrayList<>();
for (Entry<IConnectivityDiagnosticsCallback, ConnectivityDiagnosticsCallbackInfo> entry :
for (Entry<IBinder, ConnectivityDiagnosticsCallbackInfo> entry :
mConnectivityDiagnosticsCallbacks.entrySet()) {
final ConnectivityDiagnosticsCallbackInfo cbInfo = entry.getValue();
final NetworkRequestInfo nri = cbInfo.mRequestInfo;
if (nai.satisfies(nri.request)) {
if (checkConnectivityDiagnosticsPermissions(
nri.mPid, nri.mUid, nai, cbInfo.mCallingPackageName)) {
results.add(entry.getKey());
results.add(entry.getValue().mCb);
}
}
}

View File

@@ -16,6 +16,7 @@
package com.android.server.connectivity;
import static android.net.ConnectivityDiagnosticsManager.ConnectivityReport;
import static android.net.NetworkCapabilities.transportNamesOf;
import android.annotation.NonNull;
@@ -243,6 +244,10 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> {
// How many of the satisfied requests are of type BACKGROUND_REQUEST.
private int mNumBackgroundNetworkRequests = 0;
// The last ConnectivityReport made available for this network. This value is only null before a
// report is generated. Once non-null, it will never be null again.
@Nullable private ConnectivityReport mConnectivityReport;
public final Messenger messenger;
public final AsyncChannel asyncChannel;
@@ -621,6 +626,30 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> {
for (LingerTimer timer : mLingerTimers) { pw.println(timer); }
}
/**
* Sets the most recent ConnectivityReport for this network.
*
* <p>This should only be called from the ConnectivityService thread.
*
* @hide
*/
public void setConnectivityReport(@NonNull ConnectivityReport connectivityReport) {
mConnectivityReport = connectivityReport;
}
/**
* Returns the most recent ConnectivityReport for this network, or null if none have been
* reported yet.
*
* <p>This should only be called from the ConnectivityService thread.
*
* @hide
*/
@Nullable
public ConnectivityReport getConnectivityReport() {
return mConnectivityReport;
}
// TODO: Print shorter members first and only print the boolean variable which value is true
// to improve readability.
public String toString() {

View File

@@ -58,6 +58,7 @@ import androidx.test.runner.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.util.Arrays;
import java.util.Set;
@RunWith(AndroidJUnit4.class)
@@ -280,6 +281,7 @@ public class NetworkCapabilitiesTest {
.addCapability(NET_CAPABILITY_NOT_METERED);
if (isAtLeastR()) {
netCap.setOwnerUid(123);
netCap.setAdministratorUids(new int[] {5, 11});
}
assertParcelingIsLossless(netCap);
netCap.setSSID(TEST_SSID);
@@ -439,6 +441,23 @@ public class NetworkCapabilitiesTest {
return range;
}
@Test
public void testSetAdministratorUids() {
NetworkCapabilities nc =
new NetworkCapabilities().setAdministratorUids(new int[] {2, 1, 3});
assertArrayEquals(new int[] {1, 2, 3}, nc.getAdministratorUids());
}
@Test
public void testSetAdministratorUidsWithDuplicates() {
try {
new NetworkCapabilities().setAdministratorUids(new int[] {1, 1});
fail("Expected IllegalArgumentException for duplicate uids");
} catch (IllegalArgumentException expected) {
}
}
@Test
public void testCombineCapabilities() {
NetworkCapabilities nc1 = new NetworkCapabilities();
@@ -491,6 +510,25 @@ public class NetworkCapabilitiesTest {
assertFalse(nc2.appliesToUid(12));
assertTrue(nc1.appliesToUid(22));
assertTrue(nc2.appliesToUid(22));
final int[] adminUids = {3, 6, 12};
nc1.setAdministratorUids(adminUids);
nc2.combineCapabilities(nc1);
assertTrue(nc2.equalsAdministratorUids(nc1));
assertArrayEquals(nc2.getAdministratorUids(), adminUids);
final int[] adminUidsOtherOrder = {3, 12, 6};
nc1.setAdministratorUids(adminUids);
assertTrue(nc2.equalsAdministratorUids(nc1));
final int[] adminUids2 = {11, 1, 12, 3, 6};
nc1.setAdministratorUids(adminUids2);
assertFalse(nc2.equalsAdministratorUids(nc1));
assertFalse(Arrays.equals(nc2.getAdministratorUids(), adminUids2));
try {
nc2.combineCapabilities(nc1);
fail("Shouldn't be able to combine different lists of admin UIDs");
} catch (IllegalStateException expected) { }
}
@Test

View File

@@ -24,7 +24,6 @@ import android.net.Network
import android.net.metrics.IpConnectivityLog
import android.net.util.SharedLog
import android.os.IBinder
import com.android.networkstack.metrics.DataStallStatsUtils
import com.android.networkstack.netlink.TcpSocketTracker
import com.android.server.NetworkStackService
import com.android.server.NetworkStackService.NetworkMonitorConnector
@@ -91,7 +90,6 @@ class TestNetworkStackService : Service() {
mock(IpConnectivityLog::class.java), mock(SharedLog::class.java),
mock(NetworkStackService.NetworkStackServiceManager::class.java),
NetworkMonitorDeps(privateDnsBypassNetwork),
mock(DataStallStatsUtils::class.java),
mock(TcpSocketTracker::class.java))
cb.onNetworkMonitorCreated(NetworkMonitorConnector(nm, TestPermissionChecker()))
}

View File

@@ -317,6 +317,8 @@ public class ConnectivityServiceTest {
private static final String TEST_PACKAGE_NAME = "com.android.test.package";
private static final String[] EMPTY_STRING_ARRAY = new String[0];
private static final String INTERFACE_NAME = "interface";
private MockContext mServiceContext;
private HandlerThread mCsHandlerThread;
private ConnectivityService mService;
@@ -6748,16 +6750,12 @@ public class ConnectivityServiceTest {
verify(mIBinder).linkToDeath(any(ConnectivityDiagnosticsCallbackInfo.class), anyInt());
verify(mConnectivityDiagnosticsCallback).asBinder();
assertTrue(
mService.mConnectivityDiagnosticsCallbacks.containsKey(
mConnectivityDiagnosticsCallback));
assertTrue(mService.mConnectivityDiagnosticsCallbacks.containsKey(mIBinder));
mService.unregisterConnectivityDiagnosticsCallback(mConnectivityDiagnosticsCallback);
verify(mIBinder, timeout(TIMEOUT_MS))
.unlinkToDeath(any(ConnectivityDiagnosticsCallbackInfo.class), anyInt());
assertFalse(
mService.mConnectivityDiagnosticsCallbacks.containsKey(
mConnectivityDiagnosticsCallback));
assertFalse(mService.mConnectivityDiagnosticsCallbacks.containsKey(mIBinder));
verify(mConnectivityDiagnosticsCallback, atLeastOnce()).asBinder();
}
@@ -6775,9 +6773,7 @@ public class ConnectivityServiceTest {
verify(mIBinder).linkToDeath(any(ConnectivityDiagnosticsCallbackInfo.class), anyInt());
verify(mConnectivityDiagnosticsCallback).asBinder();
assertTrue(
mService.mConnectivityDiagnosticsCallbacks.containsKey(
mConnectivityDiagnosticsCallback));
assertTrue(mService.mConnectivityDiagnosticsCallbacks.containsKey(mIBinder));
// Register the same callback again
mService.registerConnectivityDiagnosticsCallback(
@@ -6786,9 +6782,7 @@ public class ConnectivityServiceTest {
// Block until all other events are done processing.
HandlerUtilsKt.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
assertTrue(
mService.mConnectivityDiagnosticsCallbacks.containsKey(
mConnectivityDiagnosticsCallback));
assertTrue(mService.mConnectivityDiagnosticsCallbacks.containsKey(mIBinder));
}
@Test
@@ -6915,6 +6909,38 @@ public class ConnectivityServiceTest {
mContext.getOpPackageName()));
}
@Test
public void testRegisterConnectivityDiagnosticsCallbackCallsOnConnectivityReport()
throws Exception {
// Set up the Network, which leads to a ConnectivityReport being cached for the network.
final TestNetworkCallback callback = new TestNetworkCallback();
mCm.registerDefaultNetworkCallback(callback);
final LinkProperties linkProperties = new LinkProperties();
linkProperties.setInterfaceName(INTERFACE_NAME);
mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, linkProperties);
mCellNetworkAgent.connect(true);
callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
callback.assertNoCallback();
final NetworkRequest request = new NetworkRequest.Builder().build();
when(mConnectivityDiagnosticsCallback.asBinder()).thenReturn(mIBinder);
mServiceContext.setPermission(
android.Manifest.permission.NETWORK_STACK, PERMISSION_GRANTED);
mService.registerConnectivityDiagnosticsCallback(
mConnectivityDiagnosticsCallback, request, mContext.getPackageName());
// Block until all other events are done processing.
HandlerUtilsKt.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
verify(mConnectivityDiagnosticsCallback)
.onConnectivityReportAvailable(argThat(report -> {
return INTERFACE_NAME.equals(report.getLinkProperties().getInterfaceName())
&& report.getNetworkCapabilities().hasTransport(TRANSPORT_CELLULAR);
}));
}
private void setUpConnectivityDiagnosticsCallback() throws Exception {
final NetworkRequest request = new NetworkRequest.Builder().build();
when(mConnectivityDiagnosticsCallback.asBinder()).thenReturn(mIBinder);