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

Commit a02b6fd8 authored by fionaxu's avatar fionaxu
Browse files

Cold Sim fix for DataConnection and DCT

Bug: 25203607
Change-Id: I3bbef77edf57eaa8d7da24d687cc9b5ab0ef111b
parent 2707808f
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -127,6 +127,10 @@ public class ServiceStateTracker extends Handler {
    static public final int OTASP_UNKNOWN = 1;
    static public final int OTASP_NEEDED = 2;
    static public final int OTASP_NOT_NEEDED = 3;
    /**
     * OtaUtil has conflict enum 4: OtaUtils.OTASP_FAILURE_SPC_RETRIES
     */
    static public final int OTASP_SIM_UNPROVISIONED = 5;

    /**
     * A unique identifier to track requests associated with a poll
+51 −6
Original line number Diff line number Diff line
@@ -290,12 +290,16 @@ public class SubscriptionController extends ISub.Stub {
        // FIXME: consider stick this into database too
        String countryIso = getSubscriptionCountryIso(id);

        int simProvisioningStatus = cursor.getInt(cursor.getColumnIndexOrThrow(
                SubscriptionManager.SIM_PROVISIONING_STATUS));

        if (VDBG) {
            String iccIdToPrint = SubscriptionInfo.givePrintableIccid(iccId);
            logd("[getSubInfoRecord] id:" + id + " iccid:" + iccIdToPrint + " simSlotIndex:" + simSlotIndex
                + " displayName:" + displayName + " nameSource:" + nameSource
            logd("[getSubInfoRecord] id:" + id + " iccid:" + iccIdToPrint + " simSlotIndex:"
                    + simSlotIndex + " displayName:" + displayName + " nameSource:" + nameSource
                    + " iconTint:" + iconTint + " dataRoaming:" + dataRoaming
                + " mcc:" + mcc + " mnc:" + mnc + " countIso:" + countryIso);
                    + " mcc:" + mcc + " mnc:" + mnc + " countIso:" + countryIso
                    + " simProvisioningStatus:" + simProvisioningStatus);
        }

        // If line1number has been set to a different number, use it instead.
@@ -304,7 +308,8 @@ public class SubscriptionController extends ISub.Stub {
            number = line1Number;
        }
        return new SubscriptionInfo(id, iccId, simSlotIndex, displayName, carrierName,
                nameSource, iconTint, number, dataRoaming, iconBitmap, mcc, mnc, countryIso);
                nameSource, iconTint, number, dataRoaming, iconBitmap, mcc, mnc, countryIso,
                simProvisioningStatus);
    }

    /**
@@ -1094,6 +1099,46 @@ public class SubscriptionController extends ISub.Stub {
        return result;
    }

    /**
     * Set SimProvisioning Status by subscription ID
     * @param provisioningStatus with the subscription:
     * {@See SubscriptionManager#SIM_PROVISIONED}
     * {@See SubscriptionManager#SIM_UNPROVISIONED_COLD}
     * {@See SubscriptionManager#SIM_UNPROVISIONED_OUT_OF_CREDIT}
     * @param subId the unique SubInfoRecord index in database
     * @return the number of records updated
     */
    @Override
    public int setSimProvisioningStatus(int provisioningStatus, int subId) {

        if (DBG) {
            logd("[setSimProvisioningStatus]+ provisioningStatus:" + provisioningStatus + " subId:"
                    + subId);
        }

        enforceModifyPhoneState("setSimProvisioningStatus");
        // Now that all security checks passes, perform the operation as ourselves.
        final long identity = Binder.clearCallingIdentity();
        try {
            validateSubId(subId);
            if (provisioningStatus < 0 || provisioningStatus >
                    SubscriptionManager.MAX_SIM_PROVISIONING_STATUS) {
                logd("[setSimProvisioningStatus]- fail with wrong provisioningStatus");
                return -1;
            }
            ContentValues value = new ContentValues(1);
            value.put(SubscriptionManager.SIM_PROVISIONING_STATUS, provisioningStatus);

            int result = mContext.getContentResolver().update(SubscriptionManager.CONTENT_URI,
                    value, SubscriptionManager.UNIQUE_KEY_SUBSCRIPTION_ID + "=" +
                            Long.toString(subId), null);
            notifySubscriptionInfoChanged();

            return result;
        } finally {
            Binder.restoreCallingIdentity(identity);
        }
    }

    @Override
    public int getSlotId(int subId) {
+13 −0
Original line number Diff line number Diff line
@@ -1800,6 +1800,19 @@ public class DataConnection extends StateMachine {
                mPhone.mCi.pullLceData(DataConnection.this.obtainMessage(EVENT_BW_REFRESH_RESPONSE));
            }
        }

        @Override
        protected void networkStatus(int status, String redirectUrl) {
            if(!TextUtils.isEmpty(redirectUrl)) {
                log("validation status: " + status + " with redirection URL: " + redirectUrl);
                /* its possible that we have multiple DataConnection with INTERNET_CAPABILITY
                   all fail the validation with the same redirection url, send CMD back to DCTracker
                   and let DcTracker to make the decision */
                Message msg = mDct.obtainMessage(DctConstants.EVENT_REDIRECTION_DETECTED,
                        redirectUrl);
                msg.sendToTarget();
            }
        }
    }

    // ******* "public" interface
