diff options
43 files changed, 692 insertions, 416 deletions
diff --git a/Android.bp b/Android.bp index 5935bfb57213..d58b48399a8f 100644 --- a/Android.bp +++ b/Android.bp @@ -704,7 +704,7 @@ java_defaults { "android.hardware.vibrator-V1.1-java", "android.hardware.vibrator-V1.2-java", "android.hardware.wifi-V1.0-java-constants", - "networkstack-aidl-interfaces-java", + "networkstack-aidl-framework-java", "netd_aidl_parcelables-java", ], @@ -818,7 +818,6 @@ aidl_interface { "core/java/android/net/DhcpResultsParcelable.aidl", "core/java/android/net/INetworkMonitor.aidl", "core/java/android/net/INetworkMonitorCallbacks.aidl", - "core/java/android/net/IIpMemoryStore.aidl", "core/java/android/net/INetworkStackConnector.aidl", "core/java/android/net/INetworkStackStatusCallback.aidl", "core/java/android/net/InitialConfigurationParcelable.aidl", @@ -837,6 +836,16 @@ aidl_interface { "core/java/android/net/dhcp/IDhcpServerCallbacks.aidl", "core/java/android/net/ip/IIpClient.aidl", "core/java/android/net/ip/IIpClientCallbacks.aidl", + ], + api_dir: "aidl/networkstack", +} + +aidl_interface { + name: "networkstack-aidl-framework", + local_include_dir: "core/java", + srcs: [ + "core/java/android/net/TcpKeepalivePacketDataParcelable.aidl", + "core/java/android/net/IIpMemoryStore.aidl", "core/java/android/net/ipmemorystore/**/*.aidl", ], api_dir: "aidl/networkstack", diff --git a/api/system-current.txt b/api/system-current.txt index 8efc3de8b4b9..9c45fb4ee5c4 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -5492,6 +5492,7 @@ package android.telecom { field public static final String EXTRA_CALL_BACK_INTENT = "android.telecom.extra.CALL_BACK_INTENT"; field public static final String EXTRA_CLEAR_MISSED_CALLS_INTENT = "android.telecom.extra.CLEAR_MISSED_CALLS_INTENT"; field public static final String EXTRA_CONNECTION_SERVICE = "android.telecom.extra.CONNECTION_SERVICE"; + field public static final String EXTRA_IS_USER_INTENT_EMERGENCY_CALL = "android.telecom.extra.IS_USER_INTENT_EMERGENCY_CALL"; field public static final int TTY_MODE_FULL = 1; // 0x1 field public static final int TTY_MODE_HCO = 2; // 0x2 field public static final int TTY_MODE_OFF = 0; // 0x0 @@ -6753,6 +6754,7 @@ package android.telephony.ims { method public int getServiceType(); method public static int getVideoStateFromCallType(int); method public static int getVideoStateFromImsCallProfile(android.telephony.ims.ImsCallProfile); + method public boolean hasKnownUserIntentEmergency(); method public boolean isEmergencyCallTesting(); method public boolean isVideoCall(); method public boolean isVideoPaused(); @@ -6765,6 +6767,7 @@ package android.telephony.ims { method public void setEmergencyCallTesting(boolean); method public void setEmergencyServiceCategories(int); method public void setEmergencyUrns(java.util.List<java.lang.String>); + method public void setHasKnownUserIntentEmergency(boolean); method public void updateCallExtras(android.telephony.ims.ImsCallProfile); method public void updateCallType(android.telephony.ims.ImsCallProfile); method public void updateMediaProfile(android.telephony.ims.ImsCallProfile); diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java index c04e61b77274..ca4a184407b4 100644 --- a/cmds/am/src/com/android/commands/am/Am.java +++ b/cmds/am/src/com/android/commands/am/Am.java @@ -174,6 +174,8 @@ public class Am extends BaseCommand { instrument.noWindowAnimation = true; } else if (opt.equals("--no-hidden-api-checks")) { instrument.disableHiddenApiChecks = true; + } else if (opt.equals("--no-isolated-storage")) { + // NOTE: currently a no-op in this branch } else if (opt.equals("--user")) { instrument.userId = parseUserArg(nextArgRequired()); } else if (opt.equals("--abi")) { diff --git a/config/hiddenapi-greylist.txt b/config/hiddenapi-greylist.txt index dd21674ba2b4..e166c31d578a 100644 --- a/config/hiddenapi-greylist.txt +++ b/config/hiddenapi-greylist.txt @@ -2930,7 +2930,6 @@ Lcom/android/internal/telephony/gsm/UsimPhoneBookManager;->reset()V Lcom/android/internal/telephony/GsmAlphabet$TextEncodingDetails;-><init>()V Lcom/android/internal/telephony/GsmCdmaCall;->attachFake(Lcom/android/internal/telephony/Connection;Lcom/android/internal/telephony/Call$State;)V Lcom/android/internal/telephony/GsmCdmaCallTracker;->clearDisconnected()V -Lcom/android/internal/telephony/GsmCdmaCallTracker;->dialThreeWay(Ljava/lang/String;)Lcom/android/internal/telephony/Connection; Lcom/android/internal/telephony/GsmCdmaCallTracker;->disableDataCallInEmergencyCall(Ljava/lang/String;)V Lcom/android/internal/telephony/GsmCdmaCallTracker;->fakeHoldForegroundBeforeDial()V Lcom/android/internal/telephony/GsmCdmaCallTracker;->getPhone()Lcom/android/internal/telephony/GsmCdmaPhone; diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java index 4bbc12fbe63b..e92efde236c4 100644 --- a/core/java/android/app/SystemServiceRegistry.java +++ b/core/java/android/app/SystemServiceRegistry.java @@ -88,7 +88,6 @@ import android.net.IpMemoryStore; import android.net.IpSecManager; import android.net.NetworkPolicyManager; import android.net.NetworkScoreManager; -import android.net.NetworkStack; import android.net.NetworkWatchlistManager; import android.net.lowpan.ILowpanManager; import android.net.lowpan.LowpanManager; @@ -296,13 +295,6 @@ final class SystemServiceRegistry { } }); - registerService(Context.NETWORK_STACK_SERVICE, NetworkStack.class, - new StaticServiceFetcher<NetworkStack>() { - @Override - public NetworkStack createService() { - return new NetworkStack(); - }}); - registerService(Context.IP_MEMORY_STORE_SERVICE, IpMemoryStore.class, new CachedServiceFetcher<IpMemoryStore>() { @Override diff --git a/core/java/android/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java index 2803856fb3bc..23f29041487d 100644 --- a/core/java/android/bluetooth/BluetoothDevice.java +++ b/core/java/android/bluetooth/BluetoothDevice.java @@ -2175,8 +2175,7 @@ public final class BluetoothDevice implements Parcelable { * encrypted. * <p> Use this socket if an authenticated socket link is possible. Authentication refers * to the authentication of the link key to prevent man-in-the-middle type of attacks. When a - * secure socket connection is not possible, use {#link createInsecureLeL2capCocSocket(int, - * int)}. + * secure socket connection is not possible, use {#link createInsecureL2capChannel(int)}. * * @param psm dynamic PSM value from remote device * @return a CoC #BluetoothSocket ready for an outgoing connection diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index 493aac6e5c40..b072740ccfdf 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -49,7 +49,6 @@ import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteDatabase.CursorFactory; import android.graphics.Bitmap; import android.graphics.drawable.Drawable; -import android.net.NetworkStack; import android.net.Uri; import android.os.Build; import android.os.Bundle; @@ -3514,11 +3513,10 @@ public abstract class Context { public static final String NETD_SERVICE = "netd"; /** - * Use with {@link #getSystemService(String)} to retrieve a - * {@link NetworkStack} for communicating with the network stack + * Use with {@link android.os.ServiceManager.getService()} to retrieve a + * {@link NetworkStackClient} IBinder for communicating with the network stack * @hide - * @see #getSystemService(String) - * @see NetworkStack + * @see NetworkStackClient */ public static final String NETWORK_STACK_SERVICE = "network_stack"; diff --git a/core/java/android/net/NetworkStack.java b/core/java/android/net/NetworkStack.java index ca49438390e9..dbb894f92f55 100644 --- a/core/java/android/net/NetworkStack.java +++ b/core/java/android/net/NetworkStack.java @@ -15,46 +15,17 @@ */ package android.net; -import static android.content.pm.PackageManager.PERMISSION_GRANTED; -import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_HIGH; -import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_NORMAL; - -import android.annotation.NonNull; -import android.annotation.Nullable; import android.annotation.SystemApi; -import android.annotation.SystemService; import android.annotation.TestApi; -import android.content.ComponentName; -import android.content.Context; -import android.content.Intent; -import android.content.ServiceConnection; -import android.content.pm.PackageManager; -import android.net.dhcp.DhcpServingParamsParcel; -import android.net.dhcp.IDhcpServerCallbacks; -import android.net.ip.IIpClientCallbacks; -import android.os.Binder; -import android.os.IBinder; -import android.os.Process; -import android.os.RemoteException; -import android.os.ServiceManager; -import android.os.UserHandle; -import android.util.Slog; - -import com.android.internal.annotations.GuardedBy; - -import java.lang.reflect.InvocationTargetException; -import java.util.ArrayList; /** - * Service used to communicate with the network stack, which is running in a separate module. + * + * Constants for client code communicating with the network stack service. * @hide */ -@SystemService(Context.NETWORK_STACK_SERVICE) @SystemApi @TestApi public class NetworkStack { - private static final String TAG = NetworkStack.class.getSimpleName(); - /** * Permission granted only to the NetworkStack APK, defined in NetworkStackStub with signature * protection level. @@ -65,235 +36,5 @@ public class NetworkStack { public static final String PERMISSION_MAINLINE_NETWORK_STACK = "android.permission.MAINLINE_NETWORK_STACK"; - private static final int NETWORKSTACK_TIMEOUT_MS = 10_000; - - @NonNull - @GuardedBy("mPendingNetStackRequests") - private final ArrayList<NetworkStackCallback> mPendingNetStackRequests = new ArrayList<>(); - @Nullable - @GuardedBy("mPendingNetStackRequests") - private INetworkStackConnector mConnector; - - private volatile boolean mNetworkStackStartRequested = false; - - private interface NetworkStackCallback { - void onNetworkStackConnected(INetworkStackConnector connector); - } - - /** @hide */ - public NetworkStack() { } - - /** - * Create a DHCP server according to the specified parameters. - * - * <p>The server will be returned asynchronously through the provided callbacks. - * @hide - */ - public void makeDhcpServer(final String ifName, final DhcpServingParamsParcel params, - final IDhcpServerCallbacks cb) { - requestConnector(connector -> { - try { - connector.makeDhcpServer(ifName, params, cb); - } catch (RemoteException e) { - e.rethrowFromSystemServer(); - } - }); - } - - /** - * Create an IpClient on the specified interface. - * - * <p>The IpClient will be returned asynchronously through the provided callbacks. - * @hide - */ - public void makeIpClient(String ifName, IIpClientCallbacks cb) { - requestConnector(connector -> { - try { - connector.makeIpClient(ifName, cb); - } catch (RemoteException e) { - e.rethrowFromSystemServer(); - } - }); - } - - /** - * Create a NetworkMonitor. - * - * <p>The INetworkMonitor will be returned asynchronously through the provided callbacks. - * @hide - */ - public void makeNetworkMonitor( - NetworkParcelable network, String name, INetworkMonitorCallbacks cb) { - requestConnector(connector -> { - try { - connector.makeNetworkMonitor(network, name, cb); - } catch (RemoteException e) { - e.rethrowFromSystemServer(); - } - }); - } - - private class NetworkStackConnection implements ServiceConnection { - @Override - public void onServiceConnected(ComponentName name, IBinder service) { - registerNetworkStackService(service); - } - - @Override - public void onServiceDisconnected(ComponentName name) { - // TODO: crash/reboot the system ? - Slog.wtf(TAG, "Lost network stack connector"); - } - }; - - private void registerNetworkStackService(@NonNull IBinder service) { - final INetworkStackConnector connector = INetworkStackConnector.Stub.asInterface(service); - - ServiceManager.addService(Context.NETWORK_STACK_SERVICE, service, false /* allowIsolated */, - DUMP_FLAG_PRIORITY_HIGH | DUMP_FLAG_PRIORITY_NORMAL); - - final ArrayList<NetworkStackCallback> requests; - synchronized (mPendingNetStackRequests) { - requests = new ArrayList<>(mPendingNetStackRequests); - mPendingNetStackRequests.clear(); - mConnector = connector; - } - - for (NetworkStackCallback r : requests) { - r.onNetworkStackConnected(connector); - } - } - - /** - * Start the network stack. Should be called only once on device startup. - * - * <p>This method will start the network stack either in the network stack process, or inside - * the system server on devices that do not support the network stack module. The network stack - * connector will then be delivered asynchronously to clients that requested it before it was - * started. - * @hide - */ - public void start(Context context) { - mNetworkStackStartRequested = true; - // Try to bind in-process if the library is available - IBinder connector = null; - try { - final Class service = Class.forName( - "com.android.server.NetworkStackService", - true /* initialize */, - context.getClassLoader()); - 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 ? - return; - } catch (ClassNotFoundException e) { - // Normal behavior if stack is provided by the app: fall through - } - - // In-process network stack. Add the service to the service manager here. - if (connector != null) { - registerNetworkStackService(connector); - return; - } - // Start the network stack process. The service will be added to the service manager in - // NetworkStackConnection.onServiceConnected(). - final Intent intent = new Intent(INetworkStackConnector.class.getName()); - final ComponentName comp = intent.resolveSystemService(context.getPackageManager(), 0); - intent.setComponent(comp); - - if (comp == null) { - Slog.wtf(TAG, "Could not resolve the network stack with " + intent); - // TODO: crash/reboot system server ? - return; - } - - final PackageManager pm = context.getPackageManager(); - int uid = -1; - try { - uid = pm.getPackageUid(comp.getPackageName(), UserHandle.USER_SYSTEM); - } catch (PackageManager.NameNotFoundException e) { - Slog.wtf("Network stack package not found", e); - // Fall through - } - - if (uid != Process.NETWORK_STACK_UID) { - throw new SecurityException("Invalid network stack UID: " + uid); - } - - final int hasPermission = - pm.checkPermission(PERMISSION_MAINLINE_NETWORK_STACK, comp.getPackageName()); - if (hasPermission != PERMISSION_GRANTED) { - throw new SecurityException( - "Network stack does not have permission " + PERMISSION_MAINLINE_NETWORK_STACK); - } - - if (!context.bindServiceAsUser(intent, new NetworkStackConnection(), - Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT, UserHandle.SYSTEM)) { - Slog.wtf(TAG, - "Could not bind to network stack in-process, or in app with " + intent); - // TODO: crash/reboot system server if no network stack after a timeout ? - } - } - - /** - * For non-system server clients, get the connector registered by the system server. - */ - private INetworkStackConnector getRemoteConnector() { - // Block until the NetworkStack connector is registered in ServiceManager. - // <p>This is only useful for non-system processes that do not have a way to be notified of - // registration completion. Adding a callback system would be too heavy weight considering - // that the connector is registered on boot, so it is unlikely that a client would request - // it before it is registered. - // TODO: consider blocking boot on registration and simplify much of the logic in this class - IBinder connector; - try { - final long before = System.currentTimeMillis(); - while ((connector = ServiceManager.getService(Context.NETWORK_STACK_SERVICE)) == null) { - Thread.sleep(20); - if (System.currentTimeMillis() - before > NETWORKSTACK_TIMEOUT_MS) { - Slog.e(TAG, "Timeout waiting for NetworkStack connector"); - return null; - } - } - } catch (InterruptedException e) { - Slog.e(TAG, "Error waiting for NetworkStack connector", e); - return null; - } - - return INetworkStackConnector.Stub.asInterface(connector); - } - - private void requestConnector(@NonNull NetworkStackCallback request) { - // TODO: PID check. - final int caller = Binder.getCallingUid(); - if (caller != Process.SYSTEM_UID && !UserHandle.isSameApp(caller, Process.BLUETOOTH_UID)) { - // Don't even attempt to obtain the connector and give a nice error message - throw new SecurityException( - "Only the system server should try to bind to the network stack."); - } - - if (!mNetworkStackStartRequested) { - // The network stack is not being started in this process, e.g. this process is not - // the system server. Get a remote connector registered by the system server. - final INetworkStackConnector connector = getRemoteConnector(); - synchronized (mPendingNetStackRequests) { - mConnector = connector; - } - request.onNetworkStackConnected(connector); - return; - } - - final INetworkStackConnector connector; - synchronized (mPendingNetStackRequests) { - connector = mConnector; - if (connector == null) { - mPendingNetStackRequests.add(request); - return; - } - } - - request.onNetworkStackConnected(connector); - } + private NetworkStack() {} } diff --git a/core/jni/Android.bp b/core/jni/Android.bp index 08a5789743cc..c385ca11611c 100644 --- a/core/jni/Android.bp +++ b/core/jni/Android.bp @@ -41,7 +41,7 @@ cc_library_shared { "com_google_android_gles_jni_EGLImpl.cpp", "com_google_android_gles_jni_GLImpl.cpp", // TODO: .arm "android_app_Activity.cpp", - "android_app_ActivityThread.cpp", + "android_app_ActivityThread.cpp", "android_app_NativeActivity.cpp", "android_app_admin_SecurityLog.cpp", "android_opengl_EGL14.cpp", @@ -225,6 +225,7 @@ cc_library_shared { ], static_libs: [ + "libasync_safe", "libgif", "libseccomp_policy", "libgrallocusage", diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp index 3012c906df7b..bc1332adacbc 100644 --- a/core/jni/com_android_internal_os_Zygote.cpp +++ b/core/jni/com_android_internal_os_Zygote.cpp @@ -25,6 +25,8 @@ #define LOG_TAG "Zygote" +#include <async_safe/log.h> + // sys/mount.h has to come before linux/fs.h due to redefinition of MS_RDONLY, MS_BIND, etc #include <sys/mount.h> #include <linux/fs.h> @@ -296,27 +298,23 @@ static void SigChldHandler(int /*signal_number*/) { int saved_errno = errno; while ((pid = waitpid(-1, &status, WNOHANG)) > 0) { - // Log process-death status that we care about. In general it is - // not safe to call LOG(...) from a signal handler because of - // possible reentrancy. However, we know a priori that the - // current implementation of LOG() is safe to call from a SIGCHLD - // handler in the zygote process. If the LOG() implementation - // changes its locking strategy or its use of syscalls within the - // lazy-init critical section, its use here may become unsafe. + // Log process-death status that we care about. if (WIFEXITED(status)) { - ALOGI("Process %d exited cleanly (%d)", pid, WEXITSTATUS(status)); + async_safe_format_log(ANDROID_LOG_INFO, LOG_TAG, + "Process %d exited cleanly (%d)", pid, WEXITSTATUS(status)); } else if (WIFSIGNALED(status)) { - ALOGI("Process %d exited due to signal (%d)", pid, WTERMSIG(status)); - if (WCOREDUMP(status)) { - ALOGI("Process %d dumped core.", pid); - } + async_safe_format_log(ANDROID_LOG_INFO, LOG_TAG, + "Process %d exited due to signal %d (%s)%s", pid, + WTERMSIG(status), strsignal(WTERMSIG(status)), + WCOREDUMP(status) ? "; core dumped" : ""); } // If the just-crashed process is the system_server, bring down zygote // so that it is restarted by init and system server will be restarted // from there. if (pid == gSystemServerPid) { - ALOGE("Exit zygote because system server (%d) has terminated", pid); + async_safe_format_log(ANDROID_LOG_ERROR, LOG_TAG, + "Exit zygote because system server (pid %d) has terminated", pid); kill(getpid(), SIGKILL); } @@ -329,14 +327,17 @@ static void SigChldHandler(int /*signal_number*/) { // Note that we shouldn't consider ECHILD an error because // the secondary zygote might have no children left to wait for. if (pid < 0 && errno != ECHILD) { - ALOGW("Zygote SIGCHLD error in waitpid: %s", strerror(errno)); + async_safe_format_log(ANDROID_LOG_WARN, LOG_TAG, + "Zygote SIGCHLD error in waitpid: %s", strerror(errno)); } if (blastulas_removed > 0) { if (write(gBlastulaPoolEventFD, &blastulas_removed, sizeof(blastulas_removed)) == -1) { // If this write fails something went terribly wrong. We will now kill // the zygote and let the system bring it back up. - ALOGE("Zygote failed to write to blastula pool event FD: %s", strerror(errno)); + async_safe_format_log(ANDROID_LOG_ERROR, LOG_TAG, + "Zygote failed to write to blastula pool event FD: %s", + strerror(errno)); kill(getpid(), SIGKILL); } } @@ -1115,8 +1116,8 @@ static jlong CalculateCapabilities(JNIEnv* env, jint uid, jint gid, jintArray gi RuntimeAbort(env, __LINE__, "Bad gids array"); } - for (int gid_index = gids_num; --gids_num >= 0;) { - if (native_gid_proxy[gid_index] == AID_WAKELOCK) { + for (int gids_index = 0; gids_index < gids_num; ++gids_index) { + if (native_gid_proxy[gids_index] == AID_WAKELOCK) { gid_wakelock_found = true; break; } diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml index 4b247c6a8c4b..78bbcf137f2a 100644 --- a/data/etc/privapp-permissions-platform.xml +++ b/data/etc/privapp-permissions-platform.xml @@ -200,7 +200,7 @@ applications that come with the platform <permission name="android.permission.USE_RESERVED_DISK"/> </privapp-permissions> - <privapp-permissions package="com.android.mainline.networkstack"> + <privapp-permissions package="com.android.networkstack"> <permission name="android.permission.ACCESS_NETWORK_CONDITIONS"/> <permission name="android.permission.CONNECTIVITY_INTERNAL"/> <permission name="android.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS"/> diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreKeyGeneratorSpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreKeyGeneratorSpi.java index aa2917484a05..3dc884eb38ad 100644 --- a/keystore/java/android/security/keystore/AndroidKeyStoreKeyGeneratorSpi.java +++ b/keystore/java/android/security/keystore/AndroidKeyStoreKeyGeneratorSpi.java @@ -17,7 +17,6 @@ package android.security.keystore; import android.security.Credentials; -import android.security.GateKeeper; import android.security.KeyStore; import android.security.keymaster.KeyCharacteristics; import android.security.keymaster.KeymasterArguments; @@ -204,7 +203,12 @@ public abstract class AndroidKeyStoreKeyGeneratorSpi extends KeyGeneratorSpi { } } } - + if (mKeymasterAlgorithm == KeymasterDefs.KM_ALGORITHM_3DES) { + if (mKeySizeBits != 168) { + throw new InvalidAlgorithmParameterException( + "3DES key size must be 168 bits."); + } + } if (mKeymasterAlgorithm == KeymasterDefs.KM_ALGORITHM_HMAC) { if (mKeySizeBits < 64) { throw new InvalidAlgorithmParameterException( diff --git a/media/java/android/media/MediaHTTPConnection.java b/media/java/android/media/MediaHTTPConnection.java index ad25a06fabe2..5f324f7f97ed 100644 --- a/media/java/android/media/MediaHTTPConnection.java +++ b/media/java/android/media/MediaHTTPConnection.java @@ -16,6 +16,8 @@ package android.media; +import static android.media.MediaPlayer.MEDIA_ERROR_UNSUPPORTED; + import android.annotation.UnsupportedAppUsage; import android.net.NetworkUtils; import android.os.IBinder; @@ -23,21 +25,19 @@ import android.os.StrictMode; import android.util.Log; import java.io.BufferedInputStream; -import java.io.InputStream; import java.io.IOException; +import java.io.InputStream; import java.net.CookieHandler; -import java.net.CookieManager; -import java.net.Proxy; -import java.net.URL; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.NoRouteToHostException; import java.net.ProtocolException; +import java.net.Proxy; +import java.net.URL; import java.net.UnknownServiceException; import java.util.HashMap; import java.util.Map; - -import static android.media.MediaPlayer.MEDIA_ERROR_UNSUPPORTED; +import java.util.concurrent.atomic.AtomicBoolean; /** @hide */ public class MediaHTTPConnection extends IMediaHTTPConnection.Stub { @@ -67,6 +67,7 @@ public class MediaHTTPConnection extends IMediaHTTPConnection.Stub { // from com.squareup.okhttp.internal.http private final static int HTTP_TEMP_REDIRECT = 307; private final static int MAX_REDIRECTS = 20; + private AtomicBoolean mIsConnected = new AtomicBoolean(false); @UnsupportedAppUsage public MediaHTTPConnection() { @@ -90,6 +91,7 @@ public class MediaHTTPConnection extends IMediaHTTPConnection.Stub { mAllowCrossDomainRedirect = true; mURL = new URL(uri); mHeaders = convertHeaderStringToMap(headers); + mIsConnected.set(true); } catch (MalformedURLException e) { return null; } @@ -140,7 +142,14 @@ public class MediaHTTPConnection extends IMediaHTTPConnection.Stub { @Override @UnsupportedAppUsage public void disconnect() { - teardownConnection(); + if (mIsConnected.getAndSet(false)) { + (new Thread() { + @Override + public void run() { + teardownConnection(); + } + }).start(); + } mHeaders = null; mURL = null; } @@ -325,7 +334,14 @@ public class MediaHTTPConnection extends IMediaHTTPConnection.Stub { @Override @UnsupportedAppUsage public int readAt(long offset, int size) { - return native_readAt(offset, size); + if (!mIsConnected.get()) { + return -1; + } + int result = native_readAt(offset, size); + if (!mIsConnected.get()) { + return -1; + } + return result; } private int readAt(long offset, byte[] data, int size) { diff --git a/packages/CaptivePortalLogin/Android.bp b/packages/CaptivePortalLogin/Android.bp index 4ac652acb18f..9c31b4d4374f 100644 --- a/packages/CaptivePortalLogin/Android.bp +++ b/packages/CaptivePortalLogin/Android.bp @@ -18,7 +18,7 @@ android_app { name: "CaptivePortalLogin", srcs: ["src/**/*.java"], sdk_version: "system_current", - certificate: "platform", + certificate: "networkstack", static_libs: [ "android-support-v4", "metrics-constants-protos", diff --git a/packages/CaptivePortalLogin/AndroidManifest.xml b/packages/CaptivePortalLogin/AndroidManifest.xml index e15dca046006..0894ee576a2d 100644 --- a/packages/CaptivePortalLogin/AndroidManifest.xml +++ b/packages/CaptivePortalLogin/AndroidManifest.xml @@ -23,8 +23,8 @@ <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> - <uses-permission android:name="android.permission.NETWORK_SETTINGS" /> <uses-permission android:name="android.permission.NETWORK_BYPASS_PRIVATE_DNS" /> + <uses-permission android:name="android.permission.MAINLINE_NETWORK_STACK" /> <application android:label="@string/app_name" android:usesCleartextTraffic="true" diff --git a/packages/NetworkStack/Android.bp b/packages/NetworkStack/Android.bp index d6565936c860..b700bf324817 100644 --- a/packages/NetworkStack/Android.bp +++ b/packages/NetworkStack/Android.bp @@ -35,11 +35,12 @@ java_library { android_app { name: "NetworkStack", sdk_version: "system_current", - certificate: "platform", + certificate: "networkstack", privileged: true, static_libs: [ "NetworkStackLib" ], + jarjar_rules: "jarjar-rules-shared.txt", manifest: "AndroidManifest.xml", required: ["NetworkStackPermissionStub"], }
\ No newline at end of file diff --git a/packages/NetworkStack/AndroidManifest.xml b/packages/NetworkStack/AndroidManifest.xml index 860ebfbf6da7..52c209e5f247 100644 --- a/packages/NetworkStack/AndroidManifest.xml +++ b/packages/NetworkStack/AndroidManifest.xml @@ -17,19 +17,17 @@ */ --> <manifest xmlns:android="http://schemas.android.com/apk/res/android" - package="com.android.mainline.networkstack" + package="com.android.networkstack" android:sharedUserId="android.uid.networkstack"> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <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" /> <!-- Signature permission defined in NetworkStackStub --> <uses-permission android:name="android.permission.MAINLINE_NETWORK_STACK" /> <!-- Send latency broadcast as current user --> <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS" /> - <uses-permission android:name="android.permission.NETWORK_STACK" /> <uses-permission android:name="android.permission.WAKE_LOCK" /> <uses-permission android:name="android.permission.READ_PRIVILEGED_PHONE_STATE" /> <application diff --git a/packages/NetworkStack/jarjar-rules-shared.txt b/packages/NetworkStack/jarjar-rules-shared.txt new file mode 100644 index 000000000000..a8c712a3336d --- /dev/null +++ b/packages/NetworkStack/jarjar-rules-shared.txt @@ -0,0 +1,19 @@ +rule com.android.internal.util.** android.net.networkstack.util.@1 + +rule android.net.shared.Inet4AddressUtils* android.net.networkstack.shared.Inet4AddressUtils@1 +rule android.net.shared.InetAddressUtils* android.net.networkstack.shared.InetAddressUtils@1 + +# Ignore DhcpResultsParcelable, but jarjar DhcpResults +# TODO: move DhcpResults into services.net and delete from here +rule android.net.DhcpResultsParcelable* @0 +rule android.net.DhcpResults* android.net.networkstack.DhcpResults@1 +rule android.net.LocalLog* android.net.networkstack.LocalLog@1 + +# TODO: remove from framework dependencies, then remove here +rule android.net.InterfaceConfigurationParcel* android.net.networkstack.InterfaceConfigurationParcel@1 +rule android.net.TetherStatsParcel* android.net.networkstack.TetherStatsParcel@1 + +# Used by UidRange, which is used by framework classes such as NetworkCapabilities. +rule android.net.UidRangeParcel* android.net.networkstack.UidRangeParcel@1 +# TODO: move TcpKeepalivePacketData to services.net and delete +rule android.net.TcpKeepalivePacketDataParcelable* android.net.networkstack.TcpKeepalivePacketDataParcelable@1
\ No newline at end of file diff --git a/packages/NetworkStack/src/android/net/dhcp/DhcpPacketListener.java b/packages/NetworkStack/src/android/net/dhcp/DhcpPacketListener.java index 96d1a287ef09..97d26c7c9c1f 100644 --- a/packages/NetworkStack/src/android/net/dhcp/DhcpPacketListener.java +++ b/packages/NetworkStack/src/android/net/dhcp/DhcpPacketListener.java @@ -18,7 +18,7 @@ package android.net.dhcp; import android.annotation.NonNull; import android.annotation.Nullable; -import android.net.shared.FdEventsReader; +import android.net.util.FdEventsReader; import android.os.Handler; import android.system.Os; diff --git a/core/java/android/net/shared/FdEventsReader.java b/packages/NetworkStack/src/android/net/util/FdEventsReader.java index bffbfb115886..1380ea720d40 100644 --- a/core/java/android/net/shared/FdEventsReader.java +++ b/packages/NetworkStack/src/android/net/util/FdEventsReader.java @@ -14,14 +14,13 @@ * limitations under the License. */ -package android.net.shared; +package android.net.util; import static android.os.MessageQueue.OnFileDescriptorEventListener.EVENT_ERROR; import static android.os.MessageQueue.OnFileDescriptorEventListener.EVENT_INPUT; import android.annotation.NonNull; import android.annotation.Nullable; -import android.net.util.SocketUtils; import android.os.Handler; import android.os.Looper; import android.os.MessageQueue; diff --git a/packages/NetworkStack/src/android/net/util/PacketReader.java b/packages/NetworkStack/src/android/net/util/PacketReader.java index 94b1e9f2e14e..4aec6b6753a6 100644 --- a/packages/NetworkStack/src/android/net/util/PacketReader.java +++ b/packages/NetworkStack/src/android/net/util/PacketReader.java @@ -18,7 +18,6 @@ package android.net.util; import static java.lang.Math.max; -import android.net.shared.FdEventsReader; import android.os.Handler; import android.system.Os; diff --git a/packages/NetworkStackPermissionStub/Android.bp b/packages/NetworkStackPermissionStub/Android.bp index 94870c919dfa..dd70cf56b51b 100644 --- a/packages/NetworkStackPermissionStub/Android.bp +++ b/packages/NetworkStackPermissionStub/Android.bp @@ -21,7 +21,7 @@ android_app { // a classes.dex. srcs: ["src/**/*.java"], platform_apis: true, - certificate: "platform", + certificate: "networkstack", privileged: true, manifest: "AndroidManifest.xml", } diff --git a/packages/NetworkStackPermissionStub/AndroidManifest.xml b/packages/NetworkStackPermissionStub/AndroidManifest.xml index 2ccf5ff1a01a..a8742d7ab34f 100644 --- a/packages/NetworkStackPermissionStub/AndroidManifest.xml +++ b/packages/NetworkStackPermissionStub/AndroidManifest.xml @@ -17,7 +17,8 @@ */ --> <manifest xmlns:android="http://schemas.android.com/apk/res/android" - package="com.android.mainline.networkstack.permissionstub"> + package="com.android.networkstack.permissionstub" + android:sharedUserId="android.uid.networkstack"> <!-- This package only exists to define the below permissions, and enforce that they are only granted to apps sharing the same signature. diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index eec93808421a..b5fcde4bf203 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -87,6 +87,7 @@ import android.net.NetworkQuotaInfo; import android.net.NetworkRequest; import android.net.NetworkSpecifier; import android.net.NetworkStack; +import android.net.NetworkStackClient; import android.net.NetworkState; import android.net.NetworkUtils; import android.net.NetworkWatchlistManager; @@ -918,7 +919,8 @@ public class ConnectivityService extends IConnectivityManager.Stub mPermissionMonitor = new PermissionMonitor(mContext, mNMS); - //set up the listener for user state for creating user VPNs + // Set up the listener for user state for creating user VPNs. + // Should run on mHandler to avoid any races. IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction(Intent.ACTION_USER_STARTED); intentFilter.addAction(Intent.ACTION_USER_STOPPED); @@ -926,7 +928,11 @@ public class ConnectivityService extends IConnectivityManager.Stub intentFilter.addAction(Intent.ACTION_USER_REMOVED); intentFilter.addAction(Intent.ACTION_USER_UNLOCKED); mContext.registerReceiverAsUser( - mIntentReceiver, UserHandle.ALL, intentFilter, null, null); + mIntentReceiver, + UserHandle.ALL, + intentFilter, + null /* broadcastPermission */, + mHandler); mContext.registerReceiverAsUser(mUserPresentReceiver, UserHandle.SYSTEM, new IntentFilter(Intent.ACTION_USER_PRESENT), null, null); @@ -937,7 +943,11 @@ public class ConnectivityService extends IConnectivityManager.Stub intentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED); intentFilter.addDataScheme("package"); mContext.registerReceiverAsUser( - mIntentReceiver, UserHandle.ALL, intentFilter, null, null); + mIntentReceiver, + UserHandle.ALL, + intentFilter, + null /* broadcastPermission */, + mHandler); try { mNMS.registerObserver(mTethering); @@ -4127,17 +4137,27 @@ public class ConnectivityService extends IConnectivityManager.Stub * handler thread through their agent, this is asynchronous. When the capabilities objects * are computed they will be up-to-date as they are computed synchronously from here and * this is running on the ConnectivityService thread. - * TODO : Fix this and call updateCapabilities inline to remove out-of-order events. */ private void updateAllVpnsCapabilities() { + Network defaultNetwork = getNetwork(getDefaultNetwork()); synchronized (mVpns) { for (int i = 0; i < mVpns.size(); i++) { final Vpn vpn = mVpns.valueAt(i); - vpn.updateCapabilities(); + NetworkCapabilities nc = vpn.updateCapabilities(defaultNetwork); + updateVpnCapabilities(vpn, nc); } } } + private void updateVpnCapabilities(Vpn vpn, @Nullable NetworkCapabilities nc) { + ensureRunningOnConnectivityServiceThread(); + NetworkAgentInfo vpnNai = getNetworkAgentInfoForNetId(vpn.getNetId()); + if (vpnNai == null || nc == null) { + return; + } + updateCapabilities(vpnNai.getCurrentScore(), vpnNai, nc); + } + @Override public boolean updateLockdownVpn() { if (Binder.getCallingUid() != Process.SYSTEM_UID) { @@ -4478,22 +4498,28 @@ public class ConnectivityService extends IConnectivityManager.Stub private void onUserAdded(int userId) { mPermissionMonitor.onUserAdded(userId); + Network defaultNetwork = getNetwork(getDefaultNetwork()); synchronized (mVpns) { final int vpnsSize = mVpns.size(); for (int i = 0; i < vpnsSize; i++) { Vpn vpn = mVpns.valueAt(i); vpn.onUserAdded(userId); + NetworkCapabilities nc = vpn.updateCapabilities(defaultNetwork); + updateVpnCapabilities(vpn, nc); } } } private void onUserRemoved(int userId) { mPermissionMonitor.onUserRemoved(userId); + Network defaultNetwork = getNetwork(getDefaultNetwork()); synchronized (mVpns) { final int vpnsSize = mVpns.size(); for (int i = 0; i < vpnsSize; i++) { Vpn vpn = mVpns.valueAt(i); vpn.onUserRemoved(userId); + NetworkCapabilities nc = vpn.updateCapabilities(defaultNetwork); + updateVpnCapabilities(vpn, nc); } } } @@ -4562,6 +4588,7 @@ public class ConnectivityService extends IConnectivityManager.Stub private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { + ensureRunningOnConnectivityServiceThread(); final String action = intent.getAction(); final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL); final int uid = intent.getIntExtra(Intent.EXTRA_UID, -1); @@ -5066,6 +5093,19 @@ public class ConnectivityService extends IConnectivityManager.Stub return getNetworkForRequest(mDefaultRequest.requestId); } + @Nullable + private Network getNetwork(@Nullable NetworkAgentInfo nai) { + return nai != null ? nai.network : null; + } + + private void ensureRunningOnConnectivityServiceThread() { + if (mHandler.getLooper().getThread() != Thread.currentThread()) { + throw new IllegalStateException( + "Not running on ConnectivityService thread: " + + Thread.currentThread().getName()); + } + } + private boolean isDefaultNetwork(NetworkAgentInfo nai) { return nai == getDefaultNetwork(); } @@ -5095,7 +5135,7 @@ public class ConnectivityService extends IConnectivityManager.Stub if (DBG) log("registerNetworkAgent " + nai); final long token = Binder.clearCallingIdentity(); try { - mContext.getSystemService(NetworkStack.class).makeNetworkMonitor( + getNetworkStack().makeNetworkMonitor( toStableParcelable(nai.network), name, new NetworkMonitorCallbacks(nai)); } finally { Binder.restoreCallingIdentity(token); @@ -5107,6 +5147,11 @@ public class ConnectivityService extends IConnectivityManager.Stub return nai.network.netId; } + @VisibleForTesting + protected NetworkStackClient getNetworkStack() { + return NetworkStackClient.getInstance(); + } + private void handleRegisterNetworkAgent(NetworkAgentInfo nai, INetworkMonitor networkMonitor) { nai.onNetworkMonitorCreated(networkMonitor); if (VDBG) log("Got NetworkAgent Messenger"); @@ -5659,6 +5704,8 @@ public class ConnectivityService extends IConnectivityManager.Stub updateTcpBufferSizes(newNetwork.linkProperties.getTcpBufferSizes()); mDnsManager.setDefaultDnsSystemProperties(newNetwork.linkProperties.getDnsServers()); notifyIfacesChangedForNetworkStats(); + // Fix up the NetworkCapabilities of any VPNs that don't specify underlying networks. + updateAllVpnsCapabilities(); } private void processListenRequests(NetworkAgentInfo nai, boolean capabilitiesChanged) { @@ -6098,6 +6145,10 @@ public class ConnectivityService extends IConnectivityManager.Stub // doing. updateSignalStrengthThresholds(networkAgent, "CONNECT", null); + if (networkAgent.isVPN()) { + updateAllVpnsCapabilities(); + } + // Consider network even though it is not yet validated. final long now = SystemClock.elapsedRealtime(); rematchNetworkAndRequests(networkAgent, ReapUnvalidatedNetworks.REAP, now); @@ -6359,7 +6410,11 @@ public class ConnectivityService extends IConnectivityManager.Stub success = mVpns.get(user).setUnderlyingNetworks(networks); } if (success) { - mHandler.post(() -> notifyIfacesChangedForNetworkStats()); + mHandler.post(() -> { + // Update VPN's capabilities based on updated underlying network set. + updateAllVpnsCapabilities(); + notifyIfacesChangedForNetworkStats(); + }); } return success; } diff --git a/services/core/java/com/android/server/connectivity/Tethering.java b/services/core/java/com/android/server/connectivity/Tethering.java index 19bdc0969e6d..c91e1a12078e 100644 --- a/services/core/java/com/android/server/connectivity/Tethering.java +++ b/services/core/java/com/android/server/connectivity/Tethering.java @@ -1859,7 +1859,7 @@ public class Tethering extends BaseNetworkObserver { final TetherState tetherState = new TetherState( new IpServer(iface, mLooper, interfaceType, mLog, mNMService, mStatsService, makeControlCallback(), mConfig.enableLegacyDhcpServer, - mDeps.getIpServerDependencies(mContext))); + mDeps.getIpServerDependencies())); mTetherStates.put(iface, tetherState); tetherState.ipServer.start(); } diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java index 9141ccb387bd..a7d16d8cd6ec 100644 --- a/services/core/java/com/android/server/connectivity/Vpn.java +++ b/services/core/java/com/android/server/connectivity/Vpn.java @@ -240,7 +240,7 @@ public class Vpn { mNetworkCapabilities = new NetworkCapabilities(); mNetworkCapabilities.addTransportType(NetworkCapabilities.TRANSPORT_VPN); mNetworkCapabilities.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN); - updateCapabilities(); + updateCapabilities(null /* defaultNetwork */); loadAlwaysOnPackage(); } @@ -267,22 +267,44 @@ public class Vpn { updateAlwaysOnNotification(detailedState); } - public void updateCapabilities() { - final Network[] underlyingNetworks = (mConfig != null) ? mConfig.underlyingNetworks : null; - // Only apps targeting Q and above can explicitly declare themselves as metered. - final boolean isAlwaysMetered = - mIsPackageTargetingAtLeastQ && (mConfig == null || mConfig.isMetered); - updateCapabilities(mContext.getSystemService(ConnectivityManager.class), underlyingNetworks, - mNetworkCapabilities, isAlwaysMetered); + /** + * Updates {@link #mNetworkCapabilities} based on current underlying networks and returns a + * defensive copy. + * + * <p>Does not propagate updated capabilities to apps. + * + * @param defaultNetwork underlying network for VPNs following platform's default + */ + public synchronized NetworkCapabilities updateCapabilities( + @Nullable Network defaultNetwork) { + if (mConfig == null) { + // VPN is not running. + return null; + } - if (mNetworkAgent != null) { - mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities); + Network[] underlyingNetworks = mConfig.underlyingNetworks; + if (underlyingNetworks == null && defaultNetwork != null) { + // null underlying networks means to track the default. + underlyingNetworks = new Network[] { defaultNetwork }; } + // Only apps targeting Q and above can explicitly declare themselves as metered. + final boolean isAlwaysMetered = mIsPackageTargetingAtLeastQ && mConfig.isMetered; + + applyUnderlyingCapabilities( + mContext.getSystemService(ConnectivityManager.class), + underlyingNetworks, + mNetworkCapabilities, + isAlwaysMetered); + + return new NetworkCapabilities(mNetworkCapabilities); } @VisibleForTesting - public static void updateCapabilities(ConnectivityManager cm, Network[] underlyingNetworks, - NetworkCapabilities caps, boolean isAlwaysMetered) { + public static void applyUnderlyingCapabilities( + ConnectivityManager cm, + Network[] underlyingNetworks, + NetworkCapabilities caps, + boolean isAlwaysMetered) { int[] transportTypes = new int[] { NetworkCapabilities.TRANSPORT_VPN }; int downKbps = NetworkCapabilities.LINK_BANDWIDTH_UNSPECIFIED; int upKbps = NetworkCapabilities.LINK_BANDWIDTH_UNSPECIFIED; @@ -295,6 +317,7 @@ public class Vpn { boolean hadUnderlyingNetworks = false; if (null != underlyingNetworks) { for (Network underlying : underlyingNetworks) { + // TODO(b/124469351): Get capabilities directly from ConnectivityService instead. final NetworkCapabilities underlyingCaps = cm.getNetworkCapabilities(underlying); if (underlyingCaps == null) continue; hadUnderlyingNetworks = true; @@ -1005,9 +1028,8 @@ public class Vpn { } /** - * Establish a VPN network and return the file descriptor of the VPN - * interface. This methods returns {@code null} if the application is - * revoked or not prepared. + * Establish a VPN network and return the file descriptor of the VPN interface. This methods + * returns {@code null} if the application is revoked or not prepared. * * @param config The parameters to configure the network. * @return The file descriptor of the VPN interface. @@ -1099,8 +1121,6 @@ public class Vpn { // as rules are deleted. This prevents data leakage as the rules are moved over. agentDisconnect(oldNetworkAgent); } - // Set up VPN's capabilities such as meteredness. - updateCapabilities(); if (oldConnection != null) { mContext.unbindService(oldConnection); @@ -1256,6 +1276,11 @@ public class Vpn { return ranges; } + /** + * Updates UID ranges for this VPN and also updates its internal capabilities. + * + * <p>Should be called on primary ConnectivityService thread. + */ public void onUserAdded(int userHandle) { // If the user is restricted tie them to the parent user's VPN UserInfo user = UserManager.get(mContext).getUserInfo(userHandle); @@ -1266,8 +1291,9 @@ public class Vpn { try { addUserToRanges(existingRanges, userHandle, mConfig.allowedApplications, mConfig.disallowedApplications); + // ConnectivityService will call {@link #updateCapabilities} and apply + // those for VPN network. mNetworkCapabilities.setUids(existingRanges); - updateCapabilities(); } catch (Exception e) { Log.wtf(TAG, "Failed to add restricted user to owner", e); } @@ -1277,6 +1303,11 @@ public class Vpn { } } + /** + * Updates UID ranges for this VPN and also updates its capabilities. + * + * <p>Should be called on primary ConnectivityService thread. + */ public void onUserRemoved(int userHandle) { // clean up if restricted UserInfo user = UserManager.get(mContext).getUserInfo(userHandle); @@ -1288,8 +1319,9 @@ public class Vpn { final List<UidRange> removedRanges = uidRangesForUser(userHandle, existingRanges); existingRanges.removeAll(removedRanges); + // ConnectivityService will call {@link #updateCapabilities} and + // apply those for VPN network. mNetworkCapabilities.setUids(existingRanges); - updateCapabilities(); } catch (Exception e) { Log.wtf(TAG, "Failed to remove restricted user to owner", e); } @@ -1502,6 +1534,12 @@ public class Vpn { return success; } + /** + * Updates underlying network set. + * + * <p>Note: Does not updates capabilities. Call {@link #updateCapabilities} from + * ConnectivityService thread to get updated capabilities. + */ public synchronized boolean setUnderlyingNetworks(Network[] networks) { if (!isCallerEstablishedOwnerLocked()) { return false; @@ -1518,7 +1556,6 @@ public class Vpn { } } } - updateCapabilities(); return true; } diff --git a/services/core/java/com/android/server/connectivity/tethering/TetheringDependencies.java b/services/core/java/com/android/server/connectivity/tethering/TetheringDependencies.java index 3fddac111ec5..173d7860e4ac 100644 --- a/services/core/java/com/android/server/connectivity/tethering/TetheringDependencies.java +++ b/services/core/java/com/android/server/connectivity/tethering/TetheringDependencies.java @@ -61,8 +61,8 @@ public class TetheringDependencies { /** * Get dependencies to be used by IpServer. */ - public IpServer.Dependencies getIpServerDependencies(Context context) { - return new IpServer.Dependencies(context); + public IpServer.Dependencies getIpServerDependencies() { + return new IpServer.Dependencies(); } /** diff --git a/services/core/java/com/android/server/om/OverlayManagerService.java b/services/core/java/com/android/server/om/OverlayManagerService.java index f1b03d1fc9d6..81d6b63d9d85 100644 --- a/services/core/java/com/android/server/om/OverlayManagerService.java +++ b/services/core/java/com/android/server/om/OverlayManagerService.java @@ -344,6 +344,11 @@ public final class OverlayManagerService extends SystemService { private final class PackageReceiver extends BroadcastReceiver { @Override public void onReceive(@NonNull final Context context, @NonNull final Intent intent) { + final String action = intent.getAction(); + if (action == null) { + Slog.e(TAG, "Cannot handle package broadcast with null action"); + return; + } final Uri data = intent.getData(); if (data == null) { Slog.e(TAG, "Cannot handle package broadcast with null data"); @@ -361,7 +366,7 @@ public final class OverlayManagerService extends SystemService { userIds = new int[] { UserHandle.getUserId(extraUid) }; } - switch (intent.getAction()) { + switch (action) { case ACTION_PACKAGE_ADDED: if (replacing) { onPackageUpgraded(packageName, userIds); diff --git a/services/core/java/com/android/server/pm/OWNERS b/services/core/java/com/android/server/pm/OWNERS index 33b8641c145e..640b155e69d5 100644 --- a/services/core/java/com/android/server/pm/OWNERS +++ b/services/core/java/com/android/server/pm/OWNERS @@ -19,6 +19,9 @@ per-file BackgroundDexOptService.java = ngeoffray@google.com per-file CompilerStats.java = agampe@google.com per-file CompilerStats.java = calin@google.com per-file CompilerStats.java = ngeoffray@google.com +per-file DynamicCodeLoggingService.java = agampe@google.com +per-file DynamicCodeLoggingService.java = calin@google.com +per-file DynamicCodeLoggingService.java = ngeoffray@google.com per-file InstructionSets.java = agampe@google.com per-file InstructionSets.java = calin@google.com per-file InstructionSets.java = ngeoffray@google.com diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index 2338fffbf26a..406822c774ca 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -37,6 +37,7 @@ import android.content.res.Resources.Theme; import android.database.sqlite.SQLiteCompatibilityWalFlags; import android.database.sqlite.SQLiteGlobal; import android.hardware.display.DisplayManagerInternal; +import android.net.NetworkStackClient; import android.os.BaseBundle; import android.os.Binder; import android.os.Build; @@ -1240,9 +1241,7 @@ public final class SystemServer { traceBeginAndSlog("StartNetworkStack"); try { - final android.net.NetworkStack networkStack = - context.getSystemService(android.net.NetworkStack.class); - networkStack.start(context); + NetworkStackClient.getInstance().start(context); } catch (Throwable e) { reportWtf("starting Network Stack", e); } diff --git a/services/net/Android.bp b/services/net/Android.bp index 9946cc3db0e8..8ad4d7679107 100644 --- a/services/net/Android.bp +++ b/services/net/Android.bp @@ -3,6 +3,7 @@ java_library_static { srcs: ["java/**/*.java"], static_libs: [ "netd_aidl_interface-java", + "networkstack-aidl-interfaces-java", ] } diff --git a/services/net/java/android/net/NetworkStackClient.java b/services/net/java/android/net/NetworkStackClient.java new file mode 100644 index 000000000000..1eb7b98d801a --- /dev/null +++ b/services/net/java/android/net/NetworkStackClient.java @@ -0,0 +1,289 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package android.net; + +import static android.content.pm.PackageManager.PERMISSION_GRANTED; +import static android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK; +import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_HIGH; +import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_NORMAL; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.ServiceConnection; +import android.content.pm.PackageManager; +import android.net.dhcp.DhcpServingParamsParcel; +import android.net.dhcp.IDhcpServerCallbacks; +import android.net.ip.IIpClientCallbacks; +import android.os.Binder; +import android.os.IBinder; +import android.os.Process; +import android.os.RemoteException; +import android.os.ServiceManager; +import android.os.UserHandle; +import android.util.Slog; + +import com.android.internal.annotations.GuardedBy; + +import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; + +/** + * Service used to communicate with the network stack, which is running in a separate module. + * @hide + */ +public class NetworkStackClient { + private static final String TAG = NetworkStackClient.class.getSimpleName(); + + private static final int NETWORKSTACK_TIMEOUT_MS = 10_000; + + private static NetworkStackClient sInstance; + + @NonNull + @GuardedBy("mPendingNetStackRequests") + private final ArrayList<NetworkStackCallback> mPendingNetStackRequests = new ArrayList<>(); + @Nullable + @GuardedBy("mPendingNetStackRequests") + private INetworkStackConnector mConnector; + + private volatile boolean mNetworkStackStartRequested = false; + + private interface NetworkStackCallback { + void onNetworkStackConnected(INetworkStackConnector connector); + } + + private NetworkStackClient() { } + + /** + * Get the NetworkStackClient singleton instance. + */ + public static synchronized NetworkStackClient getInstance() { + if (sInstance == null) { + sInstance = new NetworkStackClient(); + } + return sInstance; + } + + /** + * Create a DHCP server according to the specified parameters. + * + * <p>The server will be returned asynchronously through the provided callbacks. + */ + public void makeDhcpServer(final String ifName, final DhcpServingParamsParcel params, + final IDhcpServerCallbacks cb) { + requestConnector(connector -> { + try { + connector.makeDhcpServer(ifName, params, cb); + } catch (RemoteException e) { + e.rethrowFromSystemServer(); + } + }); + } + + /** + * Create an IpClient on the specified interface. + * + * <p>The IpClient will be returned asynchronously through the provided callbacks. + */ + public void makeIpClient(String ifName, IIpClientCallbacks cb) { + requestConnector(connector -> { + try { + connector.makeIpClient(ifName, cb); + } catch (RemoteException e) { + e.rethrowFromSystemServer(); + } + }); + } + + /** + * Create a NetworkMonitor. + * + * <p>The INetworkMonitor will be returned asynchronously through the provided callbacks. + */ + public void makeNetworkMonitor( + NetworkParcelable network, String name, INetworkMonitorCallbacks cb) { + requestConnector(connector -> { + try { + connector.makeNetworkMonitor(network, name, cb); + } catch (RemoteException e) { + e.rethrowFromSystemServer(); + } + }); + } + + private class NetworkStackConnection implements ServiceConnection { + @Override + public void onServiceConnected(ComponentName name, IBinder service) { + registerNetworkStackService(service); + } + + @Override + public void onServiceDisconnected(ComponentName name) { + // TODO: crash/reboot the system ? + Slog.wtf(TAG, "Lost network stack connector"); + } + }; + + private void registerNetworkStackService(@NonNull IBinder service) { + final INetworkStackConnector connector = INetworkStackConnector.Stub.asInterface(service); + + ServiceManager.addService(Context.NETWORK_STACK_SERVICE, service, false /* allowIsolated */, + DUMP_FLAG_PRIORITY_HIGH | DUMP_FLAG_PRIORITY_NORMAL); + + final ArrayList<NetworkStackCallback> requests; + synchronized (mPendingNetStackRequests) { + requests = new ArrayList<>(mPendingNetStackRequests); + mPendingNetStackRequests.clear(); + mConnector = connector; + } + + for (NetworkStackCallback r : requests) { + r.onNetworkStackConnected(connector); + } + } + + /** + * Start the network stack. Should be called only once on device startup. + * + * <p>This method will start the network stack either in the network stack process, or inside + * the system server on devices that do not support the network stack module. The network stack + * connector will then be delivered asynchronously to clients that requested it before it was + * started. + */ + public void start(Context context) { + mNetworkStackStartRequested = true; + // Try to bind in-process if the library is available + IBinder connector = null; + try { + final Class service = Class.forName( + "com.android.server.NetworkStackService", + true /* initialize */, + context.getClassLoader()); + 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 ? + return; + } catch (ClassNotFoundException e) { + // Normal behavior if stack is provided by the app: fall through + } + + // In-process network stack. Add the service to the service manager here. + if (connector != null) { + registerNetworkStackService(connector); + return; + } + // Start the network stack process. The service will be added to the service manager in + // NetworkStackConnection.onServiceConnected(). + final Intent intent = new Intent(INetworkStackConnector.class.getName()); + final ComponentName comp = intent.resolveSystemService(context.getPackageManager(), 0); + intent.setComponent(comp); + + if (comp == null) { + Slog.wtf(TAG, "Could not resolve the network stack with " + intent); + // TODO: crash/reboot system server ? + return; + } + final PackageManager pm = context.getPackageManager(); + int uid = -1; + try { + uid = pm.getPackageUid(comp.getPackageName(), UserHandle.USER_SYSTEM); + } catch (PackageManager.NameNotFoundException e) { + Slog.wtf("Network stack package not found", e); + // Fall through + } + if (uid != Process.NETWORK_STACK_UID) { + throw new SecurityException("Invalid network stack UID: " + uid); + } + + final int hasPermission = + pm.checkPermission(PERMISSION_MAINLINE_NETWORK_STACK, comp.getPackageName()); + if (hasPermission != PERMISSION_GRANTED) { + throw new SecurityException( + "Network stack does not have permission " + PERMISSION_MAINLINE_NETWORK_STACK); + } + + if (!context.bindServiceAsUser(intent, new NetworkStackConnection(), + Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT, UserHandle.SYSTEM)) { + Slog.wtf(TAG, + "Could not bind to network stack in-process, or in app with " + intent); + // TODO: crash/reboot system server if no network stack after a timeout ? + } + } + + /** + * For non-system server clients, get the connector registered by the system server. + */ + private INetworkStackConnector getRemoteConnector() { + // Block until the NetworkStack connector is registered in ServiceManager. + // <p>This is only useful for non-system processes that do not have a way to be notified of + // registration completion. Adding a callback system would be too heavy weight considering + // that the connector is registered on boot, so it is unlikely that a client would request + // it before it is registered. + // TODO: consider blocking boot on registration and simplify much of the logic in this class + IBinder connector; + try { + final long before = System.currentTimeMillis(); + while ((connector = ServiceManager.getService(Context.NETWORK_STACK_SERVICE)) == null) { + Thread.sleep(20); + if (System.currentTimeMillis() - before > NETWORKSTACK_TIMEOUT_MS) { + Slog.e(TAG, "Timeout waiting for NetworkStack connector"); + return null; + } + } + } catch (InterruptedException e) { + Slog.e(TAG, "Error waiting for NetworkStack connector", e); + return null; + } + + return INetworkStackConnector.Stub.asInterface(connector); + } + + private void requestConnector(@NonNull NetworkStackCallback request) { + // TODO: PID check. + final int caller = Binder.getCallingUid(); + if (caller != Process.SYSTEM_UID && !UserHandle.isSameApp(caller, Process.BLUETOOTH_UID)) { + // Don't even attempt to obtain the connector and give a nice error message + throw new SecurityException( + "Only the system server should try to bind to the network stack."); + } + + if (!mNetworkStackStartRequested) { + // The network stack is not being started in this process, e.g. this process is not + // the system server. Get a remote connector registered by the system server. + final INetworkStackConnector connector = getRemoteConnector(); + synchronized (mPendingNetStackRequests) { + mConnector = connector; + } + request.onNetworkStackConnected(connector); + return; + } + + final INetworkStackConnector connector; + synchronized (mPendingNetStackRequests) { + connector = mConnector; + if (connector == null) { + mPendingNetStackRequests.add(request); + return; + } + } + + request.onNetworkStackConnected(connector); + } +} diff --git a/core/java/android/net/dhcp/DhcpServerCallbacks.java b/services/net/java/android/net/dhcp/DhcpServerCallbacks.java index bb56876c77f5..bb56876c77f5 100644 --- a/core/java/android/net/dhcp/DhcpServerCallbacks.java +++ b/services/net/java/android/net/dhcp/DhcpServerCallbacks.java diff --git a/core/java/android/net/ip/IpClientCallbacks.java b/services/net/java/android/net/ip/IpClientCallbacks.java index db01ae4d4d9c..db01ae4d4d9c 100644 --- a/core/java/android/net/ip/IpClientCallbacks.java +++ b/services/net/java/android/net/ip/IpClientCallbacks.java diff --git a/services/net/java/android/net/ip/IpClientUtil.java b/services/net/java/android/net/ip/IpClientUtil.java index 2a2a67a92a86..bf917bf88b2d 100644 --- a/services/net/java/android/net/ip/IpClientUtil.java +++ b/services/net/java/android/net/ip/IpClientUtil.java @@ -23,8 +23,7 @@ import android.content.Context; import android.net.DhcpResultsParcelable; import android.net.LinkProperties; import android.net.LinkPropertiesParcelable; -import android.net.NetworkStack; -import android.net.ip.IIpClientCallbacks; +import android.net.NetworkStackClient; import android.os.ConditionVariable; import java.io.FileDescriptor; @@ -76,30 +75,17 @@ public class IpClientUtil { * * <p>This is a convenience method to allow clients to use {@link IpClientCallbacks} instead of * {@link IIpClientCallbacks}. - * @see {@link NetworkStack#makeIpClient(String, IIpClientCallbacks)} + * @see {@link NetworkStackClient#makeIpClient(String, IIpClientCallbacks)} */ public static void makeIpClient(Context context, String ifName, IpClientCallbacks callback) { - context.getSystemService(NetworkStack.class) - .makeIpClient(ifName, new IpClientCallbacksProxy(callback)); - } - - /** - * Create a new IpClient. - * - * <p>This is a convenience method to allow clients to use {@link IpClientCallbacksProxy} - * instead of {@link IIpClientCallbacks}. - * @see {@link NetworkStack#makeIpClient(String, IIpClientCallbacks)} - */ - public static void makeIpClient( - Context context, String ifName, IpClientCallbacksProxy callback) { - context.getSystemService(NetworkStack.class) - .makeIpClient(ifName, callback); + // TODO: migrate clients and remove context argument + NetworkStackClient.getInstance().makeIpClient(ifName, new IpClientCallbacksProxy(callback)); } /** * Wrapper to relay calls from {@link IIpClientCallbacks} to {@link IpClientCallbacks}. */ - public static class IpClientCallbacksProxy extends IIpClientCallbacks.Stub { + private static class IpClientCallbacksProxy extends IIpClientCallbacks.Stub { protected final IpClientCallbacks mCb; /** diff --git a/services/net/java/android/net/ip/IpServer.java b/services/net/java/android/net/ip/IpServer.java index 7910c9a69310..34fc7354d63e 100644 --- a/services/net/java/android/net/ip/IpServer.java +++ b/services/net/java/android/net/ip/IpServer.java @@ -22,7 +22,6 @@ import static android.net.util.NetworkConstants.FF; import static android.net.util.NetworkConstants.RFC7421_PREFIX_LENGTH; import static android.net.util.NetworkConstants.asByte; -import android.content.Context; import android.net.ConnectivityManager; import android.net.INetd; import android.net.INetworkStackStatusCallback; @@ -31,7 +30,7 @@ import android.net.InterfaceConfiguration; import android.net.IpPrefix; import android.net.LinkAddress; import android.net.LinkProperties; -import android.net.NetworkStack; +import android.net.NetworkStackClient; import android.net.RouteInfo; import android.net.dhcp.DhcpServerCallbacks; import android.net.dhcp.DhcpServingParamsParcel; @@ -132,10 +131,6 @@ public class IpServer extends StateMachine { } public static class Dependencies { - private final Context mContext; - public Dependencies(Context context) { - mContext = context; - } public RouterAdvertisementDaemon getRouterAdvertisementDaemon(InterfaceParams ifParams) { return new RouterAdvertisementDaemon(ifParams); } @@ -153,7 +148,7 @@ public class IpServer extends StateMachine { */ public void makeDhcpServer(String ifName, DhcpServingParamsParcel params, DhcpServerCallbacks cb) { - mContext.getSystemService(NetworkStack.class).makeDhcpServer(ifName, params, cb); + NetworkStackClient.getInstance().makeDhcpServer(ifName, params, cb); } } diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java index 268e70fe5d12..c60eb56005eb 100644 --- a/telecomm/java/android/telecom/TelecomManager.java +++ b/telecomm/java/android/telecom/TelecomManager.java @@ -289,6 +289,19 @@ public class TelecomManager { "android.telecom.extra.OUTGOING_CALL_EXTRAS"; /** + * An optional boolean extra on {@link android.content.Intent#ACTION_CALL_EMERGENCY} to tell + * whether the user's dial intent is emergency; this is required to specify when the dialed + * number is ambiguous, identified as both emergency number and any other non-emergency number; + * e.g. in some situation, 611 could be both an emergency number in a country and a + * non-emergency number of a carrier's customer service hotline. + * + * @hide + */ + @SystemApi + public static final String EXTRA_IS_USER_INTENT_EMERGENCY_CALL = + "android.telecom.extra.IS_USER_INTENT_EMERGENCY_CALL"; + + /** * @hide */ public static final String EXTRA_UNKNOWN_CALL_HANDLE = diff --git a/telephony/java/android/provider/Telephony.java b/telephony/java/android/provider/Telephony.java index 51c8f65a6c9d..50b8f79892fd 100644 --- a/telephony/java/android/provider/Telephony.java +++ b/telephony/java/android/provider/Telephony.java @@ -2059,6 +2059,11 @@ public final class Telephony { * @hide - not meant for public use */ public interface RcsColumns { + // TODO(sahinc): Turn this to true once the schema finalizes, so that people can update + // their messaging databases. NOTE: move the switch/case update in MmsSmsDatabaseHelper to + // the latest version of the database before turning this flag to true. + boolean IS_RCS_TABLE_SCHEMA_CODE_COMPLETE = false; + /** * The authority for the content provider */ diff --git a/telephony/java/android/telephony/ims/ImsCallProfile.java b/telephony/java/android/telephony/ims/ImsCallProfile.java index 59167b7d5bba..73f055649b3f 100644 --- a/telephony/java/android/telephony/ims/ImsCallProfile.java +++ b/telephony/java/android/telephony/ims/ImsCallProfile.java @@ -350,6 +350,9 @@ public final class ImsCallProfile implements Parcelable { /** Indicates if the call is for testing purpose */ private boolean mEmergencyCallTesting = false; + /** Indicates if we have known the intent of the user for the call is emergency */ + private boolean mHasKnownUserIntentEmergency = false; + /** * Extras associated with this {@link ImsCallProfile}. * <p> @@ -789,12 +792,13 @@ public final class ImsCallProfile implements Parcelable { * * @hide */ - public void setEmergencyCallInfo(EmergencyNumber num) { + public void setEmergencyCallInfo(EmergencyNumber num, boolean hasKnownUserIntentEmergency) { setEmergencyServiceCategories(num.getEmergencyServiceCategoryBitmaskInternalDial()); setEmergencyUrns(num.getEmergencyUrns()); setEmergencyCallRouting(num.getEmergencyCallRouting()); setEmergencyCallTesting(num.getEmergencyNumberSourceBitmask() == EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST); + setHasKnownUserIntentEmergency(hasKnownUserIntentEmergency); } /** @@ -860,6 +864,19 @@ public final class ImsCallProfile implements Parcelable { } /** + * Set if we have known the user intent of the call is emergency. + * + * This is only used to specify when the dialed number is ambiguous when it can be identified + * as both emergency number and any other non-emergency number; e.g. in some situation, 611 + * could be both an emergency number in a country and a non-emergency number of a carrier's + * customer service hotline. + */ + @VisibleForTesting + public void setHasKnownUserIntentEmergency(boolean hasKnownUserIntentEmergency) { + mHasKnownUserIntentEmergency = hasKnownUserIntentEmergency; + } + + /** * Get the emergency service categories, only valid if {@link #getServiceType} returns * {@link #SERVICE_TYPE_EMERGENCY} * @@ -916,4 +933,16 @@ public final class ImsCallProfile implements Parcelable { public boolean isEmergencyCallTesting() { return mEmergencyCallTesting; } + + /** + * Checks if we have known the user intent of the call is emergency. + * + * This is only used to specify when the dialed number is ambiguous when it can be identified + * as both emergency number and any other non-emergency number; e.g. in some situation, 611 + * could be both an emergency number in a country and a non-emergency number of a carrier's + * customer service hotline. + */ + public boolean hasKnownUserIntentEmergency() { + return mHasKnownUserIntentEmergency; + } } diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java index c83ab84d6683..d1a06925a902 100644 --- a/tests/net/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java @@ -20,6 +20,7 @@ import static android.net.ConnectivityManager.CONNECTIVITY_ACTION; 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.net.ConnectivityManager.NETID_UNSET; import static android.net.ConnectivityManager.TYPE_ETHERNET; import static android.net.ConnectivityManager.TYPE_MOBILE; import static android.net.ConnectivityManager.TYPE_MOBILE_FOTA; @@ -123,7 +124,7 @@ import android.net.NetworkMisc; import android.net.NetworkParcelable; import android.net.NetworkRequest; import android.net.NetworkSpecifier; -import android.net.NetworkStack; +import android.net.NetworkStackClient; import android.net.NetworkUtils; import android.net.ProxyInfo; import android.net.RouteInfo; @@ -245,7 +246,7 @@ public class ConnectivityServiceTest { @Mock INetworkStatsService mStatsService; @Mock INetworkPolicyManager mNpm; @Mock INetd mMockNetd; - @Mock NetworkStack mNetworkStack; + @Mock NetworkStackClient mNetworkStack; private ArgumentCaptor<String[]> mStringArrayCaptor = ArgumentCaptor.forClass(String[].class); @@ -885,11 +886,14 @@ public class ConnectivityServiceTest { public void setUids(Set<UidRange> uids) { mNetworkCapabilities.setUids(uids); - updateCapabilities(); + updateCapabilities(null /* defaultNetwork */); } @Override public int getNetId() { + if (mMockNetworkAgent == null) { + return NETID_UNSET; + } return mMockNetworkAgent.getNetwork().netId; } @@ -911,12 +915,13 @@ public class ConnectivityServiceTest { } @Override - public void updateCapabilities() { - if (!mConnected) return; - super.updateCapabilities(); - // Because super.updateCapabilities will update the capabilities of the agent but not - // the mock agent, the mock agent needs to know about them. + public NetworkCapabilities updateCapabilities(Network defaultNetwork) { + if (!mConnected) return null; + super.updateCapabilities(defaultNetwork); + // Because super.updateCapabilities will update the capabilities of the agent but + // not the mock agent, the mock agent needs to know about them. copyCapabilitiesToNetworkAgent(); + return new NetworkCapabilities(mNetworkCapabilities); } private void copyCapabilitiesToNetworkAgent() { @@ -1061,6 +1066,11 @@ public class ConnectivityServiceTest { } @Override + protected NetworkStackClient getNetworkStack() { + return mNetworkStack; + } + + @Override public WakeupMessage makeWakeupMessage( Context context, Handler handler, String cmdName, int cmd, Object obj) { return new FakeWakeupMessage(context, handler, cmdName, cmd, 0, 0, obj); @@ -4664,6 +4674,7 @@ public class ConnectivityServiceTest { vpnNetworkAgent.connect(false); mMockVpn.connect(); + mMockVpn.setUnderlyingNetworks(new Network[0]); genericNetworkCallback.expectAvailableCallbacksUnvalidated(vpnNetworkAgent); genericNotVpnNetworkCallback.assertNoCallback(); @@ -4696,6 +4707,7 @@ public class ConnectivityServiceTest { ranges.add(new UidRange(uid, uid)); mMockVpn.setUids(ranges); + vpnNetworkAgent.setUids(ranges); genericNetworkCallback.expectAvailableCallbacksValidated(vpnNetworkAgent); genericNotVpnNetworkCallback.assertNoCallback(); @@ -4729,12 +4741,11 @@ public class ConnectivityServiceTest { } @Test - public void testVpnWithAndWithoutInternet() { + public void testVpnWithoutInternet() { final int uid = Process.myUid(); final TestNetworkCallback defaultCallback = new TestNetworkCallback(); mCm.registerDefaultNetworkCallback(defaultCallback); - defaultCallback.assertNoCallback(); mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); mWiFiNetworkAgent.connect(true); @@ -4756,11 +4767,30 @@ public class ConnectivityServiceTest { vpnNetworkAgent.disconnect(); defaultCallback.assertNoCallback(); - vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN); + mCm.unregisterNetworkCallback(defaultCallback); + } + + @Test + public void testVpnWithInternet() { + final int uid = Process.myUid(); + + final TestNetworkCallback defaultCallback = new TestNetworkCallback(); + mCm.registerDefaultNetworkCallback(defaultCallback); + + mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); + mWiFiNetworkAgent.connect(true); + + defaultCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent); + assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork()); + + MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN); + final ArraySet<UidRange> ranges = new ArraySet<>(); + ranges.add(new UidRange(uid, uid)); mMockVpn.setNetworkAgent(vpnNetworkAgent); mMockVpn.setUids(ranges); vpnNetworkAgent.connect(true /* validated */, true /* hasInternet */); mMockVpn.connect(); + defaultCallback.expectAvailableThenValidatedCallbacks(vpnNetworkAgent); assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork()); @@ -4768,14 +4798,6 @@ public class ConnectivityServiceTest { defaultCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent); defaultCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent); - vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN); - ranges.clear(); - mMockVpn.setNetworkAgent(vpnNetworkAgent); - mMockVpn.setUids(ranges); - vpnNetworkAgent.connect(false /* validated */, true /* hasInternet */); - mMockVpn.connect(); - defaultCallback.assertNoCallback(); - mCm.unregisterNetworkCallback(defaultCallback); } @@ -4878,6 +4900,70 @@ public class ConnectivityServiceTest { } @Test + public void testNullUnderlyingNetworks() { + final int uid = Process.myUid(); + + final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback(); + final NetworkRequest vpnNetworkRequest = new NetworkRequest.Builder() + .removeCapability(NET_CAPABILITY_NOT_VPN) + .addTransportType(TRANSPORT_VPN) + .build(); + NetworkCapabilities nc; + mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback); + vpnNetworkCallback.assertNoCallback(); + + final MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN); + final ArraySet<UidRange> ranges = new ArraySet<>(); + ranges.add(new UidRange(uid, uid)); + mMockVpn.setNetworkAgent(vpnNetworkAgent); + mMockVpn.connect(); + mMockVpn.setUids(ranges); + vpnNetworkAgent.connect(true /* validated */, false /* hasInternet */); + + vpnNetworkCallback.expectAvailableThenValidatedCallbacks(vpnNetworkAgent); + nc = mCm.getNetworkCapabilities(vpnNetworkAgent.getNetwork()); + assertTrue(nc.hasTransport(TRANSPORT_VPN)); + assertFalse(nc.hasTransport(TRANSPORT_CELLULAR)); + assertFalse(nc.hasTransport(TRANSPORT_WIFI)); + // By default, VPN is set to track default network (i.e. its underlying networks is null). + // In case of no default network, VPN is considered metered. + assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_METERED)); + + // Connect to Cell; Cell is the default network. + mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); + mCellNetworkAgent.connect(true); + + vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN) + && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI) + && !caps.hasCapability(NET_CAPABILITY_NOT_METERED), + vpnNetworkAgent); + + // Connect to WiFi; WiFi is the new default. + mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); + mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED); + mWiFiNetworkAgent.connect(true); + + vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN) + && !caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI) + && caps.hasCapability(NET_CAPABILITY_NOT_METERED), + vpnNetworkAgent); + + // Disconnect Cell. The default network did not change, so there shouldn't be any changes in + // the capabilities. + mCellNetworkAgent.disconnect(); + + // Disconnect wifi too. Now we have no default network. + mWiFiNetworkAgent.disconnect(); + + vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN) + && !caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI) + && !caps.hasCapability(NET_CAPABILITY_NOT_METERED), + vpnNetworkAgent); + + mMockVpn.disconnect(); + } + + @Test public void testNetworkBlockedStatus() { final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback(); final NetworkRequest cellRequest = new NetworkRequest.Builder() diff --git a/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java b/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java index 9578ded1a089..aa6cbda0479d 100644 --- a/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java +++ b/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java @@ -37,7 +37,6 @@ import android.net.Network; import android.net.NetworkCapabilities; import android.net.NetworkInfo; import android.net.NetworkMisc; -import android.net.NetworkStack; import android.os.INetworkManagementService; import android.support.test.filters.SmallTest; import android.support.test.runner.AndroidJUnit4; @@ -74,16 +73,12 @@ 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(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); } diff --git a/tests/net/java/com/android/server/connectivity/TetheringTest.java b/tests/net/java/com/android/server/connectivity/TetheringTest.java index a4a735d1a89d..533d7ad2a472 100644 --- a/tests/net/java/com/android/server/connectivity/TetheringTest.java +++ b/tests/net/java/com/android/server/connectivity/TetheringTest.java @@ -195,10 +195,6 @@ public class TetheringTest { } public class MockIpServerDependencies extends IpServer.Dependencies { - MockIpServerDependencies() { - super(null); - } - @Override public RouterAdvertisementDaemon getRouterAdvertisementDaemon( InterfaceParams ifParams) { @@ -266,7 +262,7 @@ public class TetheringTest { } @Override - public IpServer.Dependencies getIpServerDependencies(Context context) { + public IpServer.Dependencies getIpServerDependencies() { return mIpServerDependencies; } diff --git a/tests/net/java/com/android/server/connectivity/VpnTest.java b/tests/net/java/com/android/server/connectivity/VpnTest.java index 46de3d0608ff..f169d6b5bee3 100644 --- a/tests/net/java/com/android/server/connectivity/VpnTest.java +++ b/tests/net/java/com/android/server/connectivity/VpnTest.java @@ -566,7 +566,7 @@ public class VpnTest { final NetworkCapabilities caps = new NetworkCapabilities(); - Vpn.updateCapabilities( + Vpn.applyUnderlyingCapabilities( mConnectivityManager, new Network[] {}, caps, false /* isAlwaysMetered */); assertTrue(caps.hasTransport(TRANSPORT_VPN)); assertFalse(caps.hasTransport(TRANSPORT_CELLULAR)); @@ -577,7 +577,7 @@ public class VpnTest { assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_ROAMING)); assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_CONGESTED)); - Vpn.updateCapabilities( + Vpn.applyUnderlyingCapabilities( mConnectivityManager, new Network[] {mobile}, caps, @@ -591,7 +591,7 @@ public class VpnTest { assertFalse(caps.hasCapability(NET_CAPABILITY_NOT_ROAMING)); assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_CONGESTED)); - Vpn.updateCapabilities( + Vpn.applyUnderlyingCapabilities( mConnectivityManager, new Network[] {wifi}, caps, false /* isAlwaysMetered */); assertTrue(caps.hasTransport(TRANSPORT_VPN)); assertFalse(caps.hasTransport(TRANSPORT_CELLULAR)); @@ -602,7 +602,7 @@ public class VpnTest { assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_ROAMING)); assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_CONGESTED)); - Vpn.updateCapabilities( + Vpn.applyUnderlyingCapabilities( mConnectivityManager, new Network[] {wifi}, caps, true /* isAlwaysMetered */); assertTrue(caps.hasTransport(TRANSPORT_VPN)); assertFalse(caps.hasTransport(TRANSPORT_CELLULAR)); @@ -613,7 +613,7 @@ public class VpnTest { assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_ROAMING)); assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_CONGESTED)); - Vpn.updateCapabilities( + Vpn.applyUnderlyingCapabilities( mConnectivityManager, new Network[] {mobile, wifi}, caps, |