Loading src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java +108 −0 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ package com.android.internal.telephony.imsphone; import static com.android.internal.telephony.Phone.CS_FALLBACK; import android.annotation.NonNull; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; Loading Loading @@ -52,6 +53,7 @@ import android.telephony.DisconnectCause; import android.telephony.PhoneNumberUtils; import android.telephony.Rlog; import android.telephony.ServiceState; import android.telephony.SubscriptionInfo; import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; import android.telephony.emergency.EmergencyNumber; Loading Loading @@ -109,6 +111,9 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Queue; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.atomic.AtomicInteger; import java.util.regex.Pattern; Loading Loading @@ -290,6 +295,8 @@ public class ImsPhoneCallTracker extends CallTracker implements ImsPullCall { private static final int TIMEOUT_REDIAL_WIFI_E911_MS = 10000; private static final int TIMEOUT_PARTICIPANT_CONNECT_TIME_CACHE_MS = 60000; //ms // Following values are for mHoldSwitchingState private enum HoldSwapState { // Not in the middle of a hold/swap operation Loading Loading @@ -323,6 +330,20 @@ public class ImsPhoneCallTracker extends CallTracker implements ImsPullCall { // Hold aggregated video call data usage for each video call since boot. // The ImsCall's call id is the key of the map. private final HashMap<Integer, Long> mVtDataUsageMap = new HashMap<>(); private final Map<String, CacheEntry> mPhoneNumAndConnTime = new ConcurrentHashMap<>(); private final Queue<CacheEntry> mUnknownPeerConnTime = new LinkedBlockingQueue<>(); private static class CacheEntry { private long mCachedTime; private long mConnectTime; private long mConnectElapsedTime; CacheEntry(long cachedTime, long connectTime, long connectElapsedTime) { mCachedTime = cachedTime; mConnectTime = connectTime; mConnectElapsedTime = connectElapsedTime; } } private volatile NetworkStats mVtDataUsageSnapshot = null; private volatile NetworkStats mVtDataUsageUidSnapshot = null; Loading Loading @@ -1247,6 +1268,79 @@ public class ImsPhoneCallTracker extends CallTracker implements ImsPullCall { } } // Clean up expired cache entries. private void maintainConnectTimeCache() { long threshold = SystemClock.elapsedRealtime() - TIMEOUT_PARTICIPANT_CONNECT_TIME_CACHE_MS; // The cached time is the system elapsed millisecond when the CacheEntry is created. mPhoneNumAndConnTime.entrySet().removeIf(e -> e.getValue().mCachedTime < threshold); // Remove all the cached records which are older than current caching threshold. Since the // queue is FIFO, keep polling records until the queue is empty or the head of the queue is // fresh enough. while (!mUnknownPeerConnTime.isEmpty() && mUnknownPeerConnTime.peek().mCachedTime < threshold) { mUnknownPeerConnTime.poll(); } } private void cacheConnectionTimeWithPhoneNumber(@NonNull ImsPhoneConnection connection) { CacheEntry cachedConnectTime = new CacheEntry(SystemClock.elapsedRealtime(), connection.getConnectTime(), connection.getConnectTimeReal()); maintainConnectTimeCache(); if (PhoneConstants.PRESENTATION_ALLOWED == connection.getNumberPresentation()) { // In case of merging calls with the same number, use the latest connect time. Since // that call might be dropped and re-connected. So if the connectTime is earlier than // the cache, skip. String phoneNumber = getFormattedPhoneNumber(connection.getAddress()); if (mPhoneNumAndConnTime.containsKey(phoneNumber) && connection.getConnectTime() <= mPhoneNumAndConnTime.get(phoneNumber).mConnectTime) { // Use the latest connect time. return; } mPhoneNumAndConnTime.put(phoneNumber, cachedConnectTime); } else { mUnknownPeerConnTime.add(cachedConnectTime); } } private CacheEntry findConnectionTimeUsePhoneNumber( @NonNull ConferenceParticipant participant) { maintainConnectTimeCache(); if (PhoneConstants.PRESENTATION_ALLOWED == participant.getParticipantPresentation()) { if (participant.getHandle() == null || participant.getHandle().getSchemeSpecificPart() == null) { return null; } String numParts = PhoneNumberUtils .extractNetworkPortion(participant.getHandle().getSchemeSpecificPart()); if (TextUtils.isEmpty(numParts)) { return null; } String formattedNumber = getFormattedPhoneNumber(numParts); return mPhoneNumAndConnTime.get(formattedNumber); } else { return mUnknownPeerConnTime.poll(); } } private String getFormattedPhoneNumber(String number) { String countryIso = getCountryIso(); if (countryIso == null) { return number; } String phoneNumber = PhoneNumberUtils.formatNumberToE164(number, countryIso); return phoneNumber == null ? number : phoneNumber; } private String getCountryIso() { int subId = mPhone.getSubId(); SubscriptionInfo info = SubscriptionManager.from(mPhone.getContext()).getActiveSubscriptionInfo(subId); return info == null ? null : info.getCountryIso(); } public void conference() { ImsCall fgImsCall = mForegroundCall.getImsCall(); Loading Loading @@ -1294,12 +1388,14 @@ public class ImsPhoneCallTracker extends CallTracker implements ImsPullCall { foregroundConnection.setConferenceConnectTime(conferenceConnectTime); foregroundConnection.handleMergeStart(); foregroundId = foregroundConnection.getTelecomCallId(); cacheConnectionTimeWithPhoneNumber(foregroundConnection); } String backgroundId = ""; ImsPhoneConnection backgroundConnection = findConnection(bgImsCall); if (backgroundConnection != null) { backgroundConnection.handleMergeStart(); backgroundId = backgroundConnection.getTelecomCallId(); cacheConnectionTimeWithPhoneNumber(backgroundConnection); } log("conference: fgCallId=" + foregroundId + ", bgCallId=" + backgroundId); Loading Loading @@ -2551,6 +2647,17 @@ public class ImsPhoneCallTracker extends CallTracker implements ImsPullCall { } } private void updateConferenceParticipantsTiming(List<ConferenceParticipant> participants) { for (ConferenceParticipant participant : participants) { // Every time participants are newly created from parcel, update their connect time. CacheEntry cachedConnectTime = findConnectionTimeUsePhoneNumber(participant); if (cachedConnectTime != null) { participant.setConnectTime(cachedConnectTime.mConnectTime); participant.setConnectElapsedTime(cachedConnectTime.mConnectElapsedTime); } } } /** * Called when the state of IMS conference participant(s) has changed. * Loading @@ -2564,6 +2671,7 @@ public class ImsPhoneCallTracker extends CallTracker implements ImsPullCall { ImsPhoneConnection conn = findConnection(call); if (conn != null) { updateConferenceParticipantsTiming(participants); conn.updateConferenceParticipants(participants); } } Loading Loading
src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java +108 −0 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ package com.android.internal.telephony.imsphone; import static com.android.internal.telephony.Phone.CS_FALLBACK; import android.annotation.NonNull; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; Loading Loading @@ -52,6 +53,7 @@ import android.telephony.DisconnectCause; import android.telephony.PhoneNumberUtils; import android.telephony.Rlog; import android.telephony.ServiceState; import android.telephony.SubscriptionInfo; import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; import android.telephony.emergency.EmergencyNumber; Loading Loading @@ -109,6 +111,9 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Queue; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.atomic.AtomicInteger; import java.util.regex.Pattern; Loading Loading @@ -290,6 +295,8 @@ public class ImsPhoneCallTracker extends CallTracker implements ImsPullCall { private static final int TIMEOUT_REDIAL_WIFI_E911_MS = 10000; private static final int TIMEOUT_PARTICIPANT_CONNECT_TIME_CACHE_MS = 60000; //ms // Following values are for mHoldSwitchingState private enum HoldSwapState { // Not in the middle of a hold/swap operation Loading Loading @@ -323,6 +330,20 @@ public class ImsPhoneCallTracker extends CallTracker implements ImsPullCall { // Hold aggregated video call data usage for each video call since boot. // The ImsCall's call id is the key of the map. private final HashMap<Integer, Long> mVtDataUsageMap = new HashMap<>(); private final Map<String, CacheEntry> mPhoneNumAndConnTime = new ConcurrentHashMap<>(); private final Queue<CacheEntry> mUnknownPeerConnTime = new LinkedBlockingQueue<>(); private static class CacheEntry { private long mCachedTime; private long mConnectTime; private long mConnectElapsedTime; CacheEntry(long cachedTime, long connectTime, long connectElapsedTime) { mCachedTime = cachedTime; mConnectTime = connectTime; mConnectElapsedTime = connectElapsedTime; } } private volatile NetworkStats mVtDataUsageSnapshot = null; private volatile NetworkStats mVtDataUsageUidSnapshot = null; Loading Loading @@ -1247,6 +1268,79 @@ public class ImsPhoneCallTracker extends CallTracker implements ImsPullCall { } } // Clean up expired cache entries. private void maintainConnectTimeCache() { long threshold = SystemClock.elapsedRealtime() - TIMEOUT_PARTICIPANT_CONNECT_TIME_CACHE_MS; // The cached time is the system elapsed millisecond when the CacheEntry is created. mPhoneNumAndConnTime.entrySet().removeIf(e -> e.getValue().mCachedTime < threshold); // Remove all the cached records which are older than current caching threshold. Since the // queue is FIFO, keep polling records until the queue is empty or the head of the queue is // fresh enough. while (!mUnknownPeerConnTime.isEmpty() && mUnknownPeerConnTime.peek().mCachedTime < threshold) { mUnknownPeerConnTime.poll(); } } private void cacheConnectionTimeWithPhoneNumber(@NonNull ImsPhoneConnection connection) { CacheEntry cachedConnectTime = new CacheEntry(SystemClock.elapsedRealtime(), connection.getConnectTime(), connection.getConnectTimeReal()); maintainConnectTimeCache(); if (PhoneConstants.PRESENTATION_ALLOWED == connection.getNumberPresentation()) { // In case of merging calls with the same number, use the latest connect time. Since // that call might be dropped and re-connected. So if the connectTime is earlier than // the cache, skip. String phoneNumber = getFormattedPhoneNumber(connection.getAddress()); if (mPhoneNumAndConnTime.containsKey(phoneNumber) && connection.getConnectTime() <= mPhoneNumAndConnTime.get(phoneNumber).mConnectTime) { // Use the latest connect time. return; } mPhoneNumAndConnTime.put(phoneNumber, cachedConnectTime); } else { mUnknownPeerConnTime.add(cachedConnectTime); } } private CacheEntry findConnectionTimeUsePhoneNumber( @NonNull ConferenceParticipant participant) { maintainConnectTimeCache(); if (PhoneConstants.PRESENTATION_ALLOWED == participant.getParticipantPresentation()) { if (participant.getHandle() == null || participant.getHandle().getSchemeSpecificPart() == null) { return null; } String numParts = PhoneNumberUtils .extractNetworkPortion(participant.getHandle().getSchemeSpecificPart()); if (TextUtils.isEmpty(numParts)) { return null; } String formattedNumber = getFormattedPhoneNumber(numParts); return mPhoneNumAndConnTime.get(formattedNumber); } else { return mUnknownPeerConnTime.poll(); } } private String getFormattedPhoneNumber(String number) { String countryIso = getCountryIso(); if (countryIso == null) { return number; } String phoneNumber = PhoneNumberUtils.formatNumberToE164(number, countryIso); return phoneNumber == null ? number : phoneNumber; } private String getCountryIso() { int subId = mPhone.getSubId(); SubscriptionInfo info = SubscriptionManager.from(mPhone.getContext()).getActiveSubscriptionInfo(subId); return info == null ? null : info.getCountryIso(); } public void conference() { ImsCall fgImsCall = mForegroundCall.getImsCall(); Loading Loading @@ -1294,12 +1388,14 @@ public class ImsPhoneCallTracker extends CallTracker implements ImsPullCall { foregroundConnection.setConferenceConnectTime(conferenceConnectTime); foregroundConnection.handleMergeStart(); foregroundId = foregroundConnection.getTelecomCallId(); cacheConnectionTimeWithPhoneNumber(foregroundConnection); } String backgroundId = ""; ImsPhoneConnection backgroundConnection = findConnection(bgImsCall); if (backgroundConnection != null) { backgroundConnection.handleMergeStart(); backgroundId = backgroundConnection.getTelecomCallId(); cacheConnectionTimeWithPhoneNumber(backgroundConnection); } log("conference: fgCallId=" + foregroundId + ", bgCallId=" + backgroundId); Loading Loading @@ -2551,6 +2647,17 @@ public class ImsPhoneCallTracker extends CallTracker implements ImsPullCall { } } private void updateConferenceParticipantsTiming(List<ConferenceParticipant> participants) { for (ConferenceParticipant participant : participants) { // Every time participants are newly created from parcel, update their connect time. CacheEntry cachedConnectTime = findConnectionTimeUsePhoneNumber(participant); if (cachedConnectTime != null) { participant.setConnectTime(cachedConnectTime.mConnectTime); participant.setConnectElapsedTime(cachedConnectTime.mConnectElapsedTime); } } } /** * Called when the state of IMS conference participant(s) has changed. * Loading @@ -2564,6 +2671,7 @@ public class ImsPhoneCallTracker extends CallTracker implements ImsPullCall { ImsPhoneConnection conn = findConnection(call); if (conn != null) { updateConferenceParticipantsTiming(participants); conn.updateConferenceParticipants(participants); } } Loading