Snap for 6160382 from c7e7661b7f7042281cab86b9bc7013652c6dc44a to rvc-release
Change-Id: I872e3f500f50d490c4c0aa4c47d293d6f730245c
This commit is contained in:
@@ -19,7 +19,9 @@ package android.net;
|
||||
import android.annotation.IntDef;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.annotation.StringDef;
|
||||
import android.content.Context;
|
||||
import android.os.Binder;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.os.PersistableBundle;
|
||||
@@ -79,6 +81,128 @@ public class ConnectivityDiagnosticsManager {
|
||||
|
||||
/** Class that includes connectivity information for a specific Network at a specific time. */
|
||||
public static final class ConnectivityReport implements Parcelable {
|
||||
/**
|
||||
* The overall status of the network is that it is invalid; it neither provides
|
||||
* connectivity nor has been exempted from validation.
|
||||
*/
|
||||
public static final int NETWORK_VALIDATION_RESULT_INVALID = 0;
|
||||
|
||||
/**
|
||||
* The overall status of the network is that it is valid, this may be because it provides
|
||||
* full Internet access (all probes succeeded), or because other properties of the network
|
||||
* caused probes not to be run.
|
||||
*/
|
||||
// TODO: link to INetworkMonitor.NETWORK_VALIDATION_RESULT_VALID
|
||||
public static final int NETWORK_VALIDATION_RESULT_VALID = 1;
|
||||
|
||||
/**
|
||||
* The overall status of the network is that it provides partial connectivity; some
|
||||
* probed services succeeded but others failed.
|
||||
*/
|
||||
// TODO: link to INetworkMonitor.NETWORK_VALIDATION_RESULT_PARTIAL;
|
||||
public static final int NETWORK_VALIDATION_RESULT_PARTIALLY_VALID = 2;
|
||||
|
||||
/**
|
||||
* Due to the properties of the network, validation was not performed.
|
||||
*/
|
||||
public static final int NETWORK_VALIDATION_RESULT_SKIPPED = 3;
|
||||
|
||||
/** @hide */
|
||||
@IntDef(
|
||||
prefix = {"NETWORK_VALIDATION_RESULT_"},
|
||||
value = {
|
||||
NETWORK_VALIDATION_RESULT_INVALID,
|
||||
NETWORK_VALIDATION_RESULT_VALID,
|
||||
NETWORK_VALIDATION_RESULT_PARTIALLY_VALID,
|
||||
NETWORK_VALIDATION_RESULT_SKIPPED
|
||||
})
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
public @interface NetworkValidationResult {}
|
||||
|
||||
/**
|
||||
* The overall validation result for the Network being reported on.
|
||||
*
|
||||
* <p>The possible values for this key are:
|
||||
* {@link #NETWORK_VALIDATION_RESULT_INVALID},
|
||||
* {@link #NETWORK_VALIDATION_RESULT_VALID},
|
||||
* {@link #NETWORK_VALIDATION_RESULT_PARTIALLY_VALID},
|
||||
* {@link #NETWORK_VALIDATION_RESULT_SKIPPED}.
|
||||
*
|
||||
* @see android.net.NetworkCapabilities#CAPABILITY_VALIDATED
|
||||
*/
|
||||
@NetworkValidationResult
|
||||
public static final String KEY_NETWORK_VALIDATION_RESULT = "networkValidationResult";
|
||||
|
||||
/** DNS probe. */
|
||||
// TODO: link to INetworkMonitor.NETWORK_VALIDATION_PROBE_DNS
|
||||
public static final int NETWORK_PROBE_DNS = 0x04;
|
||||
|
||||
/** HTTP probe. */
|
||||
// TODO: link to INetworkMonitor.NETWORK_VALIDATION_PROBE_HTTP
|
||||
public static final int NETWORK_PROBE_HTTP = 0x08;
|
||||
|
||||
/** HTTPS probe. */
|
||||
// TODO: link to INetworkMonitor.NETWORK_VALIDATION_PROBE_HTTPS;
|
||||
public static final int NETWORK_PROBE_HTTPS = 0x10;
|
||||
|
||||
/** Captive portal fallback probe. */
|
||||
// TODO: link to INetworkMonitor.NETWORK_VALIDATION_FALLBACK
|
||||
public static final int NETWORK_PROBE_FALLBACK = 0x20;
|
||||
|
||||
/** Private DNS (DNS over TLS) probd. */
|
||||
// TODO: link to INetworkMonitor.NETWORK_VALIDATION_PROBE_PRIVDNS
|
||||
public static final int NETWORK_PROBE_PRIVATE_DNS = 0x40;
|
||||
|
||||
/** @hide */
|
||||
@IntDef(
|
||||
prefix = {"NETWORK_PROBE_"},
|
||||
value = {
|
||||
NETWORK_PROBE_DNS,
|
||||
NETWORK_PROBE_HTTP,
|
||||
NETWORK_PROBE_HTTPS,
|
||||
NETWORK_PROBE_FALLBACK,
|
||||
NETWORK_PROBE_PRIVATE_DNS
|
||||
})
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
public @interface NetworkProbe {}
|
||||
|
||||
/**
|
||||
* A bitmask of network validation probes that succeeded.
|
||||
*
|
||||
* <p>The possible bits values reported by this key are:
|
||||
* {@link #NETWORK_PROBE_DNS},
|
||||
* {@link #NETWORK_PROBE_HTTP},
|
||||
* {@link #NETWORK_PROBE_HTTPS},
|
||||
* {@link #NETWORK_PROBE_FALLBACK},
|
||||
* {@link #NETWORK_PROBE_PRIVATE_DNS}.
|
||||
*/
|
||||
@NetworkProbe
|
||||
public static final String KEY_NETWORK_PROBES_SUCCEEDED_BITMASK =
|
||||
"networkProbesSucceeded";
|
||||
|
||||
/**
|
||||
* A bitmask of network validation probes that were attempted.
|
||||
*
|
||||
* <p>These probes may have failed or may be incomplete at the time of this report.
|
||||
*
|
||||
* <p>The possible bits values reported by this key are:
|
||||
* {@link #NETWORK_PROBE_DNS},
|
||||
* {@link #NETWORK_PROBE_HTTP},
|
||||
* {@link #NETWORK_PROBE_HTTPS},
|
||||
* {@link #NETWORK_PROBE_FALLBACK},
|
||||
* {@link #NETWORK_PROBE_PRIVATE_DNS}.
|
||||
*/
|
||||
@NetworkProbe
|
||||
public static final String KEY_NETWORK_PROBES_ATTEMPTED_BITMASK =
|
||||
"networkProbesAttemped";
|
||||
|
||||
/** @hide */
|
||||
@StringDef(prefix = {"KEY_"}, value = {
|
||||
KEY_NETWORK_VALIDATION_RESULT, KEY_NETWORK_PROBES_SUCCEEDED_BITMASK,
|
||||
KEY_NETWORK_PROBES_ATTEMPTED_BITMASK})
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
public @interface ConnectivityReportBundleKeys {}
|
||||
|
||||
/** The Network for which this ConnectivityReport applied */
|
||||
@NonNull private final Network mNetwork;
|
||||
|
||||
@@ -218,7 +342,7 @@ public class ConnectivityDiagnosticsManager {
|
||||
|
||||
/** Implement the Parcelable interface */
|
||||
public static final @NonNull Creator<ConnectivityReport> CREATOR =
|
||||
new Creator<>() {
|
||||
new Creator<ConnectivityReport>() {
|
||||
public ConnectivityReport createFromParcel(Parcel in) {
|
||||
return new ConnectivityReport(
|
||||
in.readParcelable(null),
|
||||
@@ -246,6 +370,49 @@ public class ConnectivityDiagnosticsManager {
|
||||
value = {DETECTION_METHOD_DNS_EVENTS, DETECTION_METHOD_TCP_METRICS})
|
||||
public @interface DetectionMethod {}
|
||||
|
||||
/**
|
||||
* This key represents the period in milliseconds over which other included TCP metrics
|
||||
* were measured.
|
||||
*
|
||||
* <p>This key will be included if the data stall detection method is
|
||||
* {@link #DETECTION_METHOD_TCP_METRICS}.
|
||||
*
|
||||
* <p>This value is an int.
|
||||
*/
|
||||
public static final String KEY_TCP_METRICS_COLLECTION_PERIOD_MILLIS =
|
||||
"tcpMetricsCollectionPeriodMillis";
|
||||
|
||||
/**
|
||||
* This key represents the fail rate of TCP packets when the suspected data stall was
|
||||
* detected.
|
||||
*
|
||||
* <p>This key will be included if the data stall detection method is
|
||||
* {@link #DETECTION_METHOD_TCP_METRICS}.
|
||||
*
|
||||
* <p>This value is an int percentage between 0 and 100.
|
||||
*/
|
||||
public static final String KEY_TCP_PACKET_FAIL_RATE = "tcpPacketFailRate";
|
||||
|
||||
/**
|
||||
* This key represents the consecutive number of DNS timeouts that have occurred.
|
||||
*
|
||||
* <p>The consecutive count will be reset any time a DNS response is received.
|
||||
*
|
||||
* <p>This key will be included if the data stall detection method is
|
||||
* {@link #DETECTION_METHOD_DNS_EVENTS}.
|
||||
*
|
||||
* <p>This value is an int.
|
||||
*/
|
||||
public static final String KEY_DNS_CONSECUTIVE_TIMEOUTS = "dnsConsecutiveTimeouts";
|
||||
|
||||
/** @hide */
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@StringDef(prefix = {"KEY_"}, value = {
|
||||
KEY_TCP_PACKET_FAIL_RATE,
|
||||
KEY_DNS_CONSECUTIVE_TIMEOUTS
|
||||
})
|
||||
public @interface DataStallReportBundleKeys {}
|
||||
|
||||
/** The Network for which this DataStallReport applied */
|
||||
@NonNull private final Network mNetwork;
|
||||
|
||||
@@ -315,6 +482,9 @@ public class ConnectivityDiagnosticsManager {
|
||||
/**
|
||||
* Returns a PersistableBundle with additional info for this report.
|
||||
*
|
||||
* <p>Gets a bundle with details about the suspected data stall including information
|
||||
* specific to the monitoring method that detected the data stall.
|
||||
*
|
||||
* @return PersistableBundle that may contain additional information on the suspected data
|
||||
* stall
|
||||
*/
|
||||
@@ -375,6 +545,53 @@ public class ConnectivityDiagnosticsManager {
|
||||
};
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
@VisibleForTesting
|
||||
public static class ConnectivityDiagnosticsBinder
|
||||
extends IConnectivityDiagnosticsCallback.Stub {
|
||||
@NonNull private final ConnectivityDiagnosticsCallback mCb;
|
||||
@NonNull private final Executor mExecutor;
|
||||
|
||||
/** @hide */
|
||||
@VisibleForTesting
|
||||
public ConnectivityDiagnosticsBinder(
|
||||
@NonNull ConnectivityDiagnosticsCallback cb, @NonNull Executor executor) {
|
||||
this.mCb = cb;
|
||||
this.mExecutor = executor;
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
@VisibleForTesting
|
||||
public void onConnectivityReport(@NonNull ConnectivityReport report) {
|
||||
Binder.withCleanCallingIdentity(() -> {
|
||||
mExecutor.execute(() -> {
|
||||
mCb.onConnectivityReport(report);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
@VisibleForTesting
|
||||
public void onDataStallSuspected(@NonNull DataStallReport report) {
|
||||
Binder.withCleanCallingIdentity(() -> {
|
||||
mExecutor.execute(() -> {
|
||||
mCb.onDataStallSuspected(report);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
@VisibleForTesting
|
||||
public void onNetworkConnectivityReported(
|
||||
@NonNull Network network, boolean hasConnectivity) {
|
||||
Binder.withCleanCallingIdentity(() -> {
|
||||
mExecutor.execute(() -> {
|
||||
mCb.onNetworkConnectivityReported(network, hasConnectivity);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Abstract base class for Connectivity Diagnostics callbacks. Used for notifications about
|
||||
* network connectivity events. Must be extended by applications wanting notifications.
|
||||
|
||||
@@ -33,7 +33,9 @@ import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.IpSecManager.UdpEncapsulationSocket;
|
||||
import android.net.SocketKeepalive.Callback;
|
||||
import android.net.TetheringManager.StartTetheringCallback;
|
||||
import android.net.TetheringManager.TetheringEventCallback;
|
||||
import android.net.TetheringManager.TetheringRequest;
|
||||
import android.os.Binder;
|
||||
import android.os.Build;
|
||||
import android.os.Build.VERSION_CODES;
|
||||
@@ -2452,10 +2454,12 @@ public class ConnectivityManager {
|
||||
*
|
||||
* @param iface the interface name to tether.
|
||||
* @return error a {@code TETHER_ERROR} value indicating success or failure type
|
||||
* @deprecated Use {@link TetheringManager#startTethering} instead
|
||||
*
|
||||
* {@hide}
|
||||
*/
|
||||
@UnsupportedAppUsage
|
||||
@Deprecated
|
||||
public int tether(String iface) {
|
||||
return getTetheringManager().tether(iface);
|
||||
}
|
||||
@@ -2512,9 +2516,12 @@ public class ConnectivityManager {
|
||||
|
||||
/**
|
||||
* Callback for use with {@link #startTethering} to find out whether tethering succeeded.
|
||||
*
|
||||
* @deprecated Use {@link TetheringManager.StartTetheringCallback} instead.
|
||||
* @hide
|
||||
*/
|
||||
@SystemApi
|
||||
@Deprecated
|
||||
public static abstract class OnStartTetheringCallback {
|
||||
/**
|
||||
* Called when tethering has been successfully started.
|
||||
@@ -2531,9 +2538,12 @@ public class ConnectivityManager {
|
||||
* Convenient overload for
|
||||
* {@link #startTethering(int, boolean, OnStartTetheringCallback, Handler)} which passes a null
|
||||
* handler to run on the current thread's {@link Looper}.
|
||||
*
|
||||
* @deprecated Use {@link TetheringManager#startTethering} instead.
|
||||
* @hide
|
||||
*/
|
||||
@SystemApi
|
||||
@Deprecated
|
||||
@RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED)
|
||||
public void startTethering(int type, boolean showProvisioningUi,
|
||||
final OnStartTetheringCallback callback) {
|
||||
@@ -2557,26 +2567,44 @@ public class ConnectivityManager {
|
||||
* @param callback an {@link OnStartTetheringCallback} which will be called to notify the caller
|
||||
* of the result of trying to tether.
|
||||
* @param handler {@link Handler} to specify the thread upon which the callback will be invoked.
|
||||
*
|
||||
* @deprecated Use {@link TetheringManager#startTethering} instead.
|
||||
* @hide
|
||||
*/
|
||||
@SystemApi
|
||||
@Deprecated
|
||||
@RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED)
|
||||
public void startTethering(int type, boolean showProvisioningUi,
|
||||
final OnStartTetheringCallback callback, Handler handler) {
|
||||
Preconditions.checkNotNull(callback, "OnStartTetheringCallback cannot be null.");
|
||||
|
||||
ResultReceiver wrappedCallback = new ResultReceiver(handler) {
|
||||
final Executor executor = new Executor() {
|
||||
@Override
|
||||
protected void onReceiveResult(int resultCode, Bundle resultData) {
|
||||
if (resultCode == TETHER_ERROR_NO_ERROR) {
|
||||
callback.onTetheringStarted();
|
||||
public void execute(Runnable command) {
|
||||
if (handler == null) {
|
||||
command.run();
|
||||
} else {
|
||||
callback.onTetheringFailed();
|
||||
handler.post(command);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
getTetheringManager().startTethering(type, wrappedCallback, showProvisioningUi);
|
||||
final StartTetheringCallback tetheringCallback = new StartTetheringCallback() {
|
||||
@Override
|
||||
public void onTetheringStarted() {
|
||||
callback.onTetheringStarted();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTetheringFailed(final int resultCode) {
|
||||
callback.onTetheringFailed();
|
||||
}
|
||||
};
|
||||
|
||||
final TetheringRequest request = new TetheringRequest.Builder(type)
|
||||
.setSilentProvisioning(!showProvisioningUi).build();
|
||||
|
||||
getTetheringManager().startTethering(request, executor, tetheringCallback);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2602,7 +2630,7 @@ public class ConnectivityManager {
|
||||
* Callback for use with {@link registerTetheringEventCallback} to find out tethering
|
||||
* upstream status.
|
||||
*
|
||||
* @deprecated Use {@line TetheringManager#OnTetheringEventCallback} instead.
|
||||
* @deprecated Use {@link TetheringManager#OnTetheringEventCallback} instead.
|
||||
* @hide
|
||||
*/
|
||||
@SystemApi
|
||||
@@ -2632,7 +2660,7 @@ public class ConnectivityManager {
|
||||
* @param executor the executor on which callback will be invoked.
|
||||
* @param callback the callback to be called when tethering has change events.
|
||||
*
|
||||
* @deprecated Use {@line TetheringManager#registerTetheringEventCallback} instead.
|
||||
* @deprecated Use {@link TetheringManager#registerTetheringEventCallback} instead.
|
||||
* @hide
|
||||
*/
|
||||
@SystemApi
|
||||
@@ -2749,10 +2777,12 @@ public class ConnectivityManager {
|
||||
*
|
||||
* @param enable a boolean - {@code true} to enable tethering
|
||||
* @return error a {@code TETHER_ERROR} value indicating success or failure type
|
||||
* @deprecated Use {@link TetheringManager#startTethering} instead
|
||||
*
|
||||
* {@hide}
|
||||
*/
|
||||
@UnsupportedAppUsage
|
||||
@Deprecated
|
||||
public int setUsbTethering(boolean enable) {
|
||||
return getTetheringManager().setUsbTethering(enable);
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ package android.net;
|
||||
|
||||
import android.app.PendingIntent;
|
||||
import android.net.ConnectionInfo;
|
||||
import android.net.IConnectivityDiagnosticsCallback;
|
||||
import android.net.LinkProperties;
|
||||
import android.net.Network;
|
||||
import android.net.NetworkAgentConfig;
|
||||
@@ -211,5 +212,9 @@ interface IConnectivityManager
|
||||
boolean isCallerCurrentAlwaysOnVpnApp();
|
||||
boolean isCallerCurrentAlwaysOnVpnLockdownApp();
|
||||
|
||||
void registerConnectivityDiagnosticsCallback(in IConnectivityDiagnosticsCallback callback,
|
||||
in NetworkRequest request);
|
||||
void unregisterConnectivityDiagnosticsCallback(in IConnectivityDiagnosticsCallback callback);
|
||||
|
||||
IBinder startOrGetTestNetworkService();
|
||||
}
|
||||
|
||||
@@ -82,7 +82,8 @@ public final class LinkProperties implements Parcelable {
|
||||
private final transient boolean mParcelSensitiveFields;
|
||||
|
||||
private static final int MIN_MTU = 68;
|
||||
private static final int MIN_MTU_V6 = 1280;
|
||||
/* package-visibility - Used in other files (such as Ikev2VpnProfile) as minimum iface MTU. */
|
||||
static final int MIN_MTU_V6 = 1280;
|
||||
private static final int MAX_MTU = 10000;
|
||||
|
||||
private static final int INET6_ADDR_LENGTH = 16;
|
||||
|
||||
@@ -26,6 +26,7 @@ import android.net.ConnectivityManager.NetworkCallback;
|
||||
import android.os.Build;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.os.Process;
|
||||
import android.util.ArraySet;
|
||||
import android.util.proto.ProtoOutputStream;
|
||||
|
||||
@@ -35,6 +36,9 @@ import com.android.internal.util.Preconditions;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.StringJoiner;
|
||||
@@ -55,7 +59,6 @@ import java.util.StringJoiner;
|
||||
*/
|
||||
public final class NetworkCapabilities implements Parcelable {
|
||||
private static final String TAG = "NetworkCapabilities";
|
||||
private static final int INVALID_UID = -1;
|
||||
|
||||
// Set to true when private DNS is broken.
|
||||
private boolean mPrivateDnsBroken;
|
||||
@@ -82,7 +85,8 @@ public final class NetworkCapabilities implements Parcelable {
|
||||
mTransportInfo = null;
|
||||
mSignalStrength = SIGNAL_STRENGTH_UNSPECIFIED;
|
||||
mUids = null;
|
||||
mEstablishingVpnAppUid = INVALID_UID;
|
||||
mAdministratorUids.clear();
|
||||
mOwnerUid = Process.INVALID_UID;
|
||||
mSSID = null;
|
||||
mPrivateDnsBroken = false;
|
||||
}
|
||||
@@ -100,7 +104,8 @@ public final class NetworkCapabilities implements Parcelable {
|
||||
mTransportInfo = nc.mTransportInfo;
|
||||
mSignalStrength = nc.mSignalStrength;
|
||||
setUids(nc.mUids); // Will make the defensive copy
|
||||
mEstablishingVpnAppUid = nc.mEstablishingVpnAppUid;
|
||||
setAdministratorUids(nc.mAdministratorUids);
|
||||
mOwnerUid = nc.mOwnerUid;
|
||||
mUnwantedNetworkCapabilities = nc.mUnwantedNetworkCapabilities;
|
||||
mSSID = nc.mSSID;
|
||||
mPrivateDnsBroken = nc.mPrivateDnsBroken;
|
||||
@@ -805,31 +810,76 @@ public final class NetworkCapabilities implements Parcelable {
|
||||
}
|
||||
|
||||
/**
|
||||
* UID of the app that manages this network, or INVALID_UID if none/unknown.
|
||||
* UID of the app that owns this network, or INVALID_UID if none/unknown.
|
||||
*
|
||||
* This field keeps track of the UID of the app that created this network and is in charge
|
||||
* of managing it. In the practice, it is used to store the UID of VPN apps so it is named
|
||||
* accordingly, but it may be renamed if other mechanisms are offered for third party apps
|
||||
* to create networks.
|
||||
*
|
||||
* Because this field is only used in the services side (and to avoid apps being able to
|
||||
* set this to whatever they want), this field is not parcelled and will not be conserved
|
||||
* across the IPC boundary.
|
||||
* @hide
|
||||
* <p>This field keeps track of the UID of the app that created this network and is in charge of
|
||||
* its lifecycle. This could be the UID of apps such as the Wifi network suggestor, the running
|
||||
* VPN, or Carrier Service app managing a cellular data connection.
|
||||
*/
|
||||
private int mEstablishingVpnAppUid = INVALID_UID;
|
||||
private int mOwnerUid = Process.INVALID_UID;
|
||||
|
||||
/**
|
||||
* Set the UID of the managing app.
|
||||
* @hide
|
||||
* Set the UID of the owner app.
|
||||
*/
|
||||
public void setEstablishingVpnAppUid(final int uid) {
|
||||
mEstablishingVpnAppUid = uid;
|
||||
public void setOwnerUid(final int uid) {
|
||||
mOwnerUid = uid;
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
public int getEstablishingVpnAppUid() {
|
||||
return mEstablishingVpnAppUid;
|
||||
/**
|
||||
* Retrieves the UID of the owner app.
|
||||
*/
|
||||
public int getOwnerUid() {
|
||||
return mOwnerUid;
|
||||
}
|
||||
|
||||
/**
|
||||
* UIDs of packages that are administrators of this network, or empty if none.
|
||||
*
|
||||
* <p>This field tracks the UIDs of packages that have permission to manage this network.
|
||||
*
|
||||
* <p>Network owners will also be listed as administrators.
|
||||
*
|
||||
* <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+.
|
||||
*/
|
||||
private final List<Integer> mAdministratorUids = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Sets the list of UIDs that are administrators of this network.
|
||||
*
|
||||
* <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
|
||||
* </ul>
|
||||
*
|
||||
* <p>In general, user-supplied networks (such as WiFi networks) do not have an administrator.
|
||||
*
|
||||
* <p>An app is granted owner privileges over Networks that it supplies. Owner privileges
|
||||
* implicitly include administrator privileges.
|
||||
*
|
||||
* @param administratorUids the UIDs to be set as administrators of this Network.
|
||||
* @hide
|
||||
*/
|
||||
@SystemApi
|
||||
public void setAdministratorUids(@NonNull final List<Integer> administratorUids) {
|
||||
mAdministratorUids.clear();
|
||||
mAdministratorUids.addAll(administratorUids);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the list of UIDs that are administrators of this Network.
|
||||
*
|
||||
* @return the List of UIDs that are administrators of this Network
|
||||
* @hide
|
||||
*/
|
||||
@NonNull
|
||||
@SystemApi
|
||||
public List<Integer> getAdministratorUids() {
|
||||
return Collections.unmodifiableList(mAdministratorUids);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1102,7 +1152,7 @@ public final class NetworkCapabilities implements Parcelable {
|
||||
* member is null, then the network is not restricted by app UID. If it's an empty list, then
|
||||
* it means nobody can use it.
|
||||
* As a special exception, the app managing this network (as identified by its UID stored in
|
||||
* mEstablishingVpnAppUid) can always see this network. This is embodied by a special check in
|
||||
* mOwnerUid) can always see this network. This is embodied by a special check in
|
||||
* satisfiedByUids. That still does not mean the network necessarily <strong>applies</strong>
|
||||
* to the app that manages it as determined by #appliesToUid.
|
||||
* <p>
|
||||
@@ -1209,7 +1259,7 @@ public final class NetworkCapabilities implements Parcelable {
|
||||
* in the passed nc (representing the UIDs that this network is available to).
|
||||
* <p>
|
||||
* As a special exception, the UID that created the passed network (as represented by its
|
||||
* mEstablishingVpnAppUid field) always satisfies a NetworkRequest requiring it (of LISTEN
|
||||
* mOwnerUid field) always satisfies a NetworkRequest requiring it (of LISTEN
|
||||
* or REQUEST types alike), even if the network does not apply to it. That is so a VPN app
|
||||
* can see its own network when it listens for it.
|
||||
* <p>
|
||||
@@ -1220,7 +1270,7 @@ public final class NetworkCapabilities implements Parcelable {
|
||||
public boolean satisfiedByUids(@NonNull NetworkCapabilities nc) {
|
||||
if (null == nc.mUids || null == mUids) return true; // The network satisfies everything.
|
||||
for (UidRange requiredRange : mUids) {
|
||||
if (requiredRange.contains(nc.mEstablishingVpnAppUid)) return true;
|
||||
if (requiredRange.contains(nc.mOwnerUid)) return true;
|
||||
if (!nc.appliesToUidRange(requiredRange)) {
|
||||
return false;
|
||||
}
|
||||
@@ -1471,6 +1521,7 @@ public final class NetworkCapabilities implements Parcelable {
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeLong(mNetworkCapabilities);
|
||||
@@ -1484,6 +1535,8 @@ public final class NetworkCapabilities implements Parcelable {
|
||||
dest.writeArraySet(mUids);
|
||||
dest.writeString(mSSID);
|
||||
dest.writeBoolean(mPrivateDnsBroken);
|
||||
dest.writeList(mAdministratorUids);
|
||||
dest.writeInt(mOwnerUid);
|
||||
}
|
||||
|
||||
public static final @android.annotation.NonNull Creator<NetworkCapabilities> CREATOR =
|
||||
@@ -1504,6 +1557,8 @@ public final class NetworkCapabilities implements Parcelable {
|
||||
null /* ClassLoader, null for default */);
|
||||
netCap.mSSID = in.readString();
|
||||
netCap.mPrivateDnsBroken = in.readBoolean();
|
||||
netCap.setAdministratorUids(in.readArrayList(null));
|
||||
netCap.mOwnerUid = in.readInt();
|
||||
return netCap;
|
||||
}
|
||||
@Override
|
||||
@@ -1553,8 +1608,12 @@ public final class NetworkCapabilities implements Parcelable {
|
||||
sb.append(" Uids: <").append(mUids).append(">");
|
||||
}
|
||||
}
|
||||
if (mEstablishingVpnAppUid != INVALID_UID) {
|
||||
sb.append(" EstablishingAppUid: ").append(mEstablishingVpnAppUid);
|
||||
if (mOwnerUid != Process.INVALID_UID) {
|
||||
sb.append(" OwnerUid: ").append(mOwnerUid);
|
||||
}
|
||||
|
||||
if (!mAdministratorUids.isEmpty()) {
|
||||
sb.append(" AdministratorUids: ").append(mAdministratorUids);
|
||||
}
|
||||
|
||||
if (null != mSSID) {
|
||||
|
||||
@@ -64,6 +64,7 @@ import android.net.CaptivePortal;
|
||||
import android.net.ConnectionInfo;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.net.ICaptivePortal;
|
||||
import android.net.IConnectivityDiagnosticsCallback;
|
||||
import android.net.IConnectivityManager;
|
||||
import android.net.IDnsResolver;
|
||||
import android.net.IIpConnectivityMetrics;
|
||||
@@ -210,6 +211,7 @@ import java.net.UnknownHostException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.ConcurrentModificationException;
|
||||
import java.util.HashMap;
|
||||
@@ -1622,7 +1624,8 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
return getNetworkCapabilitiesInternal(getNetworkAgentInfoForNetwork(network));
|
||||
}
|
||||
|
||||
private NetworkCapabilities networkCapabilitiesRestrictedForCallerPermissions(
|
||||
@VisibleForTesting
|
||||
NetworkCapabilities networkCapabilitiesRestrictedForCallerPermissions(
|
||||
NetworkCapabilities nc, int callerPid, int callerUid) {
|
||||
final NetworkCapabilities newNc = new NetworkCapabilities(nc);
|
||||
if (!checkSettingsPermission(callerPid, callerUid)) {
|
||||
@@ -1632,9 +1635,24 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
if (newNc.getNetworkSpecifier() != null) {
|
||||
newNc.setNetworkSpecifier(newNc.getNetworkSpecifier().redact());
|
||||
}
|
||||
newNc.setAdministratorUids(Collections.EMPTY_LIST);
|
||||
|
||||
maybeSanitizeLocationInfoForCaller(newNc, callerUid);
|
||||
|
||||
return newNc;
|
||||
}
|
||||
|
||||
private void maybeSanitizeLocationInfoForCaller(
|
||||
NetworkCapabilities nc, int callerUid) {
|
||||
// TODO(b/142072839): Conditionally reset the owner UID if the following
|
||||
// conditions are not met:
|
||||
// 1. The destination app is the network owner
|
||||
// 2. The destination app has the ACCESS_COARSE_LOCATION permission granted
|
||||
// if target SDK<29 or otherwise has the ACCESS_FINE_LOCATION permission granted
|
||||
// 3. The user's location toggle is on
|
||||
nc.setOwnerUid(INVALID_UID);
|
||||
}
|
||||
|
||||
private LinkProperties linkPropertiesRestrictedForCallerPermissions(
|
||||
LinkProperties lp, int callerPid, int callerUid) {
|
||||
if (lp == null) return new LinkProperties();
|
||||
@@ -1662,6 +1680,10 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
if (!checkSettingsPermission()) {
|
||||
nc.setSingleUid(Binder.getCallingUid());
|
||||
}
|
||||
nc.setAdministratorUids(Collections.EMPTY_LIST);
|
||||
|
||||
// Clear owner UID; this can never come from an app.
|
||||
nc.setOwnerUid(INVALID_UID);
|
||||
}
|
||||
|
||||
private void restrictBackgroundRequestForCaller(NetworkCapabilities nc) {
|
||||
@@ -5798,7 +5820,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
}
|
||||
|
||||
final Set<UidRange> ranges = nai.networkCapabilities.getUids();
|
||||
final int vpnAppUid = nai.networkCapabilities.getEstablishingVpnAppUid();
|
||||
final int vpnAppUid = nai.networkCapabilities.getOwnerUid();
|
||||
// TODO: this create a window of opportunity for apps to receive traffic between the time
|
||||
// when the old rules are removed and the time when new rules are added. To fix this,
|
||||
// make eBPF support two whitelisted interfaces so here new rules can be added before the
|
||||
@@ -5997,7 +6019,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
if (nc == null || lp == null) return false;
|
||||
return nai.isVPN()
|
||||
&& !nai.networkAgentConfig.allowBypass
|
||||
&& nc.getEstablishingVpnAppUid() != Process.SYSTEM_UID
|
||||
&& nc.getOwnerUid() != Process.SYSTEM_UID
|
||||
&& lp.getInterfaceName() != null
|
||||
&& (lp.hasIPv4DefaultRoute() || lp.hasIPv6DefaultRoute());
|
||||
}
|
||||
@@ -6045,12 +6067,10 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
// TODO Fix this window by computing an accurate diff on Set<UidRange>, so the old range
|
||||
// to be removed will never overlap with the new range to be added.
|
||||
if (wasFiltering && !prevRanges.isEmpty()) {
|
||||
mPermissionMonitor.onVpnUidRangesRemoved(iface, prevRanges,
|
||||
prevNc.getEstablishingVpnAppUid());
|
||||
mPermissionMonitor.onVpnUidRangesRemoved(iface, prevRanges, prevNc.getOwnerUid());
|
||||
}
|
||||
if (shouldFilter && !newRanges.isEmpty()) {
|
||||
mPermissionMonitor.onVpnUidRangesAdded(iface, newRanges,
|
||||
newNc.getEstablishingVpnAppUid());
|
||||
mPermissionMonitor.onVpnUidRangesAdded(iface, newRanges, newNc.getOwnerUid());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// Never crash!
|
||||
@@ -7311,4 +7331,20 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
return mTNS;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerConnectivityDiagnosticsCallback(
|
||||
@NonNull IConnectivityDiagnosticsCallback callback, @NonNull NetworkRequest request) {
|
||||
// TODO(b/146444622): implement register IConnectivityDiagnosticsCallback functionality
|
||||
throw new UnsupportedOperationException(
|
||||
"registerConnectivityDiagnosticsCallback not yet implemented");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unregisterConnectivityDiagnosticsCallback(
|
||||
@NonNull IConnectivityDiagnosticsCallback callback) {
|
||||
// TODO(b/146444622): implement register IConnectivityDiagnosticsCallback functionality
|
||||
throw new UnsupportedOperationException(
|
||||
"unregisterConnectivityDiagnosticsCallback not yet implemented");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -326,6 +326,7 @@ public class LinkAddressTest {
|
||||
assertParcelSane(l, 6);
|
||||
}
|
||||
|
||||
/*
|
||||
@Test
|
||||
public void testDeprecationTime() {
|
||||
try {
|
||||
@@ -392,7 +393,7 @@ public class LinkAddressTest {
|
||||
SystemClock.elapsedRealtime() + 100000);
|
||||
// Check if the permanent flag is removed
|
||||
assertTrue((l.getFlags() & IFA_F_PERMANENT) == 0);
|
||||
}
|
||||
}*/
|
||||
|
||||
|
||||
private void assertGlobalPreferred(LinkAddress l, String msg) {
|
||||
|
||||
@@ -269,9 +269,10 @@ public class NetworkCapabilitiesTest {
|
||||
.setUids(uids)
|
||||
.addCapability(NET_CAPABILITY_EIMS)
|
||||
.addCapability(NET_CAPABILITY_NOT_METERED);
|
||||
netCap.setOwnerUid(123);
|
||||
assertParcelingIsLossless(netCap);
|
||||
netCap.setSSID(TEST_SSID);
|
||||
assertParcelSane(netCap, 12);
|
||||
assertParcelSane(netCap, 13);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package android.net;
|
||||
|
||||
import static android.net.ConnectivityDiagnosticsManager.ConnectivityDiagnosticsBinder;
|
||||
import static android.net.ConnectivityDiagnosticsManager.ConnectivityDiagnosticsCallback;
|
||||
import static android.net.ConnectivityDiagnosticsManager.ConnectivityReport;
|
||||
import static android.net.ConnectivityDiagnosticsManager.DataStallReport;
|
||||
|
||||
@@ -25,12 +27,19 @@ import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import android.os.PersistableBundle;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.JUnit4;
|
||||
import org.mockito.Mock;
|
||||
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
@RunWith(JUnit4.class)
|
||||
public class ConnectivityDiagnosticsManagerTest {
|
||||
@@ -41,6 +50,19 @@ public class ConnectivityDiagnosticsManagerTest {
|
||||
private static final String BUNDLE_KEY = "key";
|
||||
private static final String BUNDLE_VALUE = "value";
|
||||
|
||||
private static final Executor INLINE_EXECUTOR = x -> x.run();
|
||||
|
||||
@Mock private ConnectivityDiagnosticsCallback mCb;
|
||||
|
||||
private ConnectivityDiagnosticsBinder mBinder;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
mCb = mock(ConnectivityDiagnosticsCallback.class);
|
||||
|
||||
mBinder = new ConnectivityDiagnosticsBinder(mCb, INLINE_EXECUTOR);
|
||||
}
|
||||
|
||||
private ConnectivityReport createSampleConnectivityReport() {
|
||||
final LinkProperties linkProperties = new LinkProperties();
|
||||
linkProperties.setInterfaceName(INTERFACE_NAME);
|
||||
@@ -193,4 +215,34 @@ public class ConnectivityDiagnosticsManagerTest {
|
||||
public void testDataStallReportParcelUnparcel() {
|
||||
assertParcelSane(createSampleDataStallReport(), 4);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConnectivityDiagnosticsCallbackOnConnectivityReport() {
|
||||
mBinder.onConnectivityReport(createSampleConnectivityReport());
|
||||
|
||||
// The callback will be invoked synchronously by inline executor. Immediately check the
|
||||
// latch without waiting.
|
||||
verify(mCb).onConnectivityReport(eq(createSampleConnectivityReport()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConnectivityDiagnosticsCallbackOnDataStallSuspected() {
|
||||
mBinder.onDataStallSuspected(createSampleDataStallReport());
|
||||
|
||||
// The callback will be invoked synchronously by inline executor. Immediately check the
|
||||
// latch without waiting.
|
||||
verify(mCb).onDataStallSuspected(eq(createSampleDataStallReport()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConnectivityDiagnosticsCallbackOnNetworkConnectivityReported() {
|
||||
final Network n = new Network(NET_ID);
|
||||
final boolean connectivity = true;
|
||||
|
||||
mBinder.onNetworkConnectivityReported(n, connectivity);
|
||||
|
||||
// The callback will be invoked synchronously by inline executor. Immediately check the
|
||||
// latch without waiting.
|
||||
verify(mCb).onNetworkConnectivityReported(eq(n), eq(connectivity));
|
||||
}
|
||||
}
|
||||
|
||||
360
tests/net/java/android/net/Ikev2VpnProfileTest.java
Normal file
360
tests/net/java/android/net/Ikev2VpnProfileTest.java
Normal file
@@ -0,0 +1,360 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import static org.junit.Assert.assertArrayEquals;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
import android.test.mock.MockContext;
|
||||
|
||||
import androidx.test.filters.SmallTest;
|
||||
import androidx.test.runner.AndroidJUnit4;
|
||||
|
||||
import com.android.internal.net.VpnProfile;
|
||||
import com.android.org.bouncycastle.x509.X509V1CertificateGenerator;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.security.KeyPair;
|
||||
import java.security.KeyPairGenerator;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.Date;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.security.auth.x500.X500Principal;
|
||||
|
||||
/** Unit tests for {@link Ikev2VpnProfile.Builder}. */
|
||||
@SmallTest
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class Ikev2VpnProfileTest {
|
||||
private static final String SERVER_ADDR_STRING = "1.2.3.4";
|
||||
private static final String IDENTITY_STRING = "Identity";
|
||||
private static final String USERNAME_STRING = "username";
|
||||
private static final String PASSWORD_STRING = "pa55w0rd";
|
||||
private static final String EXCL_LIST = "exclList";
|
||||
private static final byte[] PSK_BYTES = "preSharedKey".getBytes();
|
||||
private static final int TEST_MTU = 1300;
|
||||
|
||||
private final MockContext mMockContext =
|
||||
new MockContext() {
|
||||
@Override
|
||||
public String getOpPackageName() {
|
||||
return "fooPackage";
|
||||
}
|
||||
};
|
||||
private final ProxyInfo mProxy = new ProxyInfo(SERVER_ADDR_STRING, -1, EXCL_LIST);
|
||||
|
||||
private X509Certificate mUserCert;
|
||||
private X509Certificate mServerRootCa;
|
||||
private PrivateKey mPrivateKey;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
mServerRootCa = generateRandomCertAndKeyPair().cert;
|
||||
|
||||
final CertificateAndKey userCertKey = generateRandomCertAndKeyPair();
|
||||
mUserCert = userCertKey.cert;
|
||||
mPrivateKey = userCertKey.key;
|
||||
}
|
||||
|
||||
private Ikev2VpnProfile.Builder getBuilderWithDefaultOptions() {
|
||||
final Ikev2VpnProfile.Builder builder =
|
||||
new Ikev2VpnProfile.Builder(SERVER_ADDR_STRING, IDENTITY_STRING);
|
||||
|
||||
builder.setBypassable(true);
|
||||
builder.setProxy(mProxy);
|
||||
builder.setMaxMtu(TEST_MTU);
|
||||
builder.setMetered(true);
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBuildValidProfileWithOptions() throws Exception {
|
||||
final Ikev2VpnProfile.Builder builder = getBuilderWithDefaultOptions();
|
||||
|
||||
builder.setAuthUsernamePassword(USERNAME_STRING, PASSWORD_STRING, mServerRootCa);
|
||||
final Ikev2VpnProfile profile = builder.build();
|
||||
assertNotNull(profile);
|
||||
|
||||
// Check non-auth parameters correctly stored
|
||||
assertEquals(SERVER_ADDR_STRING, profile.getServerAddr());
|
||||
assertEquals(IDENTITY_STRING, profile.getUserIdentity());
|
||||
assertEquals(mProxy, profile.getProxyInfo());
|
||||
assertTrue(profile.isBypassable());
|
||||
assertTrue(profile.isMetered());
|
||||
assertEquals(TEST_MTU, profile.getMaxMtu());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBuildUsernamePasswordProfile() throws Exception {
|
||||
final Ikev2VpnProfile.Builder builder = getBuilderWithDefaultOptions();
|
||||
|
||||
builder.setAuthUsernamePassword(USERNAME_STRING, PASSWORD_STRING, mServerRootCa);
|
||||
final Ikev2VpnProfile profile = builder.build();
|
||||
assertNotNull(profile);
|
||||
|
||||
assertEquals(USERNAME_STRING, profile.getUsername());
|
||||
assertEquals(PASSWORD_STRING, profile.getPassword());
|
||||
assertEquals(mServerRootCa, profile.getServerRootCaCert());
|
||||
|
||||
assertNull(profile.getPresharedKey());
|
||||
assertNull(profile.getRsaPrivateKey());
|
||||
assertNull(profile.getUserCert());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBuildDigitalSignatureProfile() throws Exception {
|
||||
final Ikev2VpnProfile.Builder builder = getBuilderWithDefaultOptions();
|
||||
|
||||
builder.setAuthDigitalSignature(mUserCert, mPrivateKey, mServerRootCa);
|
||||
final Ikev2VpnProfile profile = builder.build();
|
||||
assertNotNull(profile);
|
||||
|
||||
assertEquals(profile.getUserCert(), mUserCert);
|
||||
assertEquals(mPrivateKey, profile.getRsaPrivateKey());
|
||||
assertEquals(profile.getServerRootCaCert(), mServerRootCa);
|
||||
|
||||
assertNull(profile.getPresharedKey());
|
||||
assertNull(profile.getUsername());
|
||||
assertNull(profile.getPassword());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBuildPresharedKeyProfile() throws Exception {
|
||||
final Ikev2VpnProfile.Builder builder = getBuilderWithDefaultOptions();
|
||||
|
||||
builder.setAuthPsk(PSK_BYTES);
|
||||
final Ikev2VpnProfile profile = builder.build();
|
||||
assertNotNull(profile);
|
||||
|
||||
assertArrayEquals(PSK_BYTES, profile.getPresharedKey());
|
||||
|
||||
assertNull(profile.getServerRootCaCert());
|
||||
assertNull(profile.getUsername());
|
||||
assertNull(profile.getPassword());
|
||||
assertNull(profile.getRsaPrivateKey());
|
||||
assertNull(profile.getUserCert());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBuildNoAuthMethodSet() throws Exception {
|
||||
final Ikev2VpnProfile.Builder builder = getBuilderWithDefaultOptions();
|
||||
|
||||
try {
|
||||
builder.build();
|
||||
fail("Expected exception due to lack of auth method");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBuildInvalidMtu() throws Exception {
|
||||
final Ikev2VpnProfile.Builder builder = getBuilderWithDefaultOptions();
|
||||
|
||||
try {
|
||||
builder.setMaxMtu(500);
|
||||
fail("Expected exception due to too-small MTU");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
}
|
||||
}
|
||||
|
||||
private void verifyVpnProfileCommon(VpnProfile profile) {
|
||||
assertEquals(SERVER_ADDR_STRING, profile.server);
|
||||
assertEquals(IDENTITY_STRING, profile.ipsecIdentifier);
|
||||
assertEquals(mProxy, profile.proxy);
|
||||
assertTrue(profile.isBypassable);
|
||||
assertTrue(profile.isMetered);
|
||||
assertEquals(TEST_MTU, profile.maxMtu);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPskConvertToVpnProfile() throws Exception {
|
||||
final Ikev2VpnProfile.Builder builder = getBuilderWithDefaultOptions();
|
||||
|
||||
builder.setAuthPsk(PSK_BYTES);
|
||||
final VpnProfile profile = builder.build().toVpnProfile();
|
||||
|
||||
verifyVpnProfileCommon(profile);
|
||||
assertEquals(Ikev2VpnProfile.encodeForIpsecSecret(PSK_BYTES), profile.ipsecSecret);
|
||||
|
||||
// Check nothing else is set
|
||||
assertEquals("", profile.username);
|
||||
assertEquals("", profile.password);
|
||||
assertEquals("", profile.ipsecUserCert);
|
||||
assertEquals("", profile.ipsecCaCert);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUsernamePasswordConvertToVpnProfile() throws Exception {
|
||||
final Ikev2VpnProfile.Builder builder = getBuilderWithDefaultOptions();
|
||||
|
||||
builder.setAuthUsernamePassword(USERNAME_STRING, PASSWORD_STRING, mServerRootCa);
|
||||
final VpnProfile profile = builder.build().toVpnProfile();
|
||||
|
||||
verifyVpnProfileCommon(profile);
|
||||
assertEquals(USERNAME_STRING, profile.username);
|
||||
assertEquals(PASSWORD_STRING, profile.password);
|
||||
assertEquals(Ikev2VpnProfile.certificateToPemString(mServerRootCa), profile.ipsecCaCert);
|
||||
|
||||
// Check nothing else is set
|
||||
assertEquals("", profile.ipsecUserCert);
|
||||
assertEquals("", profile.ipsecSecret);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRsaConvertToVpnProfile() throws Exception {
|
||||
final Ikev2VpnProfile.Builder builder = getBuilderWithDefaultOptions();
|
||||
|
||||
builder.setAuthDigitalSignature(mUserCert, mPrivateKey, mServerRootCa);
|
||||
final VpnProfile profile = builder.build().toVpnProfile();
|
||||
|
||||
verifyVpnProfileCommon(profile);
|
||||
assertEquals(Ikev2VpnProfile.certificateToPemString(mUserCert), profile.ipsecUserCert);
|
||||
assertEquals(
|
||||
Ikev2VpnProfile.encodeForIpsecSecret(mPrivateKey.getEncoded()),
|
||||
profile.ipsecSecret);
|
||||
assertEquals(Ikev2VpnProfile.certificateToPemString(mServerRootCa), profile.ipsecCaCert);
|
||||
|
||||
// Check nothing else is set
|
||||
assertEquals("", profile.username);
|
||||
assertEquals("", profile.password);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPskFromVpnProfileDiscardsIrrelevantValues() throws Exception {
|
||||
final Ikev2VpnProfile.Builder builder = getBuilderWithDefaultOptions();
|
||||
|
||||
builder.setAuthPsk(PSK_BYTES);
|
||||
final VpnProfile profile = builder.build().toVpnProfile();
|
||||
profile.username = USERNAME_STRING;
|
||||
profile.password = PASSWORD_STRING;
|
||||
profile.ipsecCaCert = Ikev2VpnProfile.certificateToPemString(mServerRootCa);
|
||||
profile.ipsecUserCert = Ikev2VpnProfile.certificateToPemString(mUserCert);
|
||||
|
||||
final Ikev2VpnProfile result = Ikev2VpnProfile.fromVpnProfile(profile);
|
||||
assertNull(result.getUsername());
|
||||
assertNull(result.getPassword());
|
||||
assertNull(result.getUserCert());
|
||||
assertNull(result.getRsaPrivateKey());
|
||||
assertNull(result.getServerRootCaCert());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUsernamePasswordFromVpnProfileDiscardsIrrelevantValues() throws Exception {
|
||||
final Ikev2VpnProfile.Builder builder = getBuilderWithDefaultOptions();
|
||||
|
||||
builder.setAuthUsernamePassword(USERNAME_STRING, PASSWORD_STRING, mServerRootCa);
|
||||
final VpnProfile profile = builder.build().toVpnProfile();
|
||||
profile.ipsecSecret = new String(PSK_BYTES);
|
||||
profile.ipsecUserCert = Ikev2VpnProfile.certificateToPemString(mUserCert);
|
||||
|
||||
final Ikev2VpnProfile result = Ikev2VpnProfile.fromVpnProfile(profile);
|
||||
assertNull(result.getPresharedKey());
|
||||
assertNull(result.getUserCert());
|
||||
assertNull(result.getRsaPrivateKey());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRsaFromVpnProfileDiscardsIrrelevantValues() throws Exception {
|
||||
final Ikev2VpnProfile.Builder builder = getBuilderWithDefaultOptions();
|
||||
|
||||
builder.setAuthDigitalSignature(mUserCert, mPrivateKey, mServerRootCa);
|
||||
final VpnProfile profile = builder.build().toVpnProfile();
|
||||
profile.username = USERNAME_STRING;
|
||||
profile.password = PASSWORD_STRING;
|
||||
|
||||
final Ikev2VpnProfile result = Ikev2VpnProfile.fromVpnProfile(profile);
|
||||
assertNull(result.getUsername());
|
||||
assertNull(result.getPassword());
|
||||
assertNull(result.getPresharedKey());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPskConversionIsLossless() throws Exception {
|
||||
final Ikev2VpnProfile.Builder builder = getBuilderWithDefaultOptions();
|
||||
|
||||
builder.setAuthPsk(PSK_BYTES);
|
||||
final Ikev2VpnProfile ikeProfile = builder.build();
|
||||
|
||||
assertEquals(ikeProfile, Ikev2VpnProfile.fromVpnProfile(ikeProfile.toVpnProfile()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUsernamePasswordConversionIsLossless() throws Exception {
|
||||
final Ikev2VpnProfile.Builder builder = getBuilderWithDefaultOptions();
|
||||
|
||||
builder.setAuthUsernamePassword(USERNAME_STRING, PASSWORD_STRING, mServerRootCa);
|
||||
final Ikev2VpnProfile ikeProfile = builder.build();
|
||||
|
||||
assertEquals(ikeProfile, Ikev2VpnProfile.fromVpnProfile(ikeProfile.toVpnProfile()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRsaConversionIsLossless() throws Exception {
|
||||
final Ikev2VpnProfile.Builder builder = getBuilderWithDefaultOptions();
|
||||
|
||||
builder.setAuthDigitalSignature(mUserCert, mPrivateKey, mServerRootCa);
|
||||
final Ikev2VpnProfile ikeProfile = builder.build();
|
||||
|
||||
assertEquals(ikeProfile, Ikev2VpnProfile.fromVpnProfile(ikeProfile.toVpnProfile()));
|
||||
}
|
||||
|
||||
private static class CertificateAndKey {
|
||||
public final X509Certificate cert;
|
||||
public final PrivateKey key;
|
||||
|
||||
CertificateAndKey(X509Certificate cert, PrivateKey key) {
|
||||
this.cert = cert;
|
||||
this.key = key;
|
||||
}
|
||||
}
|
||||
|
||||
private static CertificateAndKey generateRandomCertAndKeyPair() throws Exception {
|
||||
final Date validityBeginDate =
|
||||
new Date(System.currentTimeMillis() - TimeUnit.DAYS.toMillis(1L));
|
||||
final Date validityEndDate =
|
||||
new Date(System.currentTimeMillis() + TimeUnit.DAYS.toMillis(1L));
|
||||
|
||||
// Generate a keypair
|
||||
final KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
|
||||
keyPairGenerator.initialize(512);
|
||||
final KeyPair keyPair = keyPairGenerator.generateKeyPair();
|
||||
|
||||
final X500Principal dnName = new X500Principal("CN=test.android.com");
|
||||
final X509V1CertificateGenerator certGen = new X509V1CertificateGenerator();
|
||||
certGen.setSerialNumber(BigInteger.valueOf(System.currentTimeMillis()));
|
||||
certGen.setSubjectDN(dnName);
|
||||
certGen.setIssuerDN(dnName);
|
||||
certGen.setNotBefore(validityBeginDate);
|
||||
certGen.setNotAfter(validityEndDate);
|
||||
certGen.setPublicKey(keyPair.getPublic());
|
||||
certGen.setSignatureAlgorithm("SHA256WithRSAEncryption");
|
||||
|
||||
final X509Certificate cert = certGen.generate(keyPair.getPrivate(), "AndroidOpenSSL");
|
||||
return new CertificateAndKey(cert, keyPair.getPrivate());
|
||||
}
|
||||
}
|
||||
83
tests/net/java/android/net/VpnManagerTest.java
Normal file
83
tests/net/java/android/net/VpnManagerTest.java
Normal file
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
import android.test.mock.MockContext;
|
||||
|
||||
import androidx.test.filters.SmallTest;
|
||||
import androidx.test.runner.AndroidJUnit4;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
/** Unit tests for {@link VpnManager}. */
|
||||
@SmallTest
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class VpnManagerTest {
|
||||
private static final String VPN_PROFILE_KEY = "KEY";
|
||||
|
||||
private IConnectivityManager mMockCs;
|
||||
private VpnManager mVpnManager;
|
||||
private final MockContext mMockContext =
|
||||
new MockContext() {
|
||||
@Override
|
||||
public String getOpPackageName() {
|
||||
return "fooPackage";
|
||||
}
|
||||
};
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
mMockCs = mock(IConnectivityManager.class);
|
||||
mVpnManager = new VpnManager(mMockContext, mMockCs);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProvisionVpnProfile() throws Exception {
|
||||
try {
|
||||
mVpnManager.provisionVpnProfile(mock(PlatformVpnProfile.class));
|
||||
} catch (UnsupportedOperationException expected) {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeleteProvisionedVpnProfile() throws Exception {
|
||||
try {
|
||||
mVpnManager.deleteProvisionedVpnProfile();
|
||||
} catch (UnsupportedOperationException expected) {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStartProvisionedVpnProfile() throws Exception {
|
||||
try {
|
||||
mVpnManager.startProvisionedVpnProfile();
|
||||
} catch (UnsupportedOperationException expected) {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStopProvisionedVpnProfile() throws Exception {
|
||||
try {
|
||||
mVpnManager.stopProvisionedVpnProfile();
|
||||
} catch (UnsupportedOperationException expected) {
|
||||
}
|
||||
}
|
||||
}
|
||||
185
tests/net/java/com/android/internal/net/VpnProfileTest.java
Normal file
185
tests/net/java/com/android/internal/net/VpnProfileTest.java
Normal file
@@ -0,0 +1,185 @@
|
||||
/*
|
||||
* 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 com.android.internal.net;
|
||||
|
||||
import static com.android.testutils.ParcelUtilsKt.assertParcelSane;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotEquals;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import android.net.IpSecAlgorithm;
|
||||
|
||||
import androidx.test.filters.SmallTest;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.JUnit4;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/** Unit tests for {@link VpnProfile}. */
|
||||
@SmallTest
|
||||
@RunWith(JUnit4.class)
|
||||
public class VpnProfileTest {
|
||||
private static final String DUMMY_PROFILE_KEY = "Test";
|
||||
|
||||
@Test
|
||||
public void testDefaults() throws Exception {
|
||||
final VpnProfile p = new VpnProfile(DUMMY_PROFILE_KEY);
|
||||
|
||||
assertEquals(DUMMY_PROFILE_KEY, p.key);
|
||||
assertEquals("", p.name);
|
||||
assertEquals(VpnProfile.TYPE_PPTP, p.type);
|
||||
assertEquals("", p.server);
|
||||
assertEquals("", p.username);
|
||||
assertEquals("", p.password);
|
||||
assertEquals("", p.dnsServers);
|
||||
assertEquals("", p.searchDomains);
|
||||
assertEquals("", p.routes);
|
||||
assertTrue(p.mppe);
|
||||
assertEquals("", p.l2tpSecret);
|
||||
assertEquals("", p.ipsecIdentifier);
|
||||
assertEquals("", p.ipsecSecret);
|
||||
assertEquals("", p.ipsecUserCert);
|
||||
assertEquals("", p.ipsecCaCert);
|
||||
assertEquals("", p.ipsecServerCert);
|
||||
assertEquals(null, p.proxy);
|
||||
assertTrue(p.getAllowedAlgorithms() != null && p.getAllowedAlgorithms().isEmpty());
|
||||
assertFalse(p.isBypassable);
|
||||
assertFalse(p.isMetered);
|
||||
assertEquals(1400, p.maxMtu);
|
||||
assertFalse(p.areAuthParamsInline);
|
||||
}
|
||||
|
||||
private VpnProfile getSampleIkev2Profile(String key) {
|
||||
final VpnProfile p = new VpnProfile(key);
|
||||
|
||||
p.name = "foo";
|
||||
p.type = VpnProfile.TYPE_IKEV2_IPSEC_USER_PASS;
|
||||
p.server = "bar";
|
||||
p.username = "baz";
|
||||
p.password = "qux";
|
||||
p.dnsServers = "8.8.8.8";
|
||||
p.searchDomains = "";
|
||||
p.routes = "0.0.0.0/0";
|
||||
p.mppe = false;
|
||||
p.l2tpSecret = "";
|
||||
p.ipsecIdentifier = "quux";
|
||||
p.ipsecSecret = "quuz";
|
||||
p.ipsecUserCert = "corge";
|
||||
p.ipsecCaCert = "grault";
|
||||
p.ipsecServerCert = "garply";
|
||||
p.proxy = null;
|
||||
p.setAllowedAlgorithms(
|
||||
Arrays.asList(
|
||||
IpSecAlgorithm.AUTH_CRYPT_AES_GCM,
|
||||
IpSecAlgorithm.AUTH_HMAC_SHA512,
|
||||
IpSecAlgorithm.CRYPT_AES_CBC));
|
||||
p.isBypassable = true;
|
||||
p.isMetered = true;
|
||||
p.maxMtu = 1350;
|
||||
p.areAuthParamsInline = true;
|
||||
|
||||
// Not saved, but also not compared.
|
||||
p.saveLogin = true;
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEquals() {
|
||||
assertEquals(
|
||||
getSampleIkev2Profile(DUMMY_PROFILE_KEY), getSampleIkev2Profile(DUMMY_PROFILE_KEY));
|
||||
|
||||
final VpnProfile modified = getSampleIkev2Profile(DUMMY_PROFILE_KEY);
|
||||
modified.maxMtu--;
|
||||
assertNotEquals(getSampleIkev2Profile(DUMMY_PROFILE_KEY), modified);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParcelUnparcel() {
|
||||
assertParcelSane(getSampleIkev2Profile(DUMMY_PROFILE_KEY), 22);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetInvalidAlgorithmValueDelimiter() {
|
||||
final VpnProfile profile = getSampleIkev2Profile(DUMMY_PROFILE_KEY);
|
||||
|
||||
try {
|
||||
profile.setAllowedAlgorithms(
|
||||
Arrays.asList("test" + VpnProfile.VALUE_DELIMITER + "test"));
|
||||
fail("Expected failure due to value separator in algorithm name");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetInvalidAlgorithmListDelimiter() {
|
||||
final VpnProfile profile = getSampleIkev2Profile(DUMMY_PROFILE_KEY);
|
||||
|
||||
try {
|
||||
profile.setAllowedAlgorithms(
|
||||
Arrays.asList("test" + VpnProfile.LIST_DELIMITER + "test"));
|
||||
fail("Expected failure due to value separator in algorithm name");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEncodeDecode() {
|
||||
final VpnProfile profile = getSampleIkev2Profile(DUMMY_PROFILE_KEY);
|
||||
final VpnProfile decoded = VpnProfile.decode(DUMMY_PROFILE_KEY, profile.encode());
|
||||
assertEquals(profile, decoded);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEncodeDecodeTooManyValues() {
|
||||
final VpnProfile profile = getSampleIkev2Profile(DUMMY_PROFILE_KEY);
|
||||
final byte[] tooManyValues =
|
||||
(new String(profile.encode()) + VpnProfile.VALUE_DELIMITER + "invalid").getBytes();
|
||||
|
||||
assertNull(VpnProfile.decode(DUMMY_PROFILE_KEY, tooManyValues));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEncodeDecodeInvalidNumberOfValues() {
|
||||
final VpnProfile profile = getSampleIkev2Profile(DUMMY_PROFILE_KEY);
|
||||
final String encoded = new String(profile.encode());
|
||||
final byte[] tooFewValues =
|
||||
encoded.substring(0, encoded.lastIndexOf(VpnProfile.VALUE_DELIMITER)).getBytes();
|
||||
|
||||
assertNull(VpnProfile.decode(DUMMY_PROFILE_KEY, tooFewValues));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEncodeDecodeLoginsNotSaved() {
|
||||
final VpnProfile profile = getSampleIkev2Profile(DUMMY_PROFILE_KEY);
|
||||
profile.saveLogin = false;
|
||||
|
||||
final VpnProfile decoded = VpnProfile.decode(DUMMY_PROFILE_KEY, profile.encode());
|
||||
assertNotEquals(profile, decoded);
|
||||
|
||||
// Add the username/password back, everything else must be equal.
|
||||
decoded.username = profile.username;
|
||||
decoded.password = profile.password;
|
||||
assertEquals(profile, decoded);
|
||||
}
|
||||
}
|
||||
@@ -6313,12 +6313,24 @@ public class ConnectivityServiceTest {
|
||||
assertEquals(wifiLp, mService.getActiveLinkProperties());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNetworkCapabilitiesRestrictedForCallerPermissions() {
|
||||
int callerUid = Process.myUid();
|
||||
final NetworkCapabilities originalNc = new NetworkCapabilities();
|
||||
originalNc.setOwnerUid(callerUid);
|
||||
|
||||
private TestNetworkAgentWrapper establishVpn(LinkProperties lp, int establishingUid,
|
||||
Set<UidRange> vpnRange) throws Exception {
|
||||
final NetworkCapabilities newNc =
|
||||
mService.networkCapabilitiesRestrictedForCallerPermissions(
|
||||
originalNc, Process.myPid(), callerUid);
|
||||
|
||||
assertEquals(Process.INVALID_UID, newNc.getOwnerUid());
|
||||
}
|
||||
|
||||
private TestNetworkAgentWrapper establishVpn(
|
||||
LinkProperties lp, int ownerUid, Set<UidRange> vpnRange) throws Exception {
|
||||
final TestNetworkAgentWrapper
|
||||
vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN, lp);
|
||||
vpnNetworkAgent.getNetworkCapabilities().setEstablishingVpnAppUid(establishingUid);
|
||||
vpnNetworkAgent.getNetworkCapabilities().setOwnerUid(ownerUid);
|
||||
mMockVpn.setNetworkAgent(vpnNetworkAgent);
|
||||
mMockVpn.connect();
|
||||
mMockVpn.setUids(vpnRange);
|
||||
|
||||
Reference in New Issue
Block a user