• 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 com.android.internal.telephony.InboundSmsHandler.SOURCE_INJECTED_FROM_IMS;
20 import static com.android.internal.telephony.InboundSmsHandler.SOURCE_INJECTED_FROM_UNKNOWN;
21 import static com.android.internal.telephony.InboundSmsHandler.SOURCE_NOT_INJECTED;
22 import static com.android.internal.telephony.SmsResponse.NO_ERROR_CODE;
23 import static com.android.internal.telephony.TelephonyStatsLog.INCOMING_SMS__ERROR__SMS_ERROR_GENERIC;
24 import static com.android.internal.telephony.TelephonyStatsLog.INCOMING_SMS__ERROR__SMS_ERROR_NOT_SUPPORTED;
25 import static com.android.internal.telephony.TelephonyStatsLog.INCOMING_SMS__ERROR__SMS_ERROR_NO_MEMORY;
26 import static com.android.internal.telephony.TelephonyStatsLog.INCOMING_SMS__ERROR__SMS_SUCCESS;
27 import static com.android.internal.telephony.TelephonyStatsLog.INCOMING_SMS__SMS_FORMAT__SMS_FORMAT_3GPP;
28 import static com.android.internal.telephony.TelephonyStatsLog.INCOMING_SMS__SMS_FORMAT__SMS_FORMAT_3GPP2;
29 import static com.android.internal.telephony.TelephonyStatsLog.INCOMING_SMS__SMS_TECH__SMS_TECH_CS_3GPP;
30 import static com.android.internal.telephony.TelephonyStatsLog.INCOMING_SMS__SMS_TECH__SMS_TECH_CS_3GPP2;
31 import static com.android.internal.telephony.TelephonyStatsLog.INCOMING_SMS__SMS_TECH__SMS_TECH_IMS;
32 import static com.android.internal.telephony.TelephonyStatsLog.INCOMING_SMS__SMS_TECH__SMS_TECH_UNKNOWN;
33 import static com.android.internal.telephony.TelephonyStatsLog.INCOMING_SMS__SMS_TYPE__SMS_TYPE_NORMAL;
34 import static com.android.internal.telephony.TelephonyStatsLog.INCOMING_SMS__SMS_TYPE__SMS_TYPE_SMS_PP;
35 import static com.android.internal.telephony.TelephonyStatsLog.INCOMING_SMS__SMS_TYPE__SMS_TYPE_VOICEMAIL_INDICATION;
36 import static com.android.internal.telephony.TelephonyStatsLog.INCOMING_SMS__SMS_TYPE__SMS_TYPE_WAP_PUSH;
37 import static com.android.internal.telephony.TelephonyStatsLog.INCOMING_SMS__SMS_TYPE__SMS_TYPE_ZERO;
38 import static com.android.internal.telephony.TelephonyStatsLog.OUTGOING_SMS__SEND_RESULT__SMS_SEND_RESULT_ERROR;
39 import static com.android.internal.telephony.TelephonyStatsLog.OUTGOING_SMS__SEND_RESULT__SMS_SEND_RESULT_ERROR_FALLBACK;
40 import static com.android.internal.telephony.TelephonyStatsLog.OUTGOING_SMS__SEND_RESULT__SMS_SEND_RESULT_ERROR_RETRY;
41 import static com.android.internal.telephony.TelephonyStatsLog.OUTGOING_SMS__SEND_RESULT__SMS_SEND_RESULT_SUCCESS;
42 import static com.android.internal.telephony.TelephonyStatsLog.OUTGOING_SMS__SEND_RESULT__SMS_SEND_RESULT_UNKNOWN;
43 
44 import android.annotation.Nullable;
45 import android.app.Activity;
46 import android.provider.Telephony.Sms.Intents;
47 import android.telephony.Annotation.NetworkType;
48 import android.telephony.ServiceState;
49 import android.telephony.SmsManager;
50 import android.telephony.TelephonyManager;
51 import android.telephony.ims.stub.ImsRegistrationImplBase;
52 import android.telephony.ims.stub.ImsSmsImplBase;
53 import android.telephony.ims.stub.ImsSmsImplBase.SendStatusResult;
54 
55 import com.android.internal.telephony.InboundSmsHandler;
56 import com.android.internal.telephony.Phone;
57 import com.android.internal.telephony.PhoneConstants;
58 import com.android.internal.telephony.PhoneFactory;
59 import com.android.internal.telephony.ServiceStateTracker;
60 import com.android.internal.telephony.nano.PersistAtomsProto.IncomingSms;
61 import com.android.internal.telephony.nano.PersistAtomsProto.OutgoingShortCodeSms;
62 import com.android.internal.telephony.nano.PersistAtomsProto.OutgoingSms;
63 import com.android.telephony.Rlog;
64 
65 import java.util.Objects;
66 import java.util.Random;
67 
68 /** Collects sms events per phone ID for the pulled atom. */
69 public class SmsStats {
70     private static final String TAG = SmsStats.class.getSimpleName();
71 
72     /** 3GPP error for out of service: "no network service" in TS 27.005 cl 3.2.5 */
73     private static final int NO_NETWORK_ERROR_3GPP = 331;
74 
75     /** 3GPP2 error for out of service: "Other radio interface problem" in N.S0005 Table 171 */
76     private static final int NO_NETWORK_ERROR_3GPP2 = 66;
77 
78     private final Phone mPhone;
79 
80     private final PersistAtomsStorage mAtomsStorage =
81             PhoneFactory.getMetricsCollector().getAtomsStorage();
82 
83     private static final Random RANDOM = new Random();
84 
SmsStats(Phone phone)85     public SmsStats(Phone phone) {
86         mPhone = phone;
87     }
88 
89     /** Create a new atom when multi-part incoming SMS is dropped due to missing parts. */
onDroppedIncomingMultipartSms(boolean is3gpp2, int receivedCount, int totalCount)90     public void onDroppedIncomingMultipartSms(boolean is3gpp2, int receivedCount, int totalCount) {
91         IncomingSms proto = getIncomingDefaultProto(is3gpp2, SOURCE_NOT_INJECTED);
92         // Keep SMS tech as unknown because it's possible that it changed overtime and is not
93         // necessarily the current one. Similarly mark the RAT as unknown.
94         proto.smsTech = INCOMING_SMS__SMS_TECH__SMS_TECH_UNKNOWN;
95         proto.rat = TelephonyManager.NETWORK_TYPE_UNKNOWN;
96         proto.error = INCOMING_SMS__ERROR__SMS_ERROR_GENERIC;
97         proto.totalParts = totalCount;
98         proto.receivedParts = receivedCount;
99         mAtomsStorage.addIncomingSms(proto);
100     }
101 
102     /** Create a new atom when an SMS for the voicemail indicator is received. */
onIncomingSmsVoicemail(boolean is3gpp2, @InboundSmsHandler.SmsSource int smsSource)103     public void onIncomingSmsVoicemail(boolean is3gpp2,
104             @InboundSmsHandler.SmsSource int smsSource) {
105         IncomingSms proto = getIncomingDefaultProto(is3gpp2, smsSource);
106         proto.smsType = INCOMING_SMS__SMS_TYPE__SMS_TYPE_VOICEMAIL_INDICATION;
107         mAtomsStorage.addIncomingSms(proto);
108     }
109 
110     /** Create a new atom when an SMS of type zero is received. */
onIncomingSmsTypeZero(@nboundSmsHandler.SmsSource int smsSource)111     public void onIncomingSmsTypeZero(@InboundSmsHandler.SmsSource int smsSource) {
112         IncomingSms proto = getIncomingDefaultProto(false /* is3gpp2 */, smsSource);
113         proto.smsType = INCOMING_SMS__SMS_TYPE__SMS_TYPE_ZERO;
114         mAtomsStorage.addIncomingSms(proto);
115     }
116 
117     /** Create a new atom when an SMS-PP for the SIM card is received. */
onIncomingSmsPP(@nboundSmsHandler.SmsSource int smsSource, boolean success)118     public void onIncomingSmsPP(@InboundSmsHandler.SmsSource int smsSource, boolean success) {
119         IncomingSms proto = getIncomingDefaultProto(false /* is3gpp2 */, smsSource);
120         proto.smsType = INCOMING_SMS__SMS_TYPE__SMS_TYPE_SMS_PP;
121         proto.error = getIncomingSmsError(success);
122         mAtomsStorage.addIncomingSms(proto);
123     }
124 
125     /** Create a new atom when an SMS is received successfully. */
onIncomingSmsSuccess(boolean is3gpp2, @InboundSmsHandler.SmsSource int smsSource, int messageCount, boolean blocked, long messageId)126     public void onIncomingSmsSuccess(boolean is3gpp2,
127             @InboundSmsHandler.SmsSource int smsSource, int messageCount,
128             boolean blocked, long messageId) {
129         IncomingSms proto = getIncomingDefaultProto(is3gpp2, smsSource);
130         proto.totalParts = messageCount;
131         proto.receivedParts = messageCount;
132         proto.blocked = blocked;
133         proto.messageId = messageId;
134         mAtomsStorage.addIncomingSms(proto);
135     }
136 
137     /** Create a new atom when an incoming SMS has an error. */
onIncomingSmsError(boolean is3gpp2, @InboundSmsHandler.SmsSource int smsSource, int result)138     public void onIncomingSmsError(boolean is3gpp2,
139             @InboundSmsHandler.SmsSource int smsSource, int result) {
140         IncomingSms proto = getIncomingDefaultProto(is3gpp2, smsSource);
141         proto.error = getIncomingSmsError(result);
142         mAtomsStorage.addIncomingSms(proto);
143     }
144 
145     /** Create a new atom when an incoming WAP_PUSH SMS is received. */
onIncomingSmsWapPush(@nboundSmsHandler.SmsSource int smsSource, int messageCount, int result, long messageId)146     public void onIncomingSmsWapPush(@InboundSmsHandler.SmsSource int smsSource,
147             int messageCount, int result, long messageId) {
148         IncomingSms proto = getIncomingDefaultProto(false, smsSource);
149         proto.smsType = INCOMING_SMS__SMS_TYPE__SMS_TYPE_WAP_PUSH;
150         proto.totalParts = messageCount;
151         proto.receivedParts = messageCount;
152         proto.error = getIncomingSmsError(result);
153         proto.messageId = messageId;
154         mAtomsStorage.addIncomingSms(proto);
155     }
156 
157     /** Create a new atom when an outgoing SMS is sent. */
onOutgoingSms(boolean isOverIms, boolean is3gpp2, boolean fallbackToCs, @SmsManager.Result int sendErrorCode, long messageId, boolean isFromDefaultApp, long intervalMillis)158     public void onOutgoingSms(boolean isOverIms, boolean is3gpp2, boolean fallbackToCs,
159             @SmsManager.Result int sendErrorCode, long messageId, boolean isFromDefaultApp,
160             long intervalMillis) {
161         onOutgoingSms(isOverIms, is3gpp2, fallbackToCs, sendErrorCode, NO_ERROR_CODE,
162                 messageId, isFromDefaultApp, intervalMillis);
163     }
164 
165     /** Create a new atom when an outgoing SMS is sent. */
onOutgoingSms(boolean isOverIms, boolean is3gpp2, boolean fallbackToCs, @SmsManager.Result int sendErrorCode, int networkErrorCode, long messageId, boolean isFromDefaultApp, long intervalMillis)166     public void onOutgoingSms(boolean isOverIms, boolean is3gpp2, boolean fallbackToCs,
167             @SmsManager.Result int sendErrorCode, int networkErrorCode, long messageId,
168             boolean isFromDefaultApp, long intervalMillis) {
169         OutgoingSms proto =
170                 getOutgoingDefaultProto(is3gpp2, isOverIms, messageId, isFromDefaultApp,
171                         intervalMillis);
172 
173         // The field errorCode is used for up-to-Android-13 devices. From Android 14, sendErrorCode
174         // and networkErrorCode will be used. The field errorCode will be deprecated when most
175         // devices use Android 14 or higher versions.
176         if (isOverIms) {
177             // Populate error code and result for IMS case
178             proto.errorCode = sendErrorCode;
179             if (fallbackToCs) {
180                 proto.sendResult = OUTGOING_SMS__SEND_RESULT__SMS_SEND_RESULT_ERROR_FALLBACK;
181             } else if (sendErrorCode == SmsManager.RESULT_RIL_SMS_SEND_FAIL_RETRY) {
182                 proto.sendResult = OUTGOING_SMS__SEND_RESULT__SMS_SEND_RESULT_ERROR_RETRY;
183             } else if (sendErrorCode != SmsManager.RESULT_ERROR_NONE) {
184                 proto.sendResult = OUTGOING_SMS__SEND_RESULT__SMS_SEND_RESULT_ERROR;
185             }
186         } else {
187             // Populate error code and result for CS case
188             if (sendErrorCode == SmsManager.RESULT_RIL_SMS_SEND_FAIL_RETRY) {
189                 proto.sendResult = OUTGOING_SMS__SEND_RESULT__SMS_SEND_RESULT_ERROR_RETRY;
190             } else if (sendErrorCode != SmsManager.RESULT_ERROR_NONE) {
191                 proto.sendResult = OUTGOING_SMS__SEND_RESULT__SMS_SEND_RESULT_ERROR;
192             }
193             proto.errorCode = networkErrorCode;
194             if (sendErrorCode == SmsManager.RESULT_RIL_RADIO_NOT_AVAILABLE
195                     && networkErrorCode == NO_ERROR_CODE) {
196                 proto.errorCode = is3gpp2 ? NO_NETWORK_ERROR_3GPP2 : NO_NETWORK_ERROR_3GPP;
197             }
198         }
199 
200         proto.sendErrorCode = sendErrorCode;
201         proto.networkErrorCode = networkErrorCode;
202 
203         mAtomsStorage.addOutgoingSms(proto);
204     }
205 
206     /** Create a new atom when user attempted to send an outgoing short code sms. */
onOutgoingShortCodeSms(int category, int xmlVersion)207     public void onOutgoingShortCodeSms(int category, int xmlVersion) {
208         OutgoingShortCodeSms proto = new OutgoingShortCodeSms();
209         proto.category = category;
210         proto.xmlVersion = xmlVersion;
211         proto.shortCodeSmsCount = 1;
212         mAtomsStorage.addOutgoingShortCodeSms(proto);
213     }
214 
215     /** Creates a proto for a normal single-part {@code IncomingSms} with default values. */
getIncomingDefaultProto(boolean is3gpp2, @InboundSmsHandler.SmsSource int smsSource)216     private IncomingSms getIncomingDefaultProto(boolean is3gpp2,
217             @InboundSmsHandler.SmsSource int smsSource) {
218         IncomingSms proto = new IncomingSms();
219         proto.smsFormat = getSmsFormat(is3gpp2);
220         proto.smsTech = getSmsTech(smsSource, is3gpp2);
221         proto.rat = getRat(smsSource);
222         proto.smsType = INCOMING_SMS__SMS_TYPE__SMS_TYPE_NORMAL;
223         proto.totalParts = 1;
224         proto.receivedParts = 1;
225         proto.blocked = false;
226         proto.error = INCOMING_SMS__ERROR__SMS_SUCCESS;
227         proto.isRoaming = getIsRoaming();
228         proto.simSlotIndex = getPhoneId();
229         proto.isMultiSim = SimSlotState.isMultiSim();
230         proto.isEsim = SimSlotState.isEsim(getPhoneId());
231         proto.carrierId = getCarrierId();
232         // Message ID is initialized with random number, as it is not available for all incoming
233         // SMS messages (e.g. those handled by OS or error cases).
234         proto.messageId = RANDOM.nextLong();
235         proto.count = 1;
236         proto.isManagedProfile = mPhone.isManagedProfile();
237         return proto;
238     }
239 
240     /** Create a proto for a normal {@code OutgoingSms} with default values. */
getOutgoingDefaultProto(boolean is3gpp2, boolean isOverIms, long messageId, boolean isFromDefaultApp, long intervalMillis)241     private OutgoingSms getOutgoingDefaultProto(boolean is3gpp2, boolean isOverIms,
242             long messageId, boolean isFromDefaultApp, long intervalMillis) {
243         OutgoingSms proto = new OutgoingSms();
244         proto.smsFormat = getSmsFormat(is3gpp2);
245         proto.smsTech = getSmsTech(isOverIms, is3gpp2);
246         proto.rat = getRat(isOverIms);
247         proto.sendResult = OUTGOING_SMS__SEND_RESULT__SMS_SEND_RESULT_SUCCESS;
248         proto.errorCode = isOverIms ? SmsManager.RESULT_ERROR_NONE : NO_ERROR_CODE;
249         proto.isRoaming = getIsRoaming();
250         proto.isFromDefaultApp = isFromDefaultApp;
251         proto.simSlotIndex = getPhoneId();
252         proto.isMultiSim = SimSlotState.isMultiSim();
253         proto.isEsim = SimSlotState.isEsim(getPhoneId());
254         proto.carrierId = getCarrierId();
255         // If the message ID is invalid, generate a random value
256         proto.messageId = messageId != 0L ? messageId : RANDOM.nextLong();
257         // Setting the retry ID to zero. If needed, it will be incremented when the atom is added
258         // in the persistent storage.
259         proto.retryId = 0;
260         proto.intervalMillis = intervalMillis;
261         proto.count = 1;
262         proto.isManagedProfile = mPhone.isManagedProfile();
263         return proto;
264     }
265 
getSmsFormat(boolean is3gpp2)266     private static int getSmsFormat(boolean is3gpp2) {
267         if (is3gpp2) {
268             return INCOMING_SMS__SMS_FORMAT__SMS_FORMAT_3GPP2;
269         } else {
270             return INCOMING_SMS__SMS_FORMAT__SMS_FORMAT_3GPP;
271         }
272     }
273 
getSmsTech(@nboundSmsHandler.SmsSource int smsSource, boolean is3gpp2)274     private int getSmsTech(@InboundSmsHandler.SmsSource int smsSource, boolean is3gpp2) {
275         if (smsSource == SOURCE_INJECTED_FROM_UNKNOWN) {
276             return INCOMING_SMS__SMS_TECH__SMS_TECH_UNKNOWN;
277         }
278         return getSmsTech(smsSource == SOURCE_INJECTED_FROM_IMS, is3gpp2);
279     }
280 
getSmsTech(boolean isOverIms, boolean is3gpp2)281     private int getSmsTech(boolean isOverIms, boolean is3gpp2) {
282         if (isOverIms) {
283             return INCOMING_SMS__SMS_TECH__SMS_TECH_IMS;
284         } else if (is3gpp2) {
285             return INCOMING_SMS__SMS_TECH__SMS_TECH_CS_3GPP2;
286         } else {
287             return INCOMING_SMS__SMS_TECH__SMS_TECH_CS_3GPP;
288         }
289     }
290 
getIncomingSmsError(int result)291     private static int getIncomingSmsError(int result) {
292         switch (result) {
293             case Activity.RESULT_OK:
294             case Intents.RESULT_SMS_HANDLED:
295                 return INCOMING_SMS__ERROR__SMS_SUCCESS;
296             case Intents.RESULT_SMS_OUT_OF_MEMORY:
297                 return INCOMING_SMS__ERROR__SMS_ERROR_NO_MEMORY;
298             case Intents.RESULT_SMS_UNSUPPORTED:
299                 return INCOMING_SMS__ERROR__SMS_ERROR_NOT_SUPPORTED;
300             case Intents.RESULT_SMS_GENERIC_ERROR:
301             default:
302                 return INCOMING_SMS__ERROR__SMS_ERROR_GENERIC;
303         }
304     }
305 
getIncomingSmsError(boolean success)306     private static int getIncomingSmsError(boolean success) {
307         if (success) {
308             return INCOMING_SMS__ERROR__SMS_SUCCESS;
309         } else {
310             return INCOMING_SMS__ERROR__SMS_ERROR_GENERIC;
311         }
312     }
313 
getOutgoingSmsError(@endStatusResult int imsSendResult)314     private static int getOutgoingSmsError(@SendStatusResult int imsSendResult) {
315         switch (imsSendResult) {
316             case ImsSmsImplBase.SEND_STATUS_OK:
317                 return OUTGOING_SMS__SEND_RESULT__SMS_SEND_RESULT_SUCCESS;
318             case ImsSmsImplBase.SEND_STATUS_ERROR:
319                 return OUTGOING_SMS__SEND_RESULT__SMS_SEND_RESULT_ERROR;
320             case ImsSmsImplBase.SEND_STATUS_ERROR_RETRY:
321                 return OUTGOING_SMS__SEND_RESULT__SMS_SEND_RESULT_ERROR_RETRY;
322             case ImsSmsImplBase.SEND_STATUS_ERROR_FALLBACK:
323                 return OUTGOING_SMS__SEND_RESULT__SMS_SEND_RESULT_ERROR_FALLBACK;
324             default:
325                 return OUTGOING_SMS__SEND_RESULT__SMS_SEND_RESULT_UNKNOWN;
326         }
327     }
328 
329     /**
330      * Returns a hash value to identify messages that are identical for the purpose of merging them
331      * together when storage is full.
332      */
getSmsHashCode(OutgoingSms sms)333     static int getSmsHashCode(OutgoingSms sms) {
334         return Objects.hash(sms.smsFormat, sms.smsTech, sms.rat, sms.sendResult, sms.errorCode,
335                     sms.isRoaming, sms.isFromDefaultApp, sms.simSlotIndex, sms.isMultiSim,
336                     sms.isEsim, sms.carrierId);
337     }
338 
339     /**
340      * Returns a hash value to identify messages that are identical for the purpose of merging them
341      * together when storage is full.
342      */
getSmsHashCode(IncomingSms sms)343     static int getSmsHashCode(IncomingSms sms) {
344         return Objects.hash(sms.smsFormat, sms.smsTech, sms.rat, sms.smsType,
345             sms.totalParts, sms.receivedParts, sms.blocked, sms.error,
346             sms.isRoaming, sms.simSlotIndex, sms.isMultiSim, sms.isEsim, sms.carrierId);
347     }
348 
getPhoneId()349     private int getPhoneId() {
350         Phone phone = mPhone;
351         if (mPhone.getPhoneType() == PhoneConstants.PHONE_TYPE_IMS) {
352             phone = mPhone.getDefaultPhone();
353         }
354         return phone.getPhoneId();
355     }
356 
357     @Nullable
getServiceState()358     private ServiceState getServiceState() {
359         Phone phone = mPhone;
360         if (mPhone.getPhoneType() == PhoneConstants.PHONE_TYPE_IMS) {
361             phone = mPhone.getDefaultPhone();
362         }
363         ServiceStateTracker serviceStateTracker = phone.getServiceStateTracker();
364         return serviceStateTracker != null ? serviceStateTracker.getServiceState() : null;
365     }
366 
getRat(@nboundSmsHandler.SmsSource int smsSource)367     private @NetworkType int getRat(@InboundSmsHandler.SmsSource int smsSource) {
368         if (smsSource == SOURCE_INJECTED_FROM_UNKNOWN) {
369             return TelephonyManager.NETWORK_TYPE_UNKNOWN;
370         }
371         return getRat(smsSource == SOURCE_INJECTED_FROM_IMS);
372     }
373 
getRat(boolean isOverIms)374     private @NetworkType int getRat(boolean isOverIms) {
375         if (isOverIms) {
376             if (mPhone.getImsRegistrationTech()
377                     == ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN) {
378                 return TelephonyManager.NETWORK_TYPE_IWLAN;
379             }
380         }
381         // TODO(b/168837897): Returns the RAT at the time the SMS was received..
382         ServiceState serviceState = getServiceState();
383         return serviceState != null
384                 ? serviceState.getVoiceNetworkType() : TelephonyManager.NETWORK_TYPE_UNKNOWN;
385     }
386 
getIsRoaming()387     private boolean getIsRoaming() {
388         ServiceState serviceState = getServiceState();
389         return ServiceStateStats.isNetworkRoaming(serviceState);
390     }
391 
getCarrierId()392     private int getCarrierId() {
393         Phone phone = mPhone;
394         if (mPhone.getPhoneType() == PhoneConstants.PHONE_TYPE_IMS) {
395             phone = mPhone.getDefaultPhone();
396         }
397         return phone.getCarrierId();
398     }
399 
loge(String format, Object... args)400     private void loge(String format, Object... args) {
401         Rlog.e(TAG, "[" + mPhone.getPhoneId() + "]" + String.format(format, args));
402     }
403 }
404