Loading src/java/com/android/internal/telephony/Call.java +12 −0 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ import com.android.telephony.Rlog; import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; /** * {@hide} Loading Loading @@ -121,6 +122,17 @@ public abstract class Call { } } /** * @return returns a summary of the connections held in this call. */ public String getConnectionSummary() { synchronized (mLock) { return mConnections.stream() .map(c -> c.getTelecomCallId() + "/objId:" + System.identityHashCode(c)) .collect(Collectors.joining(", ")); } } @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public abstract Phone getPhone(); @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) Loading src/java/com/android/internal/telephony/data/DataNetworkController.java +11 −8 Original line number Diff line number Diff line Loading @@ -1157,7 +1157,7 @@ public class DataNetworkController extends Handler { loge("onAddNetworkRequest: Duplicate network request. " + networkRequest); return; } logv("onAddNetworkRequest: added " + networkRequest); log("onAddNetworkRequest: added " + networkRequest); onSatisfyNetworkRequest(networkRequest); } Loading Loading @@ -1495,12 +1495,15 @@ public class DataNetworkController extends Handler { } networkRequest.setEvaluation(evaluation); // EXTERNAL_QUERY generates too many log spam. if (reason != DataEvaluationReason.EXTERNAL_QUERY) { log(evaluation.toString() + ", network type=" + TelephonyManager.getNetworkTypeName(getDataNetworkType(transport)) + ", reg state=" + NetworkRegistrationInfo.registrationStateToString( getDataRegistrationState(transport)) + ", " + networkRequest); } return evaluation; } Loading Loading @@ -1921,7 +1924,7 @@ public class DataNetworkController extends Handler { if (networkRequest.getAttachedNetwork() != null) { networkRequest.getAttachedNetwork().detachNetworkRequest(networkRequest); } logv("onRemoveNetworkRequest: Removed " + networkRequest); log("onRemoveNetworkRequest: Removed " + networkRequest); } /** Loading src/java/com/android/internal/telephony/data/TelephonyNetworkFactory.java +27 −12 Original line number Diff line number Diff line Loading @@ -267,6 +267,13 @@ public class TelephonyNetworkFactory extends NetworkFactory { } } private void releaseNetworkInternal(TelephonyNetworkRequest networkRequest) { NetworkRequestsStats.addNetworkRelease(networkRequest.getNativeNetworkRequest(), mSubscriptionId); mPhone.getDataNetworkController().removeNetworkRequest(networkRequest); } // TODO: Clean this up after old data stack removed. private void releaseNetworkInternal(TelephonyNetworkRequest networkRequest, @ReleaseNetworkType int releaseType, int transport) { Loading Loading @@ -311,9 +318,13 @@ public class TelephonyNetworkFactory extends NetworkFactory { requestNetworkInternal(networkRequest, DcTracker.REQUEST_TYPE_NORMAL, getTransportTypeFromNetworkRequest(networkRequest), null); } else if (action == ACTION_RELEASE) { if (mPhone.isUsingNewDataStack()) { releaseNetworkInternal(networkRequest); } else { releaseNetworkInternal(networkRequest, DcTracker.RELEASE_TYPE_DETACH, getTransportTypeFromNetworkRequest(networkRequest)); } } mNetworkRequests.put(networkRequest, shouldApply ? transportType : AccessNetworkConstants.TRANSPORT_TYPE_INVALID); Loading Loading @@ -375,18 +386,22 @@ public class TelephonyNetworkFactory extends NetworkFactory { logl("onReleaseNetworkFor " + networkRequest + " applied " + applied); if (applied) { // Most of the time, the network request only exists in one of the DcTracker, but in the // middle of handover, the network request temporarily exists in both DcTrackers. If // connectivity service releases the network request while handover is ongoing, we need // to remove network requests from both DcTrackers. // Note that this part will be refactored in T, where we won't even have DcTracker at // all. if (mPhone.isUsingNewDataStack()) { releaseNetworkInternal(networkRequest); } else { // Most of the time, the network request only exists in one of the DcTracker, but in // the middle of handover, the network request temporarily exists in both // DcTrackers. If connectivity service releases the network request while handover // is ongoing, we need to remove network requests from both DcTrackers. // Note that this part will be refactored in T, where we won't even have DcTracker // at all. releaseNetworkInternal(networkRequest, DcTracker.RELEASE_TYPE_NORMAL, AccessNetworkConstants.TRANSPORT_TYPE_WWAN); releaseNetworkInternal(networkRequest, DcTracker.RELEASE_TYPE_NORMAL, AccessNetworkConstants.TRANSPORT_TYPE_WLAN); } } } private void onDataHandoverNeeded(@ApnType int apnType, int targetTransport, HandoverParams handoverParams) { Loading src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java +49 −5 Original line number Diff line number Diff line Loading @@ -133,6 +133,7 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Optional; import java.util.Queue; import java.util.Set; Loading Loading @@ -205,7 +206,6 @@ public class ImsPhoneCallTracker extends CallTracker implements ImsPullCall { private void processIncomingCall(IImsCallSession c, Bundle extras) { if (DBG) log("processIncomingCall: incoming call intent"); mOperationLocalLog.log("onIncomingCall Received"); if (extras == null) extras = new Bundle(); if (mImsManager == null) return; Loading Loading @@ -275,6 +275,9 @@ public class ImsPhoneCallTracker extends CallTracker implements ImsPullCall { } } mOperationLocalLog.log("onIncomingCall: isUnknown=" + isUnknown + ", connId=" + System.identityHashCode(conn)); addConnection(conn); setVideoCallProvider(conn, imsCall); Loading @@ -284,6 +287,13 @@ public class ImsPhoneCallTracker extends CallTracker implements ImsPullCall { mPhone.getVoiceCallSessionStats().onImsCallReceived(conn); if (isUnknown) { // Check for condition where an unknown connection replaces a pending // MO call. This will cause problems later in all likelihood. if (mPendingMO != null && Objects.equals(mPendingMO.getAddress(), conn.getAddress())) { mOperationLocalLog.log("onIncomingCall: unknown call " + conn + " replaces " + mPendingMO); } mPhone.notifyUnknownConnection(conn); } else { if ((mForegroundCall.getState() != ImsPhoneCall.State.IDLE) Loading Loading @@ -2258,6 +2268,7 @@ public class ImsPhoneCallTracker extends CallTracker implements ImsPullCall { return !isImsAudioCallActiveOrHolding || !VideoProfile.isVideo(videoState); } /** * Determines if there are issues which would preclude dialing an outgoing call. Throws a * {@link CallStateException} if there is an issue. Loading Loading @@ -2325,9 +2336,14 @@ public class ImsPhoneCallTracker extends CallTracker implements ImsPullCall { if (DBG) { log("updatePhoneState pendingMo = " + (mPendingMO == null ? "null" : mPendingMO.getState()) + ", fg= " + mForegroundCall.getState() + "(" + mForegroundCall.getConnectionsCount() + "), bg= " + mBackgroundCall .getState() + "(" + mBackgroundCall.getConnectionsCount() + ")"); : mPendingMO.getState() + "(" + mPendingMO.getTelecomCallId() + "/objId:" + System.identityHashCode(mPendingMO) + ")") + ", rng= " + mRingingCall.getState() + "(" + mRingingCall.getConnectionSummary() + "), fg= " + mForegroundCall.getState() + "(" + mForegroundCall.getConnectionSummary() + "), bg= " + mBackgroundCall.getState() + "(" + mBackgroundCall.getConnectionSummary() + ")"); log("updatePhoneState oldState=" + oldState + ", newState=" + mState); } Loading Loading @@ -2618,9 +2634,32 @@ public class ImsPhoneCallTracker extends CallTracker implements ImsPullCall { return null; } /** * Given a connection, detach it from any {@link ImsPhoneCall} it is associated with, remove it * from the connections lists, and ensure if it was the pending MO connection it gets removed * from there as well. * @param conn The connection to cleanup and remove. */ public synchronized void cleanupAndRemoveConnection(ImsPhoneConnection conn) { mOperationLocalLog.log("cleanupAndRemoveConnection: " + conn); // If the connection is attached to a call, detach it. if (conn.getCall() != null) { conn.getCall().detach(conn); } // Remove it from the connection list. removeConnection(conn); // Finally, if it was the pending MO, then ensure that connection gets cleaned up as well. if (conn == mPendingMO) { mPendingMO.finalize(); mPendingMO = null; } } @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) private synchronized void removeConnection(ImsPhoneConnection conn) { public synchronized void removeConnection(ImsPhoneConnection conn) { mConnections.remove(conn); // If not emergency call is remaining, notify emergency call registrants if (mIsInEmergencyCall) { boolean isEmergencyCallInList = false; Loading Loading @@ -5321,6 +5360,11 @@ public class ImsPhoneCallTracker extends CallTracker implements ImsPullCall { return mConnections; } @VisibleForTesting public ImsPhoneConnection getPendingMO() { return mPendingMO; } /** * Set up static configuration from package/services/Telephony's config.xml. * @param config the config. Loading tests/telephonytests/src/com/android/internal/telephony/data/TelephonyNetworkFactoryTest.java +0 −37 Original line number Diff line number Diff line Loading @@ -439,41 +439,4 @@ public class TelephonyNetworkFactoryTest extends TelephonyTest { verify(mDataNetworkController, times(1)).removeNetworkRequest(any()); verify(mDataNetworkController, times(1)).addNetworkRequest(any()); } @Test @SmallTest public void testNetworkRequestReleasedDuringHandover() throws Exception { createMockedTelephonyComponents(); doReturn(0).when(mSubscriptionController).getSubIdUsingPhoneId(0); mTelephonyNetworkFactoryUT.mInternalHandler.sendEmptyMessage( TelephonyNetworkFactory.EVENT_SUBSCRIPTION_CHANGED); activatePhoneInPhoneSwitcher(0, true); makeDefaultInternetRequest(); NetworkRequest mmsNetworkRequest = makeSubSpecificMmsRequest(0); processAllMessages(); Field f = TelephonyNetworkFactory.class.getDeclaredField("mInternalHandler"); f.setAccessible(true); Handler h = (Handler) f.get(mTelephonyNetworkFactoryUT); HandoverCallback handoverCallback = mock(HandoverCallback.class); //Mockito.reset(mDcTracker); doReturn(mDataConnection).when(mDcTracker).getDataConnectionByApnType(anyString()); doReturn(true).when(mDataConnection).isActive(); HandoverParams hp = new HandoverParams(ApnSetting.TYPE_MMS, AccessNetworkConstants.TRANSPORT_TYPE_WLAN, handoverCallback); AsyncResult ar = new AsyncResult(null, hp, null); h.sendMessage(h.obtainMessage(5 /* EVENT_DATA_HANDOVER_NEEDED */, ar)); processAllMessages(); // Now release the network request while handover is still ongoing. mTelephonyNetworkFactoryUT.releaseNetworkFor(mmsNetworkRequest); processAllMessages(); // Ensure the release is called one more time after the normal release verify(mDataNetworkController, times(2)).removeNetworkRequest(any()); } } Loading
src/java/com/android/internal/telephony/Call.java +12 −0 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ import com.android.telephony.Rlog; import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; /** * {@hide} Loading Loading @@ -121,6 +122,17 @@ public abstract class Call { } } /** * @return returns a summary of the connections held in this call. */ public String getConnectionSummary() { synchronized (mLock) { return mConnections.stream() .map(c -> c.getTelecomCallId() + "/objId:" + System.identityHashCode(c)) .collect(Collectors.joining(", ")); } } @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public abstract Phone getPhone(); @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) Loading
src/java/com/android/internal/telephony/data/DataNetworkController.java +11 −8 Original line number Diff line number Diff line Loading @@ -1157,7 +1157,7 @@ public class DataNetworkController extends Handler { loge("onAddNetworkRequest: Duplicate network request. " + networkRequest); return; } logv("onAddNetworkRequest: added " + networkRequest); log("onAddNetworkRequest: added " + networkRequest); onSatisfyNetworkRequest(networkRequest); } Loading Loading @@ -1495,12 +1495,15 @@ public class DataNetworkController extends Handler { } networkRequest.setEvaluation(evaluation); // EXTERNAL_QUERY generates too many log spam. if (reason != DataEvaluationReason.EXTERNAL_QUERY) { log(evaluation.toString() + ", network type=" + TelephonyManager.getNetworkTypeName(getDataNetworkType(transport)) + ", reg state=" + NetworkRegistrationInfo.registrationStateToString( getDataRegistrationState(transport)) + ", " + networkRequest); } return evaluation; } Loading Loading @@ -1921,7 +1924,7 @@ public class DataNetworkController extends Handler { if (networkRequest.getAttachedNetwork() != null) { networkRequest.getAttachedNetwork().detachNetworkRequest(networkRequest); } logv("onRemoveNetworkRequest: Removed " + networkRequest); log("onRemoveNetworkRequest: Removed " + networkRequest); } /** Loading
src/java/com/android/internal/telephony/data/TelephonyNetworkFactory.java +27 −12 Original line number Diff line number Diff line Loading @@ -267,6 +267,13 @@ public class TelephonyNetworkFactory extends NetworkFactory { } } private void releaseNetworkInternal(TelephonyNetworkRequest networkRequest) { NetworkRequestsStats.addNetworkRelease(networkRequest.getNativeNetworkRequest(), mSubscriptionId); mPhone.getDataNetworkController().removeNetworkRequest(networkRequest); } // TODO: Clean this up after old data stack removed. private void releaseNetworkInternal(TelephonyNetworkRequest networkRequest, @ReleaseNetworkType int releaseType, int transport) { Loading Loading @@ -311,9 +318,13 @@ public class TelephonyNetworkFactory extends NetworkFactory { requestNetworkInternal(networkRequest, DcTracker.REQUEST_TYPE_NORMAL, getTransportTypeFromNetworkRequest(networkRequest), null); } else if (action == ACTION_RELEASE) { if (mPhone.isUsingNewDataStack()) { releaseNetworkInternal(networkRequest); } else { releaseNetworkInternal(networkRequest, DcTracker.RELEASE_TYPE_DETACH, getTransportTypeFromNetworkRequest(networkRequest)); } } mNetworkRequests.put(networkRequest, shouldApply ? transportType : AccessNetworkConstants.TRANSPORT_TYPE_INVALID); Loading Loading @@ -375,18 +386,22 @@ public class TelephonyNetworkFactory extends NetworkFactory { logl("onReleaseNetworkFor " + networkRequest + " applied " + applied); if (applied) { // Most of the time, the network request only exists in one of the DcTracker, but in the // middle of handover, the network request temporarily exists in both DcTrackers. If // connectivity service releases the network request while handover is ongoing, we need // to remove network requests from both DcTrackers. // Note that this part will be refactored in T, where we won't even have DcTracker at // all. if (mPhone.isUsingNewDataStack()) { releaseNetworkInternal(networkRequest); } else { // Most of the time, the network request only exists in one of the DcTracker, but in // the middle of handover, the network request temporarily exists in both // DcTrackers. If connectivity service releases the network request while handover // is ongoing, we need to remove network requests from both DcTrackers. // Note that this part will be refactored in T, where we won't even have DcTracker // at all. releaseNetworkInternal(networkRequest, DcTracker.RELEASE_TYPE_NORMAL, AccessNetworkConstants.TRANSPORT_TYPE_WWAN); releaseNetworkInternal(networkRequest, DcTracker.RELEASE_TYPE_NORMAL, AccessNetworkConstants.TRANSPORT_TYPE_WLAN); } } } private void onDataHandoverNeeded(@ApnType int apnType, int targetTransport, HandoverParams handoverParams) { Loading
src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java +49 −5 Original line number Diff line number Diff line Loading @@ -133,6 +133,7 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Optional; import java.util.Queue; import java.util.Set; Loading Loading @@ -205,7 +206,6 @@ public class ImsPhoneCallTracker extends CallTracker implements ImsPullCall { private void processIncomingCall(IImsCallSession c, Bundle extras) { if (DBG) log("processIncomingCall: incoming call intent"); mOperationLocalLog.log("onIncomingCall Received"); if (extras == null) extras = new Bundle(); if (mImsManager == null) return; Loading Loading @@ -275,6 +275,9 @@ public class ImsPhoneCallTracker extends CallTracker implements ImsPullCall { } } mOperationLocalLog.log("onIncomingCall: isUnknown=" + isUnknown + ", connId=" + System.identityHashCode(conn)); addConnection(conn); setVideoCallProvider(conn, imsCall); Loading @@ -284,6 +287,13 @@ public class ImsPhoneCallTracker extends CallTracker implements ImsPullCall { mPhone.getVoiceCallSessionStats().onImsCallReceived(conn); if (isUnknown) { // Check for condition where an unknown connection replaces a pending // MO call. This will cause problems later in all likelihood. if (mPendingMO != null && Objects.equals(mPendingMO.getAddress(), conn.getAddress())) { mOperationLocalLog.log("onIncomingCall: unknown call " + conn + " replaces " + mPendingMO); } mPhone.notifyUnknownConnection(conn); } else { if ((mForegroundCall.getState() != ImsPhoneCall.State.IDLE) Loading Loading @@ -2258,6 +2268,7 @@ public class ImsPhoneCallTracker extends CallTracker implements ImsPullCall { return !isImsAudioCallActiveOrHolding || !VideoProfile.isVideo(videoState); } /** * Determines if there are issues which would preclude dialing an outgoing call. Throws a * {@link CallStateException} if there is an issue. Loading Loading @@ -2325,9 +2336,14 @@ public class ImsPhoneCallTracker extends CallTracker implements ImsPullCall { if (DBG) { log("updatePhoneState pendingMo = " + (mPendingMO == null ? "null" : mPendingMO.getState()) + ", fg= " + mForegroundCall.getState() + "(" + mForegroundCall.getConnectionsCount() + "), bg= " + mBackgroundCall .getState() + "(" + mBackgroundCall.getConnectionsCount() + ")"); : mPendingMO.getState() + "(" + mPendingMO.getTelecomCallId() + "/objId:" + System.identityHashCode(mPendingMO) + ")") + ", rng= " + mRingingCall.getState() + "(" + mRingingCall.getConnectionSummary() + "), fg= " + mForegroundCall.getState() + "(" + mForegroundCall.getConnectionSummary() + "), bg= " + mBackgroundCall.getState() + "(" + mBackgroundCall.getConnectionSummary() + ")"); log("updatePhoneState oldState=" + oldState + ", newState=" + mState); } Loading Loading @@ -2618,9 +2634,32 @@ public class ImsPhoneCallTracker extends CallTracker implements ImsPullCall { return null; } /** * Given a connection, detach it from any {@link ImsPhoneCall} it is associated with, remove it * from the connections lists, and ensure if it was the pending MO connection it gets removed * from there as well. * @param conn The connection to cleanup and remove. */ public synchronized void cleanupAndRemoveConnection(ImsPhoneConnection conn) { mOperationLocalLog.log("cleanupAndRemoveConnection: " + conn); // If the connection is attached to a call, detach it. if (conn.getCall() != null) { conn.getCall().detach(conn); } // Remove it from the connection list. removeConnection(conn); // Finally, if it was the pending MO, then ensure that connection gets cleaned up as well. if (conn == mPendingMO) { mPendingMO.finalize(); mPendingMO = null; } } @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) private synchronized void removeConnection(ImsPhoneConnection conn) { public synchronized void removeConnection(ImsPhoneConnection conn) { mConnections.remove(conn); // If not emergency call is remaining, notify emergency call registrants if (mIsInEmergencyCall) { boolean isEmergencyCallInList = false; Loading Loading @@ -5321,6 +5360,11 @@ public class ImsPhoneCallTracker extends CallTracker implements ImsPullCall { return mConnections; } @VisibleForTesting public ImsPhoneConnection getPendingMO() { return mPendingMO; } /** * Set up static configuration from package/services/Telephony's config.xml. * @param config the config. Loading
tests/telephonytests/src/com/android/internal/telephony/data/TelephonyNetworkFactoryTest.java +0 −37 Original line number Diff line number Diff line Loading @@ -439,41 +439,4 @@ public class TelephonyNetworkFactoryTest extends TelephonyTest { verify(mDataNetworkController, times(1)).removeNetworkRequest(any()); verify(mDataNetworkController, times(1)).addNetworkRequest(any()); } @Test @SmallTest public void testNetworkRequestReleasedDuringHandover() throws Exception { createMockedTelephonyComponents(); doReturn(0).when(mSubscriptionController).getSubIdUsingPhoneId(0); mTelephonyNetworkFactoryUT.mInternalHandler.sendEmptyMessage( TelephonyNetworkFactory.EVENT_SUBSCRIPTION_CHANGED); activatePhoneInPhoneSwitcher(0, true); makeDefaultInternetRequest(); NetworkRequest mmsNetworkRequest = makeSubSpecificMmsRequest(0); processAllMessages(); Field f = TelephonyNetworkFactory.class.getDeclaredField("mInternalHandler"); f.setAccessible(true); Handler h = (Handler) f.get(mTelephonyNetworkFactoryUT); HandoverCallback handoverCallback = mock(HandoverCallback.class); //Mockito.reset(mDcTracker); doReturn(mDataConnection).when(mDcTracker).getDataConnectionByApnType(anyString()); doReturn(true).when(mDataConnection).isActive(); HandoverParams hp = new HandoverParams(ApnSetting.TYPE_MMS, AccessNetworkConstants.TRANSPORT_TYPE_WLAN, handoverCallback); AsyncResult ar = new AsyncResult(null, hp, null); h.sendMessage(h.obtainMessage(5 /* EVENT_DATA_HANDOVER_NEEDED */, ar)); processAllMessages(); // Now release the network request while handover is still ongoing. mTelephonyNetworkFactoryUT.releaseNetworkFor(mmsNetworkRequest); processAllMessages(); // Ensure the release is called one more time after the normal release verify(mDataNetworkController, times(2)).removeNetworkRequest(any()); } }