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

Commit aa4b4df0 authored by Chen Xu's avatar Chen Xu Committed by Android (Google) Code Review
Browse files

Merge "Cold Sim fix for DataConnection and DCT" into nyc-dev

parents f889d7da a02b6fd8
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