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

Commit cb2776db authored by Xiangyu/Malcolm Chen's avatar Xiangyu/Malcolm Chen Committed by android-build-merger
Browse files

Merge "Providing a way for user to allow MMS data even if mobile data is off."

am: 346fbe85

Change-Id: Ied1293f63e05acaeebc74e6daced04d9fcba998b
parents 954eac51 346fbe85
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -143,6 +143,8 @@ public class MultiSimSettingController {
    /**
     * When a subscription group is created or new subscriptions are added in the group, make
     * sure the settings among them are synced.
     * TODO: b/130258159 have a separate database table for grouped subscriptions so we don't
     * manually sync each setting.
     */
    public synchronized void onSubscriptionGroupChanged(ParcelUuid groupUuid) {
        if (DBG) log("onSubscriptionGroupChanged");
@@ -186,6 +188,9 @@ public class MultiSimSettingController {
                    mContext, Settings.Global.DATA_ROAMING, INVALID_SUBSCRIPTION_ID, enable);
            onRoamingDataEnabled(refSubId, enable);
        }

        // Sync settings in subscription database..
        mSubController.syncGroupedSetting(refSubId);
    }

    /**
+2 −0
Original line number Diff line number Diff line
@@ -156,6 +156,8 @@ public interface PhoneInternalInterface {
            "carrierActionDisableMeteredApn";
    static final String REASON_CSS_INDICATOR_CHANGED = "cssIndicatorChanged";
    static final String REASON_RELEASED_BY_CONNECTIVITY_SERVICE = "releasedByConnectivityService";
    static final String REASON_APN_ADDED_TO_WHITELIST = "apnAddedToWhiteList";
    static final String REASON_APN_REMOVED_FROM_WHITELIST = "apnRemovedFromWhiteList";

    // Used for band mode selection methods
    static final int BM_UNSPECIFIED = RILConstants.BAND_MODE_UNSPECIFIED; // automatic
+65 −0
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package com.android.internal.telephony;

import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.telephony.data.ApnSetting.TYPE_MMS;

import android.Manifest;
import android.annotation.Nullable;
@@ -39,6 +40,7 @@ import android.os.UserHandle;
import android.provider.Settings;
import android.telecom.PhoneAccountHandle;
import android.telecom.TelecomManager;
import android.telephony.AccessNetworkConstants;
import android.telephony.CarrierConfigManager;
import android.telephony.RadioAccessFamily;
import android.telephony.Rlog;
@@ -47,6 +49,7 @@ import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.telephony.UiccAccessRule;
import android.telephony.UiccSlotInfo;
import android.telephony.data.ApnSetting;
import android.telephony.euicc.EuiccManager;
import android.text.TextUtils;
import android.text.format.Time;
@@ -1725,6 +1728,17 @@ public class SubscriptionController extends ISub.Stub {
        }
    }


    public void syncGroupedSetting(int refSubId) {
        // Currently it only syncs allow MMS. Sync other settings as well if needed.
        int apnWhiteList = Integer.valueOf(getSubscriptionProperty(
                refSubId, SubscriptionManager.WHITE_LISTED_APN_DATA, mContext.getOpPackageName()));

        ContentValues value = new ContentValues(1);
        value.put(SubscriptionManager.WHITE_LISTED_APN_DATA, apnWhiteList);
        databaseUpdateHelper(value, refSubId, true);
    }

    private int databaseUpdateHelper(ContentValues value, int subId, boolean updateEntireGroup) {
        List<SubscriptionInfo> infoList = getSubscriptionsInGroup(getGroupUuid(subId),
                mContext.getOpPackageName());
@@ -2578,6 +2592,7 @@ public class SubscriptionController extends ISub.Stub {
                        case SubscriptionManager.WFC_IMS_ROAMING_ENABLED:
                        case SubscriptionManager.IS_OPPORTUNISTIC:
                        case SubscriptionManager.GROUP_UUID:
                        case SubscriptionManager.WHITE_LISTED_APN_DATA:
                            resultValue = cursor.getInt(0) + "";
                            break;
                        default:
@@ -3512,4 +3527,54 @@ public class SubscriptionController extends ISub.Stub {
                    PendingIntent.getService(mContext, 0, new Intent(), 0));
        }
    }

    @Override
    public boolean setAlwaysAllowMmsData(int subId, boolean alwaysAllow) {
        if (DBG) logd("[setAlwaysAllowMmsData]+ alwaysAllow:" + alwaysAllow + " subId:" + subId);

        enforceModifyPhoneState("setAlwaysAllowMmsData");

        // Now that all security checks passes, perform the operation as ourselves.
        final long identity = Binder.clearCallingIdentity();
        try {
            validateSubId(subId);

            ContentValues value = new ContentValues(1);
            int apnWhiteList = Integer.valueOf(getSubscriptionProperty(subId,
                    SubscriptionManager.WHITE_LISTED_APN_DATA, mContext.getOpPackageName()));
            apnWhiteList = alwaysAllow ? (apnWhiteList | TYPE_MMS) : (apnWhiteList & ~TYPE_MMS);
            value.put(SubscriptionManager.WHITE_LISTED_APN_DATA, apnWhiteList);
            if (DBG) logd("[setAlwaysAllowMmsData]- alwaysAllow:" + alwaysAllow + " set");

            boolean result = databaseUpdateHelper(value, subId, true) > 0;

            if (result) {
                // Refresh the Cache of Active Subscription Info List
                refreshCachedActiveSubscriptionInfoList();
                notifySubscriptionInfoChanged();
                Phone phone = PhoneFactory.getPhone(getPhoneId(subId));
                if (phone != null) {
                    phone.getDcTracker(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)
                            .notifyApnWhiteListChange(TYPE_MMS, alwaysAllow);
                }
            }

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

    /**
     *  whether apnType is whitelisted. Being white listed means data connection is allowed
     *  even if user data is turned off.
     */
    public boolean isApnWhiteListed(int subId, String callingPackage, int apnType) {
        return (getWhiteListedApnDataTypes(subId, callingPackage) & apnType) == apnType;
    }

    private @ApnSetting.ApnType int getWhiteListedApnDataTypes(int subId, String callingPackage) {
        return Integer.valueOf(getSubscriptionProperty(subId,
                SubscriptionManager.WHITE_LISTED_APN_DATA, callingPackage));
    }
}
+9 −0
Original line number Diff line number Diff line
@@ -289,6 +289,15 @@ public class DataEnabledSettings {
        return (info != null) && info.isOpportunistic() && info.getGroupUuid() == null;
    }

    public synchronized boolean isDataEnabled(int apnType) {
        boolean userDataEnabled = isUserDataEnabled();
        boolean isApnWhiteListed = SubscriptionController.getInstance().isApnWhiteListed(
                mPhone.getSubId(), mPhone.getContext().getOpPackageName(), apnType);

        return (mInternalDataEnabled && mPolicyDataEnabled && mCarrierDataEnabled
                && (userDataEnabled || isApnWhiteListed));
    }

    private void log(String s) {
        Rlog.d(LOG_TAG, "[" + mPhone.getPhoneId() + "]" + s);
    }
