Loading src/java/com/android/internal/telephony/Phone.java +1 −0 Original line number Diff line number Diff line Loading @@ -103,6 +103,7 @@ public interface Phone { static final String REASON_DATA_DEPENDENCY_UNMET = "dependencyUnmet"; static final String REASON_LOST_DATA_CONNECTION = "lostDataConnection"; static final String REASON_CONNECTED = "connected"; static final String REASON_SINGLE_PDN_ARBITRATION = "SinglePdnArbitration"; // Used for band mode selection methods static final int BM_UNSPECIFIED = 0; // selected by baseband automatically Loading src/java/com/android/internal/telephony/dataconnection/ApnContext.java +6 −2 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ package com.android.internal.telephony.dataconnection; import android.app.PendingIntent; import android.content.Context; import android.net.NetworkConfig; import android.telephony.Rlog; import com.android.internal.R; Loading Loading @@ -47,6 +48,8 @@ public class ApnContext { private ArrayList<ApnSetting> mWaitingApns = null; public final int priority; /** A zero indicates that all waiting APNs had a permanent error */ private AtomicInteger mWaitingApnsPermanentFailureCountDown; Loading @@ -68,14 +71,15 @@ public class ApnContext { */ AtomicBoolean mDependencyMet; public ApnContext(Context context, String apnType, String logTag) { public ApnContext(Context context, String apnType, String logTag, NetworkConfig config) { mContext = context; mApnType = apnType; mState = DctConstants.State.IDLE; setReason(Phone.REASON_DATA_ENABLED); mDataEnabled = new AtomicBoolean(false); mDependencyMet = new AtomicBoolean(true); mDependencyMet = new AtomicBoolean(config.dependencyMet); mWaitingApnsPermanentFailureCountDown = new AtomicInteger(0); priority = config.priority; LOG_TAG = logTag; } Loading src/java/com/android/internal/telephony/dataconnection/DcTracker.java +96 −31 Original line number Diff line number Diff line Loading @@ -35,6 +35,7 @@ import android.net.NetworkUtils; import android.net.ProxyProperties; import android.net.Uri; import android.os.AsyncResult; import android.os.Build; import android.os.Message; import android.os.Messenger; import android.os.SystemClock; Loading Loading @@ -190,6 +191,7 @@ public final class DcTracker extends DcTrackerBase { mPhone.getContext().getContentResolver().unregisterContentObserver(mApnObserver); mApnContexts.clear(); mPrioritySortedApnContexts.clear(); destroyDataConnections(); } Loading Loading @@ -230,9 +232,9 @@ public final class DcTracker extends DcTrackerBase { } private ApnContext addApnContext(String type, NetworkConfig networkConfig) { ApnContext apnContext = new ApnContext(mPhone.getContext(), type, LOG_TAG); apnContext.setDependencyMet(networkConfig.dependencyMet); ApnContext apnContext = new ApnContext(mPhone.getContext(), type, LOG_TAG, networkConfig); mApnContexts.put(type, apnContext); mPrioritySortedApnContexts.add(apnContext); return apnContext; } Loading Loading @@ -596,7 +598,10 @@ public final class DcTracker extends DcTrackerBase { } private void setupDataOnConnectableApns(String reason) { for (ApnContext apnContext : mApnContexts.values()) { if (DBG) log("setupDataOnConnectableApns: " + reason); for (ApnContext apnContext : mPrioritySortedApnContexts) { if (DBG) log("setupDataOnConnectableApns: apnContext " + apnContext); if (apnContext.getState() == DctConstants.State.FAILED) { apnContext.setState(DctConstants.State.IDLE); } Loading @@ -608,28 +613,6 @@ public final class DcTracker extends DcTrackerBase { } } private boolean trySetupData(String reason, String type) { if (DBG) { log("trySetupData: " + type + " due to " + (reason == null ? "(unspecified)" : reason) + " isPsRestricted=" + mIsPsRestricted); } if (type == null) { type = PhoneConstants.APN_TYPE_DEFAULT; } ApnContext apnContext = mApnContexts.get(type); if (apnContext == null ){ if (DBG) log("trySetupData new apn context for type:" + type); apnContext = new ApnContext(mPhone.getContext(), type, LOG_TAG); mApnContexts.put(type, apnContext); } apnContext.setReason(reason); return trySetupData(apnContext); } private boolean trySetupData(ApnContext apnContext) { if (DBG) { log("trySetupData for type:" + apnContext.getApnType() + Loading Loading @@ -720,11 +703,16 @@ public final class DcTracker extends DcTrackerBase { * @param tearDown true if the underlying DataConnection should be * disconnected. * @param reason reason for the clean up. * @return boolean - true if we did cleanup any connections, false if they * were already all disconnected. */ protected void cleanUpAllConnections(boolean tearDown, String reason) { protected boolean cleanUpAllConnections(boolean tearDown, String reason) { if (DBG) log("cleanUpAllConnections: tearDown=" + tearDown + " reason=" + reason); boolean didDisconnect = false; for (ApnContext apnContext : mApnContexts.values()) { if (apnContext.isDisconnected() == false) didDisconnect = true; // TODO - only do cleanup if not disconnected apnContext.setReason(reason); cleanUpConnection(tearDown, apnContext); } Loading @@ -734,6 +722,7 @@ public final class DcTracker extends DcTrackerBase { // TODO: Do we need mRequestedApnType? mRequestedApnType = PhoneConstants.APN_TYPE_DEFAULT; return didDisconnect; } /** Loading Loading @@ -1033,6 +1022,29 @@ public final class DcTracker extends DcTrackerBase { } } if (dcac == null) { if (isOnlySingleDcAllowed(radioTech)) { if (isHigherPriorityApnContextActive(apnContext)) { if (DBG) { log("setupData: Higher priority ApnContext active. Ignoring call"); } return false; } // Only lower priority calls left. Disconnect them all in this single PDP case // so that we can bring up the requested higher priority call (once we receive // repsonse for deactivate request for the calls we are about to disconnect if (cleanUpAllConnections(true, Phone.REASON_SINGLE_PDN_ARBITRATION)) { // If any call actually requested to be disconnected, means we can't // bring up this connection yet as we need to wait for those data calls // to be disconnected. if (DBG) log("setupData: Some calls are disconnecting first. Wait and retry"); return false; } // No other calls are active, so proceed if (DBG) log("setupData: Single pdp. Continue setting up data call."); } dcac = findFreeDataConnection(); if (dcac == null) { Loading Loading @@ -1166,6 +1178,45 @@ public final class DcTracker extends DcTrackerBase { mActiveApn = null; } /** * "Active" here means ApnContext isEnabled() and not in FAILED state * @param apnContext to compare with * @return true if higher priority active apn found */ private boolean isHigherPriorityApnContextActive(ApnContext apnContext) { for (ApnContext otherContext : mPrioritySortedApnContexts) { if (apnContext.getApnType().equalsIgnoreCase(otherContext.getApnType())) return false; if (otherContext.isEnabled() && otherContext.getState() != DctConstants.State.FAILED) { return true; } } return false; } /** * Reports if we support multiple connections or not. * This is a combination of factors, based on carrier and RAT. * @param rilRadioTech the RIL Radio Tech currently in use * @return true if only single DataConnection is allowed */ private boolean isOnlySingleDcAllowed(int rilRadioTech) { int[] singleDcRats = mPhone.getContext().getResources().getIntArray( com.android.internal.R.array.config_onlySingleDcAllowed); boolean onlySingleDcAllowed = false; if (Build.IS_DEBUGGABLE && SystemProperties.getBoolean("persist.telephony.test.singleDc", false)) { onlySingleDcAllowed = true; } if (singleDcRats != null) { for (int i=0; i < singleDcRats.length && onlySingleDcAllowed == false; i++) { if (rilRadioTech == singleDcRats[i]) onlySingleDcAllowed = true; } } if (DBG) log("isOnlySingleDcAllowed(" + rilRadioTech + "): " + onlySingleDcAllowed); return onlySingleDcAllowed; } @Override protected void restartRadio() { if (DBG) log("restartRadio: ************TURN OFF RADIO**************"); Loading @@ -1190,10 +1241,13 @@ public final class DcTracker extends DcTrackerBase { * @param reason the reason why data is disconnected * @return true if try setup data connection is need for this reason */ private boolean retryAfterDisconnected(String reason) { private boolean retryAfterDisconnected(ApnContext apnContext) { boolean retry = true; String reason = apnContext.getReason(); if ( Phone.REASON_RADIO_TURNED_OFF.equals(reason) ) { if ( Phone.REASON_RADIO_TURNED_OFF.equals(reason) || (isOnlySingleDcAllowed(mPhone.getServiceState().getRilDataRadioTechnology()) && isHigherPriorityApnContextActive(apnContext))) { retry = false; } return retry; Loading Loading @@ -1764,8 +1818,7 @@ public final class DcTracker extends DcTrackerBase { } // If APN is still enabled, try to bring it back up automatically if (mAttached.get() && apnContext.isReady() && retryAfterDisconnected(apnContext.getReason())) { if (mAttached.get() && apnContext.isReady() && retryAfterDisconnected(apnContext)) { SystemProperties.set(PUPPET_MASTER_RADIO_STRESS_TEST, "false"); // Wait a bit before trying the next APN, so that // we're not tying up the RIL command channel. Loading @@ -1774,6 +1827,9 @@ public final class DcTracker extends DcTrackerBase { } else { apnContext.setApnSetting(null); apnContext.setDataConnectionAc(null); if (isOnlySingleDcAllowed(mPhone.getServiceState().getRilDataRadioTechnology())) { setupDataOnConnectableApns(Phone.REASON_SINGLE_PDN_ARBITRATION); } } } Loading Loading @@ -2183,7 +2239,16 @@ public final class DcTracker extends DcTrackerBase { cleanUpAllConnections(false, Phone.REASON_PS_RESTRICT_ENABLED); mReregisterOnReconnectFailure = false; } trySetupData(Phone.REASON_PS_RESTRICT_ENABLED, PhoneConstants.APN_TYPE_DEFAULT); ApnContext apnContext = mApnContexts.get(PhoneConstants.APN_TYPE_DEFAULT); if (apnContext != null) { apnContext.setReason(Phone.REASON_PS_RESTRICT_ENABLED); trySetupData(apnContext); } else { loge("**** Default ApnContext not found ****"); if (Build.IS_DEBUGGABLE) { throw new RuntimeException("Default ApnContext not found"); } } } break; Loading src/java/com/android/internal/telephony/dataconnection/DcTrackerBase.java +13 −1 Original line number Diff line number Diff line Loading @@ -63,12 +63,14 @@ import com.android.internal.util.ArrayUtils; import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.ArrayList; import java.util.Comparator; import java.util.HashMap; import java.util.Map.Entry; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; import java.util.PriorityQueue; /** * {@hide} Loading Loading @@ -251,9 +253,19 @@ public abstract class DcTrackerBase extends Handler { new HashMap<String, Integer>(); /** Phone.APN_TYPE_* ===> ApnContext */ protected ConcurrentHashMap<String, ApnContext> mApnContexts = protected final ConcurrentHashMap<String, ApnContext> mApnContexts = new ConcurrentHashMap<String, ApnContext>(); /** kept in sync with mApnContexts * Higher numbers are higher priority and sorted so highest priority is first */ protected final PriorityQueue<ApnContext>mPrioritySortedApnContexts = new PriorityQueue<ApnContext>(5, new Comparator<ApnContext>() { public int compare(ApnContext c1, ApnContext c2) { return c2.priority - c1.priority; } } ); /* Currently active APN */ protected ApnSetting mActiveApn; Loading Loading
src/java/com/android/internal/telephony/Phone.java +1 −0 Original line number Diff line number Diff line Loading @@ -103,6 +103,7 @@ public interface Phone { static final String REASON_DATA_DEPENDENCY_UNMET = "dependencyUnmet"; static final String REASON_LOST_DATA_CONNECTION = "lostDataConnection"; static final String REASON_CONNECTED = "connected"; static final String REASON_SINGLE_PDN_ARBITRATION = "SinglePdnArbitration"; // Used for band mode selection methods static final int BM_UNSPECIFIED = 0; // selected by baseband automatically Loading
src/java/com/android/internal/telephony/dataconnection/ApnContext.java +6 −2 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ package com.android.internal.telephony.dataconnection; import android.app.PendingIntent; import android.content.Context; import android.net.NetworkConfig; import android.telephony.Rlog; import com.android.internal.R; Loading Loading @@ -47,6 +48,8 @@ public class ApnContext { private ArrayList<ApnSetting> mWaitingApns = null; public final int priority; /** A zero indicates that all waiting APNs had a permanent error */ private AtomicInteger mWaitingApnsPermanentFailureCountDown; Loading @@ -68,14 +71,15 @@ public class ApnContext { */ AtomicBoolean mDependencyMet; public ApnContext(Context context, String apnType, String logTag) { public ApnContext(Context context, String apnType, String logTag, NetworkConfig config) { mContext = context; mApnType = apnType; mState = DctConstants.State.IDLE; setReason(Phone.REASON_DATA_ENABLED); mDataEnabled = new AtomicBoolean(false); mDependencyMet = new AtomicBoolean(true); mDependencyMet = new AtomicBoolean(config.dependencyMet); mWaitingApnsPermanentFailureCountDown = new AtomicInteger(0); priority = config.priority; LOG_TAG = logTag; } Loading
src/java/com/android/internal/telephony/dataconnection/DcTracker.java +96 −31 Original line number Diff line number Diff line Loading @@ -35,6 +35,7 @@ import android.net.NetworkUtils; import android.net.ProxyProperties; import android.net.Uri; import android.os.AsyncResult; import android.os.Build; import android.os.Message; import android.os.Messenger; import android.os.SystemClock; Loading Loading @@ -190,6 +191,7 @@ public final class DcTracker extends DcTrackerBase { mPhone.getContext().getContentResolver().unregisterContentObserver(mApnObserver); mApnContexts.clear(); mPrioritySortedApnContexts.clear(); destroyDataConnections(); } Loading Loading @@ -230,9 +232,9 @@ public final class DcTracker extends DcTrackerBase { } private ApnContext addApnContext(String type, NetworkConfig networkConfig) { ApnContext apnContext = new ApnContext(mPhone.getContext(), type, LOG_TAG); apnContext.setDependencyMet(networkConfig.dependencyMet); ApnContext apnContext = new ApnContext(mPhone.getContext(), type, LOG_TAG, networkConfig); mApnContexts.put(type, apnContext); mPrioritySortedApnContexts.add(apnContext); return apnContext; } Loading Loading @@ -596,7 +598,10 @@ public final class DcTracker extends DcTrackerBase { } private void setupDataOnConnectableApns(String reason) { for (ApnContext apnContext : mApnContexts.values()) { if (DBG) log("setupDataOnConnectableApns: " + reason); for (ApnContext apnContext : mPrioritySortedApnContexts) { if (DBG) log("setupDataOnConnectableApns: apnContext " + apnContext); if (apnContext.getState() == DctConstants.State.FAILED) { apnContext.setState(DctConstants.State.IDLE); } Loading @@ -608,28 +613,6 @@ public final class DcTracker extends DcTrackerBase { } } private boolean trySetupData(String reason, String type) { if (DBG) { log("trySetupData: " + type + " due to " + (reason == null ? "(unspecified)" : reason) + " isPsRestricted=" + mIsPsRestricted); } if (type == null) { type = PhoneConstants.APN_TYPE_DEFAULT; } ApnContext apnContext = mApnContexts.get(type); if (apnContext == null ){ if (DBG) log("trySetupData new apn context for type:" + type); apnContext = new ApnContext(mPhone.getContext(), type, LOG_TAG); mApnContexts.put(type, apnContext); } apnContext.setReason(reason); return trySetupData(apnContext); } private boolean trySetupData(ApnContext apnContext) { if (DBG) { log("trySetupData for type:" + apnContext.getApnType() + Loading Loading @@ -720,11 +703,16 @@ public final class DcTracker extends DcTrackerBase { * @param tearDown true if the underlying DataConnection should be * disconnected. * @param reason reason for the clean up. * @return boolean - true if we did cleanup any connections, false if they * were already all disconnected. */ protected void cleanUpAllConnections(boolean tearDown, String reason) { protected boolean cleanUpAllConnections(boolean tearDown, String reason) { if (DBG) log("cleanUpAllConnections: tearDown=" + tearDown + " reason=" + reason); boolean didDisconnect = false; for (ApnContext apnContext : mApnContexts.values()) { if (apnContext.isDisconnected() == false) didDisconnect = true; // TODO - only do cleanup if not disconnected apnContext.setReason(reason); cleanUpConnection(tearDown, apnContext); } Loading @@ -734,6 +722,7 @@ public final class DcTracker extends DcTrackerBase { // TODO: Do we need mRequestedApnType? mRequestedApnType = PhoneConstants.APN_TYPE_DEFAULT; return didDisconnect; } /** Loading Loading @@ -1033,6 +1022,29 @@ public final class DcTracker extends DcTrackerBase { } } if (dcac == null) { if (isOnlySingleDcAllowed(radioTech)) { if (isHigherPriorityApnContextActive(apnContext)) { if (DBG) { log("setupData: Higher priority ApnContext active. Ignoring call"); } return false; } // Only lower priority calls left. Disconnect them all in this single PDP case // so that we can bring up the requested higher priority call (once we receive // repsonse for deactivate request for the calls we are about to disconnect if (cleanUpAllConnections(true, Phone.REASON_SINGLE_PDN_ARBITRATION)) { // If any call actually requested to be disconnected, means we can't // bring up this connection yet as we need to wait for those data calls // to be disconnected. if (DBG) log("setupData: Some calls are disconnecting first. Wait and retry"); return false; } // No other calls are active, so proceed if (DBG) log("setupData: Single pdp. Continue setting up data call."); } dcac = findFreeDataConnection(); if (dcac == null) { Loading Loading @@ -1166,6 +1178,45 @@ public final class DcTracker extends DcTrackerBase { mActiveApn = null; } /** * "Active" here means ApnContext isEnabled() and not in FAILED state * @param apnContext to compare with * @return true if higher priority active apn found */ private boolean isHigherPriorityApnContextActive(ApnContext apnContext) { for (ApnContext otherContext : mPrioritySortedApnContexts) { if (apnContext.getApnType().equalsIgnoreCase(otherContext.getApnType())) return false; if (otherContext.isEnabled() && otherContext.getState() != DctConstants.State.FAILED) { return true; } } return false; } /** * Reports if we support multiple connections or not. * This is a combination of factors, based on carrier and RAT. * @param rilRadioTech the RIL Radio Tech currently in use * @return true if only single DataConnection is allowed */ private boolean isOnlySingleDcAllowed(int rilRadioTech) { int[] singleDcRats = mPhone.getContext().getResources().getIntArray( com.android.internal.R.array.config_onlySingleDcAllowed); boolean onlySingleDcAllowed = false; if (Build.IS_DEBUGGABLE && SystemProperties.getBoolean("persist.telephony.test.singleDc", false)) { onlySingleDcAllowed = true; } if (singleDcRats != null) { for (int i=0; i < singleDcRats.length && onlySingleDcAllowed == false; i++) { if (rilRadioTech == singleDcRats[i]) onlySingleDcAllowed = true; } } if (DBG) log("isOnlySingleDcAllowed(" + rilRadioTech + "): " + onlySingleDcAllowed); return onlySingleDcAllowed; } @Override protected void restartRadio() { if (DBG) log("restartRadio: ************TURN OFF RADIO**************"); Loading @@ -1190,10 +1241,13 @@ public final class DcTracker extends DcTrackerBase { * @param reason the reason why data is disconnected * @return true if try setup data connection is need for this reason */ private boolean retryAfterDisconnected(String reason) { private boolean retryAfterDisconnected(ApnContext apnContext) { boolean retry = true; String reason = apnContext.getReason(); if ( Phone.REASON_RADIO_TURNED_OFF.equals(reason) ) { if ( Phone.REASON_RADIO_TURNED_OFF.equals(reason) || (isOnlySingleDcAllowed(mPhone.getServiceState().getRilDataRadioTechnology()) && isHigherPriorityApnContextActive(apnContext))) { retry = false; } return retry; Loading Loading @@ -1764,8 +1818,7 @@ public final class DcTracker extends DcTrackerBase { } // If APN is still enabled, try to bring it back up automatically if (mAttached.get() && apnContext.isReady() && retryAfterDisconnected(apnContext.getReason())) { if (mAttached.get() && apnContext.isReady() && retryAfterDisconnected(apnContext)) { SystemProperties.set(PUPPET_MASTER_RADIO_STRESS_TEST, "false"); // Wait a bit before trying the next APN, so that // we're not tying up the RIL command channel. Loading @@ -1774,6 +1827,9 @@ public final class DcTracker extends DcTrackerBase { } else { apnContext.setApnSetting(null); apnContext.setDataConnectionAc(null); if (isOnlySingleDcAllowed(mPhone.getServiceState().getRilDataRadioTechnology())) { setupDataOnConnectableApns(Phone.REASON_SINGLE_PDN_ARBITRATION); } } } Loading Loading @@ -2183,7 +2239,16 @@ public final class DcTracker extends DcTrackerBase { cleanUpAllConnections(false, Phone.REASON_PS_RESTRICT_ENABLED); mReregisterOnReconnectFailure = false; } trySetupData(Phone.REASON_PS_RESTRICT_ENABLED, PhoneConstants.APN_TYPE_DEFAULT); ApnContext apnContext = mApnContexts.get(PhoneConstants.APN_TYPE_DEFAULT); if (apnContext != null) { apnContext.setReason(Phone.REASON_PS_RESTRICT_ENABLED); trySetupData(apnContext); } else { loge("**** Default ApnContext not found ****"); if (Build.IS_DEBUGGABLE) { throw new RuntimeException("Default ApnContext not found"); } } } break; Loading
src/java/com/android/internal/telephony/dataconnection/DcTrackerBase.java +13 −1 Original line number Diff line number Diff line Loading @@ -63,12 +63,14 @@ import com.android.internal.util.ArrayUtils; import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.ArrayList; import java.util.Comparator; import java.util.HashMap; import java.util.Map.Entry; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; import java.util.PriorityQueue; /** * {@hide} Loading Loading @@ -251,9 +253,19 @@ public abstract class DcTrackerBase extends Handler { new HashMap<String, Integer>(); /** Phone.APN_TYPE_* ===> ApnContext */ protected ConcurrentHashMap<String, ApnContext> mApnContexts = protected final ConcurrentHashMap<String, ApnContext> mApnContexts = new ConcurrentHashMap<String, ApnContext>(); /** kept in sync with mApnContexts * Higher numbers are higher priority and sorted so highest priority is first */ protected final PriorityQueue<ApnContext>mPrioritySortedApnContexts = new PriorityQueue<ApnContext>(5, new Comparator<ApnContext>() { public int compare(ApnContext c1, ApnContext c2) { return c2.priority - c1.priority; } } ); /* Currently active APN */ protected ApnSetting mActiveApn; Loading