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

Commit e59d4c53 authored by android-build-team Robot's avatar android-build-team Robot
Browse files

Snap for 6315035 from a482d38b to mainline-release

Change-Id: Ia30ac4d1f10433d3303ee2ee1ccdf36382e856bb
parents d0254d6d a482d38b
Loading
Loading
Loading
Loading
+4 −11
Original line number Diff line number Diff line
@@ -31,22 +31,15 @@
         information page, so that the user can access that page. [CHAR LIMIT=300] -->
    <string name="notification_channel_description_network_venue_info">Notifications shown to indicate the network has a venue information page</string>

    <!-- Notifications are shown after the user logs in to a captive portal network, to indicate
         that the network should now have internet connectivity. This is the title of the
         notification, indicating that the device is connected to the network with the SSID given
         as parameter. [CHAR LIMIT=50] -->
    <string name="connected_to_ssid_param1">Connected to %1$s</string>

    <!-- A notification is shown after the user logs in to a captive portal network, to indicate
         that the network should now have internet connectivity. This is the title of the
         notification, indicating that the device is connected to the network without SSID
         information. [CHAR LIMIT=50] -->
         that the network should now have internet connectivity. This is the description of the
         notification, indicating that the device is connected to the network. [CHAR LIMIT=50] -->
    <string name="connected">Connected</string>

    <!-- Notifications are shown when a user connects to a network that advertises a venue
         information page, so that the user can access that page. This is the message of
         information page, so that the user can access that page. This is the description of
         the notification. [CHAR LIMIT=50] -->
    <string name="tap_for_info">Tap for venue information</string>
    <string name="tap_for_info">Connected / Tap to view website</string>

    <!-- The label of application. It's also a sender name of notification. [CHAR LIMIT=50]-->
    <string name="application_label">Connectivity Manager</string>
+73 −2
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ import static android.net.RouteInfo.RTN_UNICAST;
import static android.net.shared.IpConfigurationParcelableUtil.toStableParcelable;
import static android.provider.DeviceConfig.NAMESPACE_CONNECTIVITY;

import static com.android.server.util.NetworkStackConstants.VENDOR_SPECIFIC_IE_ID;
import static com.android.server.util.PermissionUtil.enforceNetworkStackCallingPermission;

