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

Commit c3203ef1 authored by Nathan Harold's avatar Nathan Harold Committed by android-build-merger
Browse files

Merge "Rework LocaleTracker to use Asynchronous CellInfo" am: 66052d3b

am: 1dc1624f

Change-Id: I2b0089345d9877299d444317c37e323c358231e0
parents 58eb0a11 1dc1624f
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.