Loading src/java/com/android/internal/telephony/ServiceStateTracker.java +64 −0 Original line number Diff line number Diff line Loading @@ -239,6 +239,8 @@ public class ServiceStateTracker extends Handler { private RegistrantList mNrStateChangedRegistrants = new RegistrantList(); private RegistrantList mNrFrequencyChangedRegistrants = new RegistrantList(); private RegistrantList mCssIndicatorChangedRegistrants = new RegistrantList(); private final RegistrantList mAirplaneModeChangedRegistrants = new RegistrantList(); private final RegistrantList mAreaCodeChangedRegistrants = new RegistrantList(); /* Radio power off pending flag and tag counter */ private boolean mPendingRadioPowerOffAfterDataOff = false; Loading Loading @@ -648,6 +650,9 @@ public class ServiceStateTracker extends Handler { private final List<SignalRequestRecord> mSignalRequestRecords = new ArrayList<>(); /* Last known TAC/LAC */ private int mLastKnownAreaCode = CellInfo.UNAVAILABLE; public ServiceStateTracker(GsmCdmaPhone phone, CommandsInterface ci) { mNitzState = TelephonyComponentFactory.getInstance() .inject(NitzStateMachine.class.getName()) Loading Loading @@ -2010,6 +2015,7 @@ public class ServiceStateTracker extends Handler { public void onAirplaneModeChanged(boolean isAirplaneModeOn) { mLastNitzData = null; mNitzState.handleAirplaneModeChanged(isAirplaneModeOn); mAirplaneModeChangedRegistrants.notifyResult(isAirplaneModeOn); } protected Phone getPhone() { Loading Loading @@ -2551,6 +2557,19 @@ public class ServiceStateTracker extends Handler { return cid; } //TODO: Move this and getCidFromCellIdentity to CellIdentityUtils. private static int getAreaCodeFromCellIdentity(CellIdentity id) { if (id == null) return CellInfo.UNAVAILABLE; switch(id.getType()) { case CellInfo.TYPE_GSM: return ((CellIdentityGsm) id).getLac(); case CellInfo.TYPE_WCDMA: return ((CellIdentityWcdma) id).getLac(); case CellInfo.TYPE_TDSCDMA: return ((CellIdentityTdscdma) id).getLac(); case CellInfo.TYPE_LTE: return ((CellIdentityLte) id).getTac(); case CellInfo.TYPE_NR: return ((CellIdentityNr) id).getTac(); default: return CellInfo.UNAVAILABLE; } } private void setPhyCellInfoFromCellIdentity(ServiceState ss, CellIdentity cellIdentity) { if (cellIdentity == null) { if (DBG) { Loading Loading @@ -3587,6 +3606,12 @@ public class ServiceStateTracker extends Handler { mCellIdentity = primaryCellIdentity; int areaCode = getAreaCodeFromCellIdentity(mCellIdentity); if (areaCode != mLastKnownAreaCode && areaCode != CellInfo.UNAVAILABLE) { mLastKnownAreaCode = areaCode; mAreaCodeChangedRegistrants.notifyRegistrants(); } if (hasRilVoiceRadioTechnologyChanged) { updatePhoneObject(); } Loading Loading @@ -4758,6 +4783,27 @@ public class ServiceStateTracker extends Handler { } } /** * Registration for Airplane Mode changing. The state of Airplane Mode will be returned * {@link AsyncResult#result} as a {@link Boolean} Object. * The {@link AsyncResult} will be in the notification {@link Message#obj}. * @param h handler to notify * @param what what code of message when delivered * @param obj placed in {@link AsyncResult#userObj} */ public void registerForAirplaneModeChanged(Handler h, int what, Object obj) { mAirplaneModeChangedRegistrants.add(h, what, obj); } /** * Unregister for Airplane Mode changed event. * * @param h The handler */ public void unregisterForAirplaneModeChanged(Handler h) { mAirplaneModeChangedRegistrants.remove(h); } /** * Registration point for transition into network attached. * @param h handler to notify Loading Loading @@ -6162,4 +6208,22 @@ public class ServiceStateTracker extends Handler { // worry about unset flag which was set by other client. mPhone.setAlwaysReportSignalStrength(alwaysReport); } /** * Registers for TAC/LAC changed event. * @param h handler to notify * @param what what code of message when delivered * @param obj placed in Message.obj */ public void registerForAreaCodeChanged(Handler h, int what, Object obj) { mAreaCodeChangedRegistrants.addUnique(h, what, obj); } /** * Unregisters for TAC/LAC changed event. * @param h handler to notify */ public void unregisterForAreaCodeChanged(Handler h) { mAreaCodeChangedRegistrants.remove(h); } } src/java/com/android/internal/telephony/dataconnection/DataThrottler.java +148 −4 Original line number Diff line number Diff line Loading @@ -17,12 +17,24 @@ package com.android.internal.telephony.dataconnection; import android.annotation.ElapsedRealtimeLong; import android.annotation.NonNull; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.os.AsyncResult; import android.os.Handler; import android.os.Message; import android.os.PersistableBundle; import android.telephony.AccessNetworkConstants; import android.telephony.Annotation; import android.telephony.Annotation.ApnType; import android.telephony.CarrierConfigManager; import android.telephony.SubscriptionManager; import android.telephony.data.ApnSetting; import android.telephony.data.ThrottleStatus; import com.android.internal.telephony.Phone; import com.android.internal.telephony.RetryManager; import com.android.telephony.Rlog; Loading @@ -35,11 +47,19 @@ import java.util.concurrent.ConcurrentHashMap; * Data throttler tracks the throttling status of the data network and notifies registrants when * there are changes. The throttler is per phone and per transport type. */ public class DataThrottler { public class DataThrottler extends Handler { private static final String TAG = DataThrottler.class.getSimpleName(); private static final int EVENT_SET_RETRY_TIME = 1; private static final int EVENT_CARRIER_CONFIG_CHANGED = 2; private static final int EVENT_RESET = 3; private static final int EVENT_AIRPLANE_MODE_CHANGED = 4; private static final int EVENT_TRACING_AREA_CODE_CHANGED = 5; private final Phone mPhone; private final int mSlotIndex; private final @AccessNetworkConstants.TransportType int mTransportType; private boolean mResetWhenAreaCodeChanged = false; /** * Callbacks that report the apn throttle status. Loading @@ -52,9 +72,93 @@ public class DataThrottler { */ private final Map<Integer, ThrottleStatus> mThrottleStatus = new ConcurrentHashMap<>(); public DataThrottler(int slotIndex, int transportType) { mSlotIndex = slotIndex; private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { if (intent.getAction().equals(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED)) { if (mPhone.getPhoneId() == intent.getIntExtra(CarrierConfigManager.EXTRA_SLOT_INDEX, SubscriptionManager.INVALID_SIM_SLOT_INDEX)) { if (intent.getBooleanExtra( CarrierConfigManager.EXTRA_REBROADCAST_ON_UNLOCK, false)) { // Ignore the rebroadcast one to prevent multiple carrier config changed // event during boot up. return; } int subId = intent.getIntExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX, SubscriptionManager.INVALID_SUBSCRIPTION_ID); if (SubscriptionManager.isValidSubscriptionId(subId)) { sendEmptyMessage(EVENT_CARRIER_CONFIG_CHANGED); } } } } }; public DataThrottler(Phone phone, int transportType) { super(null, false); mPhone = phone; mSlotIndex = phone.getPhoneId(); mTransportType = transportType; IntentFilter filter = new IntentFilter(); filter.addAction(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED); mPhone.getContext().registerReceiver(mBroadcastReceiver, filter, null, mPhone); mPhone.getServiceStateTracker().registerForAirplaneModeChanged(this, EVENT_AIRPLANE_MODE_CHANGED, null); mPhone.getServiceStateTracker().registerForAreaCodeChanged(this, EVENT_TRACING_AREA_CODE_CHANGED, null); } @Override public void handleMessage(Message msg) { AsyncResult ar; switch (msg.what) { case EVENT_SET_RETRY_TIME: int apnTypes = msg.arg1; int newRequestType = msg.arg2; long retryElapsedTime = (long) msg.obj; setRetryTimeInternal(apnTypes, retryElapsedTime, newRequestType); break; case EVENT_CARRIER_CONFIG_CHANGED: onCarrierConfigChanged(); break; case EVENT_RESET: resetInternal(); break; case EVENT_AIRPLANE_MODE_CHANGED: ar = (AsyncResult) msg.obj; if (!(Boolean) ar.result) { resetInternal(); } break; case EVENT_TRACING_AREA_CODE_CHANGED: if (mResetWhenAreaCodeChanged) { resetInternal(); } break; } } @NonNull private PersistableBundle getCarrierConfig() { CarrierConfigManager configManager = (CarrierConfigManager) mPhone.getContext() .getSystemService(Context.CARRIER_CONFIG_SERVICE); if (configManager != null) { // If an invalid subId is used, this bundle will contain default values. PersistableBundle config = configManager.getConfigForSubId(mPhone.getSubId()); if (config != null) { return config; } } // Return static default defined in CarrierConfigManager. return CarrierConfigManager.getDefaultConfig(); } private void onCarrierConfigChanged() { PersistableBundle config = getCarrierConfig(); mResetWhenAreaCodeChanged = config.getBoolean( CarrierConfigManager.KEY_UNTHROTTLE_DATA_RETRY_WHEN_TAC_CHANGES_BOOL, false); } /** Loading @@ -65,8 +169,23 @@ public class DataThrottler { * retried. {@link RetryManager#NO_SUGGESTED_RETRY_DELAY} indicates throttling does not exist. * {@link RetryManager#NO_RETRY} indicates retry should never happen. */ public void setRetryTime(@ApnType int apnTypes, long retryElapsedTime, public void setRetryTime(@ApnType int apnTypes, @ElapsedRealtimeLong long retryElapsedTime, @DcTracker.RequestNetworkType int newRequestType) { sendMessage(obtainMessage(EVENT_SET_RETRY_TIME, apnTypes, newRequestType, retryElapsedTime)); } /** * Set the retry time and handover failure mode for the give APN types. This is running on the * handler thread. * * @param apnTypes APN types * @param retryElapsedTime The elapsed time that data connection for APN types should not be * retried. {@link RetryManager#NO_SUGGESTED_RETRY_DELAY} indicates throttling does not exist. * {@link RetryManager#NO_RETRY} indicates retry should never happen. */ private void setRetryTimeInternal(@ApnType int apnTypes, @ElapsedRealtimeLong long retryElapsedTime, @DcTracker.RequestNetworkType int newRequestType) { if (retryElapsedTime < 0) { retryElapsedTime = RetryManager.NO_SUGGESTED_RETRY_DELAY; } Loading Loading @@ -103,6 +222,9 @@ public class DataThrottler { /** * Get the earliest retry time for the given APN type. The time is the system's elapse time. * * Note the DataThrottler is running phone process's main thread, which is most of the telephony * components running on. Calling this method from other threads might run into race conditions. * * @param apnType APN type * @return The earliest retry time for APN type. The time is the system's elapse time. * {@link RetryManager#NO_SUGGESTED_RETRY_DELAY} indicates there is no throttling for given APN Loading @@ -127,6 +249,28 @@ public class DataThrottler { return RetryManager.NO_SUGGESTED_RETRY_DELAY; } /** * Resets retry times for all APNs to {@link RetryManager.NO_SUGGESTED_RETRY_DELAY}. */ public void reset() { sendEmptyMessage(EVENT_RESET); } /** * Resets retry times for all APNs to {@link RetryManager.NO_SUGGESTED_RETRY_DELAY}. */ private void resetInternal() { final List<Integer> apnTypes = new ArrayList<>(); for (ThrottleStatus throttleStatus : mThrottleStatus.values()) { apnTypes.add(throttleStatus.getApnType()); } for (int apnType : apnTypes) { setRetryTime(apnType, RetryManager.NO_SUGGESTED_RETRY_DELAY, DcTracker.REQUEST_TYPE_NORMAL); } } private ThrottleStatus createStatus(@Annotation.ApnType int apnType, long retryElapsedTime, @DcTracker.RequestNetworkType int newRequestType) { ThrottleStatus.Builder builder = new ThrottleStatus.Builder(); Loading src/java/com/android/internal/telephony/dataconnection/DcTracker.java +2 −1 Original line number Diff line number Diff line Loading @@ -739,7 +739,7 @@ public class DcTracker extends Handler { mTransportType = transportType; mDataServiceManager = new DataServiceManager(phone, transportType, tagSuffix); mDataThrottler = new DataThrottler(mPhone.getPhoneId(), transportType); mDataThrottler = new DataThrottler(mPhone, transportType); mResolver = mPhone.getContext().getContentResolver(); mAlarmManager = Loading Loading @@ -832,6 +832,7 @@ public class DcTracker extends Handler { mPhone.getServiceStateTracker().unregisterForPsRestrictedEnabled(this); mPhone.getServiceStateTracker().unregisterForPsRestrictedDisabled(this); mPhone.getServiceStateTracker().unregisterForDataRegStateOrRatChanged(mTransportType, this); mPhone.getServiceStateTracker().unregisterForAirplaneModeChanged(this); } private void registerForAllEvents() { Loading tests/telephonytests/src/com/android/internal/telephony/dataconnection/DataThrottlerTest.java +29 −10 Original line number Diff line number Diff line Loading @@ -65,7 +65,7 @@ public class DataThrottlerTest extends TelephonyTest { @Before public void setUp() throws Exception { super.setUp(getClass().getSimpleName()); mDataThrottler = new DataThrottler(1, AccessNetworkConstants.TRANSPORT_TYPE_WWAN); mDataThrottler = new DataThrottler(mPhone, AccessNetworkConstants.TRANSPORT_TYPE_WWAN); mDataThrottler.registerForThrottleStatusChanges(mMockChangedCallback1); } Loading @@ -87,9 +87,9 @@ public class DataThrottlerTest extends TelephonyTest { processAllMessages(); expectedStatuses.add(List.of()); mDataThrottler.setRetryTime(ApnSetting.TYPE_DEFAULT, 1234567890L, REQUEST_TYPE_NORMAL); processAllMessages(); assertEquals(1234567890L, mDataThrottler.getRetryTime(ApnSetting.TYPE_DEFAULT)); assertEquals(RetryManager.NO_SUGGESTED_RETRY_DELAY, mDataThrottler.getRetryTime(ApnSetting.TYPE_MMS)); Loading @@ -97,14 +97,14 @@ public class DataThrottlerTest extends TelephonyTest { processAllMessages(); expectedStatuses.add(List.of( new ThrottleStatus.Builder() .setSlotIndex(1) .setSlotIndex(0) .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN) .setApnType(ApnSetting.TYPE_HIPRI) .setThrottleExpiryTimeMillis(1234567890L) .setRetryType(ThrottleStatus.RETRY_TYPE_NEW_CONNECTION) .build(), new ThrottleStatus.Builder() .setSlotIndex(1) .setSlotIndex(0) .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN) .setApnType(DEFAULT_APN_TYPE) .setThrottleExpiryTimeMillis(1234567890L) Loading @@ -115,27 +115,28 @@ public class DataThrottlerTest extends TelephonyTest { mDataThrottler.setRetryTime(ApnSetting.TYPE_DEFAULT | ApnSetting.TYPE_DUN, 13579L, REQUEST_TYPE_HANDOVER); processAllMessages(); assertEquals(13579L, mDataThrottler.getRetryTime(ApnSetting.TYPE_DEFAULT)); assertEquals(13579L, mDataThrottler.getRetryTime(ApnSetting.TYPE_DUN)); processAllMessages(); expectedStatuses.add(List.of( new ThrottleStatus.Builder() .setSlotIndex(1) .setSlotIndex(0) .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN) .setApnType(ApnSetting.TYPE_HIPRI) .setThrottleExpiryTimeMillis(13579L) .setRetryType(ThrottleStatus.RETRY_TYPE_HANDOVER) .build(), new ThrottleStatus.Builder() .setSlotIndex(1) .setSlotIndex(0) .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN) .setApnType(ApnSetting.TYPE_DUN) .setThrottleExpiryTimeMillis(13579L) .setRetryType(ThrottleStatus.RETRY_TYPE_HANDOVER) .build(), new ThrottleStatus.Builder() .setSlotIndex(1) .setSlotIndex(0) .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN) .setApnType(DEFAULT_APN_TYPE) .setThrottleExpiryTimeMillis(13579L) Loading @@ -146,12 +147,13 @@ public class DataThrottlerTest extends TelephonyTest { mDataThrottler.setRetryTime(ApnSetting.TYPE_MMS, -10, REQUEST_TYPE_NORMAL); processAllMessages(); assertEquals(RetryManager.NO_SUGGESTED_RETRY_DELAY, mDataThrottler.getRetryTime(ApnSetting.TYPE_MMS)); processAllMessages(); expectedStatuses.add(List.of( new ThrottleStatus.Builder() .setSlotIndex(1) .setSlotIndex(0) .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN) .setNoThrottle() .setApnType(ApnSetting.TYPE_MMS) Loading @@ -165,14 +167,14 @@ public class DataThrottlerTest extends TelephonyTest { processAllMessages(); expectedStatuses.add(List.of( new ThrottleStatus.Builder() .setSlotIndex(1) .setSlotIndex(0) .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN) .setApnType(ApnSetting.TYPE_EMERGENCY) .setThrottleExpiryTimeMillis(RetryManager.NO_RETRY) .setRetryType(ThrottleStatus.RETRY_TYPE_NONE) .build(), new ThrottleStatus.Builder() .setSlotIndex(1) .setSlotIndex(0) .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN) .setApnType(ApnSetting.TYPE_FOTA) .setThrottleExpiryTimeMillis(RetryManager.NO_RETRY) Loading Loading @@ -213,4 +215,21 @@ public class DataThrottlerTest extends TelephonyTest { this.mDataThrottler.registerForThrottleStatusChanges(mMockChangedCallback2); } /** * Test the behavior of a retry manager with no waiting APNs set. */ @Test @SmallTest public void testUnthrottle() throws Exception { mDataThrottler.setRetryTime(ApnSetting.TYPE_DEFAULT, 1234567890L, REQUEST_TYPE_NORMAL); processAllMessages(); assertEquals(1234567890L, mDataThrottler.getRetryTime(ApnSetting.TYPE_DEFAULT)); mDataThrottler.reset(); processAllMessages(); assertEquals(RetryManager.NO_SUGGESTED_RETRY_DELAY, mDataThrottler.getRetryTime(ApnSetting.TYPE_DEFAULT)); } } Loading
src/java/com/android/internal/telephony/ServiceStateTracker.java +64 −0 Original line number Diff line number Diff line Loading @@ -239,6 +239,8 @@ public class ServiceStateTracker extends Handler { private RegistrantList mNrStateChangedRegistrants = new RegistrantList(); private RegistrantList mNrFrequencyChangedRegistrants = new RegistrantList(); private RegistrantList mCssIndicatorChangedRegistrants = new RegistrantList(); private final RegistrantList mAirplaneModeChangedRegistrants = new RegistrantList(); private final RegistrantList mAreaCodeChangedRegistrants = new RegistrantList(); /* Radio power off pending flag and tag counter */ private boolean mPendingRadioPowerOffAfterDataOff = false; Loading Loading @@ -648,6 +650,9 @@ public class ServiceStateTracker extends Handler { private final List<SignalRequestRecord> mSignalRequestRecords = new ArrayList<>(); /* Last known TAC/LAC */ private int mLastKnownAreaCode = CellInfo.UNAVAILABLE; public ServiceStateTracker(GsmCdmaPhone phone, CommandsInterface ci) { mNitzState = TelephonyComponentFactory.getInstance() .inject(NitzStateMachine.class.getName()) Loading Loading @@ -2010,6 +2015,7 @@ public class ServiceStateTracker extends Handler { public void onAirplaneModeChanged(boolean isAirplaneModeOn) { mLastNitzData = null; mNitzState.handleAirplaneModeChanged(isAirplaneModeOn); mAirplaneModeChangedRegistrants.notifyResult(isAirplaneModeOn); } protected Phone getPhone() { Loading Loading @@ -2551,6 +2557,19 @@ public class ServiceStateTracker extends Handler { return cid; } //TODO: Move this and getCidFromCellIdentity to CellIdentityUtils. private static int getAreaCodeFromCellIdentity(CellIdentity id) { if (id == null) return CellInfo.UNAVAILABLE; switch(id.getType()) { case CellInfo.TYPE_GSM: return ((CellIdentityGsm) id).getLac(); case CellInfo.TYPE_WCDMA: return ((CellIdentityWcdma) id).getLac(); case CellInfo.TYPE_TDSCDMA: return ((CellIdentityTdscdma) id).getLac(); case CellInfo.TYPE_LTE: return ((CellIdentityLte) id).getTac(); case CellInfo.TYPE_NR: return ((CellIdentityNr) id).getTac(); default: return CellInfo.UNAVAILABLE; } } private void setPhyCellInfoFromCellIdentity(ServiceState ss, CellIdentity cellIdentity) { if (cellIdentity == null) { if (DBG) { Loading Loading @@ -3587,6 +3606,12 @@ public class ServiceStateTracker extends Handler { mCellIdentity = primaryCellIdentity; int areaCode = getAreaCodeFromCellIdentity(mCellIdentity); if (areaCode != mLastKnownAreaCode && areaCode != CellInfo.UNAVAILABLE) { mLastKnownAreaCode = areaCode; mAreaCodeChangedRegistrants.notifyRegistrants(); } if (hasRilVoiceRadioTechnologyChanged) { updatePhoneObject(); } Loading Loading @@ -4758,6 +4783,27 @@ public class ServiceStateTracker extends Handler { } } /** * Registration for Airplane Mode changing. The state of Airplane Mode will be returned * {@link AsyncResult#result} as a {@link Boolean} Object. * The {@link AsyncResult} will be in the notification {@link Message#obj}. * @param h handler to notify * @param what what code of message when delivered * @param obj placed in {@link AsyncResult#userObj} */ public void registerForAirplaneModeChanged(Handler h, int what, Object obj) { mAirplaneModeChangedRegistrants.add(h, what, obj); } /** * Unregister for Airplane Mode changed event. * * @param h The handler */ public void unregisterForAirplaneModeChanged(Handler h) { mAirplaneModeChangedRegistrants.remove(h); } /** * Registration point for transition into network attached. * @param h handler to notify Loading Loading @@ -6162,4 +6208,22 @@ public class ServiceStateTracker extends Handler { // worry about unset flag which was set by other client. mPhone.setAlwaysReportSignalStrength(alwaysReport); } /** * Registers for TAC/LAC changed event. * @param h handler to notify * @param what what code of message when delivered * @param obj placed in Message.obj */ public void registerForAreaCodeChanged(Handler h, int what, Object obj) { mAreaCodeChangedRegistrants.addUnique(h, what, obj); } /** * Unregisters for TAC/LAC changed event. * @param h handler to notify */ public void unregisterForAreaCodeChanged(Handler h) { mAreaCodeChangedRegistrants.remove(h); } }
src/java/com/android/internal/telephony/dataconnection/DataThrottler.java +148 −4 Original line number Diff line number Diff line Loading @@ -17,12 +17,24 @@ package com.android.internal.telephony.dataconnection; import android.annotation.ElapsedRealtimeLong; import android.annotation.NonNull; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.os.AsyncResult; import android.os.Handler; import android.os.Message; import android.os.PersistableBundle; import android.telephony.AccessNetworkConstants; import android.telephony.Annotation; import android.telephony.Annotation.ApnType; import android.telephony.CarrierConfigManager; import android.telephony.SubscriptionManager; import android.telephony.data.ApnSetting; import android.telephony.data.ThrottleStatus; import com.android.internal.telephony.Phone; import com.android.internal.telephony.RetryManager; import com.android.telephony.Rlog; Loading @@ -35,11 +47,19 @@ import java.util.concurrent.ConcurrentHashMap; * Data throttler tracks the throttling status of the data network and notifies registrants when * there are changes. The throttler is per phone and per transport type. */ public class DataThrottler { public class DataThrottler extends Handler { private static final String TAG = DataThrottler.class.getSimpleName(); private static final int EVENT_SET_RETRY_TIME = 1; private static final int EVENT_CARRIER_CONFIG_CHANGED = 2; private static final int EVENT_RESET = 3; private static final int EVENT_AIRPLANE_MODE_CHANGED = 4; private static final int EVENT_TRACING_AREA_CODE_CHANGED = 5; private final Phone mPhone; private final int mSlotIndex; private final @AccessNetworkConstants.TransportType int mTransportType; private boolean mResetWhenAreaCodeChanged = false; /** * Callbacks that report the apn throttle status. Loading @@ -52,9 +72,93 @@ public class DataThrottler { */ private final Map<Integer, ThrottleStatus> mThrottleStatus = new ConcurrentHashMap<>(); public DataThrottler(int slotIndex, int transportType) { mSlotIndex = slotIndex; private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { if (intent.getAction().equals(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED)) { if (mPhone.getPhoneId() == intent.getIntExtra(CarrierConfigManager.EXTRA_SLOT_INDEX, SubscriptionManager.INVALID_SIM_SLOT_INDEX)) { if (intent.getBooleanExtra( CarrierConfigManager.EXTRA_REBROADCAST_ON_UNLOCK, false)) { // Ignore the rebroadcast one to prevent multiple carrier config changed // event during boot up. return; } int subId = intent.getIntExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX, SubscriptionManager.INVALID_SUBSCRIPTION_ID); if (SubscriptionManager.isValidSubscriptionId(subId)) { sendEmptyMessage(EVENT_CARRIER_CONFIG_CHANGED); } } } } }; public DataThrottler(Phone phone, int transportType) { super(null, false); mPhone = phone; mSlotIndex = phone.getPhoneId(); mTransportType = transportType; IntentFilter filter = new IntentFilter(); filter.addAction(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED); mPhone.getContext().registerReceiver(mBroadcastReceiver, filter, null, mPhone); mPhone.getServiceStateTracker().registerForAirplaneModeChanged(this, EVENT_AIRPLANE_MODE_CHANGED, null); mPhone.getServiceStateTracker().registerForAreaCodeChanged(this, EVENT_TRACING_AREA_CODE_CHANGED, null); } @Override public void handleMessage(Message msg) { AsyncResult ar; switch (msg.what) { case EVENT_SET_RETRY_TIME: int apnTypes = msg.arg1; int newRequestType = msg.arg2; long retryElapsedTime = (long) msg.obj; setRetryTimeInternal(apnTypes, retryElapsedTime, newRequestType); break; case EVENT_CARRIER_CONFIG_CHANGED: onCarrierConfigChanged(); break; case EVENT_RESET: resetInternal(); break; case EVENT_AIRPLANE_MODE_CHANGED: ar = (AsyncResult) msg.obj; if (!(Boolean) ar.result) { resetInternal(); } break; case EVENT_TRACING_AREA_CODE_CHANGED: if (mResetWhenAreaCodeChanged) { resetInternal(); } break; } } @NonNull private PersistableBundle getCarrierConfig() { CarrierConfigManager configManager = (CarrierConfigManager) mPhone.getContext() .getSystemService(Context.CARRIER_CONFIG_SERVICE); if (configManager != null) { // If an invalid subId is used, this bundle will contain default values. PersistableBundle config = configManager.getConfigForSubId(mPhone.getSubId()); if (config != null) { return config; } } // Return static default defined in CarrierConfigManager. return CarrierConfigManager.getDefaultConfig(); } private void onCarrierConfigChanged() { PersistableBundle config = getCarrierConfig(); mResetWhenAreaCodeChanged = config.getBoolean( CarrierConfigManager.KEY_UNTHROTTLE_DATA_RETRY_WHEN_TAC_CHANGES_BOOL, false); } /** Loading @@ -65,8 +169,23 @@ public class DataThrottler { * retried. {@link RetryManager#NO_SUGGESTED_RETRY_DELAY} indicates throttling does not exist. * {@link RetryManager#NO_RETRY} indicates retry should never happen. */ public void setRetryTime(@ApnType int apnTypes, long retryElapsedTime, public void setRetryTime(@ApnType int apnTypes, @ElapsedRealtimeLong long retryElapsedTime, @DcTracker.RequestNetworkType int newRequestType) { sendMessage(obtainMessage(EVENT_SET_RETRY_TIME, apnTypes, newRequestType, retryElapsedTime)); } /** * Set the retry time and handover failure mode for the give APN types. This is running on the * handler thread. * * @param apnTypes APN types * @param retryElapsedTime The elapsed time that data connection for APN types should not be * retried. {@link RetryManager#NO_SUGGESTED_RETRY_DELAY} indicates throttling does not exist. * {@link RetryManager#NO_RETRY} indicates retry should never happen. */ private void setRetryTimeInternal(@ApnType int apnTypes, @ElapsedRealtimeLong long retryElapsedTime, @DcTracker.RequestNetworkType int newRequestType) { if (retryElapsedTime < 0) { retryElapsedTime = RetryManager.NO_SUGGESTED_RETRY_DELAY; } Loading Loading @@ -103,6 +222,9 @@ public class DataThrottler { /** * Get the earliest retry time for the given APN type. The time is the system's elapse time. * * Note the DataThrottler is running phone process's main thread, which is most of the telephony * components running on. Calling this method from other threads might run into race conditions. * * @param apnType APN type * @return The earliest retry time for APN type. The time is the system's elapse time. * {@link RetryManager#NO_SUGGESTED_RETRY_DELAY} indicates there is no throttling for given APN Loading @@ -127,6 +249,28 @@ public class DataThrottler { return RetryManager.NO_SUGGESTED_RETRY_DELAY; } /** * Resets retry times for all APNs to {@link RetryManager.NO_SUGGESTED_RETRY_DELAY}. */ public void reset() { sendEmptyMessage(EVENT_RESET); } /** * Resets retry times for all APNs to {@link RetryManager.NO_SUGGESTED_RETRY_DELAY}. */ private void resetInternal() { final List<Integer> apnTypes = new ArrayList<>(); for (ThrottleStatus throttleStatus : mThrottleStatus.values()) { apnTypes.add(throttleStatus.getApnType()); } for (int apnType : apnTypes) { setRetryTime(apnType, RetryManager.NO_SUGGESTED_RETRY_DELAY, DcTracker.REQUEST_TYPE_NORMAL); } } private ThrottleStatus createStatus(@Annotation.ApnType int apnType, long retryElapsedTime, @DcTracker.RequestNetworkType int newRequestType) { ThrottleStatus.Builder builder = new ThrottleStatus.Builder(); Loading
src/java/com/android/internal/telephony/dataconnection/DcTracker.java +2 −1 Original line number Diff line number Diff line Loading @@ -739,7 +739,7 @@ public class DcTracker extends Handler { mTransportType = transportType; mDataServiceManager = new DataServiceManager(phone, transportType, tagSuffix); mDataThrottler = new DataThrottler(mPhone.getPhoneId(), transportType); mDataThrottler = new DataThrottler(mPhone, transportType); mResolver = mPhone.getContext().getContentResolver(); mAlarmManager = Loading Loading @@ -832,6 +832,7 @@ public class DcTracker extends Handler { mPhone.getServiceStateTracker().unregisterForPsRestrictedEnabled(this); mPhone.getServiceStateTracker().unregisterForPsRestrictedDisabled(this); mPhone.getServiceStateTracker().unregisterForDataRegStateOrRatChanged(mTransportType, this); mPhone.getServiceStateTracker().unregisterForAirplaneModeChanged(this); } private void registerForAllEvents() { Loading
tests/telephonytests/src/com/android/internal/telephony/dataconnection/DataThrottlerTest.java +29 −10 Original line number Diff line number Diff line Loading @@ -65,7 +65,7 @@ public class DataThrottlerTest extends TelephonyTest { @Before public void setUp() throws Exception { super.setUp(getClass().getSimpleName()); mDataThrottler = new DataThrottler(1, AccessNetworkConstants.TRANSPORT_TYPE_WWAN); mDataThrottler = new DataThrottler(mPhone, AccessNetworkConstants.TRANSPORT_TYPE_WWAN); mDataThrottler.registerForThrottleStatusChanges(mMockChangedCallback1); } Loading @@ -87,9 +87,9 @@ public class DataThrottlerTest extends TelephonyTest { processAllMessages(); expectedStatuses.add(List.of()); mDataThrottler.setRetryTime(ApnSetting.TYPE_DEFAULT, 1234567890L, REQUEST_TYPE_NORMAL); processAllMessages(); assertEquals(1234567890L, mDataThrottler.getRetryTime(ApnSetting.TYPE_DEFAULT)); assertEquals(RetryManager.NO_SUGGESTED_RETRY_DELAY, mDataThrottler.getRetryTime(ApnSetting.TYPE_MMS)); Loading @@ -97,14 +97,14 @@ public class DataThrottlerTest extends TelephonyTest { processAllMessages(); expectedStatuses.add(List.of( new ThrottleStatus.Builder() .setSlotIndex(1) .setSlotIndex(0) .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN) .setApnType(ApnSetting.TYPE_HIPRI) .setThrottleExpiryTimeMillis(1234567890L) .setRetryType(ThrottleStatus.RETRY_TYPE_NEW_CONNECTION) .build(), new ThrottleStatus.Builder() .setSlotIndex(1) .setSlotIndex(0) .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN) .setApnType(DEFAULT_APN_TYPE) .setThrottleExpiryTimeMillis(1234567890L) Loading @@ -115,27 +115,28 @@ public class DataThrottlerTest extends TelephonyTest { mDataThrottler.setRetryTime(ApnSetting.TYPE_DEFAULT | ApnSetting.TYPE_DUN, 13579L, REQUEST_TYPE_HANDOVER); processAllMessages(); assertEquals(13579L, mDataThrottler.getRetryTime(ApnSetting.TYPE_DEFAULT)); assertEquals(13579L, mDataThrottler.getRetryTime(ApnSetting.TYPE_DUN)); processAllMessages(); expectedStatuses.add(List.of( new ThrottleStatus.Builder() .setSlotIndex(1) .setSlotIndex(0) .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN) .setApnType(ApnSetting.TYPE_HIPRI) .setThrottleExpiryTimeMillis(13579L) .setRetryType(ThrottleStatus.RETRY_TYPE_HANDOVER) .build(), new ThrottleStatus.Builder() .setSlotIndex(1) .setSlotIndex(0) .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN) .setApnType(ApnSetting.TYPE_DUN) .setThrottleExpiryTimeMillis(13579L) .setRetryType(ThrottleStatus.RETRY_TYPE_HANDOVER) .build(), new ThrottleStatus.Builder() .setSlotIndex(1) .setSlotIndex(0) .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN) .setApnType(DEFAULT_APN_TYPE) .setThrottleExpiryTimeMillis(13579L) Loading @@ -146,12 +147,13 @@ public class DataThrottlerTest extends TelephonyTest { mDataThrottler.setRetryTime(ApnSetting.TYPE_MMS, -10, REQUEST_TYPE_NORMAL); processAllMessages(); assertEquals(RetryManager.NO_SUGGESTED_RETRY_DELAY, mDataThrottler.getRetryTime(ApnSetting.TYPE_MMS)); processAllMessages(); expectedStatuses.add(List.of( new ThrottleStatus.Builder() .setSlotIndex(1) .setSlotIndex(0) .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN) .setNoThrottle() .setApnType(ApnSetting.TYPE_MMS) Loading @@ -165,14 +167,14 @@ public class DataThrottlerTest extends TelephonyTest { processAllMessages(); expectedStatuses.add(List.of( new ThrottleStatus.Builder() .setSlotIndex(1) .setSlotIndex(0) .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN) .setApnType(ApnSetting.TYPE_EMERGENCY) .setThrottleExpiryTimeMillis(RetryManager.NO_RETRY) .setRetryType(ThrottleStatus.RETRY_TYPE_NONE) .build(), new ThrottleStatus.Builder() .setSlotIndex(1) .setSlotIndex(0) .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN) .setApnType(ApnSetting.TYPE_FOTA) .setThrottleExpiryTimeMillis(RetryManager.NO_RETRY) Loading Loading @@ -213,4 +215,21 @@ public class DataThrottlerTest extends TelephonyTest { this.mDataThrottler.registerForThrottleStatusChanges(mMockChangedCallback2); } /** * Test the behavior of a retry manager with no waiting APNs set. */ @Test @SmallTest public void testUnthrottle() throws Exception { mDataThrottler.setRetryTime(ApnSetting.TYPE_DEFAULT, 1234567890L, REQUEST_TYPE_NORMAL); processAllMessages(); assertEquals(1234567890L, mDataThrottler.getRetryTime(ApnSetting.TYPE_DEFAULT)); mDataThrottler.reset(); processAllMessages(); assertEquals(RetryManager.NO_SUGGESTED_RETRY_DELAY, mDataThrottler.getRetryTime(ApnSetting.TYPE_DEFAULT)); } }