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

Commit 0350709f authored by Lucas Lin's avatar Lucas Lin Committed by Gerrit Code Review
Browse files

Merge "Use location mcc to load the resource"

parents 2abb2cc3 9b4dfab5
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@
         permissions added would cause crashes on startup unless they are also added to the
         privileged permissions whitelist for that package. -->
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <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" />
+3 −0
Original line number Diff line number Diff line
@@ -43,4 +43,7 @@
    <!-- Customized default DNS Servers address. -->
    <string-array name="config_default_dns_servers" translatable="false">
    </string-array>
    <!-- Set to true if NetworkMonitor needs to load the resource by neighbor mcc when device
         doesn't have a SIM card inserted. -->
    <bool name="config_no_sim_card_uses_neighbor_mcc">false</bool>
</resources>
+1 −0
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@
            <item type="string" name="config_captive_portal_http_url"/>
            <item type="string" name="config_captive_portal_https_url"/>
            <item type="array" name="config_captive_portal_fallback_urls"/>
            <item type="bool" name="config_no_sim_card_uses_neighbor_mcc"/>
            <!-- Configuration value for DhcpResults -->
            <item type="array" name="config_default_dns_servers"/>
        </policy>
+97 −2
Original line number Diff line number Diff line
@@ -76,6 +76,8 @@ import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.net.ConnectivityManager;
import android.net.DnsResolver;
@@ -101,11 +103,19 @@ import android.net.wifi.WifiManager;
import android.os.Build;
import android.os.Bundle;
import android.os.Message;
import android.os.Process;
import android.os.RemoteException;
import android.os.SystemClock;
import android.os.UserHandle;
import android.provider.Settings;
import android.telephony.AccessNetworkConstants;
import android.telephony.CellIdentityNr;
import android.telephony.CellInfo;
import android.telephony.CellInfoGsm;
import android.telephony.CellInfoLte;
import android.telephony.CellInfoNr;
import android.telephony.CellInfoTdscdma;
import android.telephony.CellInfoWcdma;
import android.telephony.CellSignalStrength;
import android.telephony.NetworkRegistrationInfo;
import android.telephony.ServiceState;
@@ -116,6 +126,7 @@ import android.util.Log;
import android.util.Pair;

