• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.internal.telephony.metrics;
18 
19 import static android.telephony.ims.RegistrationManager.REGISTRATION_STATE_NOT_REGISTERED;
20 import static android.telephony.ims.RegistrationManager.REGISTRATION_STATE_REGISTERED;
21 import static android.telephony.ims.RegistrationManager.REGISTRATION_STATE_REGISTERING;
22 import static android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_SMS;
23 import static android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_UT;
24 import static android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VIDEO;
25 import static android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE;
26 import static android.telephony.ims.stub.ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN;
27 import static android.telephony.ims.stub.ImsRegistrationImplBase.REGISTRATION_TECH_LTE;
28 import static android.telephony.ims.stub.ImsRegistrationImplBase.REGISTRATION_TECH_NONE;
29 import static android.telephony.ims.stub.ImsRegistrationImplBase.REGISTRATION_TECH_NR;
30 import static android.text.format.DateUtils.SECOND_IN_MILLIS;
31 import static android.util.Patterns.EMAIL_ADDRESS;
32 
33 import android.annotation.Nullable;
34 import android.os.SystemClock;
35 import android.telephony.AccessNetworkConstants;
36 import android.telephony.AccessNetworkConstants.TransportType;
37 import android.telephony.Annotation.NetworkType;
38 import android.telephony.NetworkRegistrationInfo;
39 import android.telephony.ServiceState;
40 import android.telephony.TelephonyManager;
41 import android.telephony.ims.ImsReasonInfo;
42 import android.telephony.ims.ProvisioningManager;
43 import android.telephony.ims.RegistrationManager.ImsRegistrationState;
44 import android.telephony.ims.feature.MmTelFeature.MmTelCapabilities;
45 import android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability;
46 import android.telephony.ims.stub.ImsRegistrationImplBase.ImsRegistrationTech;
47 
48 import com.android.internal.annotations.VisibleForTesting;
49 import com.android.internal.telephony.Phone;
50 import com.android.internal.telephony.PhoneFactory;
51 import com.android.internal.telephony.imsphone.ImsPhone;
52 import com.android.internal.telephony.nano.PersistAtomsProto.ImsRegistrationStats;
53 import com.android.internal.telephony.nano.PersistAtomsProto.ImsRegistrationTermination;
54 import com.android.telephony.Rlog;
55 
56 import java.util.regex.Pattern;
57 
58 /** Tracks IMS registration metrics for each phone. */
59 public class ImsStats {
60     private static final String TAG = ImsStats.class.getSimpleName();
61 
62     /**
63      * Minimal duration of the registration state.
64      *
65      * <p>Registration state (including changes in capable/available features) with duration shorter
66      * than this will be ignored as they are considered transient states.
67      */
68     private static final long MIN_REGISTRATION_DURATION_MILLIS = 1L * SECOND_IN_MILLIS;
69 
70     /**
71      * Maximum length of the extra message in the termination reason.
72      *
73      * <p>If the extra message is longer than this length, it will be truncated.
74      */
75     private static final int MAX_EXTRA_MESSAGE_LENGTH = 128;
76 
77     /** Pattern used to match UUIDs in IMS extra messages for filtering. */
78     private static final Pattern PATTERN_UUID =
79             Pattern.compile(
80                     "[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}");
81 
82     /** Replacement for UUIDs. */
83     private static final String REPLACEMENT_UUID = "<UUID_REDACTED>";
84 
85     /**
86      * Pattern used to match URI (e.g. sip, tel) in IMS extra messages for filtering.
87      *
88      * <p>NOTE: this simple pattern aims to catch the most common URI schemes. It is not meant to be
89      * RFC-complaint.
90      */
91     private static final Pattern PATTERN_URI =
92             Pattern.compile("([a-zA-Z]{2,}:)" + EMAIL_ADDRESS.pattern());
93 
94     /** Replacement for URI. */
95     private static final String REPLACEMENT_URI = "$1<REDACTED>";
96 
97     /**
98      * Pattern used to match IPv4 addresses in IMS extra messages for filtering.
99      *
100      * <p>This is a copy of {@code android.util.Patterns.IP_ADDRESS}, which is deprecated and might
101      * be removed in the future.
102      */
103     private static final Pattern PATTERN_IPV4 =
104             Pattern.compile(
105                     "((25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9])\\.(25[0-5]|2[0-4]"
106                             + "[0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9]|0)\\.(25[0-5]|2[0-4][0-9]|[0-1]"
107                             + "[0-9]{2}|[1-9][0-9]|[1-9]|0)\\.(25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}"
108                             + "|[1-9][0-9]|[0-9]))");
109 
110     /** Replacement for IPv4 addresses. */
111     private static final String REPLACEMENT_IPV4 = "<IPV4_REDACTED>";
112 
113     /**
114      * Pattern used to match IPv6 addresses in IMS extra messages for filtering.
115      *
116      * <p>NOTE: this pattern aims to catch the most common IPv6 addresses. It is not meant to be
117      * RFC-complaint or free of false positives.
118      */
119     private static final Pattern PATTERN_IPV6 =
120             Pattern.compile(
121                     // Full address
122                     "([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}"
123                             // Abbreviated address, e.g. 2001:4860:4860::8888
124                             + "|([0-9a-fA-F]{1,4}:){1,6}(:[0-9a-fA-F]{1,4}){1,6}"
125                             // Abbreviated network address, e.g. 2607:F8B0::
126                             + "|([0-9a-fA-F]{1,4}:){1,7}:"
127                             // Abbreviated address, e.g. ::1
128                             + "|:(:[0-9a-fA-F]{1,4}){1,7}");
129 
130     /** Replacement for IPv6 addresses. */
131     private static final String REPLACEMENT_IPV6 = "<IPV6_REDACTED>";
132 
133     /**
134      * Pattern used to match potential IMEI values in IMS extra messages for filtering.
135      *
136      * <p>This includes segmented IMEI or IMEI/SV, as well as unsegmented IMEI/SV.
137      */
138     private static final Pattern PATTERN_IMEI =
139             Pattern.compile(
140                     "(^|[^0-9])(?:"
141                             // IMEI, AABBBBBB-CCCCCC-D format; IMEI/SV, AABBBBBB-CCCCCC-EE format
142                             + "[0-9]{8}-[0-9]{6}-[0-9][0-9]?"
143                             // IMEI, AA-BBBBBB-CCCCCC-D format; IMEI/SV, AA-BBBBBB-CCCCCC-EE format
144                             + "|[0-9]{2}-[0-9]{6}-[0-9]{6}-[0-9][0-9]?"
145                             // IMEI/SV, unsegmented
146                             + "|[0-9]{16}"
147                             + ")($|[^0-9])");
148 
149     /** Replacement for IMEI. */
150     private static final String REPLACEMENT_IMEI = "$1<IMEI_REDACTED>$2";
151 
152     /**
153      * Pattern used to match potential unsegmented IMEI/IMSI values in IMS extra messages for
154      * filtering.
155      */
156     private static final Pattern PATTERN_UNSEGMENTED_IMEI_IMSI =
157             Pattern.compile("(^|[^0-9])[0-9]{15}($|[^0-9])");
158 
159     /** Replacement for unsegmented IMEI/IMSI. */
160     private static final String REPLACEMENT_UNSEGMENTED_IMEI_IMSI = "$1<IMEI_IMSI_REDACTED>$2";
161 
162     /**
163      * Pattern used to match hostnames in IMS extra messages for filtering.
164      *
165      * <p>This pattern differs from {@link android.util.Patterns.DOMAIN_NAME} in a few ways: it
166      * requires the name to have at least 3 segments (shorter names are nearly always public or
167      * typos, i.e. missing space after period), does not check the validity of TLDs, and does not
168      * support punycodes in TLDs.
169      */
170     private static final Pattern PATTERN_HOSTNAME =
171             Pattern.compile("([0-9a-zA-Z][0-9a-zA-Z_\\-]{0,61}[0-9a-zA-Z]\\.){2,}[a-zA-Z]{2,}");
172 
173     /** Replacement for hostnames. */
174     private static final String REPLACEMENT_HOSTNAME = "<HOSTNAME_REDACTED>";
175 
176     /**
177      * Pattern used to match potential IDs in IMS extra messages for filtering.
178      *
179      * <p>This pattern target numbers that are potential IDs in unknown formats. It should be
180      * replaced after all other replacements are done to ensure complete and correct filtering.
181      *
182      * <p>Specifically, this pattern looks for any number (including hex) that is separated by dots
183      * or dashes has at least 6 significant digits, and any unsegmented numbers that has at least 5
184      * significant digits.
185      */
186     private static final Pattern PATTERN_UNKNOWN_ID =
187             Pattern.compile(
188                     "(^|[^0-9a-fA-F])(([-\\.]?0)*[1-9a-fA-F]([-\\.]?[0-9a-fA-F]){5,}"
189                             + "|0*[1-9a-fA-F]([0-9a-fA-F]){4,})");
190 
191     /** Replacement for potential IDs. */
192     private static final String REPLACEMENT_UNKNOWN_ID = "$1<ID_REDACTED>";
193 
194     private final ImsPhone mPhone;
195     private final PersistAtomsStorage mStorage;
196 
197     @ImsRegistrationState private int mLastRegistrationState = REGISTRATION_STATE_NOT_REGISTERED;
198 
199     private long mLastTimestamp;
200     @Nullable private ImsRegistrationStats mLastRegistrationStats;
201     @TransportType int mLastTransportType = AccessNetworkConstants.TRANSPORT_TYPE_INVALID;
202     // Available features are those reported by ImsService to be available for use.
203     private MmTelCapabilities mLastAvailableFeatures = new MmTelCapabilities();
204 
205     // Capable features (enabled by device/carrier). Theses are available before IMS is registered
206     // and not necessarily updated when RAT changes.
207     private final MmTelCapabilities mLastWwanCapableFeatures = new MmTelCapabilities();
208     private final MmTelCapabilities mLastWlanCapableFeatures = new MmTelCapabilities();
209 
ImsStats(ImsPhone phone)210     public ImsStats(ImsPhone phone) {
211         mPhone = phone;
212         mStorage = PhoneFactory.getMetricsCollector().getAtomsStorage();
213     }
214 
215     /**
216      * Finalizes the durations of the current IMS registration stats segment.
217      *
218      * <p>This method is also invoked whenever the registration state, feature capability, or
219      * feature availability changes.
220      */
conclude()221     public synchronized void conclude() {
222         long now = getTimeMillis();
223 
224         // Currently not tracking time spent on registering.
225         if (mLastRegistrationState == REGISTRATION_STATE_REGISTERED) {
226             ImsRegistrationStats stats = copyOf(mLastRegistrationStats);
227             long duration = now - mLastTimestamp;
228 
229             if (duration < MIN_REGISTRATION_DURATION_MILLIS) {
230                 logw("conclude: discarding transient stats, duration=%d", duration);
231             } else {
232                 stats.registeredMillis = duration;
233 
234                 stats.voiceAvailableMillis =
235                         mLastAvailableFeatures.isCapable(CAPABILITY_TYPE_VOICE) ? duration : 0;
236                 stats.videoAvailableMillis =
237                         mLastAvailableFeatures.isCapable(CAPABILITY_TYPE_VIDEO) ? duration : 0;
238                 stats.utAvailableMillis =
239                         mLastAvailableFeatures.isCapable(CAPABILITY_TYPE_UT) ? duration : 0;
240                 stats.smsAvailableMillis =
241                         mLastAvailableFeatures.isCapable(CAPABILITY_TYPE_SMS) ? duration : 0;
242 
243                 MmTelCapabilities lastCapableFeatures =
244                         stats.rat == TelephonyManager.NETWORK_TYPE_IWLAN
245                                 ? mLastWlanCapableFeatures
246                                 : mLastWwanCapableFeatures;
247                 stats.voiceCapableMillis =
248                         lastCapableFeatures.isCapable(CAPABILITY_TYPE_VOICE) ? duration : 0;
249                 stats.videoCapableMillis =
250                         lastCapableFeatures.isCapable(CAPABILITY_TYPE_VIDEO) ? duration : 0;
251                 stats.utCapableMillis =
252                         lastCapableFeatures.isCapable(CAPABILITY_TYPE_UT) ? duration : 0;
253                 stats.smsCapableMillis =
254                         lastCapableFeatures.isCapable(CAPABILITY_TYPE_SMS) ? duration : 0;
255 
256                 mStorage.addImsRegistrationStats(stats);
257             }
258         }
259 
260         mLastTimestamp = now;
261     }
262 
263     /** Updates the stats when registered features changed. */
onImsCapabilitiesChanged( @msRegistrationTech int radioTech, MmTelCapabilities capabilities)264     public synchronized void onImsCapabilitiesChanged(
265             @ImsRegistrationTech int radioTech, MmTelCapabilities capabilities) {
266         conclude();
267 
268         boolean ratChanged = false;
269         @NetworkType int newRat = convertRegistrationTechToNetworkType(radioTech);
270         mLastTransportType =
271                 (newRat == TelephonyManager.NETWORK_TYPE_IWLAN)
272                         ? AccessNetworkConstants.TRANSPORT_TYPE_WLAN
273                         : AccessNetworkConstants.TRANSPORT_TYPE_WWAN;
274         if (mLastRegistrationStats != null && mLastRegistrationStats.rat != newRat) {
275             mLastRegistrationStats.rat = newRat;
276             ratChanged = true;
277         }
278 
279         boolean voiceAvailableNow = capabilities.isCapable(CAPABILITY_TYPE_VOICE);
280         boolean voiceAvailabilityChanged =
281                 (mLastAvailableFeatures.isCapable(CAPABILITY_TYPE_VOICE) != voiceAvailableNow);
282         mLastAvailableFeatures = capabilities;
283 
284         // Notify voice RAT change if 1. RAT changed while voice over IMS is available, or 2. voice
285         // over IMS availability changed
286         if ((ratChanged && voiceAvailableNow) || voiceAvailabilityChanged) {
287             mPhone.getDefaultPhone().getServiceStateTracker().getServiceStateStats()
288                     .onImsVoiceRegistrationChanged();
289         }
290     }
291 
292     /** Updates the stats when capable features changed. */
onSetFeatureResponse( @mTelCapability int feature, @ImsRegistrationTech int network, int value)293     public synchronized void onSetFeatureResponse(
294             @MmTelCapability int feature, @ImsRegistrationTech int network, int value) {
295         MmTelCapabilities lastCapableFeatures = getLastCapableFeaturesForTech(network);
296         if (lastCapableFeatures != null) {
297             conclude();
298             if (value == ProvisioningManager.PROVISIONING_VALUE_ENABLED) {
299                 lastCapableFeatures.addCapabilities(feature);
300             } else {
301                 lastCapableFeatures.removeCapabilities(feature);
302             }
303         }
304     }
305 
306     /** Updates the stats when IMS registration is progressing. */
onImsRegistering(@ransportType int imsRadioTech)307     public synchronized void onImsRegistering(@TransportType int imsRadioTech) {
308         conclude();
309 
310         mLastTransportType = imsRadioTech;
311         mLastRegistrationStats = getDefaultImsRegistrationStats();
312         mLastRegistrationStats.rat = convertTransportTypeToNetworkType(imsRadioTech);
313         mLastRegistrationState = REGISTRATION_STATE_REGISTERING;
314     }
315 
316     /** Updates the stats when IMS registration succeeds. */
onImsRegistered(@ransportType int imsRadioTech)317     public synchronized void onImsRegistered(@TransportType int imsRadioTech) {
318         conclude();
319 
320         mLastTransportType = imsRadioTech;
321         // NOTE: mLastRegistrationStats can be null (no registering phase).
322         if (mLastRegistrationStats == null) {
323             mLastRegistrationStats = getDefaultImsRegistrationStats();
324         }
325         mLastRegistrationStats.rat = convertTransportTypeToNetworkType(imsRadioTech);
326         mLastRegistrationState = REGISTRATION_STATE_REGISTERED;
327     }
328 
329     /** Updates the stats and generates a termination atom when IMS registration fails/ends. */
onImsUnregistered(ImsReasonInfo reasonInfo)330     public synchronized void onImsUnregistered(ImsReasonInfo reasonInfo) {
331         conclude();
332 
333         // Generate end reason atom.
334         // NOTE: mLastRegistrationStats can be null (no registering phase).
335         ImsRegistrationTermination termination = new ImsRegistrationTermination();
336         if (mLastRegistrationStats != null) {
337             termination.carrierId = mLastRegistrationStats.carrierId;
338             termination.ratAtEnd = getRatAtEnd(mLastRegistrationStats.rat);
339         } else {
340             termination.carrierId = mPhone.getDefaultPhone().getCarrierId();
341             // We cannot tell whether the registration was intended for WWAN or WLAN
342             termination.ratAtEnd = TelephonyManager.NETWORK_TYPE_UNKNOWN;
343         }
344         termination.isMultiSim = SimSlotState.isMultiSim();
345         termination.setupFailed = (mLastRegistrationState != REGISTRATION_STATE_REGISTERED);
346         termination.reasonCode = reasonInfo.getCode();
347         termination.extraCode = reasonInfo.getExtraCode();
348         termination.extraMessage = filterExtraMessage(reasonInfo.getExtraMessage());
349         termination.count = 1;
350         mStorage.addImsRegistrationTermination(termination);
351 
352         // Reset state to unregistered.
353         mLastRegistrationState = REGISTRATION_STATE_NOT_REGISTERED;
354         mLastRegistrationStats = null;
355         mLastAvailableFeatures = new MmTelCapabilities();
356     }
357 
358     /** Updates the RAT when service state changes. */
onServiceStateChanged(ServiceState state)359     public synchronized void onServiceStateChanged(ServiceState state) {
360         if (mLastTransportType == AccessNetworkConstants.TRANSPORT_TYPE_WWAN
361                 && mLastRegistrationStats != null) {
362             mLastRegistrationStats.rat =
363                     ServiceStateStats.getRat(state, NetworkRegistrationInfo.DOMAIN_PS);
364         }
365     }
366 
367     /**
368      * Returns the current RAT used for IMS voice registration, or {@link
369      * TelephonyManager#NETWORK_TYPE_UNKNOWN} if there isn't any.
370      */
371     @NetworkType
getImsVoiceRadioTech()372     public synchronized int getImsVoiceRadioTech() {
373         if (mLastRegistrationStats == null
374                 || !mLastAvailableFeatures.isCapable(CAPABILITY_TYPE_VOICE)) {
375             return TelephonyManager.NETWORK_TYPE_UNKNOWN;
376         }
377         return mLastRegistrationStats.rat;
378     }
379 
380     @NetworkType
getRatAtEnd(@etworkType int lastStateRat)381     private int getRatAtEnd(@NetworkType int lastStateRat) {
382         return lastStateRat == TelephonyManager.NETWORK_TYPE_IWLAN ? lastStateRat : getWwanPsRat();
383     }
384 
385     @NetworkType
convertTransportTypeToNetworkType(@ransportType int transportType)386     private int convertTransportTypeToNetworkType(@TransportType int transportType) {
387         switch (transportType) {
388             case AccessNetworkConstants.TRANSPORT_TYPE_WWAN:
389                 return getWwanPsRat();
390             case AccessNetworkConstants.TRANSPORT_TYPE_WLAN:
391                 return TelephonyManager.NETWORK_TYPE_IWLAN;
392             default:
393                 return TelephonyManager.NETWORK_TYPE_UNKNOWN;
394         }
395     }
396 
397     @NetworkType
getWwanPsRat()398     private int getWwanPsRat() {
399         return ServiceStateStats.getRat(
400                 mPhone.getServiceStateTracker().getServiceState(),
401                 NetworkRegistrationInfo.DOMAIN_PS);
402     }
403 
getDefaultImsRegistrationStats()404     private ImsRegistrationStats getDefaultImsRegistrationStats() {
405         Phone phone = mPhone.getDefaultPhone();
406         ImsRegistrationStats stats = new ImsRegistrationStats();
407         stats.carrierId = phone.getCarrierId();
408         stats.simSlotIndex = phone.getPhoneId();
409         return stats;
410     }
411 
412     @Nullable
getLastCapableFeaturesForTech(@msRegistrationTech int radioTech)413     private MmTelCapabilities getLastCapableFeaturesForTech(@ImsRegistrationTech int radioTech) {
414         switch (radioTech) {
415             case REGISTRATION_TECH_NONE:
416                 return null;
417             case REGISTRATION_TECH_IWLAN:
418                 return mLastWlanCapableFeatures;
419             default:
420                 return mLastWwanCapableFeatures;
421         }
422     }
423 
424     @NetworkType
convertRegistrationTechToNetworkType(@msRegistrationTech int radioTech)425     private int convertRegistrationTechToNetworkType(@ImsRegistrationTech int radioTech) {
426         switch (radioTech) {
427             case REGISTRATION_TECH_NONE:
428                 return TelephonyManager.NETWORK_TYPE_UNKNOWN;
429             case REGISTRATION_TECH_LTE:
430                 return TelephonyManager.NETWORK_TYPE_LTE;
431             case REGISTRATION_TECH_IWLAN:
432                 return TelephonyManager.NETWORK_TYPE_IWLAN;
433             case REGISTRATION_TECH_NR:
434                 return TelephonyManager.NETWORK_TYPE_NR;
435             default:
436                 loge("convertRegistrationTechToNetworkType: unknown radio tech %d", radioTech);
437                 return getWwanPsRat();
438         }
439     }
440 
copyOf(ImsRegistrationStats source)441     private static ImsRegistrationStats copyOf(ImsRegistrationStats source) {
442         ImsRegistrationStats dest = new ImsRegistrationStats();
443 
444         dest.carrierId = source.carrierId;
445         dest.simSlotIndex = source.simSlotIndex;
446         dest.rat = source.rat;
447         dest.registeredMillis = source.registeredMillis;
448         dest.voiceCapableMillis = source.voiceCapableMillis;
449         dest.voiceAvailableMillis = source.voiceAvailableMillis;
450         dest.smsCapableMillis = source.smsCapableMillis;
451         dest.smsAvailableMillis = source.smsAvailableMillis;
452         dest.videoCapableMillis = source.videoCapableMillis;
453         dest.videoAvailableMillis = source.videoAvailableMillis;
454         dest.utCapableMillis = source.utCapableMillis;
455         dest.utAvailableMillis = source.utAvailableMillis;
456 
457         return dest;
458     }
459 
460     @VisibleForTesting
getTimeMillis()461     protected long getTimeMillis() {
462         return SystemClock.elapsedRealtime();
463     }
464 
465     /** Filters IMS extra messages to ensure length limit and remove IDs. */
filterExtraMessage(@ullable String str)466     public static String filterExtraMessage(@Nullable String str) {
467         if (str == null) {
468             return "";
469         }
470 
471         str = PATTERN_UUID.matcher(str).replaceAll(REPLACEMENT_UUID);
472         str = PATTERN_URI.matcher(str).replaceAll(REPLACEMENT_URI);
473         str = PATTERN_HOSTNAME.matcher(str).replaceAll(REPLACEMENT_HOSTNAME);
474         str = PATTERN_IPV4.matcher(str).replaceAll(REPLACEMENT_IPV4);
475         str = PATTERN_IPV6.matcher(str).replaceAll(REPLACEMENT_IPV6);
476         str = PATTERN_IMEI.matcher(str).replaceAll(REPLACEMENT_IMEI);
477         str = PATTERN_UNSEGMENTED_IMEI_IMSI.matcher(str)
478                 .replaceAll(REPLACEMENT_UNSEGMENTED_IMEI_IMSI);
479         str = PATTERN_UNKNOWN_ID.matcher(str).replaceAll(REPLACEMENT_UNKNOWN_ID);
480 
481         return str.length() > MAX_EXTRA_MESSAGE_LENGTH
482                 ? str.substring(0, MAX_EXTRA_MESSAGE_LENGTH)
483                 : str;
484     }
485 
logw(String format, Object... args)486     private void logw(String format, Object... args) {
487         Rlog.w(TAG, "[" + mPhone.getPhoneId() + "] " + String.format(format, args));
488     }
489 
loge(String format, Object... args)490     private void loge(String format, Object... args) {
491         Rlog.e(TAG, "[" + mPhone.getPhoneId() + "] " + String.format(format, args));
492     }
493 }
494