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

Commit 3af5f9bc authored by Jack Yu's avatar Jack Yu
Browse files

Fixed that locale was not updated after airplane mode off

Fixed a case that when network MCC/MNC is unavailable after
airplane mode off, locale tracker did not pull cell tower info
to determine the current country.

Now telephony gets the cell info from the modem when the device
is out of airplane mode. Also it periodically gets cell info from
the modem when network MCC/MNC is unavailable.

Test: Manual + unit tests
Bug: 80261412
Merged-In: I71810284a2d0b1e767d97e8e014f2a8497a77784
Change-Id: I71810284a2d0b1e767d97e8e014f2a8497a77784
(cherry picked from commit e9de5f60)
parent 3fd56935
Loading
Loading
Loading
Loading
+71 −12
Original line number Diff line number Diff line
@@ -16,7 +16,7 @@

package com.android.internal.telephony;

import static android.text.format.DateUtils.HOUR_IN_MILLIS;
import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
import static android.text.format.DateUtils.SECOND_IN_MILLIS;

import android.annotation.NonNull;
@@ -26,6 +26,7 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.wifi.WifiManager;
import android.os.AsyncResult;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
@@ -34,6 +35,7 @@ import android.telephony.CellInfoGsm;
import android.telephony.CellInfoLte;
import android.telephony.CellInfoWcdma;
import android.telephony.Rlog;
import android.telephony.ServiceState;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.LocalLog;
@@ -54,19 +56,26 @@ public class LocaleTracker extends Handler {
    private static final boolean DBG = true;
    private static final String TAG = LocaleTracker.class.getSimpleName();

    /** Event to trigger get cell info from the modem */
    /** Event for getting cell info from the modem */
    private static final int EVENT_GET_CELL_INFO                = 1;

    /** Event to trigger update operator numeric */
    /** Event for operator numeric update */
    private static final int EVENT_UPDATE_OPERATOR_NUMERIC      = 2;

    /** Event for service state changed */
    private static final int EVENT_SERVICE_STATE_CHANGED        = 3;

    // Todo: Read this from Settings.
    /** The minimum delay to get cell info from the modem */
    private static final long CELL_INFO_MIN_DELAY_MS = 2 * SECOND_IN_MILLIS;

    // Todo: Read this from Settings.
    /** The maximum delay to get cell info from the modem */
    private static final long CELL_INFO_MAX_DELAY_MS = 1 * HOUR_IN_MILLIS;
    private static final long CELL_INFO_MAX_DELAY_MS = 10 * MINUTE_IN_MILLIS;

    // Todo: Read this from Settings.
    /** The delay for periodically getting cell info from the modem */
    private static final long CELL_INFO_PERIODIC_POLLING_DELAY_MS = 10 * MINUTE_IN_MILLIS;

    private final Phone mPhone;

@@ -88,6 +97,9 @@ public class LocaleTracker extends Handler {
    @Nullable
    private String mCurrentCountryIso;

    /** Current service state. Must be one of ServiceState.STATE_XXX. */
    private int mLastServiceState = -1;

    private final LocalLog mLocalLog = new LocalLog(50);

    /** Broadcast receiver to get SIM card state changed event */
@@ -121,6 +133,10 @@ public class LocaleTracker extends Handler {
            case EVENT_UPDATE_OPERATOR_NUMERIC:
                updateOperatorNumericSync((String) msg.obj);
                break;
            case EVENT_SERVICE_STATE_CHANGED:
                AsyncResult ar = (AsyncResult) msg.obj;
                onServiceStateChanged((ServiceState) ar.result);
                break;
            default:
                throw new IllegalStateException("Unexpected message arrives. msg = " + msg.what);
        }
@@ -140,6 +156,8 @@ public class LocaleTracker extends Handler {
        final IntentFilter filter = new IntentFilter();
        filter.addAction(TelephonyManager.ACTION_SIM_CARD_STATE_CHANGED);
        mPhone.getContext().registerReceiver(mBroadcastReceiver, filter);

        mPhone.registerForServiceStateChanged(this, EVENT_SERVICE_STATE_CHANGED, null);
    }

    /**
@@ -206,6 +224,32 @@ public class LocaleTracker extends Handler {
        mSimState = state;
    }

    /**
     * Called when service state changed.
     *
     * @param serviceState Service state
     */
    private void onServiceStateChanged(ServiceState serviceState) {
        int state = serviceState.getState();
        if (state != mLastServiceState) {
            if (state != ServiceState.STATE_POWER_OFF && TextUtils.isEmpty(mOperatorNumeric)) {
                // When the device is out of airplane mode or powered on, and network's MCC/MNC is
                // not available, we get cell info from the modem.
                String msg = "Service state " + ServiceState.rilServiceStateToString(state)
                        + ". Get cell info now.";
                if (DBG) log(msg);
                mLocalLog.log(msg);
                getCellInfo();
            } else if (state == ServiceState.STATE_POWER_OFF) {
                // Clear the cell info when the device is in airplane mode.
                if (mCellInfo != null) mCellInfo.clear();
                stopCellInfoRetry();
            }
            updateLocale();
            mLastServiceState = state;
        }
    }

    /**
     * Update MCC/MNC from network service state synchronously. Note if this is called from phone
     * process's main thread and if the update operation requires getting cell info from the modem,
@@ -231,9 +275,10 @@ public class LocaleTracker extends Handler {
                }
                getCellInfo();
            } else {
                // If operator numeric is available, that means we camp on network. So reset the
                // fail cell info count.
                mFailCellInfoCount = 0;
                // If operator numeric is available, that means we camp on network. So we should
                // clear the cell info and stop cell info retry.
                if (mCellInfo != null) mCellInfo.clear();
                stopCellInfoRetry();
            }
            updateLocale();
        }
@@ -270,16 +315,26 @@ public class LocaleTracker extends Handler {
        return delay;
    }

    /**
     * Stop retrying getting cell info from the modem. It cancels any scheduled cell info retrieving
     * request.
     */
    private void stopCellInfoRetry() {
        mFailCellInfoCount = 0;
        removeMessages(EVENT_GET_CELL_INFO);
    }

    /**
     * Get cell info from the modem.
     */
    private void getCellInfo() {
        String msg;
        if (!mPhone.getServiceStateTracker().getDesiredPowerState()) {
            msg = "Radio is off. Skipped getting cell info. Cleared the previous cached cell info.";
            msg = "Radio is off. Stopped cell info retry. Cleared the previous cached cell info.";
            if (mCellInfo != null) mCellInfo.clear();
            if (DBG) log(msg);
            mLocalLog.log(msg);
            stopCellInfoRetry();
            return;
        }

@@ -293,12 +348,16 @@ public class LocaleTracker extends Handler {
            // If we can't get a valid cell info. Try it again later.
            long delay = getCellInfoDelayTime(++mFailCellInfoCount);
            if (DBG) log("Can't get cell info. Try again in " + delay / 1000 + " secs.");
            removeMessages(EVENT_GET_CELL_INFO);
            sendMessageDelayed(obtainMessage(EVENT_GET_CELL_INFO), delay);
        } else {
            mFailCellInfoCount = 0;
            // We successfully got cell info from the modem. Cancel the queued get cell info event
            // if there is any.
            removeMessages(EVENT_GET_CELL_INFO);
            // We successfully got cell info from the modem. We should stop cell info retry.
            stopCellInfoRetry();

            // Now we need to get the cell info from the modem periodically even if we already got
            // the cell info because the user can move.
            sendMessageDelayed(obtainMessage(EVENT_GET_CELL_INFO),
                    CELL_INFO_PERIODIC_POLLING_DELAY_MS);
        }
    }

+0 −2
Original line number Diff line number Diff line
@@ -1420,8 +1420,6 @@ public abstract class Phone extends Handler implements PhoneInternalInterface {
     */
    public void registerForServiceStateChanged(
            Handler h, int what, Object obj) {
        checkCorrectThread(h);

        mServiceStateRegistrants.add(h, what, obj);
    }

+21 −0
Original line number Diff line number Diff line
@@ -26,9 +26,11 @@ import static org.mockito.Mockito.verify;

import android.content.Context;
import android.net.wifi.WifiManager;
import android.os.AsyncResult;
import android.os.HandlerThread;
import android.telephony.CellIdentityGsm;
import android.telephony.CellInfoGsm;
import android.telephony.ServiceState;
import android.test.suitebuilder.annotation.SmallTest;

import org.junit.After;
@@ -160,4 +162,23 @@ public class LocaleTrackerTest extends TelephonyTest {
        assertEquals(US_COUNTRY_CODE, mLocaleTracker.getCurrentCountry());
        verify(mWifiManager).setCountryCode(US_COUNTRY_CODE, false);
    }

    @Test
    @SmallTest
    public void testOutOfAirplaneMode() throws Exception {
        doReturn(null).when(mPhone).getAllCellInfo(isNull());
        mLocaleTracker.updateOperatorNumericAsync("");
        waitForHandlerAction(mLocaleTracker, 100);
        assertEquals(COUNTRY_CODE_UNAVAILABLE, mLocaleTracker.getCurrentCountry());
        verify(mWifiManager).setCountryCode(COUNTRY_CODE_UNAVAILABLE, false);

        doReturn(Arrays.asList(mCellInfo)).when(mPhone).getAllCellInfo(isNull());
        ServiceState ss = new ServiceState();
        ss.setState(ServiceState.STATE_IN_SERVICE);
        AsyncResult ar = new AsyncResult(null, ss, null);
        mLocaleTracker.sendMessage(mLocaleTracker.obtainMessage(3, ar));
        waitForHandlerAction(mLocaleTracker, 100);
        assertEquals(US_COUNTRY_CODE, mLocaleTracker.getCurrentCountry());
        verify(mWifiManager).setCountryCode(US_COUNTRY_CODE, false);
    }
}