+143 −4
Original line number Diff line number Diff line
@@ -27,10 +27,12 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.database.ContentObserver;
import android.database.Cursor;
import android.net.ConnectivityManager;
import android.net.ConnectivityManager.NetworkCallback;
import android.net.LinkProperties;
import android.net.NetworkCapabilities;
import android.net.NetworkConfig;
@@ -48,6 +50,7 @@ import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import android.os.PersistableBundle;
import android.os.RegistrantList;
import android.os.ServiceManager;
import android.os.SystemClock;
@@ -56,8 +59,10 @@ import android.preference.PreferenceManager;
import android.provider.Settings;
import android.provider.Settings.SettingNotFoundException;
import android.provider.Telephony;
import android.telephony.CarrierConfigManager;
import android.telephony.CellLocation;
import android.telephony.ServiceState;
import android.telephony.SubscriptionInfo;
import android.telephony.TelephonyManager;
import android.telephony.SubscriptionManager;
import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener;
@@ -80,6 +85,8 @@ import com.android.internal.telephony.EventLogTags;
import com.android.internal.telephony.ITelephony;
import com.android.internal.telephony.PhoneConstants;
import com.android.internal.telephony.RILConstants;
import com.android.internal.telephony.SubscriptionController;
import com.android.internal.telephony.TelephonyIntents;
import com.android.internal.telephony.uicc.IccRecords;
import com.android.internal.telephony.uicc.UiccController;
import com.android.internal.util.AsyncChannel;
@@ -166,6 +173,10 @@ public class DcTracker extends Handler {
    private static final String INTENT_DATA_STALL_ALARM =
            "com.android.internal.telephony.data-stall";

    private static final String REDIRECTION_URL_KEY = "redirectionUrl";
    private static final String ERROR_CODE_KEY = "errorCode";
    private static final String APN_TYPE_KEY = "apnType";

    private DcTesterFailBringUpAll mDcTesterFailBringUpAll;
    private DcController mDcc;

@@ -310,6 +321,8 @@ public class DcTracker extends Handler {
                    int subId = mPhone.getSubId();
                    if (SubscriptionManager.isValidSubscriptionId(subId)) {
                        registerSettingsObserver();
                         /* check if sim is un-provisioned due to cold sim detection */
                        applyColdSimDetected(subId);
                    }
                    if (mPreviousSubId.getAndSet(subId) != subId &&
                            SubscriptionManager.isValidSubscriptionId(subId)) {
@@ -563,6 +576,14 @@ public class DcTracker extends Handler {

    private int mDisconnectPendingCount = 0;

    /** mRedirected is set to true when we first got the validation failure with the redirection URL
     * based on this value we start the Carrier App to check the sim state */
    private boolean mRedirected = false;

    /** mColdSimDetected is set to true when we received SubInfoChanged &&
     * SubscriptionInfo.simProvisioningStatus equals to SIM_UNPROVISIONED_COLD */
    private boolean mColdSimDetected = false;

    /**
     * Handles changes to the APN db.
     */
@@ -895,6 +916,22 @@ public class DcTracker extends Handler {
        return true;
    }

    /**
     * Called when there is any change to any SubscriptionInfo Typically
     * this method invokes {@link SubscriptionManager#getActiveSubscriptionInfoList}
     */
    private boolean isColdSimDetected(int subId) {
        final SubscriptionInfo subInfo = mSubscriptionManager.getActiveSubscriptionInfo(subId);
        if (subInfo != null) {
            final int simProvisioningStatus = subInfo.getSimProvisioningStatus();
            if(simProvisioningStatus == SubscriptionManager.SIM_UNPROVISIONED_COLD) {
                log("Cold Sim Detected on SubId: " + subId);
                return true;
            }
        }
        return false;
    }

    public int getApnPriority(String name) {
        ApnContext apnContext = mApnContexts.get(name);
        if (apnContext == null) {
@@ -1471,7 +1508,7 @@ public class DcTracker extends Handler {
        StringBuilder failureReason = new StringBuilder();
        if (apnContext.isConnectable() && (isEmergencyApn ||
                (isDataAllowed(failureReason) && isDataAllowedForApn(apnContext) &&
                getAnyDataEnabled(checkUserDataEnabled) && !isEmergency()))) {
                getAnyDataEnabled(checkUserDataEnabled) && !isEmergency())) && !mColdSimDetected) {
            if (apnContext.getState() == DctConstants.State.FAILED) {
                String str ="trySetupData: make a FAILED ApnContext IDLE so its reusable";
                if (DBG) log(str);
@@ -1537,6 +1574,9 @@ public class DcTracker extends Handler {
            if (isEmergency()) {
                str.append("emergency = true");
            }
            if(mColdSimDetected) {
                str.append("coldSimDetected = true");
            }

            if (DBG) log(str.toString());
            apnContext.requestLog(str.toString());
@@ -2280,6 +2320,24 @@ public class DcTracker extends Handler {
        setupDataOnConnectableApns(Phone.REASON_SIM_LOADED);
    }

    private void applyColdSimDetected(int subId) {
        if(isColdSimDetected(subId)) {
            if(!mColdSimDetected) {
                if(DBG) {
                    log("onColdSimDetected on subId " + subId +": cleanUpAllDataConnections");
                }
                cleanUpAllConnections(null);
                //send otasp_sim_unprovisioned so that SuW is able to proceed and notify users
                mPhone.notifyOtaspChanged(ServiceStateTracker.OTASP_SIM_UNPROVISIONED);
                mColdSimDetected = true;
            }
        } else {
            if (DBG) log("onColdSimDetected on subId: " + + subId + " reset coldSimDetected");
            mColdSimDetected = false;
            mRedirected = false;
        }
    }

    private void onSimNotReady() {
        if (DBG) log("onSimNotReady");

@@ -2841,6 +2899,12 @@ public class DcTracker extends Handler {
            mPhone.notifyPreciseDataConnectionFailed(apnContext.getReason(),
                    apnContext.getApnType(), apn != null ? apn.apn : "unknown", cause.toString());

            //compose broadcast intent send to the specific carrier apps
            Intent intent = new Intent(TelephonyIntents.ACTION_REQUEST_NETWORK_FAILED);
            intent.putExtra(ERROR_CODE_KEY, cause.getErrorCode());
            intent.putExtra(APN_TYPE_KEY, apnContext.getApnType());
            notifyCarrierAppWithIntent(intent);

            if (cause.isRestartRadioFail() || apnContext.restartOnError(cause.getErrorCode())) {
                if (DBG) log("Modem restarted.");
                sendRestartRadio();
@@ -2924,6 +2988,45 @@ public class DcTracker extends Handler {
        }
    }

    /**
     * Read Carrier App name from CarrierConfig
     * @return String[0] Package name, String[1] Activity name
     */
    private String[] getActivationAppName() {
        CarrierConfigManager configManager = (CarrierConfigManager) mPhone.getContext()
                .getSystemService(Context.CARRIER_CONFIG_SERVICE);
        PersistableBundle b = null;
        String[] activationApp;

       if (configManager != null) {
            b = configManager.getConfig();
        }
        if (b != null) {
            activationApp = b.getStringArray(CarrierConfigManager
                    .KEY_SIM_PROVISIONING_STATUS_DETECTION_CARRIER_APP_STRING_ARRAY);
        } else {
            // Return static default defined in CarrierConfigManager.
            activationApp = CarrierConfigManager.getDefaultConfig().getStringArray
                    (CarrierConfigManager
                            .KEY_SIM_PROVISIONING_STATUS_DETECTION_CARRIER_APP_STRING_ARRAY);
        }
        return activationApp;
    }

    /**
     * Called when EVENT_REDIRECTION_DETECTED is received.
     */
    private void onDataConnectionRedirected(String redirectUrl) {
        if (!TextUtils.isEmpty(redirectUrl)) {
            mRedirected = true;
            Intent intent = new Intent(TelephonyIntents.ACTION_DATA_CONNECTION_REDIRECTED);
            intent.putExtra(REDIRECTION_URL_KEY, redirectUrl);
            if(notifyCarrierAppWithIntent(intent)) {
                log("Starting Activation Carrier app with redirectUrl : " + redirectUrl);
            }
        }
    }

    /**
     * Called when EVENT_DISCONNECT_DONE is received.
     */
@@ -2958,7 +3061,6 @@ public class DcTracker extends Handler {
                return;
            }
        }

        // If APN is still enabled, try to bring it back up automatically
        if (mAttached.get() && apnContext.isReady() && retryAfterDisconnected(apnContext)) {
            try {
@@ -3617,6 +3719,10 @@ public class DcTracker extends Handler {
                onDeviceProvisionedChange();
                break;

            case DctConstants.EVENT_REDIRECTION_DETECTED:
                log("dataConnectionTracker.handleMessage: EVENT_REDIRECTION_DETECTED=" + msg);
                onDataConnectionRedirected((String) msg.obj);

            case DctConstants.EVENT_RADIO_AVAILABLE:
                onRadioAvailable();
                break;
@@ -3632,6 +3738,7 @@ public class DcTracker extends Handler {
            case DctConstants.EVENT_DATA_SETUP_COMPLETE_ERROR:
                onDataSetupCompleteError((AsyncResult) msg.obj);
                break;

            case DctConstants.EVENT_DISCONNECT_DONE:
                log("DataConnectionTracker.handleMessage: EVENT_DISCONNECT_DONE msg=" + msg);
                onDisconnectDone((AsyncResult) msg.obj);
@@ -3866,6 +3973,8 @@ public class DcTracker extends Handler {
                    mIccRecords.set(newIccRecords);
                    newIccRecords.registerForRecordsLoaded(
                            this, DctConstants.EVENT_RECORDS_LOADED, null);
                    SubscriptionController.getInstance().setSimProvisioningStatus(
                            SubscriptionManager.SIM_PROVISIONED, mPhone.getSubId());
                }
            } else {
                onSimNotReady();
@@ -3902,6 +4011,36 @@ public class DcTracker extends Handler {
        sendMessage(msg);
    }

    private boolean notifyCarrierAppWithIntent(Intent intent) {
        //read from carrier config manager
        String[] activationApp = getActivationAppName();
        if(activationApp == null || activationApp.length != 2) {
            return false;
        }

        intent.setClassName(activationApp[0], activationApp[1]);
        intent.putExtra(PhoneConstants.SUBSCRIPTION_KEY, mPhone.getSubId());
        //check if Activation App is available */
        final PackageManager packageManager = mPhone.getContext().getPackageManager();
        if (packageManager.queryBroadcastReceivers(intent,
                PackageManager.MATCH_DEFAULT_ONLY).isEmpty()) {
            loge("Activation Carrier app is configured, but not available: "
                    + activationApp[0] + "." + activationApp[1]);
            return false;
        }

        try {
            mPhone.getContext().sendBroadcast(intent);
        } catch (ActivityNotFoundException e) {
            loge("sendBroadcast failed: " + e);
            return false;
        }

        if (DBG) log("send Intent to : " + activationApp[0] + "." + activationApp[1]
                + " with action: " + intent.getAction());
        return true;
    }

    private void notifyDataDisconnectComplete() {
        log("notifyDataDisconnectComplete");
        for (Message m: mDisconnectAllCompleteMsgList) {
+3 −1
Original line number Diff line number Diff line
@@ -15,6 +15,7 @@
 */
package com.android.internal.telephony;

import android.telephony.SubscriptionManager;
import android.test.suitebuilder.annotation.SmallTest;
import static org.junit.Assert.*;
import org.junit.After;
@@ -34,7 +35,8 @@ public class SubscriptionInfoTest {
    @Before
    public void setUp() throws Exception {
        mSubscriptionInfoUT = new SubscriptionInfo(1, "890126042XXXXXXXXXXX", 0, "T-mobile",
                "T-mobile", 0, 255, "12345", 0, null, 310, 260, "156");
                "T-mobile", 0, 255, "12345", 0, null, 310, 260, "156",
                SubscriptionManager.SIM_PROVISIONED);
    }

    @Test