+99 −47
Original line number Diff line number Diff line
@@ -1212,7 +1212,7 @@ public class DcTracker extends Handler {
        if (mAutoAttachOnCreationConfig) {
            mAutoAttachEnabled.set(true);
        }
        setupDataOnConnectableApns(Phone.REASON_DATA_ATTACHED, RetryFailures.ALWAYS);
        setupDataOnAllConnectableApns(Phone.REASON_DATA_ATTACHED, RetryFailures.ALWAYS);
    }

    /**
@@ -1338,7 +1338,11 @@ public class DcTracker extends Handler {
        if (!radioStateFromCarrier) {
            reasons.add(DataDisallowedReasonType.RADIO_DISABLED_BY_CARRIER);
        }
        if (!mDataEnabledSettings.isDataEnabled()) {

        boolean isDataEnabled = apnContext == null ? mDataEnabledSettings.isDataEnabled()
                : mDataEnabledSettings.isDataEnabled(apnContext.getApnTypeBitmask());

        if (!isDataEnabled) {
            reasons.add(DataDisallowedReasonType.DATA_DISABLED);
        }

@@ -1382,7 +1386,7 @@ public class DcTracker extends Handler {
        return reasons.allowed();
    }

    // arg for setupDataOnConnectableApns
    // arg for setupDataOnAllConnectableApns
    private enum RetryFailures {
        // retry failed networks always (the old default)
        ALWAYS,
@@ -1392,8 +1396,8 @@ public class DcTracker extends Handler {
        ONLY_ON_CHANGE
    };

    private void setupDataOnConnectableApns(String reason, RetryFailures retryFailures) {
        if (VDBG) log("setupDataOnConnectableApns: " + reason);
    private void setupDataOnAllConnectableApns(String reason, RetryFailures retryFailures) {
        if (VDBG) log("setupDataOnAllConnectableApns: " + reason);

        if (DBG && !VDBG) {
            StringBuilder sb = new StringBuilder(120);
@@ -1405,18 +1409,24 @@ public class DcTracker extends Handler {
                sb.append(apnContext.isEnabled());
                sb.append("] ");
            }
            log("setupDataOnConnectableApns: " + reason + " " + sb);
            log("setupDataOnAllConnectableApns: " + reason + " " + sb);
        }

        for (ApnContext apnContext : mPrioritySortedApnContexts) {
            if (VDBG) log("setupDataOnConnectableApns: apnContext " + apnContext);
            setupDataOnConnectableApn(apnContext, reason, retryFailures);
        }
    }

    private void setupDataOnConnectableApn(ApnContext apnContext, String reason,
            RetryFailures retryFailures) {
        if (VDBG) log("setupDataOnAllConnectableApns: apnContext " + apnContext);

        if (apnContext.getState() == DctConstants.State.FAILED
                || apnContext.getState() == DctConstants.State.RETRYING) {
            if (retryFailures == RetryFailures.ALWAYS) {
                apnContext.releaseDataConnection(reason);
                } else if (apnContext.isConcurrentVoiceAndDataAllowed() == false &&
                        mPhone.getServiceStateTracker().isConcurrentVoiceAndDataAllowed()) {
            } else if (!apnContext.isConcurrentVoiceAndDataAllowed()
                    && mPhone.getServiceStateTracker().isConcurrentVoiceAndDataAllowed()) {
                // RetryFailures.ONLY_ON_CHANGE - check if voice concurrency has changed
                apnContext.releaseDataConnection(reason);
            }
@@ -1427,7 +1437,6 @@ public class DcTracker extends Handler {
            trySetupData(apnContext, REQUEST_TYPE_NORMAL);
        }
    }
    }

    boolean isEmergency() {
        final boolean result = mPhone.isInEcm() || mPhone.isInEmergencyCall();
@@ -1552,22 +1561,13 @@ public class DcTracker extends Handler {
        }

        for (ApnContext apnContext : mApnContexts.values()) {
            if (disableMeteredOnly) {
                // Use ApnSetting to decide metered or non-metered.
                // Tear down all metered data connections.
                ApnSetting apnSetting = apnContext.getApnSetting();
                if (apnSetting != null && ApnSettingUtils.isMetered(apnSetting, mPhone)) {
                    if (apnContext.isDisconnected() == false) didDisconnect = true;
                    if (DBG) log("clean up metered ApnContext Type: " + apnContext.getApnType());
                    apnContext.setReason(reason);
                    cleanUpConnectionInternal(detach, RELEASE_TYPE_DETACH, apnContext);
                }
            } else {
            // Exclude the IMS APN from single data connection case.
            if (reason.equals(Phone.REASON_SINGLE_PDN_ARBITRATION)
                    && apnContext.getApnType().equals(PhoneConstants.APN_TYPE_IMS)) {
                continue;
            }

            if (shouldCleanUpConnection(apnContext, disableMeteredOnly)) {
                // TODO - only do cleanup if not disconnected
                if (apnContext.isDisconnected() == false) didDisconnect = true;
                apnContext.setReason(reason);
@@ -1589,6 +1589,25 @@ public class DcTracker extends Handler {
        return didDisconnect;
    }

    boolean shouldCleanUpConnection(ApnContext apnContext, boolean disableMeteredOnly) {
        if (apnContext == null) return false;

        // If meteredOnly is false, clean up all connections.
        if (!disableMeteredOnly) return true;

        // If meteredOnly is true, and apnSetting is null or it's un-metered, no need to clean up.
        ApnSetting apnSetting = apnContext.getApnSetting();
        if (apnSetting == null || !ApnSettingUtils.isMetered(apnSetting, mPhone)) return false;

        // Depending on it's roaming or not, return whether data is enabled or roaming data
        // is enabled.
        if (mPhone.getServiceState().getDataRoaming()) {
            return !getDataRoamingEnabled();
        } else {
            return mDataEnabledSettings.isDataEnabled(apnSetting.getApnTypeBitmask());
        }
    }

    /**
     * Detach the APN context from the associated data connection. This data connection might be
     * torn down if no other APN context is attached to it.
@@ -2040,7 +2059,7 @@ public class DcTracker extends Handler {

        // FIXME: See bug 17426028 maybe no conditional is needed.
        if (mPhone.getSubId() == SubscriptionManager.getDefaultDataSubscriptionId()) {
            setupDataOnConnectableApns(Phone.REASON_APN_CHANGED, RetryFailures.ALWAYS);
            setupDataOnAllConnectableApns(Phone.REASON_APN_CHANGED, RetryFailures.ALWAYS);
        }
    }

@@ -2195,7 +2214,7 @@ public class DcTracker extends Handler {
        setDataProfilesAsNeeded();
        setInitialAttachApn();
        mPhone.notifyDataConnection();
        setupDataOnConnectableApns(Phone.REASON_SIM_LOADED, RetryFailures.ALWAYS);
        setupDataOnAllConnectableApns(Phone.REASON_SIM_LOADED, RetryFailures.ALWAYS);
    }

    private void onSimNotReady() {
@@ -2445,7 +2464,8 @@ public class DcTracker extends Handler {
            if (DBG) log("disableApn:isOnlySingleDcAllowed true & higher priority APN disabled");
            // If the highest priority APN is disabled and only single
            // data call is allowed, try to setup data call on other connectable APN.
            setupDataOnConnectableApns(Phone.REASON_SINGLE_PDN_ARBITRATION, RetryFailures.ALWAYS);
            setupDataOnAllConnectableApns(Phone.REASON_SINGLE_PDN_ARBITRATION,
                    RetryFailures.ALWAYS);
        }
    }

@@ -2539,7 +2559,7 @@ public class DcTracker extends Handler {
            // If the user did not enable data roaming, now when we transit from roaming to
            // non-roaming, we should try to reestablish the data connection.

            setupDataOnConnectableApns(Phone.REASON_ROAMING_OFF, RetryFailures.ALWAYS);
            setupDataOnAllConnectableApns(Phone.REASON_ROAMING_OFF, RetryFailures.ALWAYS);
        } else {
            mPhone.notifyDataConnection();
        }
@@ -2571,7 +2591,7 @@ public class DcTracker extends Handler {

            if (DBG) log("onDataRoamingOnOrSettingsChanged: setup data on roaming");

            setupDataOnConnectableApns(Phone.REASON_ROAMING_ON, RetryFailures.ALWAYS);
            setupDataOnAllConnectableApns(Phone.REASON_ROAMING_ON, RetryFailures.ALWAYS);
            mPhone.notifyDataConnection();
        } else {
            // If the user does not turn on data roaming, when we transit from non-roaming to
@@ -2980,7 +3000,7 @@ public class DcTracker extends Handler {
            apnContext.setDataConnection(null);
            if (isOnlySingleDcAllowed(getDataRat())) {
                if(DBG) log("onDisconnectDone: isOnlySigneDcAllowed true so setup single apn");
                setupDataOnConnectableApns(Phone.REASON_SINGLE_PDN_ARBITRATION,
                setupDataOnAllConnectableApns(Phone.REASON_SINGLE_PDN_ARBITRATION,
                        RetryFailures.ALWAYS);
            } else {
                if(DBG) log("onDisconnectDone: not retrying");
@@ -3023,7 +3043,7 @@ public class DcTracker extends Handler {
            }
        }
        // reset reconnect timer
        setupDataOnConnectableApns(Phone.REASON_VOICE_CALL_ENDED, RetryFailures.ALWAYS);
        setupDataOnAllConnectableApns(Phone.REASON_VOICE_CALL_ENDED, RetryFailures.ALWAYS);
    }

    private boolean isConnected() {
@@ -3507,7 +3527,7 @@ public class DcTracker extends Handler {
                }
                cleanUpConnectionsOnUpdatedApns(false, Phone.REASON_NW_TYPE_CHANGED);
                //May new Network allow setupData, so try it here
                setupDataOnConnectableApns(Phone.REASON_NW_TYPE_CHANGED,
                setupDataOnAllConnectableApns(Phone.REASON_NW_TYPE_CHANGED,
                        RetryFailures.ONLY_ON_CHANGE);
                break;

@@ -3759,6 +3779,11 @@ public class DcTracker extends Handler {
                    onDataEnabledChanged(enabled, reason);
                }
                break;
            case DctConstants.EVENT_APN_WHITE_LIST_CHANGE:
                int apnType = msg.arg1;
                boolean enable = msg.arg2 == 1;
                onApnWhiteListChange(apnType, enable);
                break;
            default:
                Rlog.e("DcTracker", "Unhandled event=" + msg);
                break;
@@ -3893,7 +3918,7 @@ public class DcTracker extends Handler {

        if (enable) {
            reevaluateDataConnections();
            setupDataOnConnectableApns(Phone.REASON_DATA_ENABLED, RetryFailures.ALWAYS);
            setupDataOnAllConnectableApns(Phone.REASON_DATA_ENABLED, RetryFailures.ALWAYS);
        } else {
            String cleanupReason;
            switch (enabledChangedReason) {
@@ -4234,6 +4259,33 @@ public class DcTracker extends Handler {
        setActivity(activity);
    }

    public void notifyApnWhiteListChange(int apnType, boolean enable) {
        Message msg = obtainMessage(DctConstants.EVENT_APN_WHITE_LIST_CHANGE);
        msg.arg1 = apnType;
        msg.arg2 = enable ? 1 : 0;
        sendMessage(msg);
    }

    private void onApnWhiteListChange(int apnType, boolean enable) {
        if (DBG) {
            log("onApnWhiteListChange: enable=" + enable + ", apnType=" + apnType);
        }

        final ApnContext apnContext = mApnContextsByType.get(apnType);
        if (apnContext == null) return;

        if (isDataAllowed(apnContext, null)) {
            if (apnContext.getDataConnection() != null) {
                apnContext.getDataConnection().reevaluateRestrictedState();
            }
            setupDataOnConnectableApn(apnContext, Phone.REASON_APN_ADDED_TO_WHITELIST,
                    RetryFailures.ALWAYS);
        } else if (shouldCleanUpConnection(apnContext, true)) {
            apnContext.setReason(Phone.REASON_APN_REMOVED_FROM_WHITELIST);
            cleanUpConnectionInternal(true, RELEASE_TYPE_DETACH, apnContext);
        }
    }

    private void updateDataActivity() {
        long sent, received;

Loading