import android.content.Context;
@@ -40,10 +41,13 @@ import android.net.Uri;
import android.net.apf.ApfCapabilities;
import android.net.apf.ApfFilter;
import android.net.dhcp.DhcpClient;
import android.net.dhcp.DhcpPacket;
import android.net.metrics.IpConnectivityLog;
import android.net.metrics.IpManagerEvent;
import android.net.shared.InitialConfiguration;
import android.net.shared.ProvisioningConfiguration;
import android.net.shared.ProvisioningConfiguration.ScanResultInfo;
import android.net.shared.ProvisioningConfiguration.ScanResultInfo.InformationElement;
import android.net.util.InterfaceParams;
import android.net.util.NetworkStackUtils;
import android.net.util.SharedLog;
@@ -64,6 +68,7 @@ import android.util.SparseArray;
import androidx.annotation.NonNull;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.HexDump;
import com.android.internal.util.IState;
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.MessageUtils;
@@ -80,6 +85,10 @@ import com.android.server.NetworkStackService.NetworkStackServiceManager;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.nio.BufferUnderflowException;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
@@ -406,6 +415,13 @@ public class IpClient extends StateMachine {
    private static final int PROV_CHANGE_GAINED_PROVISIONING = 3;
    private static final int PROV_CHANGE_STILL_PROVISIONED = 4;

    // Specific vendor OUI(3 bytes)/vendor specific type(1 byte) pattern for upstream hotspot
    // device detection. Add new byte array pattern below in turn.
    private static final List<byte[]> METERED_IE_PATTERN_LIST = Collections.unmodifiableList(
            Arrays.asList(
                    new byte[] { (byte) 0x00, (byte) 0x17, (byte) 0xf2, (byte) 0x06 }
    ));

    private final State mStoppedState = new StoppedState();
    private final State mStoppingState = new StoppingState();
    private final State mClearingIpAddressesState = new ClearingIpAddressesState();
@@ -1269,16 +1285,71 @@ public class IpClient extends StateMachine {
        return (delta != PROV_CHANGE_LOST_PROVISIONING);
    }

    @VisibleForTesting
    static String removeDoubleQuotes(@NonNull String ssid) {
        final int length = ssid.length();
        if ((length > 1) && (ssid.charAt(0) == '"') && (ssid.charAt(length - 1) == '"')) {
            return ssid.substring(1, length - 1);
        }
        return ssid;
    }

    private List<ByteBuffer> getVendorSpecificIEs(@NonNull ScanResultInfo scanResultInfo) {
        ArrayList<ByteBuffer> vendorSpecificPayloadList = new ArrayList<>();
        for (InformationElement ie : scanResultInfo.getInformationElements()) {
            if (ie.getId() == VENDOR_SPECIFIC_IE_ID) {
                vendorSpecificPayloadList.add(ie.getPayload());
            }
        }
        return vendorSpecificPayloadList;
    }

    private boolean detectUpstreamHotspotFromVendorIe() {
        if (mConfiguration.mScanResultInfo == null) return false;
        final ScanResultInfo scanResultInfo = mConfiguration.mScanResultInfo;
        final String ssid = scanResultInfo.getSsid();
        final List<ByteBuffer> vendorSpecificPayloadList = getVendorSpecificIEs(scanResultInfo);

        if (mConfiguration.mDisplayName == null
                || !removeDoubleQuotes(mConfiguration.mDisplayName).equals(ssid)) {
            return false;
        }

        for (ByteBuffer payload : vendorSpecificPayloadList) {
            byte[] ouiAndType = new byte[4];
            try {
                payload.get(ouiAndType);
            } catch (BufferUnderflowException e) {
                Log.e(mTag, "Couldn't parse vendor specific IE, buffer underflow");
                return false;
            }
            for (byte[] pattern : METERED_IE_PATTERN_LIST) {
                if (Arrays.equals(pattern, ouiAndType)) {
                    if (DBG) {
                        Log.d(mTag, "detected upstream hotspot that matches OUI:"
                                + HexDump.toHexString(ouiAndType));
                    }
                    return true;
                }
            }
        }
        return false;
    }

    private void handleIPv4Success(DhcpResults dhcpResults) {
        mDhcpResults = new DhcpResults(dhcpResults);
        final LinkProperties newLp = assembleLinkProperties();
        final int delta = setLinkProperties(newLp);

        if (mDhcpResults.vendorInfo == null && detectUpstreamHotspotFromVendorIe()) {
            mDhcpResults.vendorInfo = DhcpPacket.VENDOR_INFO_ANDROID_METERED;
        }

        if (DBG) {
            Log.d(mTag, "onNewDhcpResults(" + Objects.toString(dhcpResults) + ")");
            Log.d(mTag, "onNewDhcpResults(" + Objects.toString(mDhcpResults) + ")");
            Log.d(mTag, "handleIPv4Success newLp{" + newLp + "}");
        }
        mCallback.onNewDhcpResults(dhcpResults);
        mCallback.onNewDhcpResults(mDhcpResults);
        maybeSaveNetworkToIpMemoryStore();

        dispatchCallback(delta, newLp);
+4 −4
Original line number Diff line number Diff line
@@ -84,8 +84,8 @@ public class ConnectivityPacketSummary {

    /**
     * Create a string summary of a received packet.
     * @param hwaddr MacAddress of the receiving device.
     * @param buffer Buffer of the packet. Length is assumed to be the buffer length.
     * @param hwaddr MacAddress of the interface sending/receiving the packet.
     * @param buffer The packet bytes. Length is assumed to be the buffer length.
     * @return A summary of the packet.
     */
    public static String summarize(MacAddress hwaddr, byte[] buffer) {
@@ -97,8 +97,8 @@ public class ConnectivityPacketSummary {

    /**
     * Create a string summary of a received packet.
     * @param macAddr MacAddress of the receiving device.
     * @param buffer Buffer of the packet.
     * @param macAddr MacAddress of the interface sending/receiving the packet.
     * @param buffer The packet bytes.
     * @param length Length of the packet.
     * @return A summary of the packet.
     */
+14 −16
Original line number Diff line number Diff line
@@ -181,6 +181,9 @@ public class NetworkStackNotifier {
        final TrackedNetworkStatus networkStatus = mNetworkStatus.get(network);
        // The required network attributes callbacks were not fired yet for this network
        if (networkStatus == null) return;
        // Don't show the notification when SSID is unknown to prevent sending something vague to
        // the user.
        final boolean hasSsid = !TextUtils.isEmpty(getSsid(networkStatus));

        final CaptivePortalDataShim capportData = getCaptivePortalData(networkStatus);
        final boolean showVenueInfo = capportData != null && capportData.getVenueInfoUrl() != null
@@ -191,9 +194,11 @@ public class NetworkStackNotifier {
                && isVenueInfoNotificationEnabled()
                // Most browsers do not yet support opening a page on a non-default network, so the
                // venue info link should not be shown if the network is not the default one.
                && network.equals(mDefaultNetwork);
                && network.equals(mDefaultNetwork)
                && hasSsid;
        final boolean showValidated =
                networkStatus.mValidatedNotificationPending && networkStatus.isValidated();
                networkStatus.mValidatedNotificationPending && networkStatus.isValidated()
                && hasSsid;
        final String notificationTag = getNotificationTag(network);

        final Resources res = mContext.getResources();
@@ -216,7 +221,7 @@ public class NetworkStackNotifier {
            // channel even if the notification contains venue info: the "venue info" notification
            // then doubles as a "connected" notification.
            final String channel = showValidated ? CHANNEL_CONNECTED : CHANNEL_VENUE_INFO;
            builder = getNotificationBuilder(channel, networkStatus, res)
            builder = getNotificationBuilder(channel, networkStatus, res, getSsid(networkStatus))
                    .setContentText(res.getString(R.string.tap_for_info))
                    .setContentIntent(mDependencies.getActivityPendingIntent(
                            getContextAsUser(mContext, UserHandle.CURRENT),
@@ -226,8 +231,10 @@ public class NetworkStackNotifier {
        } else if (showValidated) {
            if (networkStatus.mShownNotification == NOTE_CONNECTED) return;

            builder = getNotificationBuilder(CHANNEL_CONNECTED, networkStatus, res)
            builder = getNotificationBuilder(CHANNEL_CONNECTED, networkStatus, res,
                    getSsid(networkStatus))
                    .setTimeoutAfter(CONNECTED_NOTIFICATION_TIMEOUT_MS)
                    .setContentText(res.getString(R.string.connected))
                    .setContentIntent(mDependencies.getActivityPendingIntent(
                            getContextAsUser(mContext, UserHandle.CURRENT),
                            new Intent(Settings.ACTION_WIFI_SETTINGS),
@@ -256,9 +263,10 @@ public class NetworkStackNotifier {
    }

    private Notification.Builder getNotificationBuilder(@NonNull String channelId,
            @NonNull TrackedNetworkStatus networkStatus, @NonNull Resources res) {
            @NonNull TrackedNetworkStatus networkStatus, @NonNull Resources res,
            @NonNull String ssid) {
        return new Notification.Builder(mContext, channelId)
                .setContentTitle(getConnectedNotificationTitle(res, networkStatus))
                .setContentTitle(ssid)
                .setSmallIcon(R.drawable.icon_wifi);
    }

@@ -279,16 +287,6 @@ public class NetworkStackNotifier {
        return mNotificationManager.getNotificationChannel(CHANNEL_VENUE_INFO) != null;
    }

    private String getConnectedNotificationTitle(@NonNull Resources res,
            @NonNull TrackedNetworkStatus status) {
        final String ssid = getSsid(status);
        if (TextUtils.isEmpty(ssid)) {
            return res.getString(R.string.connected);
        }

        return res.getString(R.string.connected_to_ssid_param1, ssid);
    }

    private static String getNotificationTag(@NonNull Network network) {
        return Long.toString(network.getNetworkHandle());
    }
+8 −0
Original line number Diff line number Diff line
@@ -148,6 +148,14 @@ public final class NetworkStackConstants {
    public static final int INFINITE_LEASE = 0xffffffff;
    public static final int DHCP4_CLIENT_PORT = 68;

    /**
     * IEEE802.11 standard constants.
     *
     * See also:
     *     - https://ieeexplore.ieee.org/document/7786995
     */
    public static final int VENDOR_SPECIFIC_IE_ID = 0xdd;

    private NetworkStackConstants() {
        throw new UnsupportedOperationException("This class is not to be instantiated");
    }
Loading