import androidx.annotation.ArrayRes;
import androidx.annotation.BoolRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.StringRes;
@@ -141,8 +152,10 @@ import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.StringJoiner;
import java.util.UUID;
@@ -1318,8 +1331,78 @@ public class NetworkMonitor extends StateMachine {
                CAPTIVE_PORTAL_USE_HTTPS, 1) == 1;
    }

    @Nullable
    private String getMccFromCellInfo(final CellInfo cell) {
        if (cell instanceof CellInfoGsm) {
            return ((CellInfoGsm) cell).getCellIdentity().getMccString();
        } else if (cell instanceof CellInfoLte) {
            return ((CellInfoLte) cell).getCellIdentity().getMccString();
        } else if (cell instanceof CellInfoWcdma) {
            return ((CellInfoWcdma) cell).getCellIdentity().getMccString();
        } else if (cell instanceof CellInfoTdscdma) {
            return ((CellInfoTdscdma) cell).getCellIdentity().getMccString();
        } else if (cell instanceof CellInfoNr) {
            return ((CellIdentityNr) ((CellInfoNr) cell).getCellIdentity()).getMccString();
        } else {
            return null;
        }
    }

    /**
     * Return location mcc.
     */
    @VisibleForTesting
    @Nullable
    protected String getLocationMcc() {
        // Adding this check is because the new permission won't be granted by mainline update,
        // the new permission only be granted by OTA for current design. Tracking: b/145774617.
        if (mContext.checkPermission(android.Manifest.permission.ACCESS_FINE_LOCATION,
                Process.myPid(), Process.myUid())
                == PackageManager.PERMISSION_DENIED) {
            log("getLocationMcc : NetworkStack does not hold ACCESS_FINE_LOCATION");
            return null;
        }
        try {
            final List<CellInfo> cells = mTelephonyManager.getAllCellInfo();
            final Map<String, Integer> countryCodeMap = new HashMap<>();
            int maxCount = 0;
            for (final CellInfo cell : cells) {
                final String mcc = getMccFromCellInfo(cell);
                if (mcc != null) {
                    final int count = countryCodeMap.getOrDefault(mcc, 0) + 1;
                    countryCodeMap.put(mcc, count);
                }
            }
            // Return the MCC which occurs most.
            if (countryCodeMap.size() <= 0) return null;
            return Collections.max(countryCodeMap.entrySet(),
                    (e1, e2) -> e1.getValue().compareTo(e2.getValue())).getKey();
        } catch (SecurityException e) {
            log("Permission is not granted:" + e);
            return null;
        }
    }

    @VisibleForTesting
    protected Context getContextByMccIfNoSimCardOrDefault() {
        final boolean useNeighborResource =
                getResBooleanConfig(mContext, R.bool.config_no_sim_card_uses_neighbor_mcc);
        if (!useNeighborResource
                || TelephonyManager.SIM_STATE_READY == mTelephonyManager.getSimState()) {
            return mContext;
        }
        final String mcc = getLocationMcc();
        if (TextUtils.isEmpty(mcc)) {
            return mContext;
        }
        final Configuration config = mContext.getResources().getConfiguration();
        config.mcc = Integer.parseInt(mcc);
        return mContext.createConfigurationContext(config);
    }

    private String getCaptivePortalServerHttpsUrl() {
        return getSettingFromResource(mContext, R.string.config_captive_portal_https_url,
        final Context targetContext = getContextByMccIfNoSimCardOrDefault();
        return getSettingFromResource(targetContext, R.string.config_captive_portal_https_url,
                R.string.default_captive_portal_https_url, CAPTIVE_PORTAL_HTTPS_URL);
    }

@@ -1350,6 +1433,17 @@ public class NetworkMonitor extends StateMachine {
        }
    }

    @VisibleForTesting
    protected boolean getResBooleanConfig(@NonNull final Context context,
            @BoolRes int configResource) {
        final Resources res = context.getResources();
        try {
            return res.getBoolean(configResource);
        } catch (Resources.NotFoundException e) {
            return false;
        }
    }

    /**
     * Get the captive portal server HTTP URL that is configured on the device.
     *
@@ -1358,7 +1452,8 @@ public class NetworkMonitor extends StateMachine {
     * on one URL that can be used, while NetworkMonitor may implement more complex logic.
     */
    public String getCaptivePortalServerHttpUrl() {
        return getSettingFromResource(mContext, R.string.config_captive_portal_http_url,
        final Context targetContext = getContextByMccIfNoSimCardOrDefault();
        return getSettingFromResource(targetContext, R.string.config_captive_portal_http_url,
                R.string.default_captive_portal_http_url, CAPTIVE_PORTAL_HTTP_URL);
    }

+52 −0
Original line number Diff line number Diff line
@@ -64,7 +64,10 @@ import static org.mockito.Mockito.when;
import android.annotation.NonNull;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.net.ConnectivityManager;
import android.net.DnsResolver;
@@ -87,6 +90,11 @@ import android.os.Process;
import android.os.RemoteException;
import android.os.SystemClock;
import android.provider.Settings;
import android.telephony.CellIdentityGsm;
import android.telephony.CellIdentityLte;
import android.telephony.CellInfo;
import android.telephony.CellInfoGsm;
import android.telephony.CellInfoLte;
import android.telephony.CellSignalStrength;
import android.telephony.TelephonyManager;
import android.util.ArrayMap;
@@ -133,6 +141,7 @@ public class NetworkMonitorTest {
    private static final String LOCATION_HEADER = "location";

    private @Mock Context mContext;
    private @Mock Configuration mConfiguration;
    private @Mock Resources mResources;
    private @Mock IpConnectivityLog mLogger;
    private @Mock SharedLog mValidationLogger;
@@ -484,6 +493,10 @@ public class NetworkMonitorTest {
            assertTrue("NetworkMonitor did not quit after " + HANDLER_TIMEOUT_MS + "ms",
                    mQuitCv.block(HANDLER_TIMEOUT_MS));
        }

        protected Context getContext() {
            return mContext;
        }
    }

    private WrappedNetworkMonitor makeMonitor(NetworkCapabilities nc) {
@@ -512,6 +525,45 @@ public class NetworkMonitorTest {
        HandlerUtilsKt.waitForIdle(nm.getHandler(), HANDLER_TIMEOUT_MS);
    }

    @Test
    public void testGetLocationMcc() throws Exception {
        final WrappedNetworkMonitor wnm = makeNotMeteredNetworkMonitor();
        doReturn(PackageManager.PERMISSION_DENIED).when(mContext).checkPermission(
                eq(android.Manifest.permission.ACCESS_FINE_LOCATION),  anyInt(), anyInt());
        assertNull(wnm.getLocationMcc());
        doReturn(PackageManager.PERMISSION_GRANTED).when(mContext).checkPermission(
                eq(android.Manifest.permission.ACCESS_FINE_LOCATION),  anyInt(), anyInt());
        doReturn(new ContextWrapper(mContext)).when(mContext).createConfigurationContext(any());
        // Prepare CellInfo and check if the vote mechanism is working or not.
        final CellInfoGsm cellInfoGsm1 = new CellInfoGsm();
        final CellInfoGsm cellInfoGsm2 = new CellInfoGsm();
        final CellInfoLte cellInfoLte = new CellInfoLte();
        final CellIdentityGsm cellIdentityGsm =
                new CellIdentityGsm(0, 0, 0, 0, "460", "01", "", "");
        final CellIdentityLte cellIdentityLte =
                new CellIdentityLte(0, 0, 0, 0, 0, "466", "01", "", "");
        cellInfoGsm1.setCellIdentity(cellIdentityGsm);
        cellInfoGsm2.setCellIdentity(cellIdentityGsm);
        cellInfoLte.setCellIdentity(cellIdentityLte);
        final List<CellInfo> cellList = new ArrayList<CellInfo>();
        cellList.add(cellInfoGsm1);
        cellList.add(cellInfoGsm2);
        cellList.add(cellInfoLte);
        doReturn(cellList).when(mTelephony).getAllCellInfo();
        // The count of 460 is 2 and the count of 466 is 1, so the getLocationMcc() should return
        // 460.
        assertEquals("460", wnm.getLocationMcc());
        // getContextByMccIfNoSimCardOrDefault() shouldn't return mContext when using neighbor mcc
        // is enabled and the sim is not ready.
        doReturn(true).when(mResources).getBoolean(R.bool.config_no_sim_card_uses_neighbor_mcc);
        doReturn(TelephonyManager.SIM_STATE_ABSENT).when(mTelephony).getSimState();
        doReturn(mConfiguration).when(mResources).getConfiguration();
        assertEquals(460,
                wnm.getContextByMccIfNoSimCardOrDefault().getResources().getConfiguration().mcc);
        doReturn(false).when(mResources).getBoolean(R.bool.config_no_sim_card_uses_neighbor_mcc);
        assertEquals(wnm.getContext(), wnm.getContextByMccIfNoSimCardOrDefault());
    }

    @Test
    public void testGetIntSetting() throws Exception {
        WrappedNetworkMonitor wnm = makeNotMeteredNetworkMonitor();