Move NetworkMonitor to NetworkStack
Bug: b/112869080 Test: atest FrameworksNetTests NetworkStackTests Change-Id: I1b8b6a3f4390adbabf92fb9e48da61c47b08b2ec
This commit is contained in:
@@ -824,8 +824,11 @@ aidl_interface {
|
||||
name: "networkstack-aidl-interfaces",
|
||||
local_include_dir: "core/java",
|
||||
srcs: [
|
||||
"core/java/android/net/INetworkMonitor.aidl",
|
||||
"core/java/android/net/INetworkMonitorCallbacks.aidl",
|
||||
"core/java/android/net/INetworkStackConnector.aidl",
|
||||
"core/java/android/net/INetworkStackStatusCallback.aidl",
|
||||
"core/java/android/net/PrivateDnsConfigParcel.aidl",
|
||||
"core/java/android/net/dhcp/DhcpServingParamsParcel.aidl",
|
||||
"core/java/android/net/dhcp/IDhcpServer.aidl",
|
||||
"core/java/android/net/dhcp/IDhcpServerCallbacks.aidl",
|
||||
|
||||
@@ -2051,6 +2051,16 @@ public class ConnectivityManager {
|
||||
return (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
public NetworkRequest getDefaultRequest() {
|
||||
try {
|
||||
// This is not racy as the default request is final in ConnectivityService.
|
||||
return mService.getDefaultRequest();
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO: These permissions checks don't belong in client-side code. Move them to
|
||||
* services.jar, possibly in com.android.server.net. */
|
||||
|
||||
|
||||
@@ -167,6 +167,8 @@ interface IConnectivityManager
|
||||
|
||||
int getMultipathPreference(in Network Network);
|
||||
|
||||
NetworkRequest getDefaultRequest();
|
||||
|
||||
int getRestoreDefaultNetworkDelay(int networkType);
|
||||
|
||||
boolean addVpnAddress(String address, int prefixLength);
|
||||
|
||||
45
core/java/android/net/INetworkMonitor.aidl
Normal file
45
core/java/android/net/INetworkMonitor.aidl
Normal file
@@ -0,0 +1,45 @@
|
||||
/**
|
||||
* Copyright (c) 2018, 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 perNmissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package android.net;
|
||||
|
||||
import android.net.PrivateDnsConfigParcel;
|
||||
|
||||
/** @hide */
|
||||
oneway interface INetworkMonitor {
|
||||
// After a network has been tested this result can be sent with EVENT_NETWORK_TESTED.
|
||||
// The network should be used as a default internet connection. It was found to be:
|
||||
// 1. a functioning network providing internet access, or
|
||||
// 2. a captive portal and the user decided to use it as is.
|
||||
const int NETWORK_TEST_RESULT_VALID = 0;
|
||||
|
||||
// After a network has been tested this result can be sent with EVENT_NETWORK_TESTED.
|
||||
// The network should not be used as a default internet connection. It was found to be:
|
||||
// 1. a captive portal and the user is prompted to sign-in, or
|
||||
// 2. a captive portal and the user did not want to use it, or
|
||||
// 3. a broken network (e.g. DNS failed, connect failed, HTTP request failed).
|
||||
const int NETWORK_TEST_RESULT_INVALID = 1;
|
||||
|
||||
void start();
|
||||
void launchCaptivePortalApp();
|
||||
void forceReevaluation(int uid);
|
||||
void notifyPrivateDnsChanged(in PrivateDnsConfigParcel config);
|
||||
void notifyDnsResponse(int returnCode);
|
||||
void notifySystemReady();
|
||||
void notifyNetworkConnected();
|
||||
void notifyNetworkDisconnected();
|
||||
void notifyLinkPropertiesChanged();
|
||||
void notifyNetworkCapabilitiesChanged();
|
||||
}
|
||||
29
core/java/android/net/INetworkMonitorCallbacks.aidl
Normal file
29
core/java/android/net/INetworkMonitorCallbacks.aidl
Normal file
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright (C) 2018 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 android.net.INetworkMonitor;
|
||||
import android.net.PrivateDnsConfigParcel;
|
||||
|
||||
/** @hide */
|
||||
oneway interface INetworkMonitorCallbacks {
|
||||
void onNetworkMonitorCreated(in INetworkMonitor networkMonitor);
|
||||
void notifyNetworkTested(int testResult, @nullable String redirectUrl);
|
||||
void notifyPrivateDnsConfigResolved(in PrivateDnsConfigParcel config);
|
||||
void showProvisioningNotification(String action);
|
||||
void hideProvisioningNotification();
|
||||
}
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package android.net;
|
||||
|
||||
import android.net.INetworkMonitorCallbacks;
|
||||
import android.net.dhcp.DhcpServingParamsParcel;
|
||||
import android.net.dhcp.IDhcpServerCallbacks;
|
||||
|
||||
@@ -22,4 +23,5 @@ import android.net.dhcp.IDhcpServerCallbacks;
|
||||
oneway interface INetworkStackConnector {
|
||||
void makeDhcpServer(in String ifName, in DhcpServingParamsParcel params,
|
||||
in IDhcpServerCallbacks cb);
|
||||
void makeNetworkMonitor(int netId, String name, in INetworkMonitorCallbacks cb);
|
||||
}
|
||||
@@ -48,14 +48,16 @@ import java.util.ArrayList;
|
||||
public class NetworkStack {
|
||||
private static final String TAG = NetworkStack.class.getSimpleName();
|
||||
|
||||
public static final String NETWORKSTACK_PACKAGE_NAME = "com.android.mainline.networkstack";
|
||||
|
||||
@NonNull
|
||||
@GuardedBy("mPendingNetStackRequests")
|
||||
private final ArrayList<NetworkStackRequest> mPendingNetStackRequests = new ArrayList<>();
|
||||
private final ArrayList<NetworkStackCallback> mPendingNetStackRequests = new ArrayList<>();
|
||||
@Nullable
|
||||
@GuardedBy("mPendingNetStackRequests")
|
||||
private INetworkStackConnector mConnector;
|
||||
|
||||
private interface NetworkStackRequest {
|
||||
private interface NetworkStackCallback {
|
||||
void onNetworkStackConnected(INetworkStackConnector connector);
|
||||
}
|
||||
|
||||
@@ -77,6 +79,21 @@ public class NetworkStack {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a NetworkMonitor.
|
||||
*
|
||||
* <p>The INetworkMonitor will be returned asynchronously through the provided callbacks.
|
||||
*/
|
||||
public void makeNetworkMonitor(Network network, String name, INetworkMonitorCallbacks cb) {
|
||||
requestConnector(connector -> {
|
||||
try {
|
||||
connector.makeNetworkMonitor(network.netId, name, cb);
|
||||
} catch (RemoteException e) {
|
||||
e.rethrowFromSystemServer();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private class NetworkStackConnection implements ServiceConnection {
|
||||
@Override
|
||||
public void onServiceConnected(ComponentName name, IBinder service) {
|
||||
@@ -96,14 +113,14 @@ public class NetworkStack {
|
||||
ServiceManager.addService(Context.NETWORK_STACK_SERVICE, service, false /* allowIsolated */,
|
||||
DUMP_FLAG_PRIORITY_HIGH | DUMP_FLAG_PRIORITY_NORMAL);
|
||||
|
||||
final ArrayList<NetworkStackRequest> requests;
|
||||
final ArrayList<NetworkStackCallback> requests;
|
||||
synchronized (mPendingNetStackRequests) {
|
||||
requests = new ArrayList<>(mPendingNetStackRequests);
|
||||
mPendingNetStackRequests.clear();
|
||||
mConnector = connector;
|
||||
}
|
||||
|
||||
for (NetworkStackRequest r : requests) {
|
||||
for (NetworkStackCallback r : requests) {
|
||||
r.onNetworkStackConnected(connector);
|
||||
}
|
||||
}
|
||||
@@ -124,7 +141,8 @@ public class NetworkStack {
|
||||
"com.android.server.NetworkStackService",
|
||||
true /* initialize */,
|
||||
context.getClassLoader());
|
||||
connector = (IBinder) service.getMethod("makeConnector").invoke(null);
|
||||
connector = (IBinder) service.getMethod("makeConnector", Context.class)
|
||||
.invoke(null, context);
|
||||
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
|
||||
Slog.wtf(TAG, "Could not create network stack connector from NetworkStackService");
|
||||
// TODO: crash/reboot system here ?
|
||||
@@ -153,7 +171,7 @@ public class NetworkStack {
|
||||
}
|
||||
|
||||
// TODO: use this method to obtain the connector when implementing network stack operations
|
||||
private void requestConnector(@NonNull NetworkStackRequest request) {
|
||||
private void requestConnector(@NonNull NetworkStackCallback request) {
|
||||
// TODO: PID check.
|
||||
if (Binder.getCallingUid() != Process.SYSTEM_UID) {
|
||||
// Don't even attempt to obtain the connector and give a nice error message
|
||||
|
||||
22
core/java/android/net/PrivateDnsConfigParcel.aidl
Normal file
22
core/java/android/net/PrivateDnsConfigParcel.aidl
Normal file
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright (C) 2018 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;
|
||||
|
||||
parcelable PrivateDnsConfigParcel {
|
||||
String hostname;
|
||||
String[] ips;
|
||||
}
|
||||
@@ -21,10 +21,10 @@ java_library {
|
||||
installable: true,
|
||||
srcs: [
|
||||
"src/**/*.java",
|
||||
":services-networkstack-shared-srcs",
|
||||
],
|
||||
static_libs: [
|
||||
"dhcp-packet-lib",
|
||||
"frameworks-net-shared-utils",
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
@@ -22,8 +22,11 @@
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
|
||||
<uses-permission android:name="android.permission.CONNECTIVITY_INTERNAL" />
|
||||
<uses-permission android:name="android.permission.NETWORK_SETTINGS" />
|
||||
<!-- Launch captive portal app as specific user -->
|
||||
<uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" />
|
||||
<uses-permission android:name="android.permission.NETWORK_STACK" />
|
||||
<application
|
||||
android:label="NetworkStack"
|
||||
android:defaultToDeviceProtectedStorage="true"
|
||||
|
||||
@@ -69,6 +69,10 @@ public class SharedLog {
|
||||
mComponent = component;
|
||||
}
|
||||
|
||||
public String getTag() {
|
||||
return mTag;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a SharedLog based on this log with an additional component prefix on each logged line.
|
||||
*/
|
||||
|
||||
@@ -38,9 +38,9 @@ public class Stopwatch {
|
||||
return (isStarted() && !isStopped());
|
||||
}
|
||||
|
||||
// Returning |this| makes possible the following usage pattern:
|
||||
//
|
||||
// Stopwatch s = new Stopwatch().start();
|
||||
/**
|
||||
* Start the Stopwatch.
|
||||
*/
|
||||
public Stopwatch start() {
|
||||
if (!isStarted()) {
|
||||
mStartTimeMs = SystemClock.elapsedRealtime();
|
||||
@@ -48,7 +48,10 @@ public class Stopwatch {
|
||||
return this;
|
||||
}
|
||||
|
||||
// Returns the total time recorded, in milliseconds, or 0 if not started.
|
||||
/**
|
||||
* Stop the Stopwatch.
|
||||
* @return the total time recorded, in milliseconds, or 0 if not started.
|
||||
*/
|
||||
public long stop() {
|
||||
if (isRunning()) {
|
||||
mStopTimeMs = SystemClock.elapsedRealtime();
|
||||
@@ -57,9 +60,11 @@ public class Stopwatch {
|
||||
return (mStopTimeMs - mStartTimeMs);
|
||||
}
|
||||
|
||||
// Returns the total time recorded to date, in milliseconds.
|
||||
// If the Stopwatch is not running, returns the same value as stop(),
|
||||
// i.e. either the total time recorded before stopping or 0.
|
||||
/**
|
||||
* Return the total time recorded to date, in milliseconds.
|
||||
* If the Stopwatch is not running, returns the same value as stop(),
|
||||
* i.e. either the total time recorded before stopping or 0.
|
||||
*/
|
||||
public long lap() {
|
||||
if (isRunning()) {
|
||||
return (SystemClock.elapsedRealtime() - mStartTimeMs);
|
||||
@@ -68,6 +73,9 @@ public class Stopwatch {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the Stopwatch. It will be stopped when this method returns.
|
||||
*/
|
||||
public void reset() {
|
||||
mStartTimeMs = 0;
|
||||
mStopTimeMs = 0;
|
||||
@@ -25,18 +25,31 @@ import static com.android.server.util.PermissionUtil.checkNetworkStackCallingPer
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.app.Service;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.net.INetworkMonitor;
|
||||
import android.net.INetworkMonitorCallbacks;
|
||||
import android.net.INetworkStackConnector;
|
||||
import android.net.Network;
|
||||
import android.net.NetworkRequest;
|
||||
import android.net.PrivateDnsConfigParcel;
|
||||
import android.net.dhcp.DhcpServer;
|
||||
import android.net.dhcp.DhcpServingParams;
|
||||
import android.net.dhcp.DhcpServingParamsParcel;
|
||||
import android.net.dhcp.IDhcpServerCallbacks;
|
||||
import android.net.shared.PrivateDnsConfig;
|
||||
import android.net.util.SharedLog;
|
||||
import android.os.IBinder;
|
||||
import android.os.RemoteException;
|
||||
|
||||
import com.android.internal.annotations.GuardedBy;
|
||||
import com.android.internal.util.IndentingPrintWriter;
|
||||
import com.android.server.connectivity.NetworkMonitor;
|
||||
|
||||
import java.io.FileDescriptor;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.ArrayDeque;
|
||||
|
||||
/**
|
||||
* Android service used to start the network stack when bound to via an intent.
|
||||
@@ -52,17 +65,41 @@ public class NetworkStackService extends Service {
|
||||
* <p>On platforms where the network stack runs in the system server process, this method may
|
||||
* be called directly instead of obtaining the connector by binding to the service.
|
||||
*/
|
||||
public static IBinder makeConnector() {
|
||||
return new NetworkStackConnector();
|
||||
public static IBinder makeConnector(Context context) {
|
||||
return new NetworkStackConnector(context);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public IBinder onBind(Intent intent) {
|
||||
return makeConnector();
|
||||
return makeConnector(this);
|
||||
}
|
||||
|
||||
private static class NetworkStackConnector extends INetworkStackConnector.Stub {
|
||||
private static final int NUM_VALIDATION_LOG_LINES = 20;
|
||||
private final Context mContext;
|
||||
private final ConnectivityManager mCm;
|
||||
|
||||
private static final int MAX_VALIDATION_LOGS = 10;
|
||||
@GuardedBy("mValidationLogs")
|
||||
private final ArrayDeque<SharedLog> mValidationLogs = new ArrayDeque<>(MAX_VALIDATION_LOGS);
|
||||
|
||||
private SharedLog addValidationLogs(Network network, String name) {
|
||||
final SharedLog log = new SharedLog(NUM_VALIDATION_LOG_LINES, network + " - " + name);
|
||||
synchronized (mValidationLogs) {
|
||||
while (mValidationLogs.size() >= MAX_VALIDATION_LOGS) {
|
||||
mValidationLogs.removeLast();
|
||||
}
|
||||
mValidationLogs.addFirst(log);
|
||||
}
|
||||
return log;
|
||||
}
|
||||
|
||||
NetworkStackConnector(Context context) {
|
||||
mContext = context;
|
||||
mCm = context.getSystemService(ConnectivityManager.class);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private final SharedLog mLog = new SharedLog(TAG);
|
||||
|
||||
@@ -88,12 +125,103 @@ public class NetworkStackService extends Service {
|
||||
cb.onDhcpServerCreated(STATUS_SUCCESS, server);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void makeNetworkMonitor(int netId, String name, INetworkMonitorCallbacks cb)
|
||||
throws RemoteException {
|
||||
final Network network = new Network(netId, false /* privateDnsBypass */);
|
||||
final NetworkRequest defaultRequest = mCm.getDefaultRequest();
|
||||
final SharedLog log = addValidationLogs(network, name);
|
||||
final NetworkMonitor nm = new NetworkMonitor(
|
||||
mContext, cb, network, defaultRequest, log);
|
||||
cb.onNetworkMonitorCreated(new NetworkMonitorImpl(nm));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter fout,
|
||||
@Nullable String[] args) {
|
||||
checkNetworkStackCallingPermission();
|
||||
fout.println("NetworkStack logs:");
|
||||
mLog.dump(fd, fout, args);
|
||||
final IndentingPrintWriter pw = new IndentingPrintWriter(fout, " ");
|
||||
pw.println("NetworkStack logs:");
|
||||
mLog.dump(fd, pw, args);
|
||||
|
||||
pw.println();
|
||||
pw.println("Validation logs (most recent first):");
|
||||
synchronized (mValidationLogs) {
|
||||
for (SharedLog p : mValidationLogs) {
|
||||
pw.println(p.getTag());
|
||||
pw.increaseIndent();
|
||||
p.dump(fd, pw, args);
|
||||
pw.decreaseIndent();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class NetworkMonitorImpl extends INetworkMonitor.Stub {
|
||||
private final NetworkMonitor mNm;
|
||||
|
||||
NetworkMonitorImpl(NetworkMonitor nm) {
|
||||
mNm = nm;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
checkNetworkStackCallingPermission();
|
||||
mNm.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void launchCaptivePortalApp() {
|
||||
checkNetworkStackCallingPermission();
|
||||
mNm.launchCaptivePortalApp();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void forceReevaluation(int uid) {
|
||||
checkNetworkStackCallingPermission();
|
||||
mNm.forceReevaluation(uid);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyPrivateDnsChanged(PrivateDnsConfigParcel config) {
|
||||
checkNetworkStackCallingPermission();
|
||||
mNm.notifyPrivateDnsSettingsChanged(PrivateDnsConfig.fromParcel(config));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyDnsResponse(int returnCode) {
|
||||
checkNetworkStackCallingPermission();
|
||||
mNm.notifyDnsResponse(returnCode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifySystemReady() {
|
||||
checkNetworkStackCallingPermission();
|
||||
mNm.notifySystemReady();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyNetworkConnected() {
|
||||
checkNetworkStackCallingPermission();
|
||||
mNm.notifyNetworkConnected();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyNetworkDisconnected() {
|
||||
checkNetworkStackCallingPermission();
|
||||
mNm.notifyNetworkDisconnected();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyLinkPropertiesChanged() {
|
||||
checkNetworkStackCallingPermission();
|
||||
mNm.notifyLinkPropertiesChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyNetworkCapabilitiesChanged() {
|
||||
checkNetworkStackCallingPermission();
|
||||
mNm.notifyNetworkCapabilitiesChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,11 @@ import static android.net.CaptivePortal.APP_RETURN_UNWANTED;
|
||||
import static android.net.CaptivePortal.APP_RETURN_WANTED_AS_IS;
|
||||
import static android.net.ConnectivityManager.EXTRA_CAPTIVE_PORTAL_PROBE_SPEC;
|
||||
import static android.net.ConnectivityManager.EXTRA_CAPTIVE_PORTAL_URL;
|
||||
import static android.net.ConnectivityManager.TYPE_MOBILE;
|
||||
import static android.net.ConnectivityManager.TYPE_WIFI;
|
||||
import static android.net.INetworkMonitor.NETWORK_TEST_RESULT_INVALID;
|
||||
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
|
||||
import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
|
||||
import static android.net.metrics.ValidationProbeEvent.DNS_FAILURE;
|
||||
import static android.net.metrics.ValidationProbeEvent.DNS_SUCCESS;
|
||||
import static android.net.metrics.ValidationProbeEvent.PROBE_FALLBACK;
|
||||
@@ -35,6 +40,9 @@ import android.content.IntentFilter;
|
||||
import android.net.CaptivePortal;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.net.ICaptivePortal;
|
||||
import android.net.INetworkMonitor;
|
||||
import android.net.INetworkMonitorCallbacks;
|
||||
import android.net.LinkProperties;
|
||||
import android.net.Network;
|
||||
import android.net.NetworkCapabilities;
|
||||
import android.net.NetworkRequest;
|
||||
@@ -46,11 +54,14 @@ import android.net.captiveportal.CaptivePortalProbeSpec;
|
||||
import android.net.metrics.IpConnectivityLog;
|
||||
import android.net.metrics.NetworkEvent;
|
||||
import android.net.metrics.ValidationProbeEvent;
|
||||
import android.net.shared.NetworkMonitorUtils;
|
||||
import android.net.shared.PrivateDnsConfig;
|
||||
import android.net.util.SharedLog;
|
||||
import android.net.util.Stopwatch;
|
||||
import android.net.wifi.WifiInfo;
|
||||
import android.net.wifi.WifiManager;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import android.os.RemoteException;
|
||||
import android.os.SystemClock;
|
||||
import android.os.UserHandle;
|
||||
import android.provider.Settings;
|
||||
@@ -65,8 +76,6 @@ import android.telephony.CellInfoLte;
|
||||
import android.telephony.CellInfoWcdma;
|
||||
import android.telephony.TelephonyManager;
|
||||
import android.text.TextUtils;
|
||||
import android.util.LocalLog;
|
||||
import android.util.LocalLog.ReadOnlyLocalLog;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
@@ -75,7 +84,6 @@ import com.android.internal.util.Protocol;
|
||||
import com.android.internal.util.RingBufferIndices;
|
||||
import com.android.internal.util.State;
|
||||
import com.android.internal.util.StateMachine;
|
||||
import com.android.server.connectivity.DnsManager.PrivateDnsConfig;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.HttpURLConnection;
|
||||
@@ -104,9 +112,7 @@ public class NetworkMonitor extends StateMachine {
|
||||
// Default configuration values for captive portal detection probes.
|
||||
// TODO: append a random length parameter to the default HTTPS url.
|
||||
// TODO: randomize browser version ids in the default User-Agent String.
|
||||
private static final String DEFAULT_HTTPS_URL = "https://www.google.com/generate_204";
|
||||
private static final String DEFAULT_HTTP_URL =
|
||||
"http://connectivitycheck.gstatic.com/generate_204";
|
||||
private static final String DEFAULT_HTTPS_URL = "https://www.google.com/generate_204";
|
||||
private static final String DEFAULT_FALLBACK_URL = "http://www.google.com/gen_204";
|
||||
private static final String DEFAULT_OTHER_FALLBACK_URLS =
|
||||
"http://play.googleapis.com/generate_204";
|
||||
@@ -144,33 +150,12 @@ public class NetworkMonitor extends StateMachine {
|
||||
}
|
||||
}
|
||||
|
||||
// After a network has been tested this result can be sent with EVENT_NETWORK_TESTED.
|
||||
// The network should be used as a default internet connection. It was found to be:
|
||||
// 1. a functioning network providing internet access, or
|
||||
// 2. a captive portal and the user decided to use it as is.
|
||||
public static final int NETWORK_TEST_RESULT_VALID = 0;
|
||||
// After a network has been tested this result can be sent with EVENT_NETWORK_TESTED.
|
||||
// The network should not be used as a default internet connection. It was found to be:
|
||||
// 1. a captive portal and the user is prompted to sign-in, or
|
||||
// 2. a captive portal and the user did not want to use it, or
|
||||
// 3. a broken network (e.g. DNS failed, connect failed, HTTP request failed).
|
||||
public static final int NETWORK_TEST_RESULT_INVALID = 1;
|
||||
|
||||
private static final int BASE = Protocol.BASE_NETWORK_MONITOR;
|
||||
|
||||
/**
|
||||
* Inform NetworkMonitor that their network is connected.
|
||||
* ConnectivityService has sent a notification to indicate that network has connected.
|
||||
* Initiates Network Validation.
|
||||
*/
|
||||
public static final int CMD_NETWORK_CONNECTED = BASE + 1;
|
||||
|
||||
/**
|
||||
* Inform ConnectivityService that the network has been tested.
|
||||
* obj = String representing URL that Internet probe was redirect to, if it was redirected.
|
||||
* arg1 = One of the NETWORK_TESTED_RESULT_* constants.
|
||||
* arg2 = NetID.
|
||||
*/
|
||||
public static final int EVENT_NETWORK_TESTED = BASE + 2;
|
||||
private static final int CMD_NETWORK_CONNECTED = BASE + 1;
|
||||
|
||||
/**
|
||||
* Message to self indicating it's time to evaluate a network's connectivity.
|
||||
@@ -179,9 +164,9 @@ public class NetworkMonitor extends StateMachine {
|
||||
private static final int CMD_REEVALUATE = BASE + 6;
|
||||
|
||||
/**
|
||||
* Inform NetworkMonitor that the network has disconnected.
|
||||
* ConnectivityService has sent a notification to indicate that network has disconnected.
|
||||
*/
|
||||
public static final int CMD_NETWORK_DISCONNECTED = BASE + 7;
|
||||
private static final int CMD_NETWORK_DISCONNECTED = BASE + 7;
|
||||
|
||||
/**
|
||||
* Force evaluation even if it has succeeded in the past.
|
||||
@@ -198,14 +183,6 @@ public class NetworkMonitor extends StateMachine {
|
||||
*/
|
||||
private static final int CMD_CAPTIVE_PORTAL_APP_FINISHED = BASE + 9;
|
||||
|
||||
/**
|
||||
* Request ConnectivityService display provisioning notification.
|
||||
* arg1 = Whether to make the notification visible.
|
||||
* arg2 = NetID.
|
||||
* obj = Intent to be launched when notification selected by user, null if !arg1.
|
||||
*/
|
||||
public static final int EVENT_PROVISIONING_NOTIFICATION = BASE + 10;
|
||||
|
||||
/**
|
||||
* Message indicating sign-in app should be launched.
|
||||
* Sent by mLaunchCaptivePortalAppBroadcastReceiver when the
|
||||
@@ -213,7 +190,7 @@ public class NetworkMonitor extends StateMachine {
|
||||
* ConnectivityService when the user touches the "sign into
|
||||
* network" button in the wifi access point detail page.
|
||||
*/
|
||||
public static final int CMD_LAUNCH_CAPTIVE_PORTAL_APP = BASE + 11;
|
||||
private static final int CMD_LAUNCH_CAPTIVE_PORTAL_APP = BASE + 11;
|
||||
|
||||
/**
|
||||
* Retest network to see if captive portal is still in place.
|
||||
@@ -234,7 +211,6 @@ public class NetworkMonitor extends StateMachine {
|
||||
* validation phase is completed.
|
||||
*/
|
||||
private static final int CMD_PRIVATE_DNS_SETTINGS_CHANGED = BASE + 13;
|
||||
public static final int EVENT_PRIVATE_DNS_CONFIG_RESOLVED = BASE + 14;
|
||||
private static final int CMD_EVALUATE_PRIVATE_DNS = BASE + 15;
|
||||
|
||||
/**
|
||||
@@ -263,23 +239,16 @@ public class NetworkMonitor extends StateMachine {
|
||||
// Delay between reevaluations once a captive portal has been found.
|
||||
private static final int CAPTIVE_PORTAL_REEVALUATE_DELAY_MS = 10 * 60 * 1000;
|
||||
|
||||
private static final int NUM_VALIDATION_LOG_LINES = 20;
|
||||
|
||||
private String mPrivateDnsProviderHostname = "";
|
||||
|
||||
public static boolean isValidationRequired(
|
||||
NetworkCapabilities dfltNetCap, NetworkCapabilities nc) {
|
||||
// TODO: Consider requiring validation for DUN networks.
|
||||
return dfltNetCap.satisfiedByNetworkCapabilities(nc);
|
||||
}
|
||||
|
||||
private final Context mContext;
|
||||
private final Handler mConnectivityServiceHandler;
|
||||
private final NetworkAgentInfo mNetworkAgentInfo;
|
||||
private final INetworkMonitorCallbacks mCallback;
|
||||
private final Network mNetwork;
|
||||
private final Network mNonPrivateDnsBypassNetwork;
|
||||
private final int mNetId;
|
||||
private final TelephonyManager mTelephonyManager;
|
||||
private final WifiManager mWifiManager;
|
||||
private final ConnectivityManager mCm;
|
||||
private final NetworkRequest mDefaultRequest;
|
||||
private final IpConnectivityLog mMetricsLog;
|
||||
private final Dependencies mDependencies;
|
||||
@@ -292,6 +261,9 @@ public class NetworkMonitor extends StateMachine {
|
||||
@Nullable
|
||||
private final CaptivePortalProbeSpec[] mCaptivePortalFallbackSpecs;
|
||||
|
||||
private NetworkCapabilities mNetworkCapabilities;
|
||||
private LinkProperties mLinkProperties;
|
||||
|
||||
@VisibleForTesting
|
||||
protected boolean mIsCaptivePortalCheckEnabled;
|
||||
|
||||
@@ -304,7 +276,7 @@ public class NetworkMonitor extends StateMachine {
|
||||
// Avoids surfacing "Sign in to network" notification.
|
||||
private boolean mDontDisplaySigninNotification = false;
|
||||
|
||||
public boolean systemReady = false;
|
||||
private volatile boolean mSystemReady = false;
|
||||
|
||||
private final State mDefaultState = new DefaultState();
|
||||
private final State mValidatedState = new ValidatedState();
|
||||
@@ -317,7 +289,7 @@ public class NetworkMonitor extends StateMachine {
|
||||
|
||||
private CustomIntentReceiver mLaunchCaptivePortalAppBroadcastReceiver = null;
|
||||
|
||||
private final LocalLog validationLogs = new LocalLog(NUM_VALIDATION_LOG_LINES);
|
||||
private final SharedLog mValidationLogs;
|
||||
|
||||
private final Stopwatch mEvaluationTimer = new Stopwatch();
|
||||
|
||||
@@ -328,6 +300,7 @@ public class NetworkMonitor extends StateMachine {
|
||||
private final Random mRandom;
|
||||
private int mNextFallbackUrlIndex = 0;
|
||||
|
||||
|
||||
private int mReevaluateDelayMs = INITIAL_REEVALUATE_DELAY_MS;
|
||||
private int mEvaluateAttempts = 0;
|
||||
private volatile int mProbeToken = 0;
|
||||
@@ -338,17 +311,18 @@ public class NetworkMonitor extends StateMachine {
|
||||
private final DnsStallDetector mDnsStallDetector;
|
||||
private long mLastProbeTime;
|
||||
|
||||
public NetworkMonitor(Context context, Handler handler, NetworkAgentInfo networkAgentInfo,
|
||||
NetworkRequest defaultRequest) {
|
||||
this(context, handler, networkAgentInfo, defaultRequest, new IpConnectivityLog(),
|
||||
public NetworkMonitor(Context context, INetworkMonitorCallbacks cb, Network network,
|
||||
NetworkRequest defaultRequest, SharedLog validationLog) {
|
||||
this(context, cb, network, defaultRequest, new IpConnectivityLog(), validationLog,
|
||||
Dependencies.DEFAULT);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
protected NetworkMonitor(Context context, Handler handler, NetworkAgentInfo networkAgentInfo,
|
||||
NetworkRequest defaultRequest, IpConnectivityLog logger, Dependencies deps) {
|
||||
protected NetworkMonitor(Context context, INetworkMonitorCallbacks cb, Network network,
|
||||
NetworkRequest defaultRequest, IpConnectivityLog logger, SharedLog validationLogs,
|
||||
Dependencies deps) {
|
||||
// Add suffix indicating which NetworkMonitor we're talking about.
|
||||
super(TAG + networkAgentInfo.name());
|
||||
super(TAG + "/" + network.netId);
|
||||
|
||||
// Logs with a tag of the form given just above, e.g.
|
||||
// <timestamp> 862 2402 D NetworkMonitor/NetworkAgentInfo [WIFI () - 100]: ...
|
||||
@@ -356,15 +330,18 @@ public class NetworkMonitor extends StateMachine {
|
||||
|
||||
mContext = context;
|
||||
mMetricsLog = logger;
|
||||
mConnectivityServiceHandler = handler;
|
||||
mValidationLogs = validationLogs;
|
||||
mCallback = cb;
|
||||
mDependencies = deps;
|
||||
mNetworkAgentInfo = networkAgentInfo;
|
||||
mNetwork = deps.getNetwork(networkAgentInfo).getPrivateDnsBypassingCopy();
|
||||
mNonPrivateDnsBypassNetwork = network;
|
||||
mNetwork = deps.getPrivateDnsBypassNetwork(network);
|
||||
mNetId = mNetwork.netId;
|
||||
mTelephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
|
||||
mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
|
||||
mCm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||
mDefaultRequest = defaultRequest;
|
||||
|
||||
// CHECKSTYLE:OFF IndentationCheck
|
||||
addState(mDefaultState);
|
||||
addState(mMaybeNotifyState, mDefaultState);
|
||||
addState(mEvaluatingState, mMaybeNotifyState);
|
||||
@@ -374,12 +351,13 @@ public class NetworkMonitor extends StateMachine {
|
||||
addState(mEvaluatingPrivateDnsState, mDefaultState);
|
||||
addState(mValidatedState, mDefaultState);
|
||||
setInitialState(mDefaultState);
|
||||
// CHECKSTYLE:ON IndentationCheck
|
||||
|
||||
mIsCaptivePortalCheckEnabled = getIsCaptivePortalCheckEnabled();
|
||||
mUseHttps = getUseHttpsValidation();
|
||||
mCaptivePortalUserAgent = getCaptivePortalUserAgent();
|
||||
mCaptivePortalHttpsUrl = makeURL(getCaptivePortalServerHttpsUrl());
|
||||
mCaptivePortalHttpUrl = makeURL(getCaptivePortalServerHttpUrl(deps, context));
|
||||
mCaptivePortalHttpUrl = makeURL(deps.getCaptivePortalServerHttpUrl(context));
|
||||
mCaptivePortalFallbackUrls = makeCaptivePortalFallbackUrls();
|
||||
mCaptivePortalFallbackSpecs = makeCaptivePortalFallbackProbeSpecs();
|
||||
mRandom = deps.getRandom();
|
||||
@@ -390,7 +368,13 @@ public class NetworkMonitor extends StateMachine {
|
||||
mDataStallValidDnsTimeThreshold = getDataStallValidDnsTimeThreshold();
|
||||
mDataStallEvaluationType = getDataStallEvalutionType();
|
||||
|
||||
start();
|
||||
// mLinkProperties and mNetworkCapbilities must never be null or we will NPE.
|
||||
// Provide empty objects in case we are started and the network disconnects before
|
||||
// we can ever fetch them.
|
||||
// TODO: Delete ASAP.
|
||||
mLinkProperties = new LinkProperties();
|
||||
mNetworkCapabilities = new NetworkCapabilities();
|
||||
mNetworkCapabilities.clearAll();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -400,6 +384,14 @@ public class NetworkMonitor extends StateMachine {
|
||||
sendMessage(CMD_FORCE_REEVALUATION, responsibleUid, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a notification to NetworkMonitor indicating that there was a DNS query response event.
|
||||
* @param returnCode the DNS return code of the response.
|
||||
*/
|
||||
public void notifyDnsResponse(int returnCode) {
|
||||
sendMessage(EVENT_DNS_NOTIFICATION, returnCode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a notification to NetworkMonitor indicating that private DNS settings have changed.
|
||||
* @param newCfg The new private DNS configuration.
|
||||
@@ -411,9 +403,75 @@ public class NetworkMonitor extends StateMachine {
|
||||
sendMessage(CMD_PRIVATE_DNS_SETTINGS_CHANGED, newCfg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a notification to NetworkMonitor indicating that the system is ready.
|
||||
*/
|
||||
public void notifySystemReady() {
|
||||
// No need to run on the handler thread: mSystemReady is volatile and read only once on the
|
||||
// isCaptivePortal() thread.
|
||||
mSystemReady = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a notification to NetworkMonitor indicating that the network is now connected.
|
||||
*/
|
||||
public void notifyNetworkConnected() {
|
||||
sendMessage(CMD_NETWORK_CONNECTED);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a notification to NetworkMonitor indicating that the network is now disconnected.
|
||||
*/
|
||||
public void notifyNetworkDisconnected() {
|
||||
sendMessage(CMD_NETWORK_DISCONNECTED);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a notification to NetworkMonitor indicating that link properties have changed.
|
||||
*/
|
||||
public void notifyLinkPropertiesChanged() {
|
||||
getHandler().post(() -> {
|
||||
updateLinkProperties();
|
||||
});
|
||||
}
|
||||
|
||||
private void updateLinkProperties() {
|
||||
final LinkProperties lp = mCm.getLinkProperties(mNetwork);
|
||||
// If null, we should soon get a message that the network was disconnected, and will stop.
|
||||
if (lp != null) {
|
||||
// TODO: send LinkProperties parceled in notifyLinkPropertiesChanged() and start().
|
||||
mLinkProperties = lp;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a notification to NetworkMonitor indicating that network capabilities have changed.
|
||||
*/
|
||||
public void notifyNetworkCapabilitiesChanged() {
|
||||
getHandler().post(() -> {
|
||||
updateNetworkCapabilities();
|
||||
});
|
||||
}
|
||||
|
||||
private void updateNetworkCapabilities() {
|
||||
final NetworkCapabilities nc = mCm.getNetworkCapabilities(mNetwork);
|
||||
// If null, we should soon get a message that the network was disconnected, and will stop.
|
||||
if (nc != null) {
|
||||
// TODO: send NetworkCapabilities parceled in notifyNetworkCapsChanged() and start().
|
||||
mNetworkCapabilities = nc;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Request the captive portal application to be launched.
|
||||
*/
|
||||
public void launchCaptivePortalApp() {
|
||||
sendMessage(CMD_LAUNCH_CAPTIVE_PORTAL_APP);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void log(String s) {
|
||||
if (DBG) Log.d(TAG + "/" + mNetworkAgentInfo.name(), s);
|
||||
if (DBG) Log.d(TAG + "/" + mNetwork.netId, s);
|
||||
}
|
||||
|
||||
private void validationLog(int probeType, Object url, String msg) {
|
||||
@@ -423,11 +481,7 @@ public class NetworkMonitor extends StateMachine {
|
||||
|
||||
private void validationLog(String s) {
|
||||
if (DBG) log(s);
|
||||
validationLogs.log(s);
|
||||
}
|
||||
|
||||
public ReadOnlyLocalLog getValidationLogs() {
|
||||
return validationLogs.readOnlyLocalLog();
|
||||
mValidationLogs.log(s);
|
||||
}
|
||||
|
||||
private ValidationStage validationStage() {
|
||||
@@ -435,19 +489,45 @@ public class NetworkMonitor extends StateMachine {
|
||||
}
|
||||
|
||||
private boolean isValidationRequired() {
|
||||
return isValidationRequired(
|
||||
mDefaultRequest.networkCapabilities, mNetworkAgentInfo.networkCapabilities);
|
||||
return NetworkMonitorUtils.isValidationRequired(
|
||||
mDefaultRequest.networkCapabilities, mNetworkCapabilities);
|
||||
}
|
||||
|
||||
|
||||
private void notifyNetworkTestResultInvalid(Object obj) {
|
||||
mConnectivityServiceHandler.sendMessage(obtainMessage(
|
||||
EVENT_NETWORK_TESTED, NETWORK_TEST_RESULT_INVALID, mNetId, obj));
|
||||
private void notifyNetworkTested(int result, @Nullable String redirectUrl) {
|
||||
try {
|
||||
mCallback.notifyNetworkTested(result, redirectUrl);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Error sending network test result", e);
|
||||
}
|
||||
}
|
||||
|
||||
private void showProvisioningNotification(String action) {
|
||||
try {
|
||||
mCallback.showProvisioningNotification(action);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Error showing provisioning notification", e);
|
||||
}
|
||||
}
|
||||
|
||||
private void hideProvisioningNotification() {
|
||||
try {
|
||||
mCallback.hideProvisioningNotification();
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Error hiding provisioning notification", e);
|
||||
}
|
||||
}
|
||||
|
||||
// DefaultState is the parent of all States. It exists only to handle CMD_* messages but
|
||||
// does not entail any real state (hence no enter() or exit() routines).
|
||||
private class DefaultState extends State {
|
||||
@Override
|
||||
public void enter() {
|
||||
// TODO: have those passed parceled in start() and remove this
|
||||
updateLinkProperties();
|
||||
updateNetworkCapabilities();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean processMessage(Message message) {
|
||||
switch (message.what) {
|
||||
@@ -499,7 +579,7 @@ public class NetworkMonitor extends StateMachine {
|
||||
case APP_RETURN_UNWANTED:
|
||||
mDontDisplaySigninNotification = true;
|
||||
mUserDoesNotWant = true;
|
||||
notifyNetworkTestResultInvalid(null);
|
||||
notifyNetworkTested(NETWORK_TEST_RESULT_INVALID, null);
|
||||
// TODO: Should teardown network.
|
||||
mUidResponsibleForReeval = 0;
|
||||
transitionTo(mEvaluatingState);
|
||||
@@ -563,8 +643,7 @@ public class NetworkMonitor extends StateMachine {
|
||||
public void enter() {
|
||||
maybeLogEvaluationResult(
|
||||
networkEventType(validationStage(), EvaluationResult.VALIDATED));
|
||||
mConnectivityServiceHandler.sendMessage(obtainMessage(EVENT_NETWORK_TESTED,
|
||||
NETWORK_TEST_RESULT_VALID, mNetId, null));
|
||||
notifyNetworkTested(INetworkMonitor.NETWORK_TEST_RESULT_VALID, null);
|
||||
mValidations++;
|
||||
}
|
||||
|
||||
@@ -633,8 +712,7 @@ public class NetworkMonitor extends StateMachine {
|
||||
|
||||
@Override
|
||||
public void exit() {
|
||||
Message message = obtainMessage(EVENT_PROVISIONING_NOTIFICATION, 0, mNetId, null);
|
||||
mConnectivityServiceHandler.sendMessage(message);
|
||||
hideProvisioningNotification();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -751,9 +829,7 @@ public class NetworkMonitor extends StateMachine {
|
||||
CMD_LAUNCH_CAPTIVE_PORTAL_APP);
|
||||
}
|
||||
// Display the sign in notification.
|
||||
Message message = obtainMessage(EVENT_PROVISIONING_NOTIFICATION, 1, mNetId,
|
||||
mLaunchCaptivePortalAppBroadcastReceiver.getPendingIntent());
|
||||
mConnectivityServiceHandler.sendMessage(message);
|
||||
showProvisioningNotification(mLaunchCaptivePortalAppBroadcastReceiver.mAction);
|
||||
// Retest for captive portal occasionally.
|
||||
sendMessageDelayed(CMD_CAPTIVE_PORTAL_RECHECK, 0 /* no UID */,
|
||||
CAPTIVE_PORTAL_REEVALUATE_DELAY_MS);
|
||||
@@ -839,12 +915,15 @@ public class NetworkMonitor extends StateMachine {
|
||||
}
|
||||
|
||||
private void notifyPrivateDnsConfigResolved() {
|
||||
mConnectivityServiceHandler.sendMessage(obtainMessage(
|
||||
EVENT_PRIVATE_DNS_CONFIG_RESOLVED, 0, mNetId, mPrivateDnsConfig));
|
||||
try {
|
||||
mCallback.notifyPrivateDnsConfigResolved(mPrivateDnsConfig.toParcel());
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Error sending private DNS config resolved notification", e);
|
||||
}
|
||||
}
|
||||
|
||||
private void handlePrivateDnsEvaluationFailure() {
|
||||
notifyNetworkTestResultInvalid(null);
|
||||
notifyNetworkTested(NETWORK_TEST_RESULT_INVALID, null);
|
||||
|
||||
// Queue up a re-evaluation with backoff.
|
||||
//
|
||||
@@ -865,7 +944,7 @@ public class NetworkMonitor extends StateMachine {
|
||||
+ oneTimeHostnameSuffix;
|
||||
final Stopwatch watch = new Stopwatch().start();
|
||||
try {
|
||||
final InetAddress[] ips = mNetworkAgentInfo.network().getAllByName(host);
|
||||
final InetAddress[] ips = mNonPrivateDnsBypassNetwork.getAllByName(host);
|
||||
final long time = watch.stop();
|
||||
final String strIps = Arrays.toString(ips);
|
||||
final boolean success = (ips != null && ips.length > 0);
|
||||
@@ -915,12 +994,12 @@ public class NetworkMonitor extends StateMachine {
|
||||
// state (even if no Private DNS validation required).
|
||||
transitionTo(mEvaluatingPrivateDnsState);
|
||||
} else if (probeResult.isPortal()) {
|
||||
notifyNetworkTestResultInvalid(probeResult.redirectUrl);
|
||||
notifyNetworkTested(NETWORK_TEST_RESULT_INVALID, probeResult.redirectUrl);
|
||||
mLastPortalProbeResult = probeResult;
|
||||
transitionTo(mCaptivePortalState);
|
||||
} else {
|
||||
logNetworkEvent(NetworkEvent.NETWORK_VALIDATION_FAILED);
|
||||
notifyNetworkTestResultInvalid(probeResult.redirectUrl);
|
||||
notifyNetworkTested(NETWORK_TEST_RESULT_INVALID, probeResult.redirectUrl);
|
||||
transitionTo(mWaitingForNextProbeState);
|
||||
}
|
||||
return HANDLED;
|
||||
@@ -996,18 +1075,18 @@ public class NetworkMonitor extends StateMachine {
|
||||
}
|
||||
}
|
||||
|
||||
public boolean getIsCaptivePortalCheckEnabled() {
|
||||
private boolean getIsCaptivePortalCheckEnabled() {
|
||||
String symbol = Settings.Global.CAPTIVE_PORTAL_MODE;
|
||||
int defaultValue = Settings.Global.CAPTIVE_PORTAL_MODE_PROMPT;
|
||||
int mode = mDependencies.getSetting(mContext, symbol, defaultValue);
|
||||
return mode != Settings.Global.CAPTIVE_PORTAL_MODE_IGNORE;
|
||||
}
|
||||
|
||||
public boolean getUseHttpsValidation() {
|
||||
private boolean getUseHttpsValidation() {
|
||||
return mDependencies.getSetting(mContext, Settings.Global.CAPTIVE_PORTAL_USE_HTTPS, 1) == 1;
|
||||
}
|
||||
|
||||
public boolean getWifiScansAlwaysAvailableDisabled() {
|
||||
private boolean getWifiScansAlwaysAvailableDisabled() {
|
||||
return mDependencies.getSetting(
|
||||
mContext, Settings.Global.WIFI_SCAN_ALWAYS_AVAILABLE, 0) == 0;
|
||||
}
|
||||
@@ -1040,15 +1119,6 @@ public class NetworkMonitor extends StateMachine {
|
||||
DEFAULT_DATA_STALL_EVALUATION_TYPES);
|
||||
}
|
||||
|
||||
// Static for direct access by ConnectivityService
|
||||
public static String getCaptivePortalServerHttpUrl(Context context) {
|
||||
return getCaptivePortalServerHttpUrl(Dependencies.DEFAULT, context);
|
||||
}
|
||||
|
||||
public static String getCaptivePortalServerHttpUrl(Dependencies deps, Context context) {
|
||||
return deps.getSetting(context, Settings.Global.CAPTIVE_PORTAL_HTTP_URL, DEFAULT_HTTP_URL);
|
||||
}
|
||||
|
||||
private URL[] makeCaptivePortalFallbackUrls() {
|
||||
try {
|
||||
String separator = ",";
|
||||
@@ -1144,7 +1214,7 @@ public class NetworkMonitor extends StateMachine {
|
||||
// 3. PAC scripts are sometimes used to block or restrict Internet access and may in
|
||||
// fact block fetching of the generate_204 URL which would lead to false negative
|
||||
// results for network validation.
|
||||
final ProxyInfo proxyInfo = mNetworkAgentInfo.linkProperties.getHttpProxy();
|
||||
final ProxyInfo proxyInfo = mLinkProperties.getHttpProxy();
|
||||
if (proxyInfo != null && !Uri.EMPTY.equals(proxyInfo.getPacFileUrl())) {
|
||||
pacUrl = makeURL(proxyInfo.getPacFileUrl().toString());
|
||||
if (pacUrl == null) {
|
||||
@@ -1416,89 +1486,86 @@ public class NetworkMonitor extends StateMachine {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!systemReady) {
|
||||
if (!mSystemReady) {
|
||||
return;
|
||||
}
|
||||
|
||||
Intent latencyBroadcast =
|
||||
new Intent(ConnectivityConstants.ACTION_NETWORK_CONDITIONS_MEASURED);
|
||||
switch (mNetworkAgentInfo.networkInfo.getType()) {
|
||||
case ConnectivityManager.TYPE_WIFI:
|
||||
WifiInfo currentWifiInfo = mWifiManager.getConnectionInfo();
|
||||
if (currentWifiInfo != null) {
|
||||
// NOTE: getSSID()'s behavior changed in API 17; before that, SSIDs were not
|
||||
// surrounded by double quotation marks (thus violating the Javadoc), but this
|
||||
// was changed to match the Javadoc in API 17. Since clients may have started
|
||||
// sanitizing the output of this method since API 17 was released, we should
|
||||
// not change it here as it would become impossible to tell whether the SSID is
|
||||
// simply being surrounded by quotes due to the API, or whether those quotes
|
||||
// are actually part of the SSID.
|
||||
latencyBroadcast.putExtra(ConnectivityConstants.EXTRA_SSID,
|
||||
currentWifiInfo.getSSID());
|
||||
latencyBroadcast.putExtra(ConnectivityConstants.EXTRA_BSSID,
|
||||
currentWifiInfo.getBSSID());
|
||||
} else {
|
||||
if (VDBG) logw("network info is TYPE_WIFI but no ConnectionInfo found");
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case ConnectivityManager.TYPE_MOBILE:
|
||||
latencyBroadcast.putExtra(ConnectivityConstants.EXTRA_NETWORK_TYPE,
|
||||
mTelephonyManager.getNetworkType());
|
||||
List<CellInfo> info = mTelephonyManager.getAllCellInfo();
|
||||
if (info == null) return;
|
||||
int numRegisteredCellInfo = 0;
|
||||
for (CellInfo cellInfo : info) {
|
||||
if (cellInfo.isRegistered()) {
|
||||
numRegisteredCellInfo++;
|
||||
if (numRegisteredCellInfo > 1) {
|
||||
if (VDBG) {
|
||||
logw("more than one registered CellInfo."
|
||||
+ " Can't tell which is active. Bailing.");
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (cellInfo instanceof CellInfoCdma) {
|
||||
CellIdentityCdma cellId = ((CellInfoCdma) cellInfo).getCellIdentity();
|
||||
latencyBroadcast.putExtra(ConnectivityConstants.EXTRA_CELL_ID, cellId);
|
||||
} else if (cellInfo instanceof CellInfoGsm) {
|
||||
CellIdentityGsm cellId = ((CellInfoGsm) cellInfo).getCellIdentity();
|
||||
latencyBroadcast.putExtra(ConnectivityConstants.EXTRA_CELL_ID, cellId);
|
||||
} else if (cellInfo instanceof CellInfoLte) {
|
||||
CellIdentityLte cellId = ((CellInfoLte) cellInfo).getCellIdentity();
|
||||
latencyBroadcast.putExtra(ConnectivityConstants.EXTRA_CELL_ID, cellId);
|
||||
} else if (cellInfo instanceof CellInfoWcdma) {
|
||||
CellIdentityWcdma cellId = ((CellInfoWcdma) cellInfo).getCellIdentity();
|
||||
latencyBroadcast.putExtra(ConnectivityConstants.EXTRA_CELL_ID, cellId);
|
||||
} else {
|
||||
if (VDBG) logw("Registered cellinfo is unrecognized");
|
||||
return;
|
||||
new Intent(NetworkMonitorUtils.ACTION_NETWORK_CONDITIONS_MEASURED);
|
||||
if (mNetworkCapabilities.hasTransport(TRANSPORT_WIFI)) {
|
||||
WifiInfo currentWifiInfo = mWifiManager.getConnectionInfo();
|
||||
if (currentWifiInfo != null) {
|
||||
// NOTE: getSSID()'s behavior changed in API 17; before that, SSIDs were not
|
||||
// surrounded by double quotation marks (thus violating the Javadoc), but this
|
||||
// was changed to match the Javadoc in API 17. Since clients may have started
|
||||
// sanitizing the output of this method since API 17 was released, we should
|
||||
// not change it here as it would become impossible to tell whether the SSID is
|
||||
// simply being surrounded by quotes due to the API, or whether those quotes
|
||||
// are actually part of the SSID.
|
||||
latencyBroadcast.putExtra(NetworkMonitorUtils.EXTRA_SSID,
|
||||
currentWifiInfo.getSSID());
|
||||
latencyBroadcast.putExtra(NetworkMonitorUtils.EXTRA_BSSID,
|
||||
currentWifiInfo.getBSSID());
|
||||
} else {
|
||||
if (VDBG) logw("network info is TYPE_WIFI but no ConnectionInfo found");
|
||||
return;
|
||||
}
|
||||
latencyBroadcast.putExtra(NetworkMonitorUtils.EXTRA_CONNECTIVITY_TYPE, TYPE_WIFI);
|
||||
} else if (mNetworkCapabilities.hasTransport(TRANSPORT_CELLULAR)) {
|
||||
latencyBroadcast.putExtra(NetworkMonitorUtils.EXTRA_NETWORK_TYPE,
|
||||
mTelephonyManager.getNetworkType());
|
||||
List<CellInfo> info = mTelephonyManager.getAllCellInfo();
|
||||
if (info == null) return;
|
||||
int numRegisteredCellInfo = 0;
|
||||
for (CellInfo cellInfo : info) {
|
||||
if (cellInfo.isRegistered()) {
|
||||
numRegisteredCellInfo++;
|
||||
if (numRegisteredCellInfo > 1) {
|
||||
if (VDBG) {
|
||||
logw("more than one registered CellInfo."
|
||||
+ " Can't tell which is active. Bailing.");
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (cellInfo instanceof CellInfoCdma) {
|
||||
CellIdentityCdma cellId = ((CellInfoCdma) cellInfo).getCellIdentity();
|
||||
latencyBroadcast.putExtra(NetworkMonitorUtils.EXTRA_CELL_ID, cellId);
|
||||
} else if (cellInfo instanceof CellInfoGsm) {
|
||||
CellIdentityGsm cellId = ((CellInfoGsm) cellInfo).getCellIdentity();
|
||||
latencyBroadcast.putExtra(NetworkMonitorUtils.EXTRA_CELL_ID, cellId);
|
||||
} else if (cellInfo instanceof CellInfoLte) {
|
||||
CellIdentityLte cellId = ((CellInfoLte) cellInfo).getCellIdentity();
|
||||
latencyBroadcast.putExtra(NetworkMonitorUtils.EXTRA_CELL_ID, cellId);
|
||||
} else if (cellInfo instanceof CellInfoWcdma) {
|
||||
CellIdentityWcdma cellId = ((CellInfoWcdma) cellInfo).getCellIdentity();
|
||||
latencyBroadcast.putExtra(NetworkMonitorUtils.EXTRA_CELL_ID, cellId);
|
||||
} else {
|
||||
if (VDBG) logw("Registered cellinfo is unrecognized");
|
||||
return;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
latencyBroadcast.putExtra(NetworkMonitorUtils.EXTRA_CONNECTIVITY_TYPE, TYPE_MOBILE);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
latencyBroadcast.putExtra(ConnectivityConstants.EXTRA_CONNECTIVITY_TYPE,
|
||||
mNetworkAgentInfo.networkInfo.getType());
|
||||
latencyBroadcast.putExtra(ConnectivityConstants.EXTRA_RESPONSE_RECEIVED,
|
||||
latencyBroadcast.putExtra(NetworkMonitorUtils.EXTRA_RESPONSE_RECEIVED,
|
||||
responseReceived);
|
||||
latencyBroadcast.putExtra(ConnectivityConstants.EXTRA_REQUEST_TIMESTAMP_MS,
|
||||
latencyBroadcast.putExtra(NetworkMonitorUtils.EXTRA_REQUEST_TIMESTAMP_MS,
|
||||
requestTimestampMs);
|
||||
|
||||
if (responseReceived) {
|
||||
latencyBroadcast.putExtra(ConnectivityConstants.EXTRA_IS_CAPTIVE_PORTAL,
|
||||
latencyBroadcast.putExtra(NetworkMonitorUtils.EXTRA_IS_CAPTIVE_PORTAL,
|
||||
isCaptivePortal);
|
||||
latencyBroadcast.putExtra(ConnectivityConstants.EXTRA_RESPONSE_TIMESTAMP_MS,
|
||||
latencyBroadcast.putExtra(NetworkMonitorUtils.EXTRA_RESPONSE_TIMESTAMP_MS,
|
||||
responseTimestampMs);
|
||||
}
|
||||
mContext.sendBroadcastAsUser(latencyBroadcast, UserHandle.CURRENT,
|
||||
ConnectivityConstants.PERMISSION_ACCESS_NETWORK_CONDITIONS);
|
||||
NetworkMonitorUtils.PERMISSION_ACCESS_NETWORK_CONDITIONS);
|
||||
}
|
||||
|
||||
private void logNetworkEvent(int evtype) {
|
||||
int[] transports = mNetworkAgentInfo.networkCapabilities.getTransportTypes();
|
||||
int[] transports = mNetworkCapabilities.getTransportTypes();
|
||||
mMetricsLog.log(mNetId, transports, new NetworkEvent(evtype));
|
||||
}
|
||||
|
||||
@@ -1520,14 +1587,14 @@ public class NetworkMonitor extends StateMachine {
|
||||
|
||||
private void maybeLogEvaluationResult(int evtype) {
|
||||
if (mEvaluationTimer.isRunning()) {
|
||||
int[] transports = mNetworkAgentInfo.networkCapabilities.getTransportTypes();
|
||||
int[] transports = mNetworkCapabilities.getTransportTypes();
|
||||
mMetricsLog.log(mNetId, transports, new NetworkEvent(evtype, mEvaluationTimer.stop()));
|
||||
mEvaluationTimer.reset();
|
||||
}
|
||||
}
|
||||
|
||||
private void logValidationProbe(long durationMs, int probeType, int probeResult) {
|
||||
int[] transports = mNetworkAgentInfo.networkCapabilities.getTransportTypes();
|
||||
int[] transports = mNetworkCapabilities.getTransportTypes();
|
||||
boolean isFirstValidation = validationStage().mIsFirstValidation;
|
||||
ValidationProbeEvent ev = new ValidationProbeEvent();
|
||||
ev.probeType = ValidationProbeEvent.makeProbeType(probeType, isFirstValidation);
|
||||
@@ -1537,15 +1604,22 @@ public class NetworkMonitor extends StateMachine {
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
public static class Dependencies {
|
||||
public Network getNetwork(NetworkAgentInfo networkAgentInfo) {
|
||||
return new OneAddressPerFamilyNetwork(networkAgentInfo.network());
|
||||
static class Dependencies {
|
||||
public Network getPrivateDnsBypassNetwork(Network network) {
|
||||
return new OneAddressPerFamilyNetwork(network);
|
||||
}
|
||||
|
||||
public Random getRandom() {
|
||||
return new Random();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the captive portal server HTTP URL that is configured on the device.
|
||||
*/
|
||||
public String getCaptivePortalServerHttpUrl(Context context) {
|
||||
return NetworkMonitorUtils.getCaptivePortalServerHttpUrl(context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of a global integer setting.
|
||||
* @param symbol Name of the setting
|
||||
@@ -1666,7 +1740,7 @@ public class NetworkMonitor extends StateMachine {
|
||||
boolean result = false;
|
||||
// Reevaluation will generate traffic. Thus, set a minimal reevaluation timer to limit the
|
||||
// possible traffic cost in metered network.
|
||||
if (mNetworkAgentInfo.networkCapabilities.isMetered()
|
||||
if (mNetworkCapabilities.isMetered()
|
||||
&& (SystemClock.elapsedRealtime() - getLastProbeTime()
|
||||
< mDataStallMinEvaluateTime)) {
|
||||
return false;
|
||||
@@ -16,6 +16,14 @@
|
||||
|
||||
package com.android.server.connectivity;
|
||||
|
||||
import static android.net.ConnectivityManager.ACTION_CAPTIVE_PORTAL_SIGN_IN;
|
||||
import static android.net.ConnectivityManager.EXTRA_CAPTIVE_PORTAL;
|
||||
import static android.net.INetworkMonitor.NETWORK_TEST_RESULT_INVALID;
|
||||
import static android.net.INetworkMonitor.NETWORK_TEST_RESULT_VALID;
|
||||
import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
|
||||
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED;
|
||||
|
||||
import static junit.framework.Assert.assertEquals;
|
||||
import static junit.framework.Assert.assertFalse;
|
||||
|
||||
import static org.junit.Assert.assertTrue;
|
||||
@@ -24,13 +32,21 @@ import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.any;
|
||||
import static org.mockito.Mockito.anyInt;
|
||||
import static org.mockito.Mockito.doAnswer;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.doThrow;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.timeout;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.CaptivePortal;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.net.INetworkMonitorCallbacks;
|
||||
import android.net.InetAddresses;
|
||||
import android.net.LinkProperties;
|
||||
import android.net.Network;
|
||||
import android.net.NetworkCapabilities;
|
||||
@@ -38,9 +54,12 @@ import android.net.NetworkInfo;
|
||||
import android.net.NetworkRequest;
|
||||
import android.net.captiveportal.CaptivePortalProbeResult;
|
||||
import android.net.metrics.IpConnectivityLog;
|
||||
import android.net.util.SharedLog;
|
||||
import android.net.wifi.WifiManager;
|
||||
import android.os.ConditionVariable;
|
||||
import android.os.Handler;
|
||||
import android.os.SystemClock;
|
||||
import android.os.UserHandle;
|
||||
import android.provider.Settings;
|
||||
import android.support.test.filters.SmallTest;
|
||||
import android.support.test.runner.AndroidJUnit4;
|
||||
@@ -50,8 +69,10 @@ import android.util.ArrayMap;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.mockito.Spy;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.HttpURLConnection;
|
||||
@@ -68,21 +89,23 @@ public class NetworkMonitorTest {
|
||||
private static final String LOCATION_HEADER = "location";
|
||||
|
||||
private @Mock Context mContext;
|
||||
private @Mock Handler mHandler;
|
||||
private @Mock IpConnectivityLog mLogger;
|
||||
private @Mock NetworkAgentInfo mAgent;
|
||||
private @Mock NetworkAgentInfo mNotMeteredAgent;
|
||||
private @Mock SharedLog mValidationLogger;
|
||||
private @Mock NetworkInfo mNetworkInfo;
|
||||
private @Mock NetworkRequest mRequest;
|
||||
private @Mock ConnectivityManager mCm;
|
||||
private @Mock TelephonyManager mTelephony;
|
||||
private @Mock WifiManager mWifi;
|
||||
private @Mock Network mNetwork;
|
||||
private @Mock HttpURLConnection mHttpConnection;
|
||||
private @Mock HttpURLConnection mHttpsConnection;
|
||||
private @Mock HttpURLConnection mFallbackConnection;
|
||||
private @Mock HttpURLConnection mOtherFallbackConnection;
|
||||
private @Mock Random mRandom;
|
||||
private @Mock NetworkMonitor.Dependencies mDependencies;
|
||||
private @Mock INetworkMonitorCallbacks mCallbacks;
|
||||
private @Spy Network mNetwork = new Network(TEST_NETID);
|
||||
private NetworkRequest mRequest;
|
||||
|
||||
private static final int TEST_NETID = 4242;
|
||||
|
||||
private static final String TEST_HTTP_URL = "http://www.google.com/gen_204";
|
||||
private static final String TEST_HTTPS_URL = "https://www.google.com/gen_204";
|
||||
@@ -93,33 +116,37 @@ public class NetworkMonitorTest {
|
||||
private static final int RETURN_CODE_DNS_SUCCESS = 0;
|
||||
private static final int RETURN_CODE_DNS_TIMEOUT = 255;
|
||||
|
||||
private static final int HANDLER_TIMEOUT_MS = 1000;
|
||||
|
||||
private static final LinkProperties TEST_LINKPROPERTIES = new LinkProperties();
|
||||
|
||||
private static final NetworkCapabilities METERED_CAPABILITIES = new NetworkCapabilities()
|
||||
.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
|
||||
.addCapability(NET_CAPABILITY_INTERNET);
|
||||
|
||||
private static final NetworkCapabilities NOT_METERED_CAPABILITIES = new NetworkCapabilities()
|
||||
.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
|
||||
.addCapability(NET_CAPABILITY_INTERNET)
|
||||
.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
|
||||
|
||||
private static final NetworkCapabilities NO_INTERNET_CAPABILITIES = new NetworkCapabilities()
|
||||
.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
|
||||
|
||||
@Before
|
||||
public void setUp() throws IOException {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
mAgent.linkProperties = new LinkProperties();
|
||||
mAgent.networkCapabilities = new NetworkCapabilities()
|
||||
.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
|
||||
mAgent.networkInfo = mNetworkInfo;
|
||||
|
||||
mNotMeteredAgent.linkProperties = new LinkProperties();
|
||||
mNotMeteredAgent.networkCapabilities = new NetworkCapabilities()
|
||||
.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
|
||||
.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
|
||||
mNotMeteredAgent.networkInfo = mNetworkInfo;
|
||||
|
||||
when(mAgent.network()).thenReturn(mNetwork);
|
||||
when(mDependencies.getNetwork(any())).thenReturn(mNetwork);
|
||||
when(mDependencies.getPrivateDnsBypassNetwork(any())).thenReturn(mNetwork);
|
||||
when(mDependencies.getRandom()).thenReturn(mRandom);
|
||||
when(mDependencies.getSetting(any(), eq(Settings.Global.CAPTIVE_PORTAL_MODE), anyInt()))
|
||||
.thenReturn(Settings.Global.CAPTIVE_PORTAL_MODE_PROMPT);
|
||||
when(mDependencies.getSetting(any(), eq(Settings.Global.CAPTIVE_PORTAL_USE_HTTPS),
|
||||
anyInt())).thenReturn(1);
|
||||
when(mDependencies.getSetting(any(), eq(Settings.Global.CAPTIVE_PORTAL_HTTP_URL),
|
||||
anyString())).thenReturn(TEST_HTTP_URL);
|
||||
when(mDependencies.getCaptivePortalServerHttpUrl(any())).thenReturn(TEST_HTTP_URL);
|
||||
when(mDependencies.getSetting(any(), eq(Settings.Global.CAPTIVE_PORTAL_HTTPS_URL),
|
||||
anyString())).thenReturn(TEST_HTTPS_URL);
|
||||
when(mNetwork.getPrivateDnsBypassingCopy()).thenReturn(mNetwork);
|
||||
doReturn(mNetwork).when(mNetwork).getPrivateDnsBypassingCopy();
|
||||
|
||||
when(mContext.getSystemService(Context.CONNECTIVITY_SERVICE)).thenReturn(mCm);
|
||||
when(mContext.getSystemService(Context.TELEPHONY_SERVICE)).thenReturn(mTelephony);
|
||||
when(mContext.getSystemService(Context.WIFI_SERVICE)).thenReturn(mWifi);
|
||||
|
||||
@@ -129,7 +156,7 @@ public class NetworkMonitorTest {
|
||||
setFallbackSpecs(null); // Test with no fallback spec by default
|
||||
when(mRandom.nextInt()).thenReturn(0);
|
||||
|
||||
when(mNetwork.openConnection(any())).then((invocation) -> {
|
||||
doAnswer((invocation) -> {
|
||||
URL url = invocation.getArgument(0);
|
||||
switch(url.toString()) {
|
||||
case TEST_HTTP_URL:
|
||||
@@ -144,12 +171,20 @@ public class NetworkMonitorTest {
|
||||
fail("URL not mocked: " + url.toString());
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}).when(mNetwork).openConnection(any());
|
||||
when(mHttpConnection.getRequestProperties()).thenReturn(new ArrayMap<>());
|
||||
when(mHttpsConnection.getRequestProperties()).thenReturn(new ArrayMap<>());
|
||||
when(mNetwork.getAllByName(any())).thenReturn(new InetAddress[] {
|
||||
InetAddress.parseNumericAddress("192.168.0.0")
|
||||
});
|
||||
doReturn(new InetAddress[] {
|
||||
InetAddresses.parseNumericAddress("192.168.0.0")
|
||||
}).when(mNetwork).getAllByName(any());
|
||||
|
||||
mRequest = new NetworkRequest.Builder()
|
||||
.addCapability(NET_CAPABILITY_INTERNET)
|
||||
.addCapability(NET_CAPABILITY_NOT_RESTRICTED)
|
||||
.build();
|
||||
// Default values. Individual tests can override these.
|
||||
when(mCm.getLinkProperties(any())).thenReturn(TEST_LINKPROPERTIES);
|
||||
when(mCm.getNetworkCapabilities(any())).thenReturn(METERED_CAPABILITIES);
|
||||
|
||||
setMinDataStallEvaluateInterval(500);
|
||||
setDataStallEvaluationType(1 << DATA_STALL_EVALUATION_TYPE_DNS);
|
||||
@@ -160,10 +195,10 @@ public class NetworkMonitorTest {
|
||||
private class WrappedNetworkMonitor extends NetworkMonitor {
|
||||
private long mProbeTime = 0;
|
||||
|
||||
WrappedNetworkMonitor(Context context, Handler handler,
|
||||
NetworkAgentInfo networkAgentInfo, NetworkRequest defaultRequest,
|
||||
WrappedNetworkMonitor(Context context, Network network, NetworkRequest defaultRequest,
|
||||
IpConnectivityLog logger, Dependencies deps) {
|
||||
super(context, handler, networkAgentInfo, defaultRequest, logger, deps);
|
||||
super(context, mCallbacks, network, defaultRequest, logger,
|
||||
new SharedLog("test_nm"), deps);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -176,19 +211,39 @@ public class NetworkMonitorTest {
|
||||
}
|
||||
}
|
||||
|
||||
WrappedNetworkMonitor makeMeteredWrappedNetworkMonitor() {
|
||||
return new WrappedNetworkMonitor(
|
||||
mContext, mHandler, mAgent, mRequest, mLogger, mDependencies);
|
||||
private WrappedNetworkMonitor makeMeteredWrappedNetworkMonitor() {
|
||||
final WrappedNetworkMonitor nm = new WrappedNetworkMonitor(
|
||||
mContext, mNetwork, mRequest, mLogger, mDependencies);
|
||||
when(mCm.getNetworkCapabilities(any())).thenReturn(METERED_CAPABILITIES);
|
||||
nm.start();
|
||||
waitForIdle(nm.getHandler());
|
||||
return nm;
|
||||
}
|
||||
|
||||
WrappedNetworkMonitor makeNotMeteredWrappedNetworkMonitor() {
|
||||
return new WrappedNetworkMonitor(
|
||||
mContext, mHandler, mNotMeteredAgent, mRequest, mLogger, mDependencies);
|
||||
private WrappedNetworkMonitor makeNotMeteredWrappedNetworkMonitor() {
|
||||
final WrappedNetworkMonitor nm = new WrappedNetworkMonitor(
|
||||
mContext, mNetwork, mRequest, mLogger, mDependencies);
|
||||
when(mCm.getNetworkCapabilities(any())).thenReturn(NOT_METERED_CAPABILITIES);
|
||||
nm.start();
|
||||
waitForIdle(nm.getHandler());
|
||||
return nm;
|
||||
}
|
||||
|
||||
NetworkMonitor makeMonitor() {
|
||||
return new NetworkMonitor(
|
||||
mContext, mHandler, mAgent, mRequest, mLogger, mDependencies);
|
||||
private NetworkMonitor makeMonitor() {
|
||||
final NetworkMonitor nm = new NetworkMonitor(
|
||||
mContext, mCallbacks, mNetwork, mRequest, mLogger, mValidationLogger,
|
||||
mDependencies);
|
||||
nm.start();
|
||||
waitForIdle(nm.getHandler());
|
||||
return nm;
|
||||
}
|
||||
|
||||
private void waitForIdle(Handler handler) {
|
||||
final ConditionVariable cv = new ConditionVariable(false);
|
||||
handler.post(cv::open);
|
||||
if (!cv.block(HANDLER_TIMEOUT_MS)) {
|
||||
fail("Timed out waiting for handler");
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -318,6 +373,15 @@ public class NetworkMonitorTest {
|
||||
assertPortal(makeMonitor().isCaptivePortal());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsCaptivePortal_IgnorePortals() throws IOException {
|
||||
setCaptivePortalMode(Settings.Global.CAPTIVE_PORTAL_MODE_IGNORE);
|
||||
setSslException(mHttpsConnection);
|
||||
setPortal302(mHttpConnection);
|
||||
|
||||
assertNotPortal(makeMonitor().isCaptivePortal());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsDataStall_EvaluationDisabled() {
|
||||
setDataStallEvaluationType(0);
|
||||
@@ -390,6 +454,63 @@ public class NetworkMonitorTest {
|
||||
assertFalse(wrappedMonitor.isDataStall());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBrokenNetworkNotValidated() throws Exception {
|
||||
setSslException(mHttpsConnection);
|
||||
setStatus(mHttpConnection, 500);
|
||||
setStatus(mFallbackConnection, 404);
|
||||
when(mCm.getNetworkCapabilities(any())).thenReturn(METERED_CAPABILITIES);
|
||||
|
||||
final NetworkMonitor nm = makeMonitor();
|
||||
nm.notifyNetworkConnected();
|
||||
|
||||
verify(mCallbacks, timeout(HANDLER_TIMEOUT_MS).times(1))
|
||||
.notifyNetworkTested(NETWORK_TEST_RESULT_INVALID, null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNoInternetCapabilityValidated() throws Exception {
|
||||
when(mCm.getNetworkCapabilities(any())).thenReturn(NO_INTERNET_CAPABILITIES);
|
||||
|
||||
final NetworkMonitor nm = makeMonitor();
|
||||
nm.notifyNetworkConnected();
|
||||
|
||||
verify(mCallbacks, timeout(HANDLER_TIMEOUT_MS).times(1))
|
||||
.notifyNetworkTested(NETWORK_TEST_RESULT_VALID, null);
|
||||
verify(mNetwork, never()).openConnection(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLaunchCaptivePortalApp() throws Exception {
|
||||
setSslException(mHttpsConnection);
|
||||
setPortal302(mHttpConnection);
|
||||
|
||||
final NetworkMonitor nm = makeMonitor();
|
||||
nm.notifyNetworkConnected();
|
||||
|
||||
verify(mCallbacks, timeout(HANDLER_TIMEOUT_MS).times(1))
|
||||
.showProvisioningNotification(any());
|
||||
|
||||
// Check that startCaptivePortalApp sends the expected intent.
|
||||
nm.launchCaptivePortalApp();
|
||||
|
||||
final ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
|
||||
verify(mContext, timeout(HANDLER_TIMEOUT_MS).times(1))
|
||||
.startActivityAsUser(intentCaptor.capture(), eq(UserHandle.CURRENT));
|
||||
final Intent intent = intentCaptor.getValue();
|
||||
assertEquals(ACTION_CAPTIVE_PORTAL_SIGN_IN, intent.getAction());
|
||||
final Network network = intent.getParcelableExtra(ConnectivityManager.EXTRA_NETWORK);
|
||||
assertEquals(TEST_NETID, network.netId);
|
||||
|
||||
// Have the app report that the captive portal is dismissed, and check that we revalidate.
|
||||
setStatus(mHttpsConnection, 204);
|
||||
setStatus(mHttpConnection, 204);
|
||||
final CaptivePortal captivePortal = intent.getParcelableExtra(EXTRA_CAPTIVE_PORTAL);
|
||||
captivePortal.reportCaptivePortalDismissed();
|
||||
verify(mCallbacks, timeout(HANDLER_TIMEOUT_MS).times(1))
|
||||
.notifyNetworkTested(NETWORK_TEST_RESULT_VALID, null);
|
||||
}
|
||||
|
||||
private void makeDnsTimeoutEvent(WrappedNetworkMonitor wrappedMonitor, int count) {
|
||||
for (int i = 0; i < count; i++) {
|
||||
wrappedMonitor.getDnsStallDetector().accumulateConsecutiveDnsTimeoutCount(
|
||||
@@ -440,6 +561,11 @@ public class NetworkMonitorTest {
|
||||
eq(Settings.Global.CAPTIVE_PORTAL_FALLBACK_PROBE_SPECS), any())).thenReturn(specs);
|
||||
}
|
||||
|
||||
private void setCaptivePortalMode(int mode) {
|
||||
when(mDependencies.getSetting(any(),
|
||||
eq(Settings.Global.CAPTIVE_PORTAL_MODE), anyInt())).thenReturn(mode);
|
||||
}
|
||||
|
||||
private void assertPortal(CaptivePortalProbeResult result) {
|
||||
assertTrue(result.isPortal());
|
||||
assertFalse(result.isFailed());
|
||||
@@ -459,12 +585,12 @@ public class NetworkMonitorTest {
|
||||
}
|
||||
|
||||
private void setSslException(HttpURLConnection connection) throws IOException {
|
||||
when(connection.getResponseCode()).thenThrow(new SSLHandshakeException("Invalid cert"));
|
||||
doThrow(new SSLHandshakeException("Invalid cert")).when(connection).getResponseCode();
|
||||
}
|
||||
|
||||
private void set302(HttpURLConnection connection, String location) throws IOException {
|
||||
setStatus(connection, 302);
|
||||
when(connection.getHeaderField(LOCATION_HEADER)).thenReturn(location);
|
||||
doReturn(location).when(connection).getHeaderField(LOCATION_HEADER);
|
||||
}
|
||||
|
||||
private void setPortal302(HttpURLConnection connection) throws IOException {
|
||||
@@ -472,7 +598,7 @@ public class NetworkMonitorTest {
|
||||
}
|
||||
|
||||
private void setStatus(HttpURLConnection connection, int status) throws IOException {
|
||||
when(connection.getResponseCode()).thenReturn(status);
|
||||
doReturn(status).when(connection).getResponseCode();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ import static android.net.ConnectivityManager.TYPE_NONE;
|
||||
import static android.net.ConnectivityManager.TYPE_VPN;
|
||||
import static android.net.ConnectivityManager.getNetworkTypeName;
|
||||
import static android.net.ConnectivityManager.isNetworkTypeValid;
|
||||
import static android.net.INetworkMonitor.NETWORK_TEST_RESULT_VALID;
|
||||
import static android.net.NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL;
|
||||
import static android.net.NetworkCapabilities.NET_CAPABILITY_FOREGROUND;
|
||||
import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
|
||||
@@ -37,6 +38,8 @@ import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
|
||||
import static android.net.NetworkCapabilities.TRANSPORT_VPN;
|
||||
import static android.net.NetworkPolicyManager.RULE_NONE;
|
||||
import static android.net.NetworkPolicyManager.uidRulesToString;
|
||||
import static android.net.NetworkStack.NETWORKSTACK_PACKAGE_NAME;
|
||||
import static android.net.shared.NetworkMonitorUtils.isValidationRequired;
|
||||
import static android.os.Process.INVALID_UID;
|
||||
import static android.system.OsConstants.IPPROTO_TCP;
|
||||
import static android.system.OsConstants.IPPROTO_UDP;
|
||||
@@ -62,6 +65,8 @@ import android.net.IIpConnectivityMetrics;
|
||||
import android.net.INetd;
|
||||
import android.net.INetdEventCallback;
|
||||
import android.net.INetworkManagementEventObserver;
|
||||
import android.net.INetworkMonitor;
|
||||
import android.net.INetworkMonitorCallbacks;
|
||||
import android.net.INetworkPolicyListener;
|
||||
import android.net.INetworkPolicyManager;
|
||||
import android.net.INetworkStatsService;
|
||||
@@ -79,9 +84,11 @@ import android.net.NetworkPolicyManager;
|
||||
import android.net.NetworkQuotaInfo;
|
||||
import android.net.NetworkRequest;
|
||||
import android.net.NetworkSpecifier;
|
||||
import android.net.NetworkStack;
|
||||
import android.net.NetworkState;
|
||||
import android.net.NetworkUtils;
|
||||
import android.net.NetworkWatchlistManager;
|
||||
import android.net.PrivateDnsConfigParcel;
|
||||
import android.net.ProxyInfo;
|
||||
import android.net.RouteInfo;
|
||||
import android.net.UidRange;
|
||||
@@ -90,12 +97,13 @@ import android.net.VpnService;
|
||||
import android.net.metrics.IpConnectivityLog;
|
||||
import android.net.metrics.NetworkEvent;
|
||||
import android.net.netlink.InetDiagMessage;
|
||||
import android.net.shared.NetworkMonitorUtils;
|
||||
import android.net.shared.PrivateDnsConfig;
|
||||
import android.net.util.MultinetworkPolicyTracker;
|
||||
import android.net.util.NetdService;
|
||||
import android.os.Binder;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.FileUtils;
|
||||
import android.os.Handler;
|
||||
import android.os.HandlerThread;
|
||||
import android.os.IBinder;
|
||||
@@ -123,8 +131,8 @@ import android.telephony.TelephonyManager;
|
||||
import android.text.TextUtils;
|
||||
import android.util.ArraySet;
|
||||
import android.util.LocalLog;
|
||||
import android.util.LocalLog.ReadOnlyLocalLog;
|
||||
import android.util.Log;
|
||||
import android.util.Pair;
|
||||
import android.util.Slog;
|
||||
import android.util.SparseArray;
|
||||
import android.util.SparseBooleanArray;
|
||||
@@ -149,7 +157,6 @@ import com.android.internal.util.XmlUtils;
|
||||
import com.android.server.am.BatteryStatsService;
|
||||
import com.android.server.connectivity.DataConnectionStats;
|
||||
import com.android.server.connectivity.DnsManager;
|
||||
import com.android.server.connectivity.DnsManager.PrivateDnsConfig;
|
||||
import com.android.server.connectivity.DnsManager.PrivateDnsValidationUpdate;
|
||||
import com.android.server.connectivity.IpConnectivityMetrics;
|
||||
import com.android.server.connectivity.KeepaliveTracker;
|
||||
@@ -158,7 +165,6 @@ import com.android.server.connectivity.MockableSystemProperties;
|
||||
import com.android.server.connectivity.MultipathPolicyTracker;
|
||||
import com.android.server.connectivity.NetworkAgentInfo;
|
||||
import com.android.server.connectivity.NetworkDiagnostics;
|
||||
import com.android.server.connectivity.NetworkMonitor;
|
||||
import com.android.server.connectivity.NetworkNotificationManager;
|
||||
import com.android.server.connectivity.NetworkNotificationManager.NotificationType;
|
||||
import com.android.server.connectivity.PermissionMonitor;
|
||||
@@ -186,7 +192,6 @@ import java.io.PrintWriter;
|
||||
import java.net.Inet4Address;
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
@@ -442,6 +447,43 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
*/
|
||||
private static final int EVENT_DATA_SAVER_CHANGED = 40;
|
||||
|
||||
/**
|
||||
* Event for NetworkMonitor/NetworkAgentInfo to inform ConnectivityService that the network has
|
||||
* been tested.
|
||||
* obj = String representing URL that Internet probe was redirect to, if it was redirected.
|
||||
* arg1 = One of the NETWORK_TESTED_RESULT_* constants.
|
||||
* arg2 = NetID.
|
||||
*/
|
||||
public static final int EVENT_NETWORK_TESTED = 41;
|
||||
|
||||
/**
|
||||
* Event for NetworkMonitor/NetworkAgentInfo to inform ConnectivityService that the private DNS
|
||||
* config was resolved.
|
||||
* obj = PrivateDnsConfig
|
||||
* arg2 = netid
|
||||
*/
|
||||
public static final int EVENT_PRIVATE_DNS_CONFIG_RESOLVED = 42;
|
||||
|
||||
/**
|
||||
* Request ConnectivityService display provisioning notification.
|
||||
* arg1 = Whether to make the notification visible.
|
||||
* arg2 = NetID.
|
||||
* obj = Intent to be launched when notification selected by user, null if !arg1.
|
||||
*/
|
||||
public static final int EVENT_PROVISIONING_NOTIFICATION = 43;
|
||||
|
||||
/**
|
||||
* Argument for {@link #EVENT_PROVISIONING_NOTIFICATION} to indicate that the notification
|
||||
* should be shown.
|
||||
*/
|
||||
public static final int PROVISIONING_NOTIFICATION_SHOW = 1;
|
||||
|
||||
/**
|
||||
* Argument for {@link #EVENT_PROVISIONING_NOTIFICATION} to indicate that the notification
|
||||
* should be hidden.
|
||||
*/
|
||||
public static final int PROVISIONING_NOTIFICATION_HIDE = 0;
|
||||
|
||||
private static String eventName(int what) {
|
||||
return sMagicDecoderRing.get(what, Integer.toString(what));
|
||||
}
|
||||
@@ -506,30 +548,6 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
private long mMaxWakelockDurationMs = 0;
|
||||
private long mLastWakeLockAcquireTimestamp = 0;
|
||||
|
||||
// Array of <Network,ReadOnlyLocalLogs> tracking network validation and results
|
||||
private static final int MAX_VALIDATION_LOGS = 10;
|
||||
private static class ValidationLog {
|
||||
final Network mNetwork;
|
||||
final String mName;
|
||||
final ReadOnlyLocalLog mLog;
|
||||
|
||||
ValidationLog(Network network, String name, ReadOnlyLocalLog log) {
|
||||
mNetwork = network;
|
||||
mName = name;
|
||||
mLog = log;
|
||||
}
|
||||
}
|
||||
private final ArrayDeque<ValidationLog> mValidationLogs = new ArrayDeque<>(MAX_VALIDATION_LOGS);
|
||||
|
||||
private void addValidationLogs(ReadOnlyLocalLog log, Network network, String name) {
|
||||
synchronized (mValidationLogs) {
|
||||
while (mValidationLogs.size() >= MAX_VALIDATION_LOGS) {
|
||||
mValidationLogs.removeLast();
|
||||
}
|
||||
mValidationLogs.addFirst(new ValidationLog(network, name, log));
|
||||
}
|
||||
}
|
||||
|
||||
private final IpConnectivityLog mMetricsLog;
|
||||
|
||||
@GuardedBy("mBandwidthRequests")
|
||||
@@ -1684,7 +1702,11 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
// caller type. Need to re-factor NetdEventListenerService to allow multiple
|
||||
// NetworkMonitor registrants.
|
||||
if (nai != null && nai.satisfies(mDefaultRequest)) {
|
||||
nai.networkMonitor.sendMessage(NetworkMonitor.EVENT_DNS_NOTIFICATION, returnCode);
|
||||
try {
|
||||
nai.networkMonitor().notifyDnsResponse(returnCode);
|
||||
} catch (RemoteException e) {
|
||||
e.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -2265,17 +2287,6 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
mMultipathPolicyTracker.dump(pw);
|
||||
|
||||
if (ArrayUtils.contains(args, SHORT_ARG) == false) {
|
||||
pw.println();
|
||||
synchronized (mValidationLogs) {
|
||||
pw.println("mValidationLogs (most recent first):");
|
||||
for (ValidationLog p : mValidationLogs) {
|
||||
pw.println(p.mNetwork + " - " + p.mName);
|
||||
pw.increaseIndent();
|
||||
p.mLog.dump(fd, pw, args);
|
||||
pw.decreaseIndent();
|
||||
}
|
||||
}
|
||||
|
||||
pw.println();
|
||||
pw.println("mNetworkRequestInfoLogs (most recent first):");
|
||||
pw.increaseIndent();
|
||||
@@ -2455,11 +2466,11 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
switch (msg.what) {
|
||||
default:
|
||||
return false;
|
||||
case NetworkMonitor.EVENT_NETWORK_TESTED: {
|
||||
case EVENT_NETWORK_TESTED: {
|
||||
final NetworkAgentInfo nai = getNetworkAgentInfoForNetId(msg.arg2);
|
||||
if (nai == null) break;
|
||||
|
||||
final boolean valid = (msg.arg1 == NetworkMonitor.NETWORK_TEST_RESULT_VALID);
|
||||
final boolean valid = (msg.arg1 == NETWORK_TEST_RESULT_VALID);
|
||||
final boolean wasValidated = nai.lastValidated;
|
||||
final boolean wasDefault = isDefaultNetwork(nai);
|
||||
|
||||
@@ -2497,7 +2508,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
}
|
||||
break;
|
||||
}
|
||||
case NetworkMonitor.EVENT_PROVISIONING_NOTIFICATION: {
|
||||
case EVENT_PROVISIONING_NOTIFICATION: {
|
||||
final int netId = msg.arg2;
|
||||
final boolean visible = toBool(msg.arg1);
|
||||
final NetworkAgentInfo nai = getNetworkAgentInfoForNetId(netId);
|
||||
@@ -2530,7 +2541,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
}
|
||||
break;
|
||||
}
|
||||
case NetworkMonitor.EVENT_PRIVATE_DNS_CONFIG_RESOLVED: {
|
||||
case EVENT_PRIVATE_DNS_CONFIG_RESOLVED: {
|
||||
final NetworkAgentInfo nai = getNetworkAgentInfoForNetId(msg.arg2);
|
||||
if (nai == null) break;
|
||||
|
||||
@@ -2572,8 +2583,61 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
}
|
||||
}
|
||||
|
||||
private class NetworkMonitorCallbacks extends INetworkMonitorCallbacks.Stub {
|
||||
private final NetworkAgentInfo mNai;
|
||||
|
||||
private NetworkMonitorCallbacks(NetworkAgentInfo nai) {
|
||||
mNai = nai;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNetworkMonitorCreated(INetworkMonitor networkMonitor) {
|
||||
mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_AGENT,
|
||||
new Pair<>(mNai, networkMonitor)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyNetworkTested(int testResult, @Nullable String redirectUrl) {
|
||||
mTrackerHandler.sendMessage(mTrackerHandler.obtainMessage(EVENT_NETWORK_TESTED,
|
||||
testResult, mNai.network.netId, redirectUrl));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyPrivateDnsConfigResolved(PrivateDnsConfigParcel config) {
|
||||
mTrackerHandler.sendMessage(mTrackerHandler.obtainMessage(
|
||||
EVENT_PRIVATE_DNS_CONFIG_RESOLVED,
|
||||
0, mNai.network.netId, PrivateDnsConfig.fromParcel(config)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showProvisioningNotification(String action) {
|
||||
final Intent intent = new Intent(action);
|
||||
intent.setPackage(NETWORKSTACK_PACKAGE_NAME);
|
||||
|
||||
final PendingIntent pendingIntent;
|
||||
// Only the system server can register notifications with package "android"
|
||||
final long token = Binder.clearCallingIdentity();
|
||||
try {
|
||||
pendingIntent = PendingIntent.getBroadcast(mContext, 0, intent, 0);
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(token);
|
||||
}
|
||||
mTrackerHandler.sendMessage(mTrackerHandler.obtainMessage(
|
||||
EVENT_PROVISIONING_NOTIFICATION, PROVISIONING_NOTIFICATION_SHOW,
|
||||
mNai.network.netId,
|
||||
pendingIntent));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hideProvisioningNotification() {
|
||||
mTrackerHandler.sendMessage(mTrackerHandler.obtainMessage(
|
||||
EVENT_PROVISIONING_NOTIFICATION, PROVISIONING_NOTIFICATION_HIDE,
|
||||
mNai.network.netId));
|
||||
}
|
||||
}
|
||||
|
||||
private boolean networkRequiresValidation(NetworkAgentInfo nai) {
|
||||
return NetworkMonitor.isValidationRequired(
|
||||
return isValidationRequired(
|
||||
mDefaultRequest.networkCapabilities, nai.networkCapabilities);
|
||||
}
|
||||
|
||||
@@ -2603,10 +2667,14 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
// Internet access and therefore also require validation.
|
||||
if (!networkRequiresValidation(nai)) return;
|
||||
|
||||
// Notify the NetworkMonitor thread in case it needs to cancel or
|
||||
// Notify the NetworkAgentInfo/NetworkMonitor in case NetworkMonitor needs to cancel or
|
||||
// schedule DNS resolutions. If a DNS resolution is required the
|
||||
// result will be sent back to us.
|
||||
nai.networkMonitor.notifyPrivateDnsSettingsChanged(cfg);
|
||||
try {
|
||||
nai.networkMonitor().notifyPrivateDnsChanged(cfg.toParcel());
|
||||
} catch (RemoteException e) {
|
||||
e.rethrowFromSystemServer();
|
||||
}
|
||||
|
||||
// With Private DNS bypass support, we can proceed to update the
|
||||
// Private DNS config immediately, even if we're in strict mode
|
||||
@@ -2736,7 +2804,11 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
// Disable wakeup packet monitoring for each interface.
|
||||
wakeupModifyInterface(iface, nai.networkCapabilities, false);
|
||||
}
|
||||
nai.networkMonitor.sendMessage(NetworkMonitor.CMD_NETWORK_DISCONNECTED);
|
||||
try {
|
||||
nai.networkMonitor().notifyNetworkDisconnected();
|
||||
} catch (RemoteException e) {
|
||||
e.rethrowFromSystemServer();
|
||||
}
|
||||
mNetworkAgentInfos.remove(nai.messenger);
|
||||
nai.maybeStopClat();
|
||||
synchronized (mNetworkForNetId) {
|
||||
@@ -3096,7 +3168,11 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network);
|
||||
if (nai == null) return;
|
||||
if (!nai.networkCapabilities.hasCapability(NET_CAPABILITY_CAPTIVE_PORTAL)) return;
|
||||
nai.networkMonitor.sendMessage(NetworkMonitor.CMD_LAUNCH_CAPTIVE_PORTAL_APP);
|
||||
try {
|
||||
nai.networkMonitor().launchCaptivePortalApp();
|
||||
} catch (RemoteException e) {
|
||||
e.rethrowFromSystemServer();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -3217,6 +3293,11 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
return mMultinetworkPolicyTracker.getMeteredMultipathPreference();
|
||||
}
|
||||
|
||||
@Override
|
||||
public NetworkRequest getDefaultRequest() {
|
||||
return mDefaultRequest;
|
||||
}
|
||||
|
||||
private class InternalHandler extends Handler {
|
||||
public InternalHandler(Looper looper) {
|
||||
super(looper);
|
||||
@@ -3247,7 +3328,9 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
break;
|
||||
}
|
||||
case EVENT_REGISTER_NETWORK_AGENT: {
|
||||
handleRegisterNetworkAgent((NetworkAgentInfo)msg.obj);
|
||||
final Pair<NetworkAgentInfo, INetworkMonitor> arg =
|
||||
(Pair<NetworkAgentInfo, INetworkMonitor>) msg.obj;
|
||||
handleRegisterNetworkAgent(arg.first, arg.second);
|
||||
break;
|
||||
}
|
||||
case EVENT_REGISTER_NETWORK_REQUEST:
|
||||
@@ -3305,7 +3388,14 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
}
|
||||
case EVENT_SYSTEM_READY: {
|
||||
for (NetworkAgentInfo nai : mNetworkAgentInfos.values()) {
|
||||
nai.networkMonitor.systemReady = true;
|
||||
// Might have been called already in handleRegisterNetworkAgent since
|
||||
// mSystemReady is set before sending EVENT_SYSTEM_READY, but calling
|
||||
// this several times is fine.
|
||||
try {
|
||||
nai.networkMonitor().notifySystemReady();
|
||||
} catch (RemoteException e) {
|
||||
e.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
mMultipathPolicyTracker.start();
|
||||
break;
|
||||
@@ -3577,7 +3667,11 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
if (isNetworkWithLinkPropertiesBlocked(lp, uid, false)) {
|
||||
return;
|
||||
}
|
||||
nai.networkMonitor.forceReevaluation(uid);
|
||||
try {
|
||||
nai.networkMonitor().forceReevaluation(uid);
|
||||
} catch (RemoteException e) {
|
||||
e.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -4785,27 +4879,49 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
final NetworkCapabilities nc = new NetworkCapabilities(networkCapabilities);
|
||||
final NetworkAgentInfo nai = new NetworkAgentInfo(messenger, new AsyncChannel(),
|
||||
new Network(reserveNetId()), new NetworkInfo(networkInfo), lp, nc, currentScore,
|
||||
mContext, mTrackerHandler, new NetworkMisc(networkMisc), mDefaultRequest, this);
|
||||
mContext, mTrackerHandler, new NetworkMisc(networkMisc), this);
|
||||
// Make sure the network capabilities reflect what the agent info says.
|
||||
nai.networkCapabilities = mixInCapabilities(nai, nc);
|
||||
synchronized (this) {
|
||||
nai.networkMonitor.systemReady = mSystemReady;
|
||||
}
|
||||
final String extraInfo = networkInfo.getExtraInfo();
|
||||
final String name = TextUtils.isEmpty(extraInfo)
|
||||
? nai.networkCapabilities.getSSID() : extraInfo;
|
||||
addValidationLogs(nai.networkMonitor.getValidationLogs(), nai.network, name);
|
||||
if (DBG) log("registerNetworkAgent " + nai);
|
||||
mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_AGENT, nai));
|
||||
final long token = Binder.clearCallingIdentity();
|
||||
try {
|
||||
mContext.getSystemService(NetworkStack.class)
|
||||
.makeNetworkMonitor(nai.network, name, new NetworkMonitorCallbacks(nai));
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(token);
|
||||
}
|
||||
// NetworkAgentInfo registration will finish when the NetworkMonitor is created.
|
||||
// If the network disconnects or sends any other event before that, messages are deferred by
|
||||
// NetworkAgent until nai.asyncChannel.connect(), which will be called when finalizing the
|
||||
// registration.
|
||||
return nai.network.netId;
|
||||
}
|
||||
|
||||
private void handleRegisterNetworkAgent(NetworkAgentInfo nai) {
|
||||
private void handleRegisterNetworkAgent(NetworkAgentInfo nai, INetworkMonitor networkMonitor) {
|
||||
nai.onNetworkMonitorCreated(networkMonitor);
|
||||
if (VDBG) log("Got NetworkAgent Messenger");
|
||||
mNetworkAgentInfos.put(nai.messenger, nai);
|
||||
synchronized (mNetworkForNetId) {
|
||||
mNetworkForNetId.put(nai.network.netId, nai);
|
||||
}
|
||||
synchronized (this) {
|
||||
if (mSystemReady) {
|
||||
try {
|
||||
networkMonitor.notifySystemReady();
|
||||
} catch (RemoteException e) {
|
||||
e.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
networkMonitor.start();
|
||||
} catch (RemoteException e) {
|
||||
e.rethrowFromSystemServer();
|
||||
}
|
||||
nai.asyncChannel.connect(mContext, mTrackerHandler, nai.messenger);
|
||||
NetworkInfo networkInfo = nai.networkInfo;
|
||||
nai.networkInfo = null;
|
||||
@@ -4855,6 +4971,11 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
networkAgent.updateClat(mNMS);
|
||||
notifyIfacesChangedForNetworkStats();
|
||||
if (networkAgent.everConnected) {
|
||||
try {
|
||||
networkAgent.networkMonitor().notifyLinkPropertiesChanged();
|
||||
} catch (RemoteException e) {
|
||||
e.rethrowFromSystemServer();
|
||||
}
|
||||
notifyNetworkCallbacks(networkAgent, ConnectivityManager.CALLBACK_IP_CHANGED);
|
||||
}
|
||||
}
|
||||
@@ -5092,6 +5213,11 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
// If the requestable capabilities have changed or the score changed, we can't have been
|
||||
// called by rematchNetworkAndRequests, so it's safe to start a rematch.
|
||||
rematchAllNetworksAndRequests(nai, oldScore);
|
||||
try {
|
||||
nai.networkMonitor().notifyNetworkCapabilitiesChanged();
|
||||
} catch (RemoteException e) {
|
||||
e.rethrowFromSystemServer();
|
||||
}
|
||||
notifyNetworkCallbacks(nai, ConnectivityManager.CALLBACK_CAP_CHANGED);
|
||||
}
|
||||
|
||||
@@ -5339,6 +5465,11 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
}
|
||||
|
||||
if (capabilitiesChanged) {
|
||||
try {
|
||||
nai.networkMonitor().notifyNetworkCapabilitiesChanged();
|
||||
} catch (RemoteException e) {
|
||||
e.rethrowFromSystemServer();
|
||||
}
|
||||
notifyNetworkCallbacks(nai, ConnectivityManager.CALLBACK_CAP_CHANGED);
|
||||
}
|
||||
|
||||
@@ -5739,7 +5870,15 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
updateLinkProperties(networkAgent, new LinkProperties(networkAgent.linkProperties),
|
||||
null);
|
||||
|
||||
networkAgent.networkMonitor.sendMessage(NetworkMonitor.CMD_NETWORK_CONNECTED);
|
||||
// Until parceled LinkProperties are sent directly to NetworkMonitor, the connect
|
||||
// command must be sent after updating LinkProperties to maximize chances of
|
||||
// NetworkMonitor seeing the correct LinkProperties when starting.
|
||||
// TODO: pass LinkProperties to the NetworkMonitor in the notifyNetworkConnected call.
|
||||
try {
|
||||
networkAgent.networkMonitor().notifyNetworkConnected();
|
||||
} catch (RemoteException e) {
|
||||
e.rethrowFromSystemServer();
|
||||
}
|
||||
scheduleUnvalidatedPrompt(networkAgent);
|
||||
|
||||
if (networkAgent.isVPN()) {
|
||||
@@ -6020,7 +6159,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
@Override
|
||||
public String getCaptivePortalServerUrl() {
|
||||
enforceConnectivityInternalPermission();
|
||||
return NetworkMonitor.getCaptivePortalServerHttpUrl(mContext);
|
||||
return NetworkMonitorUtils.getCaptivePortalServerHttpUrl(mContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -6112,12 +6251,6 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
return nwm.getWatchlistConfigHash();
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
public NetworkMonitor createNetworkMonitor(Context context, Handler handler,
|
||||
NetworkAgentInfo nai, NetworkRequest defaultRequest) {
|
||||
return new NetworkMonitor(context, handler, nai, defaultRequest);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
MultinetworkPolicyTracker createMultinetworkPolicyTracker(Context c, Handler h, Runnable r) {
|
||||
return new MultinetworkPolicyTracker(c, h, r);
|
||||
|
||||
@@ -21,22 +21,6 @@ package com.android.server.connectivity;
|
||||
* @hide
|
||||
*/
|
||||
public class ConnectivityConstants {
|
||||
// IPC constants
|
||||
public static final String ACTION_NETWORK_CONDITIONS_MEASURED =
|
||||
"android.net.conn.NETWORK_CONDITIONS_MEASURED";
|
||||
public static final String EXTRA_CONNECTIVITY_TYPE = "extra_connectivity_type";
|
||||
public static final String EXTRA_NETWORK_TYPE = "extra_network_type";
|
||||
public static final String EXTRA_RESPONSE_RECEIVED = "extra_response_received";
|
||||
public static final String EXTRA_IS_CAPTIVE_PORTAL = "extra_is_captive_portal";
|
||||
public static final String EXTRA_CELL_ID = "extra_cellid";
|
||||
public static final String EXTRA_SSID = "extra_ssid";
|
||||
public static final String EXTRA_BSSID = "extra_bssid";
|
||||
/** real time since boot */
|
||||
public static final String EXTRA_REQUEST_TIMESTAMP_MS = "extra_request_timestamp_ms";
|
||||
public static final String EXTRA_RESPONSE_TIMESTAMP_MS = "extra_response_timestamp_ms";
|
||||
|
||||
public static final String PERMISSION_ACCESS_NETWORK_CONDITIONS =
|
||||
"android.permission.ACCESS_NETWORK_CONDITIONS";
|
||||
|
||||
// Penalty applied to scores of Networks that have not been validated.
|
||||
public static final int UNVALIDATED_SCORE_PENALTY = 40;
|
||||
|
||||
@@ -18,10 +18,9 @@ package com.android.server.connectivity;
|
||||
|
||||
import static android.net.ConnectivityManager.PRIVATE_DNS_DEFAULT_MODE_FALLBACK;
|
||||
import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_OFF;
|
||||
import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_OPPORTUNISTIC;
|
||||
import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_PROVIDER_HOSTNAME;
|
||||
import static android.provider.Settings.Global.DNS_RESOLVER_MIN_SAMPLES;
|
||||
import static android.provider.Settings.Global.DNS_RESOLVER_MAX_SAMPLES;
|
||||
import static android.provider.Settings.Global.DNS_RESOLVER_MIN_SAMPLES;
|
||||
import static android.provider.Settings.Global.DNS_RESOLVER_SAMPLE_VALIDITY_SECONDS;
|
||||
import static android.provider.Settings.Global.DNS_RESOLVER_SUCCESS_THRESHOLD_PERCENT;
|
||||
import static android.provider.Settings.Global.PRIVATE_DNS_DEFAULT_MODE;
|
||||
@@ -35,6 +34,7 @@ import android.net.LinkProperties;
|
||||
import android.net.Network;
|
||||
import android.net.NetworkUtils;
|
||||
import android.net.Uri;
|
||||
import android.net.shared.PrivateDnsConfig;
|
||||
import android.os.Binder;
|
||||
import android.os.INetworkManagementService;
|
||||
import android.os.UserHandle;
|
||||
@@ -43,10 +43,7 @@ import android.text.TextUtils;
|
||||
import android.util.Pair;
|
||||
import android.util.Slog;
|
||||
|
||||
import com.android.server.connectivity.MockableSystemProperties;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
@@ -54,10 +51,8 @@ import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.Set;
|
||||
import java.util.StringJoiner;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
|
||||
/**
|
||||
@@ -123,43 +118,6 @@ public class DnsManager {
|
||||
private static final int DNS_RESOLVER_DEFAULT_MIN_SAMPLES = 8;
|
||||
private static final int DNS_RESOLVER_DEFAULT_MAX_SAMPLES = 64;
|
||||
|
||||
public static class PrivateDnsConfig {
|
||||
public final boolean useTls;
|
||||
public final String hostname;
|
||||
public final InetAddress[] ips;
|
||||
|
||||
public PrivateDnsConfig() {
|
||||
this(false);
|
||||
}
|
||||
|
||||
public PrivateDnsConfig(boolean useTls) {
|
||||
this.useTls = useTls;
|
||||
this.hostname = "";
|
||||
this.ips = new InetAddress[0];
|
||||
}
|
||||
|
||||
public PrivateDnsConfig(String hostname, InetAddress[] ips) {
|
||||
this.useTls = !TextUtils.isEmpty(hostname);
|
||||
this.hostname = useTls ? hostname : "";
|
||||
this.ips = (ips != null) ? ips : new InetAddress[0];
|
||||
}
|
||||
|
||||
public PrivateDnsConfig(PrivateDnsConfig cfg) {
|
||||
useTls = cfg.useTls;
|
||||
hostname = cfg.hostname;
|
||||
ips = cfg.ips;
|
||||
}
|
||||
|
||||
public boolean inStrictMode() {
|
||||
return useTls && !TextUtils.isEmpty(hostname);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return PrivateDnsConfig.class.getSimpleName() +
|
||||
"{" + useTls + ":" + hostname + "/" + Arrays.toString(ips) + "}";
|
||||
}
|
||||
}
|
||||
|
||||
public static PrivateDnsConfig getPrivateDnsConfig(ContentResolver cr) {
|
||||
final String mode = getPrivateDnsMode(cr);
|
||||
|
||||
|
||||
@@ -16,9 +16,8 @@
|
||||
|
||||
package com.android.server.connectivity;
|
||||
|
||||
import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
|
||||
|
||||
import android.content.Context;
|
||||
import android.net.INetworkMonitor;
|
||||
import android.net.LinkProperties;
|
||||
import android.net.Network;
|
||||
import android.net.NetworkCapabilities;
|
||||
@@ -29,7 +28,6 @@ import android.net.NetworkState;
|
||||
import android.os.Handler;
|
||||
import android.os.INetworkManagementService;
|
||||
import android.os.Messenger;
|
||||
import android.os.RemoteException;
|
||||
import android.os.SystemClock;
|
||||
import android.util.Log;
|
||||
import android.util.SparseArray;
|
||||
@@ -37,11 +35,8 @@ import android.util.SparseArray;
|
||||
import com.android.internal.util.AsyncChannel;
|
||||
import com.android.internal.util.WakeupMessage;
|
||||
import com.android.server.ConnectivityService;
|
||||
import com.android.server.connectivity.NetworkMonitor;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.Objects;
|
||||
import java.util.SortedSet;
|
||||
import java.util.TreeSet;
|
||||
@@ -126,7 +121,6 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> {
|
||||
public LinkProperties linkProperties;
|
||||
// This should only be modified via ConnectivityService.updateCapabilities().
|
||||
public NetworkCapabilities networkCapabilities;
|
||||
public final NetworkMonitor networkMonitor;
|
||||
public final NetworkMisc networkMisc;
|
||||
// Indicates if netd has been told to create this Network. From this point on the appropriate
|
||||
// routing rules are setup and routes are added so packets can begin flowing over the Network.
|
||||
@@ -239,6 +233,9 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> {
|
||||
// Used by ConnectivityService to keep track of 464xlat.
|
||||
public Nat464Xlat clatd;
|
||||
|
||||
// Set after asynchronous creation of the NetworkMonitor.
|
||||
private volatile INetworkMonitor mNetworkMonitor;
|
||||
|
||||
private static final String TAG = ConnectivityService.class.getSimpleName();
|
||||
private static final boolean VDBG = false;
|
||||
private final ConnectivityService mConnService;
|
||||
@@ -247,7 +244,7 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> {
|
||||
|
||||
public NetworkAgentInfo(Messenger messenger, AsyncChannel ac, Network net, NetworkInfo info,
|
||||
LinkProperties lp, NetworkCapabilities nc, int score, Context context, Handler handler,
|
||||
NetworkMisc misc, NetworkRequest defaultRequest, ConnectivityService connService) {
|
||||
NetworkMisc misc, ConnectivityService connService) {
|
||||
this.messenger = messenger;
|
||||
asyncChannel = ac;
|
||||
network = net;
|
||||
@@ -258,10 +255,16 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> {
|
||||
mConnService = connService;
|
||||
mContext = context;
|
||||
mHandler = handler;
|
||||
networkMonitor = mConnService.createNetworkMonitor(context, handler, this, defaultRequest);
|
||||
networkMisc = misc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inform NetworkAgentInfo that a new NetworkMonitor was created.
|
||||
*/
|
||||
public void onNetworkMonitorCreated(INetworkMonitor networkMonitor) {
|
||||
mNetworkMonitor = networkMonitor;
|
||||
}
|
||||
|
||||
public ConnectivityService connService() {
|
||||
return mConnService;
|
||||
}
|
||||
@@ -278,6 +281,15 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> {
|
||||
return network;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the INetworkMonitor in this NetworkAgentInfo.
|
||||
*
|
||||
* <p>This will be null before {@link #onNetworkMonitorCreated(INetworkMonitor)} is called.
|
||||
*/
|
||||
public INetworkMonitor networkMonitor() {
|
||||
return mNetworkMonitor;
|
||||
}
|
||||
|
||||
// Functions for manipulating the requests satisfied by this network.
|
||||
//
|
||||
// These functions must only called on ConnectivityService's main thread.
|
||||
|
||||
@@ -11,10 +11,10 @@ java_library {
|
||||
]
|
||||
}
|
||||
|
||||
// TODO: move to networking module with IpNeighborMonitor/ConnectivityPacketTracker and remove lib
|
||||
java_library {
|
||||
name: "frameworks-net-shared-utils",
|
||||
filegroup {
|
||||
name: "services-networkstack-shared-srcs",
|
||||
srcs: [
|
||||
"java/android/net/util/FdEventsReader.java",
|
||||
"java/android/net/util/FdEventsReader.java", // TODO: move to NetworkStack with IpClient
|
||||
"java/android/net/shared/*.java",
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright (C) 2018 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.net.shared;
|
||||
|
||||
import android.content.Context;
|
||||
import android.net.NetworkCapabilities;
|
||||
import android.provider.Settings;
|
||||
|
||||
/** @hide */
|
||||
public class NetworkMonitorUtils {
|
||||
|
||||
// Network conditions broadcast constants
|
||||
public static final String ACTION_NETWORK_CONDITIONS_MEASURED =
|
||||
"android.net.conn.NETWORK_CONDITIONS_MEASURED";
|
||||
public static final String EXTRA_CONNECTIVITY_TYPE = "extra_connectivity_type";
|
||||
public static final String EXTRA_NETWORK_TYPE = "extra_network_type";
|
||||
public static final String EXTRA_RESPONSE_RECEIVED = "extra_response_received";
|
||||
public static final String EXTRA_IS_CAPTIVE_PORTAL = "extra_is_captive_portal";
|
||||
public static final String EXTRA_CELL_ID = "extra_cellid";
|
||||
public static final String EXTRA_SSID = "extra_ssid";
|
||||
public static final String EXTRA_BSSID = "extra_bssid";
|
||||
/** real time since boot */
|
||||
public static final String EXTRA_REQUEST_TIMESTAMP_MS = "extra_request_timestamp_ms";
|
||||
public static final String EXTRA_RESPONSE_TIMESTAMP_MS = "extra_response_timestamp_ms";
|
||||
public static final String PERMISSION_ACCESS_NETWORK_CONDITIONS =
|
||||
"android.permission.ACCESS_NETWORK_CONDITIONS";
|
||||
|
||||
// TODO: once the URL is a resource overlay, remove and have the resource define the default
|
||||
private static final String DEFAULT_HTTP_URL =
|
||||
"http://connectivitycheck.gstatic.com/generate_204";
|
||||
|
||||
/**
|
||||
* Get the captive portal server HTTP URL that is configured on the device.
|
||||
*/
|
||||
public static String getCaptivePortalServerHttpUrl(Context context) {
|
||||
final String settingUrl = Settings.Global.getString(
|
||||
context.getContentResolver(),
|
||||
Settings.Global.CAPTIVE_PORTAL_HTTP_URL);
|
||||
return settingUrl != null ? settingUrl : DEFAULT_HTTP_URL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether validation is required for a network.
|
||||
* @param dfltNetCap Default requested network capabilities.
|
||||
* @param nc Network capabilities of the network to test.
|
||||
*/
|
||||
public static boolean isValidationRequired(
|
||||
NetworkCapabilities dfltNetCap, NetworkCapabilities nc) {
|
||||
// TODO: Consider requiring validation for DUN networks.
|
||||
return dfltNetCap.satisfiedByNetworkCapabilities(nc);
|
||||
}
|
||||
}
|
||||
94
services/net/java/android/net/shared/PrivateDnsConfig.java
Normal file
94
services/net/java/android/net/shared/PrivateDnsConfig.java
Normal file
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Copyright (C) 2018 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.net.shared;
|
||||
|
||||
import android.net.InetAddresses;
|
||||
import android.net.PrivateDnsConfigParcel;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.util.Arrays;
|
||||
|
||||
/** @hide */
|
||||
public class PrivateDnsConfig {
|
||||
public final boolean useTls;
|
||||
public final String hostname;
|
||||
public final InetAddress[] ips;
|
||||
|
||||
public PrivateDnsConfig() {
|
||||
this(false);
|
||||
}
|
||||
|
||||
public PrivateDnsConfig(boolean useTls) {
|
||||
this.useTls = useTls;
|
||||
this.hostname = "";
|
||||
this.ips = new InetAddress[0];
|
||||
}
|
||||
|
||||
public PrivateDnsConfig(String hostname, InetAddress[] ips) {
|
||||
this.useTls = !TextUtils.isEmpty(hostname);
|
||||
this.hostname = useTls ? hostname : "";
|
||||
this.ips = (ips != null) ? ips : new InetAddress[0];
|
||||
}
|
||||
|
||||
public PrivateDnsConfig(PrivateDnsConfig cfg) {
|
||||
useTls = cfg.useTls;
|
||||
hostname = cfg.hostname;
|
||||
ips = cfg.ips;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether this is a strict mode private DNS configuration.
|
||||
*/
|
||||
public boolean inStrictMode() {
|
||||
return useTls && !TextUtils.isEmpty(hostname);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return PrivateDnsConfig.class.getSimpleName()
|
||||
+ "{" + useTls + ":" + hostname + "/" + Arrays.toString(ips) + "}";
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a stable AIDL-compatible parcel from the current instance.
|
||||
*/
|
||||
public PrivateDnsConfigParcel toParcel() {
|
||||
final PrivateDnsConfigParcel parcel = new PrivateDnsConfigParcel();
|
||||
parcel.hostname = hostname;
|
||||
|
||||
final String[] parceledIps = new String[ips.length];
|
||||
for (int i = 0; i < ips.length; i++) {
|
||||
parceledIps[i] = ips[i].getHostAddress();
|
||||
}
|
||||
parcel.ips = parceledIps;
|
||||
|
||||
return parcel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a configuration from a stable AIDL-compatible parcel.
|
||||
*/
|
||||
public static PrivateDnsConfig fromParcel(PrivateDnsConfigParcel parcel) {
|
||||
final InetAddress[] ips = new InetAddress[parcel.ips.length];
|
||||
for (int i = 0; i < ips.length; i++) {
|
||||
ips[i] = InetAddresses.parseNumericAddress(parcel.ips[i]);
|
||||
}
|
||||
|
||||
return new PrivateDnsConfig(parcel.hostname, ips);
|
||||
}
|
||||
}
|
||||
@@ -70,6 +70,10 @@ public class SharedLog {
|
||||
mComponent = component;
|
||||
}
|
||||
|
||||
public String getTag() {
|
||||
return mTag;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a SharedLog based on this log with an additional component prefix on each logged line.
|
||||
*/
|
||||
|
||||
@@ -26,6 +26,8 @@ import static android.net.ConnectivityManager.TYPE_MOBILE_FOTA;
|
||||
import static android.net.ConnectivityManager.TYPE_MOBILE_MMS;
|
||||
import static android.net.ConnectivityManager.TYPE_NONE;
|
||||
import static android.net.ConnectivityManager.TYPE_WIFI;
|
||||
import static android.net.INetworkMonitor.NETWORK_TEST_RESULT_INVALID;
|
||||
import static android.net.INetworkMonitor.NETWORK_TEST_RESULT_VALID;
|
||||
import static android.net.NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL;
|
||||
import static android.net.NetworkCapabilities.NET_CAPABILITY_CBS;
|
||||
import static android.net.NetworkCapabilities.NET_CAPABILITY_DUN;
|
||||
@@ -69,17 +71,19 @@ import static org.junit.Assert.fail;
|
||||
import static org.mockito.Matchers.anyInt;
|
||||
import static org.mockito.Mockito.any;
|
||||
import static org.mockito.Mockito.atLeastOnce;
|
||||
import static org.mockito.Mockito.doAnswer;
|
||||
import static org.mockito.Mockito.doNothing;
|
||||
import static org.mockito.Mockito.eq;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.reset;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.timeout;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
|
||||
import android.app.NotificationManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.BroadcastReceiver;
|
||||
@@ -89,7 +93,6 @@ import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.res.Resources;
|
||||
import android.net.CaptivePortal;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.net.ConnectivityManager.NetworkCallback;
|
||||
import android.net.ConnectivityManager.PacketKeepalive;
|
||||
@@ -97,6 +100,8 @@ import android.net.ConnectivityManager.PacketKeepaliveCallback;
|
||||
import android.net.ConnectivityManager.TooManyRequestsException;
|
||||
import android.net.ConnectivityThread;
|
||||
import android.net.INetd;
|
||||
import android.net.INetworkMonitor;
|
||||
import android.net.INetworkMonitorCallbacks;
|
||||
import android.net.INetworkPolicyListener;
|
||||
import android.net.INetworkPolicyManager;
|
||||
import android.net.INetworkStatsService;
|
||||
@@ -114,12 +119,14 @@ import android.net.NetworkInfo.DetailedState;
|
||||
import android.net.NetworkMisc;
|
||||
import android.net.NetworkRequest;
|
||||
import android.net.NetworkSpecifier;
|
||||
import android.net.NetworkStack;
|
||||
import android.net.NetworkUtils;
|
||||
import android.net.RouteInfo;
|
||||
import android.net.StringNetworkSpecifier;
|
||||
import android.net.UidRange;
|
||||
import android.net.captiveportal.CaptivePortalProbeResult;
|
||||
import android.net.metrics.IpConnectivityLog;
|
||||
import android.net.shared.NetworkMonitorUtils;
|
||||
import android.net.shared.PrivateDnsConfig;
|
||||
import android.net.util.MultinetworkPolicyTracker;
|
||||
import android.os.ConditionVariable;
|
||||
import android.os.Handler;
|
||||
@@ -148,12 +155,9 @@ import com.android.internal.util.test.BroadcastInterceptingContext;
|
||||
import com.android.internal.util.test.FakeSettingsProvider;
|
||||
import com.android.server.connectivity.ConnectivityConstants;
|
||||
import com.android.server.connectivity.DefaultNetworkMetrics;
|
||||
import com.android.server.connectivity.DnsManager;
|
||||
import com.android.server.connectivity.IpConnectivityMetrics;
|
||||
import com.android.server.connectivity.MockableSystemProperties;
|
||||
import com.android.server.connectivity.Nat464Xlat;
|
||||
import com.android.server.connectivity.NetworkAgentInfo;
|
||||
import com.android.server.connectivity.NetworkMonitor;
|
||||
import com.android.server.connectivity.Tethering;
|
||||
import com.android.server.connectivity.Vpn;
|
||||
import com.android.server.net.NetworkPinner;
|
||||
@@ -168,6 +172,7 @@ import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.mockito.Spy;
|
||||
import org.mockito.stubbing.Answer;
|
||||
|
||||
import java.net.Inet4Address;
|
||||
import java.net.InetAddress;
|
||||
@@ -230,6 +235,7 @@ public class ConnectivityServiceTest {
|
||||
@Mock INetworkStatsService mStatsService;
|
||||
@Mock INetworkPolicyManager mNpm;
|
||||
@Mock INetd mMockNetd;
|
||||
@Mock NetworkStack mNetworkStack;
|
||||
|
||||
private ArgumentCaptor<String[]> mStringArrayCaptor = ArgumentCaptor.forClass(String[].class);
|
||||
|
||||
@@ -299,6 +305,7 @@ public class ConnectivityServiceTest {
|
||||
public Object getSystemService(String name) {
|
||||
if (Context.CONNECTIVITY_SERVICE.equals(name)) return mCm;
|
||||
if (Context.NOTIFICATION_SERVICE.equals(name)) return mock(NotificationManager.class);
|
||||
if (Context.NETWORK_STACK_SERVICE.equals(name)) return mNetworkStack;
|
||||
return super.getSystemService(name);
|
||||
}
|
||||
|
||||
@@ -386,7 +393,7 @@ public class ConnectivityServiceTest {
|
||||
}
|
||||
|
||||
private class MockNetworkAgent {
|
||||
private final WrappedNetworkMonitor mWrappedNetworkMonitor;
|
||||
private final INetworkMonitor mNetworkMonitor;
|
||||
private final NetworkInfo mNetworkInfo;
|
||||
private final NetworkCapabilities mNetworkCapabilities;
|
||||
private final HandlerThread mHandlerThread;
|
||||
@@ -402,6 +409,26 @@ public class ConnectivityServiceTest {
|
||||
// mNetworkStatusReceived.
|
||||
private String mRedirectUrl;
|
||||
|
||||
private INetworkMonitorCallbacks mNmCallbacks;
|
||||
private int mNmValidationResult = NETWORK_TEST_RESULT_INVALID;
|
||||
private String mNmValidationRedirectUrl = null;
|
||||
private boolean mNmProvNotificationRequested = false;
|
||||
|
||||
void setNetworkValid() {
|
||||
mNmValidationResult = NETWORK_TEST_RESULT_VALID;
|
||||
mNmValidationRedirectUrl = null;
|
||||
}
|
||||
|
||||
void setNetworkInvalid() {
|
||||
mNmValidationResult = NETWORK_TEST_RESULT_INVALID;
|
||||
mNmValidationRedirectUrl = null;
|
||||
}
|
||||
|
||||
void setNetworkPortal(String redirectUrl) {
|
||||
setNetworkInvalid();
|
||||
mNmValidationRedirectUrl = redirectUrl;
|
||||
}
|
||||
|
||||
MockNetworkAgent(int transport) {
|
||||
this(transport, new LinkProperties());
|
||||
}
|
||||
@@ -434,6 +461,29 @@ public class ConnectivityServiceTest {
|
||||
}
|
||||
mHandlerThread = new HandlerThread("Mock-" + typeName);
|
||||
mHandlerThread.start();
|
||||
|
||||
mNetworkMonitor = mock(INetworkMonitor.class);
|
||||
final Answer validateAnswer = inv -> {
|
||||
new Thread(this::onValidationRequested).start();
|
||||
return null;
|
||||
};
|
||||
|
||||
try {
|
||||
doAnswer(validateAnswer).when(mNetworkMonitor).notifyNetworkConnected();
|
||||
doAnswer(validateAnswer).when(mNetworkMonitor).forceReevaluation(anyInt());
|
||||
} catch (RemoteException e) {
|
||||
fail(e.getMessage());
|
||||
}
|
||||
|
||||
final ArgumentCaptor<Network> nmNetworkCaptor =
|
||||
ArgumentCaptor.forClass(Network.class);
|
||||
final ArgumentCaptor<INetworkMonitorCallbacks> nmCbCaptor =
|
||||
ArgumentCaptor.forClass(INetworkMonitorCallbacks.class);
|
||||
doNothing().when(mNetworkStack).makeNetworkMonitor(
|
||||
nmNetworkCaptor.capture(),
|
||||
any() /* name */,
|
||||
nmCbCaptor.capture());
|
||||
|
||||
mNetworkAgent = new NetworkAgent(mHandlerThread.getLooper(), mServiceContext,
|
||||
"Mock-" + typeName, mNetworkInfo, mNetworkCapabilities,
|
||||
linkProperties, mScore, new NetworkMisc()) {
|
||||
@@ -465,10 +515,40 @@ public class ConnectivityServiceTest {
|
||||
mPreventReconnectReceived.open();
|
||||
}
|
||||
};
|
||||
|
||||
assertEquals(mNetworkAgent.netId, nmNetworkCaptor.getValue().netId);
|
||||
mNmCallbacks = nmCbCaptor.getValue();
|
||||
|
||||
try {
|
||||
mNmCallbacks.onNetworkMonitorCreated(mNetworkMonitor);
|
||||
} catch (RemoteException e) {
|
||||
fail(e.getMessage());
|
||||
}
|
||||
|
||||
// Waits for the NetworkAgent to be registered, which includes the creation of the
|
||||
// NetworkMonitor.
|
||||
waitForIdle();
|
||||
mWrappedNetworkMonitor = mService.getLastCreatedWrappedNetworkMonitor();
|
||||
}
|
||||
|
||||
private void onValidationRequested() {
|
||||
try {
|
||||
if (mNmProvNotificationRequested
|
||||
&& mNmValidationResult == NETWORK_TEST_RESULT_VALID) {
|
||||
mNmCallbacks.hideProvisioningNotification();
|
||||
mNmProvNotificationRequested = false;
|
||||
}
|
||||
|
||||
mNmCallbacks.notifyNetworkTested(
|
||||
mNmValidationResult, mNmValidationRedirectUrl);
|
||||
|
||||
if (mNmValidationRedirectUrl != null) {
|
||||
mNmCallbacks.showProvisioningNotification(
|
||||
"test_provisioning_notif_action");
|
||||
mNmProvNotificationRequested = true;
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
fail(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public void adjustScore(int change) {
|
||||
@@ -539,7 +619,7 @@ public class ConnectivityServiceTest {
|
||||
NetworkCallback callback = null;
|
||||
final ConditionVariable validatedCv = new ConditionVariable();
|
||||
if (validated) {
|
||||
mWrappedNetworkMonitor.gen204ProbeResult = 204;
|
||||
setNetworkValid();
|
||||
NetworkRequest request = new NetworkRequest.Builder()
|
||||
.addTransportType(mNetworkCapabilities.getTransportTypes()[0])
|
||||
.clearCapabilities()
|
||||
@@ -564,15 +644,14 @@ public class ConnectivityServiceTest {
|
||||
if (validated) {
|
||||
// Wait for network to validate.
|
||||
waitFor(validatedCv);
|
||||
mWrappedNetworkMonitor.gen204ProbeResult = 500;
|
||||
setNetworkInvalid();
|
||||
}
|
||||
|
||||
if (callback != null) mCm.unregisterNetworkCallback(callback);
|
||||
}
|
||||
|
||||
public void connectWithCaptivePortal(String redirectUrl) {
|
||||
mWrappedNetworkMonitor.gen204ProbeResult = 200;
|
||||
mWrappedNetworkMonitor.gen204ProbeRedirectUrl = redirectUrl;
|
||||
setNetworkPortal(redirectUrl);
|
||||
connect(false);
|
||||
}
|
||||
|
||||
@@ -603,10 +682,6 @@ public class ConnectivityServiceTest {
|
||||
return mDisconnected;
|
||||
}
|
||||
|
||||
public WrappedNetworkMonitor getWrappedNetworkMonitor() {
|
||||
return mWrappedNetworkMonitor;
|
||||
}
|
||||
|
||||
public void sendLinkProperties(LinkProperties lp) {
|
||||
mNetworkAgent.sendLinkProperties(lp);
|
||||
}
|
||||
@@ -880,28 +955,6 @@ public class ConnectivityServiceTest {
|
||||
}
|
||||
}
|
||||
|
||||
// NetworkMonitor implementation allowing overriding of Internet connectivity probe result.
|
||||
private class WrappedNetworkMonitor extends NetworkMonitor {
|
||||
public final Handler connectivityHandler;
|
||||
// HTTP response code fed back to NetworkMonitor for Internet connectivity probe.
|
||||
public int gen204ProbeResult = 500;
|
||||
public String gen204ProbeRedirectUrl = null;
|
||||
|
||||
public WrappedNetworkMonitor(Context context, Handler handler,
|
||||
NetworkAgentInfo networkAgentInfo, NetworkRequest defaultRequest,
|
||||
IpConnectivityLog log) {
|
||||
super(context, handler, networkAgentInfo, defaultRequest, log,
|
||||
NetworkMonitor.Dependencies.DEFAULT);
|
||||
connectivityHandler = handler;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected CaptivePortalProbeResult isCaptivePortal() {
|
||||
if (!mIsCaptivePortalCheckEnabled) { return new CaptivePortalProbeResult(204); }
|
||||
return new CaptivePortalProbeResult(gen204ProbeResult, gen204ProbeRedirectUrl, null);
|
||||
}
|
||||
}
|
||||
|
||||
private class WrappedMultinetworkPolicyTracker extends MultinetworkPolicyTracker {
|
||||
public volatile boolean configRestrictsAvoidBadWifi;
|
||||
public volatile int configMeteredMultipathPreference;
|
||||
@@ -923,7 +976,6 @@ public class ConnectivityServiceTest {
|
||||
|
||||
private class WrappedConnectivityService extends ConnectivityService {
|
||||
public WrappedMultinetworkPolicyTracker wrappedMultinetworkPolicyTracker;
|
||||
private WrappedNetworkMonitor mLastCreatedNetworkMonitor;
|
||||
private MockableSystemProperties mSystemProperties;
|
||||
|
||||
public WrappedConnectivityService(Context context, INetworkManagementService netManager,
|
||||
@@ -971,15 +1023,6 @@ public class ConnectivityServiceTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public NetworkMonitor createNetworkMonitor(Context context, Handler handler,
|
||||
NetworkAgentInfo nai, NetworkRequest defaultRequest) {
|
||||
final WrappedNetworkMonitor monitor = new WrappedNetworkMonitor(
|
||||
context, handler, nai, defaultRequest, mock(IpConnectivityLog.class));
|
||||
mLastCreatedNetworkMonitor = monitor;
|
||||
return monitor;
|
||||
}
|
||||
|
||||
public Nat464Xlat getNat464Xlat(MockNetworkAgent mna) {
|
||||
return getNetworkAgentInfoForNetwork(mna.getNetwork()).clatd;
|
||||
}
|
||||
@@ -1017,10 +1060,6 @@ public class ConnectivityServiceTest {
|
||||
protected void registerNetdEventCallback() {
|
||||
}
|
||||
|
||||
public WrappedNetworkMonitor getLastCreatedWrappedNetworkMonitor() {
|
||||
return mLastCreatedNetworkMonitor;
|
||||
}
|
||||
|
||||
public void mockVpn(int uid) {
|
||||
synchronized (mVpns) {
|
||||
int userId = UserHandle.getUserId(uid);
|
||||
@@ -2439,7 +2478,7 @@ public class ConnectivityServiceTest {
|
||||
|
||||
// Make captive portal disappear then revalidate.
|
||||
// Expect onLost callback because network no longer provides NET_CAPABILITY_CAPTIVE_PORTAL.
|
||||
mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 204;
|
||||
mWiFiNetworkAgent.setNetworkValid();
|
||||
mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
|
||||
captivePortalCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
|
||||
|
||||
@@ -2448,13 +2487,13 @@ public class ConnectivityServiceTest {
|
||||
|
||||
// Break network connectivity.
|
||||
// Expect NET_CAPABILITY_VALIDATED onLost callback.
|
||||
mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 500;
|
||||
mWiFiNetworkAgent.setNetworkInvalid();
|
||||
mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), false);
|
||||
validatedCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCaptivePortalApp() {
|
||||
public void testCaptivePortalApp() throws RemoteException {
|
||||
final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
|
||||
final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
|
||||
.addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
|
||||
@@ -2477,21 +2516,19 @@ public class ConnectivityServiceTest {
|
||||
mServiceContext.expectNoStartActivityIntent(fastTimeoutMs);
|
||||
|
||||
// Turn into a captive portal.
|
||||
mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 302;
|
||||
mWiFiNetworkAgent.setNetworkPortal("http://example.com");
|
||||
mCm.reportNetworkConnectivity(wifiNetwork, false);
|
||||
captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
|
||||
validatedCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
|
||||
|
||||
// Check that startCaptivePortalApp sends the expected intent.
|
||||
// Check that startCaptivePortalApp sends the expected command to NetworkMonitor.
|
||||
mCm.startCaptivePortalApp(wifiNetwork);
|
||||
Intent intent = mServiceContext.expectStartActivityIntent(TIMEOUT_MS);
|
||||
assertEquals(ConnectivityManager.ACTION_CAPTIVE_PORTAL_SIGN_IN, intent.getAction());
|
||||
assertEquals(wifiNetwork, intent.getExtra(ConnectivityManager.EXTRA_NETWORK));
|
||||
verify(mWiFiNetworkAgent.mNetworkMonitor, timeout(TIMEOUT_MS).times(1))
|
||||
.launchCaptivePortalApp();
|
||||
|
||||
// Have the app report that the captive portal is dismissed, and check that we revalidate.
|
||||
mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 204;
|
||||
CaptivePortal c = (CaptivePortal) intent.getExtra(ConnectivityManager.EXTRA_CAPTIVE_PORTAL);
|
||||
c.reportCaptivePortalDismissed();
|
||||
// Report that the captive portal is dismissed, and check that callbacks are fired
|
||||
mWiFiNetworkAgent.setNetworkValid();
|
||||
mWiFiNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
|
||||
validatedCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
|
||||
captivePortalCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
|
||||
|
||||
@@ -2524,20 +2561,6 @@ public class ConnectivityServiceTest {
|
||||
waitFor(avoidCv);
|
||||
|
||||
assertNoCallbacks(captivePortalCallback, validatedCallback);
|
||||
|
||||
// Now test ignore mode.
|
||||
setCaptivePortalMode(Settings.Global.CAPTIVE_PORTAL_MODE_IGNORE);
|
||||
|
||||
// Bring up a network with a captive portal.
|
||||
// Since we're ignoring captive portals, the network will validate.
|
||||
mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
|
||||
String secondRedirectUrl = "http://example.com/secondPath";
|
||||
mWiFiNetworkAgent.connectWithCaptivePortal(secondRedirectUrl);
|
||||
|
||||
// Expect NET_CAPABILITY_VALIDATED onAvailable callback.
|
||||
validatedCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
|
||||
// But there should be no CaptivePortal callback.
|
||||
captivePortalCallback.assertNoCallback();
|
||||
}
|
||||
|
||||
private NetworkRequest.Builder newWifiRequestBuilder() {
|
||||
@@ -3169,7 +3192,7 @@ public class ConnectivityServiceTest {
|
||||
Network wifiNetwork = mWiFiNetworkAgent.getNetwork();
|
||||
|
||||
// Fail validation on wifi.
|
||||
mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 599;
|
||||
mWiFiNetworkAgent.setNetworkInvalid();
|
||||
mCm.reportNetworkConnectivity(wifiNetwork, false);
|
||||
defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
|
||||
validatedWifiCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
|
||||
@@ -3213,7 +3236,7 @@ public class ConnectivityServiceTest {
|
||||
wifiNetwork = mWiFiNetworkAgent.getNetwork();
|
||||
|
||||
// Fail validation on wifi and expect the dialog to appear.
|
||||
mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 599;
|
||||
mWiFiNetworkAgent.setNetworkInvalid();
|
||||
mCm.reportNetworkConnectivity(wifiNetwork, false);
|
||||
defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
|
||||
validatedWifiCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
|
||||
@@ -4002,11 +4025,9 @@ public class ConnectivityServiceTest {
|
||||
final String TLS_SERVER6 = "2001:db8:53::53";
|
||||
final InetAddress[] TLS_IPS = new InetAddress[]{ InetAddress.getByName(TLS_SERVER6) };
|
||||
final String[] TLS_SERVERS = new String[]{ TLS_SERVER6 };
|
||||
final Handler h = mCellNetworkAgent.getWrappedNetworkMonitor().connectivityHandler;
|
||||
h.sendMessage(h.obtainMessage(
|
||||
NetworkMonitor.EVENT_PRIVATE_DNS_CONFIG_RESOLVED, 0,
|
||||
mCellNetworkAgent.getNetwork().netId,
|
||||
new DnsManager.PrivateDnsConfig(TLS_SPECIFIER, TLS_IPS)));
|
||||
mCellNetworkAgent.mNmCallbacks.notifyPrivateDnsConfigResolved(
|
||||
new PrivateDnsConfig(TLS_SPECIFIER, TLS_IPS).toParcel());
|
||||
|
||||
waitForIdle();
|
||||
verify(mNetworkManagementService, atLeastOnce()).setDnsConfigurationForNetwork(
|
||||
anyInt(), mStringArrayCaptor.capture(), any(), any(),
|
||||
@@ -4294,6 +4315,12 @@ public class ConnectivityServiceTest {
|
||||
ranges.add(new UidRange(uid, uid));
|
||||
mMockVpn.setNetworkAgent(vpnNetworkAgent);
|
||||
mMockVpn.setUids(ranges);
|
||||
// VPN networks do not satisfy the default request and are automatically validated
|
||||
// by NetworkMonitor
|
||||
assertFalse(NetworkMonitorUtils.isValidationRequired(
|
||||
mCm.getDefaultRequest().networkCapabilities, vpnNetworkAgent.mNetworkCapabilities));
|
||||
vpnNetworkAgent.setNetworkValid();
|
||||
|
||||
vpnNetworkAgent.connect(false);
|
||||
mMockVpn.connect();
|
||||
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
package com.android.server.connectivity;
|
||||
|
||||
import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_OFF;
|
||||
import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_OPPORTUNISTIC;
|
||||
import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_PROVIDER_HOSTNAME;
|
||||
import static android.provider.Settings.Global.PRIVATE_DNS_DEFAULT_MODE;
|
||||
import static android.provider.Settings.Global.PRIVATE_DNS_MODE;
|
||||
@@ -29,13 +28,13 @@ import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.net.IpPrefix;
|
||||
import android.net.LinkAddress;
|
||||
import android.net.LinkProperties;
|
||||
import android.net.Network;
|
||||
import android.net.RouteInfo;
|
||||
import android.net.shared.PrivateDnsConfig;
|
||||
import android.os.INetworkManagementService;
|
||||
import android.provider.Settings;
|
||||
import android.support.test.filters.SmallTest;
|
||||
@@ -43,18 +42,16 @@ import android.support.test.runner.AndroidJUnit4;
|
||||
import android.test.mock.MockContentResolver;
|
||||
|
||||
import com.android.internal.util.test.FakeSettingsProvider;
|
||||
import com.android.server.connectivity.DnsManager.PrivateDnsConfig;
|
||||
import com.android.server.connectivity.MockableSystemProperties;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
/**
|
||||
* Tests for {@link DnsManager}.
|
||||
*
|
||||
@@ -133,7 +130,7 @@ public class DnsManagerTest {
|
||||
PRIVATE_DNS_MODE, PRIVATE_DNS_MODE_PROVIDER_HOSTNAME);
|
||||
Settings.Global.putString(mContentResolver, PRIVATE_DNS_SPECIFIER, "strictmode.com");
|
||||
mDnsManager.updatePrivateDns(new Network(TEST_NETID),
|
||||
new DnsManager.PrivateDnsConfig("strictmode.com", new InetAddress[] {
|
||||
new PrivateDnsConfig("strictmode.com", new InetAddress[] {
|
||||
InetAddress.parseNumericAddress("6.6.6.6"),
|
||||
InetAddress.parseNumericAddress("2001:db8:66:66::1")
|
||||
}));
|
||||
|
||||
@@ -23,10 +23,10 @@ import static org.mockito.Mockito.anyBoolean;
|
||||
import static org.mockito.Mockito.anyInt;
|
||||
import static org.mockito.Mockito.eq;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.reset;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.mockito.Mockito.reset;
|
||||
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Context;
|
||||
@@ -36,18 +36,18 @@ import android.net.Network;
|
||||
import android.net.NetworkCapabilities;
|
||||
import android.net.NetworkInfo;
|
||||
import android.net.NetworkMisc;
|
||||
import android.support.test.runner.AndroidJUnit4;
|
||||
import android.net.NetworkStack;
|
||||
import android.support.test.filters.SmallTest;
|
||||
import android.support.test.runner.AndroidJUnit4;
|
||||
import android.text.format.DateUtils;
|
||||
|
||||
import com.android.internal.R;
|
||||
import com.android.server.ConnectivityService;
|
||||
import com.android.server.connectivity.NetworkNotificationManager;
|
||||
import com.android.server.connectivity.NetworkNotificationManager.NotificationType;
|
||||
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
@@ -70,13 +70,16 @@ public class LingerMonitorTest {
|
||||
@Mock NetworkMisc mMisc;
|
||||
@Mock NetworkNotificationManager mNotifier;
|
||||
@Mock Resources mResources;
|
||||
@Mock NetworkStack mNetworkStack;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
when(mCtx.getResources()).thenReturn(mResources);
|
||||
when(mCtx.getPackageName()).thenReturn("com.android.server.connectivity");
|
||||
when(mConnService.createNetworkMonitor(any(), any(), any(), any())).thenReturn(null);
|
||||
when(mCtx.getSystemServiceName(NetworkStack.class))
|
||||
.thenReturn(Context.NETWORK_STACK_SERVICE);
|
||||
when(mCtx.getSystemService(Context.NETWORK_STACK_SERVICE)).thenReturn(mNetworkStack);
|
||||
|
||||
mMonitor = new TestableLingerMonitor(mCtx, mNotifier, HIGH_DAILY_LIMIT, HIGH_RATE_LIMIT);
|
||||
}
|
||||
@@ -349,7 +352,7 @@ public class LingerMonitorTest {
|
||||
caps.addCapability(0);
|
||||
caps.addTransportType(transport);
|
||||
NetworkAgentInfo nai = new NetworkAgentInfo(null, null, new Network(netId), info, null,
|
||||
caps, 50, mCtx, null, mMisc, null, mConnService);
|
||||
caps, 50, mCtx, null, mMisc, mConnService);
|
||||
nai.everValidated = true;
|
||||
return nai;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user