Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ccab250a authored by lucaslin's avatar lucaslin
Browse files

Fix title of PRIVATE_DNS_BROKEN notification when connecting VPN

NetworkNotificationManager will only get the first transport
type from the NetworkCapabilities of network, and if the device
connects to a VPN and its underlying network is wifi, then the
first finding transport type will be TRANSPORT_WIFI. So, if the
private DNS is broken when device connected to VPN,
NetworkNotificationManager will try to get the SSID for the
title of notification but failed. For this kind of case, the
title of PRIVATE_DNS_BROKEN notification will show
"null has no internet access".

Bug: 143340533
Test: 1. Build pass.
      2. Connect to VPN and let private DNS to be broken, check
      title of PRIVATE_DNS_BROKEN notification.
      3. atest FrameworksNetTests

Change-Id: I1ed018cc8774d4fce4b94854f8e8703a28818463
parent cf46823f
Loading
Loading
Loading
Loading
+14 −5
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package com.android.server.connectivity;

import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
import static android.net.NetworkCapabilities.TRANSPORT_VPN;
import static android.net.NetworkCapabilities.TRANSPORT_WIFI;

import android.app.Notification;
@@ -89,14 +90,22 @@ public class NetworkNotificationManager {
        mNotificationTypeMap = new SparseIntArray();
    }

    @VisibleForTesting
    protected static int approximateTransportType(NetworkAgentInfo nai) {
        return nai.isVPN() ? TRANSPORT_VPN : getFirstTransportType(nai);
    }

    // TODO: deal more gracefully with multi-transport networks.
    private static int getFirstTransportType(NetworkAgentInfo nai) {
        // TODO: The range is wrong, the safer and correct way is to change the range from
        // MIN_TRANSPORT to MAX_TRANSPORT.
        for (int i = 0; i < 64; i++) {
            if (nai.networkCapabilities.hasTransport(i)) return i;
        }
        return -1;
    }

    // TODO: Remove @TransportType or change it to @Transport.
    private static String getTransportName(@TransportType int transportType) {
        Resources r = Resources.getSystem();
        String[] networkTypes = r.getStringArray(R.array.network_switch_type_name);
@@ -146,7 +155,7 @@ public class NetworkNotificationManager {
        final int transportType;
        final String name;
        if (nai != null) {
            transportType = getFirstTransportType(nai);
            transportType = approximateTransportType(nai);
            final String extraInfo = nai.networkInfo.getExtraInfo();
            name = TextUtils.isEmpty(extraInfo) ? nai.networkCapabilities.getSSID() : extraInfo;
            // Only notify for Internet-capable networks.
@@ -175,7 +184,7 @@ public class NetworkNotificationManager {
                    tag, nameOf(eventId), getTransportName(transportType), name, highPriority));
        }

        Resources r = Resources.getSystem();
        Resources r = mContext.getResources();
        final CharSequence title;
        final CharSequence details;
        int icon = getIcon(transportType, notifyType);
@@ -239,7 +248,7 @@ public class NetworkNotificationManager {
            details = r.getString(R.string.captive_portal_logged_in_detailed);
        } else if (notifyType == NotificationType.NETWORK_SWITCH) {
            String fromTransport = getTransportName(transportType);
            String toTransport = getTransportName(getFirstTransportType(switchToNai));
            String toTransport = getTransportName(approximateTransportType(switchToNai));
            title = r.getString(R.string.network_switch_metered, toTransport);
            details = r.getString(R.string.network_switch_metered_detail, toTransport,
                    fromTransport);
@@ -340,8 +349,8 @@ public class NetworkNotificationManager {
    }

    public void showToast(NetworkAgentInfo fromNai, NetworkAgentInfo toNai) {
        String fromTransport = getTransportName(getFirstTransportType(fromNai));
        String toTransport = getTransportName(getFirstTransportType(toNai));
        String fromTransport = getTransportName(approximateTransportType(fromNai));
        String toTransport = getTransportName(approximateTransportType(toNai));
        String text = mContext.getResources().getString(
                R.string.network_switch_metered_toast, fromTransport, toTransport);
        Toast.makeText(mContext, text, Toast.LENGTH_LONG).show();
+42 −0
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ import static com.android.server.connectivity.NetworkNotificationManager.Notific

import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
@@ -40,6 +41,7 @@ import android.telephony.TelephonyManager;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;

import com.android.internal.R;
import com.android.server.connectivity.NetworkNotificationManager.NotificationType;

import org.junit.Before;
@@ -60,12 +62,19 @@ public class NetworkNotificationManagerTest {

    static final NetworkCapabilities CELL_CAPABILITIES = new NetworkCapabilities();
    static final NetworkCapabilities WIFI_CAPABILITIES = new NetworkCapabilities();
    static final NetworkCapabilities VPN_CAPABILITIES = new NetworkCapabilities();
    static {
        CELL_CAPABILITIES.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
        CELL_CAPABILITIES.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);

        WIFI_CAPABILITIES.addTransportType(NetworkCapabilities.TRANSPORT_WIFI);
        WIFI_CAPABILITIES.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);

        // Set the underyling network to wifi.
        VPN_CAPABILITIES.addTransportType(NetworkCapabilities.TRANSPORT_WIFI);
        VPN_CAPABILITIES.addTransportType(NetworkCapabilities.TRANSPORT_VPN);
        VPN_CAPABILITIES.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
        VPN_CAPABILITIES.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN);
    }

    @Mock Context mCtx;
@@ -75,6 +84,7 @@ public class NetworkNotificationManagerTest {
    @Mock NotificationManager mNotificationManager;
    @Mock NetworkAgentInfo mWifiNai;
    @Mock NetworkAgentInfo mCellNai;
    @Mock NetworkAgentInfo mVpnNai;
    @Mock NetworkInfo mNetworkInfo;
    ArgumentCaptor<Notification> mCaptor;

@@ -88,6 +98,9 @@ public class NetworkNotificationManagerTest {
        mWifiNai.networkInfo = mNetworkInfo;
        mCellNai.networkCapabilities = CELL_CAPABILITIES;
        mCellNai.networkInfo = mNetworkInfo;
        mVpnNai.networkCapabilities = VPN_CAPABILITIES;
        mVpnNai.networkInfo = mNetworkInfo;
        doReturn(true).when(mVpnNai).isVPN();
        when(mCtx.getResources()).thenReturn(mResources);
        when(mCtx.getPackageManager()).thenReturn(mPm);
        when(mCtx.getApplicationInfo()).thenReturn(new ApplicationInfo());
@@ -97,6 +110,35 @@ public class NetworkNotificationManagerTest {
        mManager = new NetworkNotificationManager(mCtx, mTelephonyManager, mNotificationManager);
    }

    private void verifyTitleByNetwork(final int id, final NetworkAgentInfo nai, final int title) {
        final String tag = NetworkNotificationManager.tagFor(id);
        mManager.showNotification(id, PRIVATE_DNS_BROKEN, nai, null, null, true);
        verify(mNotificationManager, times(1))
                .notifyAsUser(eq(tag), eq(PRIVATE_DNS_BROKEN.eventId), any(), any());
        final int transportType = NetworkNotificationManager.approximateTransportType(nai);
        if (transportType == NetworkCapabilities.TRANSPORT_WIFI) {
            verify(mResources, times(1)).getString(title, eq(any()));
        } else {
            verify(mResources, times(1)).getString(title);
        }
        verify(mResources, times(1)).getString(R.string.private_dns_broken_detailed);
    }

    @Test
    public void testTitleOfPrivateDnsBroken() {
        // Test the title of mobile data.
        verifyTitleByNetwork(100, mCellNai, R.string.mobile_no_internet);
        reset(mResources);

        // Test the title of wifi.
        verifyTitleByNetwork(101, mWifiNai, R.string.wifi_no_internet);
        reset(mResources);

        // Test the title of other networks.
        verifyTitleByNetwork(102, mVpnNai, R.string.other_networks_no_internet);
        reset(mResources);
    }

    @Test
    public void testNotificationsShownAndCleared() {
        final int NETWORK_ID_BASE = 100;