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

Commit 66052d3b authored by Nathan Harold's avatar Nathan Harold Committed by Gerrit Code Review
Browse files

Merge "Rework LocaleTracker to use Asynchronous CellInfo"

parents 780ae8bd 575f3502
Loading
Loading
Loading
Loading
+110 −103
Original line number Diff line number Diff line
@@ -57,13 +57,19 @@ public class LocaleTracker extends Handler {
    private static final String TAG = LocaleTracker.class.getSimpleName();

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

    /** Event for operator numeric update */
    private static final int EVENT_UPDATE_OPERATOR_NUMERIC      = 2;
    private static final int EVENT_REQUEST_CELL_INFO = 1;

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

    /** Event for sim state changed */
    private static final int EVENT_SIM_STATE_CHANGED = 3;

    /** Event for incoming unsolicited cell info */
    private static final int EVENT_UNSOL_CELL_INFO = 4;

    /** Event for incoming cell info */
    private static final int EVENT_RESPONSE_CELL_INFO = 5;

    // Todo: Read this from Settings.
    /** The minimum delay to get cell info from the modem */
@@ -98,7 +104,9 @@ public class LocaleTracker extends Handler {
    private String mCurrentCountryIso;

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

    private boolean mIsTracking = false;

    private final LocalLog mLocalLog = new LocalLog(50);

@@ -109,8 +117,9 @@ public class LocaleTracker extends Handler {
            if (TelephonyManager.ACTION_SIM_CARD_STATE_CHANGED.equals(intent.getAction())) {
                int phoneId = intent.getIntExtra(PhoneConstants.PHONE_KEY, 0);
                if (phoneId == mPhone.getPhoneId()) {
                    onSimCardStateChanged(intent.getIntExtra(TelephonyManager.EXTRA_SIM_STATE,
                            TelephonyManager.SIM_STATE_UNKNOWN));
                    obtainMessage(EVENT_SIM_STATE_CHANGED,
                            intent.getIntExtra(TelephonyManager.EXTRA_SIM_STATE,
                                    TelephonyManager.SIM_STATE_UNKNOWN), 0).sendToTarget();
                }
            }
        }
@@ -124,19 +133,32 @@ public class LocaleTracker extends Handler {
    @Override
    public void handleMessage(Message msg) {
        switch (msg.what) {
            case EVENT_GET_CELL_INFO:
                synchronized (this) {
                    getCellInfo();
                    updateLocale();
                }
            case EVENT_REQUEST_CELL_INFO:
                mPhone.getAllCellInfo(null, obtainMessage(EVENT_RESPONSE_CELL_INFO));
                break;
            case EVENT_UPDATE_OPERATOR_NUMERIC:
                updateOperatorNumericSync((String) msg.obj);

            case EVENT_UNSOL_CELL_INFO:
                processCellInfo((AsyncResult) msg.obj);
                // If the unsol happened to be useful, use it; otherwise, pretend it didn't happen.
                if (mCellInfo != null && mCellInfo.size() > 0) requestNextCellInfo(true);
                break;

            case EVENT_RESPONSE_CELL_INFO:
                processCellInfo((AsyncResult) msg.obj);
                // If the cellInfo was non-empty then it's business as usual. Either way, this
                // cell info was requested by us, so it's our trigger to schedule another one.
                requestNextCellInfo(mCellInfo != null && mCellInfo.size() > 0);
                break;

            case EVENT_SERVICE_STATE_CHANGED:
                AsyncResult ar = (AsyncResult) msg.obj;
                onServiceStateChanged((ServiceState) ar.result);
                break;

            case EVENT_SIM_STATE_CHANGED:
                onSimCardStateChanged(msg.arg1);
                break;

            default:
                throw new IllegalStateException("Unexpected message arrives. msg = " + msg.what);
        }
@@ -158,6 +180,7 @@ public class LocaleTracker extends Handler {
        mPhone.getContext().registerReceiver(mBroadcastReceiver, filter);

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

    /**
@@ -166,7 +189,7 @@ public class LocaleTracker extends Handler {
     * @return The device's current country. Empty string if the information is not available.
     */
    @NonNull
    public synchronized String getCurrentCountry() {
    public String getCurrentCountry() {
        return (mCurrentCountryIso != null) ? mCurrentCountryIso : "";
    }

@@ -216,12 +239,9 @@ public class LocaleTracker extends Handler {
     * @param state SIM card state. Must be one of TelephonyManager.SIM_STATE_XXX.
     */
    private synchronized void onSimCardStateChanged(int state) {
        if (mSimState != state && state == TelephonyManager.SIM_STATE_ABSENT) {
            if (DBG) log("Sim absent. Get latest cell info from the modem.");
            getCellInfo();
            updateLocale();
        }
        mSimState = state;
        updateLocale();
        updateTrackingStatus();
    }

    /**
@@ -230,71 +250,57 @@ public class LocaleTracker extends Handler {
     * @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();
            }
        mLastServiceState = serviceState.getState();
        updateLocale();
            mLastServiceState = state;
        }
        updateTrackingStatus();
    }

    /**
     * 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,
     * the cached cell info will be used to determine the locale. If the cached cell info is not
     * acceptable, use {@link #updateOperatorNumericAsync(String)} instead.
     * Update MCC/MNC from network service state.
     *
     * @param operatorNumeric MCC/MNC of the operator
     */
    public synchronized void updateOperatorNumericSync(String operatorNumeric) {
    public void updateOperatorNumeric(String operatorNumeric) {
        // Check if the operator numeric changes.
        if (DBG) log("updateOperatorNumericSync. mcc/mnc=" + operatorNumeric);
        if (!Objects.equals(mOperatorNumeric, operatorNumeric)) {
            String msg = "Operator numeric changes to " + operatorNumeric;
            if (DBG) log(msg);
            mLocalLog.log(msg);
            mOperatorNumeric = operatorNumeric;

            // If the operator numeric becomes unavailable, we need to get the latest cell info so
            // that we can get MCC from it.
            if (TextUtils.isEmpty(mOperatorNumeric)) {
                if (DBG) {
                    log("Operator numeric unavailable. Get latest cell info from the modem.");
            updateLocale();
        }
                getCellInfo();
            } else {
                // 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();

    private void processCellInfo(AsyncResult ar) {
        if (ar == null || ar.exception != null) {
            mCellInfo = null;
            return;
        }
        mCellInfo = (List<CellInfo>) ar.result;
        String msg = "getCellInfo: cell info=" + mCellInfo;
        if (DBG) log(msg);
        mLocalLog.log(msg);
        updateLocale();
    }

    /**
     * Update MCC/MNC from network service state asynchronously. The update operation will run
     * in locale tracker's handler's thread, which can get cell info synchronously from service
     * state tracker. Note that the country code will not be available immediately after calling
     * this method.
     *
     * @param operatorNumeric MCC/MNC of the operator
     */
    public void updateOperatorNumericAsync(String operatorNumeric) {
        if (DBG) log("updateOperatorNumericAsync. mcc/mnc=" + operatorNumeric);
        sendMessage(obtainMessage(EVENT_UPDATE_OPERATOR_NUMERIC, operatorNumeric));
    private void requestNextCellInfo(boolean succeeded) {
        if (!mIsTracking) return;

        removeMessages(EVENT_REQUEST_CELL_INFO);
        if (succeeded) {
            resetCellInfoRetry();
            // 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.
            removeMessages(EVENT_UNSOL_CELL_INFO);
            removeMessages(EVENT_RESPONSE_CELL_INFO);
            sendMessageDelayed(obtainMessage(EVENT_REQUEST_CELL_INFO),
                    CELL_INFO_PERIODIC_POLLING_DELAY_MS);
        } else {
            // 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.");
            sendMessageDelayed(obtainMessage(EVENT_REQUEST_CELL_INFO), delay);
        }
    }

    /**
@@ -319,52 +325,47 @@ public class LocaleTracker extends Handler {
     * Stop retrying getting cell info from the modem. It cancels any scheduled cell info retrieving
     * request.
     */
    private void stopCellInfoRetry() {
    private void resetCellInfoRetry() {
        mFailCellInfoCount = 0;
        removeMessages(EVENT_GET_CELL_INFO);
        removeMessages(EVENT_REQUEST_CELL_INFO);
    }

    /**
     * Get cell info from the modem.
     */
    private void getCellInfo() {
        String msg;
        if (!mPhone.getServiceStateTracker().getDesiredPowerState()) {
            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;
    private void updateTrackingStatus() {
        boolean shouldTrackLocale =
                (mSimState == TelephonyManager.SIM_STATE_ABSENT
                        || TextUtils.isEmpty(mOperatorNumeric))
                && (mLastServiceState == ServiceState.STATE_OUT_OF_SERVICE
                        || mLastServiceState == ServiceState.STATE_EMERGENCY_ONLY);
        if (shouldTrackLocale) {
            startTracking();
        } else {
            stopTracking();
        }
    }

        // FIXME: This needs to use the async version of getAllCellInfo()
        mCellInfo = mPhone.getAllCellInfo();
        msg = "getCellInfo: cell info=" + mCellInfo;
    private void stopTracking() {
        if (!mIsTracking) return;
        mIsTracking = false;
        String msg = "Stopping LocaleTracker";
        if (DBG) log(msg);
        mLocalLog.log(msg);

        if (mCellInfo == null || mCellInfo.size() == 0) {
            // 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 {
            // 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);
        mCellInfo = null;
        resetCellInfoRetry();
    }

    private void startTracking() {
        if (mIsTracking) return;
        String msg = "Starting LocaleTracker";
        mLocalLog.log(msg);
        if (DBG) log(msg);
        mIsTracking = true;
        sendMessage(obtainMessage(EVENT_REQUEST_CELL_INFO));
    }

    /**
     * Update the device's current locale
     */
    private void updateLocale() {
    private synchronized void updateLocale() {
        // If MCC is available from network service state, use it first.
        String mcc = null;
        String countryIso = "";
@@ -405,6 +406,11 @@ public class LocaleTracker extends Handler {
        }
    }

    /** Exposed for testing purposes */
    public boolean isTracking() {
        return mIsTracking;
    }

    private void log(String msg) {
        Rlog.d(TAG, msg);
    }
@@ -424,6 +430,7 @@ public class LocaleTracker extends Handler {
        final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, "  ");
        pw.println("LocaleTracker:");
        ipw.increaseIndent();
        ipw.println("mIsTracking = " + mIsTracking);
        ipw.println("mOperatorNumeric = " + mOperatorNumeric);
        ipw.println("mSimState = " + mSimState);
        ipw.println("mCellInfo = " + mCellInfo);
+24 −0
Original line number Diff line number Diff line
@@ -348,6 +348,8 @@ public abstract class Phone extends Handler implements PhoneInternalInterface {
    protected final RegistrantList mEmergencyCallToggledRegistrants
            = new RegistrantList();

    private final RegistrantList mCellInfoRegistrants = new RegistrantList();

    protected Registrant mPostDialHandler;

    private Looper mLooper; /* to insure registrants are in correct thread*/
@@ -873,6 +875,7 @@ public abstract class Phone extends Handler implements PhoneInternalInterface {
        migrate(mMmiRegistrants, from.mMmiRegistrants);
        migrate(mUnknownConnectionRegistrants, from.mUnknownConnectionRegistrants);
        migrate(mSuppServiceFailedRegistrants, from.mSuppServiceFailedRegistrants);
        migrate(mCellInfoRegistrants, from.mCellInfoRegistrants);
        if (from.isInEmergencyCall()) {
            setIsInEmergencyCall();
        }
@@ -1485,6 +1488,24 @@ public abstract class Phone extends Handler implements PhoneInternalInterface {
        mCi.unregisterForResendIncallMute(h);
    }

    /**
     * Registers for CellInfo changed.
     * Message.obj will contain an AsyncResult.
     * AsyncResult.result will be a List<CellInfo> instance
     */
    public void registerForCellInfo(
            Handler h, int what, Object obj) {
        mCellInfoRegistrants.add(h, what, obj);
    }

    /**
     * Unregisters for CellInfo notification.
     * Extraneous calls are tolerated silently
     */
    public void unregisterForCellInfo(Handler h) {
        mCellInfoRegistrants.remove(h);
    }

    /**
     * Enables or disables echo suppression.
     */
@@ -2178,6 +2199,9 @@ public abstract class Phone extends Handler implements PhoneInternalInterface {
    }

    public void notifyCellInfo(List<CellInfo> cellInfo) {
        AsyncResult ar = new AsyncResult(null, cellInfo, null);
        mCellInfoRegistrants.notifyRegistrants(ar);

        mNotifier.notifyCellInfo(this, cellInfo);
    }

+3 −10
Original line number Diff line number Diff line
@@ -37,7 +37,6 @@ import android.os.AsyncResult;
import android.os.BaseBundle;
import android.os.Build;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Message;
import android.os.PersistableBundle;
import android.os.Registrant;
@@ -278,7 +277,6 @@ public class ServiceStateTracker extends Handler {

    private final RatRatcheter mRatRatcheter;

    private final HandlerThread mHandlerThread;
    private final LocaleTracker mLocaleTracker;

    private final LocalLog mRoamingLog = new LocalLog(10);
@@ -522,12 +520,8 @@ public class ServiceStateTracker extends Handler {
                    this, EVENT_NETWORK_STATE_CHANGED, null);
        }

        // Create a new handler thread dedicated for locale tracker because the blocking
        // getAllCellInfo call requires clients calling from a different thread.
        mHandlerThread = new HandlerThread(LocaleTracker.class.getSimpleName());
        mHandlerThread.start();
        mLocaleTracker = TelephonyComponentFactory.getInstance().makeLocaleTracker(
                mPhone, mHandlerThread.getLooper());
                mPhone, getLooper());

        mCi.registerForImsNetworkStateChanged(this, EVENT_IMS_STATE_CHANGED, null);
        mCi.registerForRadioStateChanged(this, EVENT_RADIO_STATE_CHANGED, null);
@@ -683,7 +677,6 @@ public class ServiceStateTracker extends Handler {
        mCi.unregisterForPhysicalChannelConfiguration(this);
        mSubscriptionManager
            .removeOnSubscriptionsChangedListener(mOnSubscriptionsChangedListener);
        mHandlerThread.quit();
        mCi.unregisterForImsNetworkStateChanged(this);
        mPhone.getCarrierActionAgent().unregisterForCarrierAction(this,
                CARRIER_ACTION_SET_RADIO_ENABLED);
@@ -2994,7 +2987,7 @@ public class ServiceStateTracker extends Handler {
                // Passing empty string is important for the first update. The initial value of
                // operator numeric in locale tracker is null. The async update will allow getting
                // cell info from the modem instead of using the cached one.
                mLocaleTracker.updateOperatorNumericAsync("");
                mLocaleTracker.updateOperatorNumeric("");
                mNitzState.handleNetworkUnavailable();
            } else if (mSS.getRilDataRadioTechnology() != ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN) {
                // If the device is on IWLAN, modems manufacture a ServiceState with the MCC/MNC of
@@ -3006,7 +2999,7 @@ public class ServiceStateTracker extends Handler {
                    setOperatorIdd(operatorNumeric);
                }

                mLocaleTracker.updateOperatorNumericSync(operatorNumeric);
                mLocaleTracker.updateOperatorNumeric(operatorNumeric);
                String countryIsoCode = mLocaleTracker.getCurrentCountry();

                // Update Time Zone.
+58 −57

File changed.

Preview size limit exceeded, changes collapsed.