• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2008 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 android.net;
18 
19 import static com.android.internal.telephony.DataConnectionTracker.CMD_SET_POLICY_DATA_ENABLE;
20 import static com.android.internal.telephony.DataConnectionTracker.CMD_SET_USER_DATA_ENABLE;
21 import static com.android.internal.telephony.DataConnectionTracker.DISABLED;
22 import static com.android.internal.telephony.DataConnectionTracker.ENABLED;
23 
24 import android.content.BroadcastReceiver;
25 import android.content.Context;
26 import android.content.Intent;
27 import android.content.IntentFilter;
28 import android.net.NetworkInfo.DetailedState;
29 import android.os.Bundle;
30 import android.os.Handler;
31 import android.os.Looper;
32 import android.os.Message;
33 import android.os.Messenger;
34 import android.os.RemoteException;
35 import android.os.ServiceManager;
36 import android.telephony.TelephonyManager;
37 import android.text.TextUtils;
38 import android.util.Slog;
39 
40 import com.android.internal.telephony.DataConnectionTracker;
41 import com.android.internal.telephony.ITelephony;
42 import com.android.internal.telephony.Phone;
43 import com.android.internal.telephony.TelephonyIntents;
44 import com.android.internal.util.AsyncChannel;
45 
46 import java.io.CharArrayWriter;
47 import java.io.PrintWriter;
48 
49 /**
50  * Track the state of mobile data connectivity. This is done by
51  * receiving broadcast intents from the Phone process whenever
52  * the state of data connectivity changes.
53  *
54  * {@hide}
55  */
56 public class MobileDataStateTracker implements NetworkStateTracker {
57 
58     private static final String TAG = "MobileDataStateTracker";
59     private static final boolean DBG = false;
60     private static final boolean VDBG = false;
61 
62     private Phone.DataState mMobileDataState;
63     private ITelephony mPhoneService;
64 
65     private String mApnType;
66     private NetworkInfo mNetworkInfo;
67     private boolean mTeardownRequested = false;
68     private Handler mTarget;
69     private Context mContext;
70     private LinkProperties mLinkProperties;
71     private LinkCapabilities mLinkCapabilities;
72     private boolean mPrivateDnsRouteSet = false;
73     private boolean mDefaultRouteSet = false;
74 
75     // NOTE: these are only kept for debugging output; actual values are
76     // maintained in DataConnectionTracker.
77     protected boolean mUserDataEnabled = true;
78     protected boolean mPolicyDataEnabled = true;
79 
80     private Handler mHandler;
81     private AsyncChannel mDataConnectionTrackerAc;
82     private Messenger mMessenger;
83 
84     /**
85      * Create a new MobileDataStateTracker
86      * @param netType the ConnectivityManager network type
87      * @param tag the name of this network
88      */
MobileDataStateTracker(int netType, String tag)89     public MobileDataStateTracker(int netType, String tag) {
90         mNetworkInfo = new NetworkInfo(netType,
91                 TelephonyManager.getDefault().getNetworkType(), tag,
92                 TelephonyManager.getDefault().getNetworkTypeName());
93         mApnType = networkTypeToApnType(netType);
94     }
95 
96     /**
97      * Begin monitoring data connectivity.
98      *
99      * @param context is the current Android context
100      * @param target is the Hander to which to return the events.
101      */
startMonitoring(Context context, Handler target)102     public void startMonitoring(Context context, Handler target) {
103         mTarget = target;
104         mContext = context;
105 
106         mHandler = new MdstHandler(target.getLooper(), this);
107 
108         IntentFilter filter = new IntentFilter();
109         filter.addAction(TelephonyIntents.ACTION_ANY_DATA_CONNECTION_STATE_CHANGED);
110         filter.addAction(TelephonyIntents.ACTION_DATA_CONNECTION_FAILED);
111         filter.addAction(DataConnectionTracker.ACTION_DATA_CONNECTION_TRACKER_MESSENGER);
112 
113         mContext.registerReceiver(new MobileDataStateReceiver(), filter);
114         mMobileDataState = Phone.DataState.DISCONNECTED;
115     }
116 
117     static class MdstHandler extends Handler {
118         private MobileDataStateTracker mMdst;
119 
MdstHandler(Looper looper, MobileDataStateTracker mdst)120         MdstHandler(Looper looper, MobileDataStateTracker mdst) {
121             super(looper);
122             mMdst = mdst;
123         }
124 
125         @Override
handleMessage(Message msg)126         public void handleMessage(Message msg) {
127             switch (msg.what) {
128                 case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED:
129                     if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
130                         if (VDBG) {
131                             mMdst.log("MdstHandler connected");
132                         }
133                         mMdst.mDataConnectionTrackerAc = (AsyncChannel) msg.obj;
134                     } else {
135                         if (VDBG) {
136                             mMdst.log("MdstHandler %s NOT connected error=" + msg.arg1);
137                         }
138                     }
139                     break;
140                 case AsyncChannel.CMD_CHANNEL_DISCONNECTED:
141                     if (VDBG) mMdst.log("Disconnected from DataStateTracker");
142                     mMdst.mDataConnectionTrackerAc = null;
143                     break;
144                 default: {
145                     if (VDBG) mMdst.log("Ignorning unknown message=" + msg);
146                     break;
147                 }
148             }
149         }
150     }
151 
isPrivateDnsRouteSet()152     public boolean isPrivateDnsRouteSet() {
153         return mPrivateDnsRouteSet;
154     }
155 
privateDnsRouteSet(boolean enabled)156     public void privateDnsRouteSet(boolean enabled) {
157         mPrivateDnsRouteSet = enabled;
158     }
159 
getNetworkInfo()160     public NetworkInfo getNetworkInfo() {
161         return mNetworkInfo;
162     }
163 
isDefaultRouteSet()164     public boolean isDefaultRouteSet() {
165         return mDefaultRouteSet;
166     }
167 
defaultRouteSet(boolean enabled)168     public void defaultRouteSet(boolean enabled) {
169         mDefaultRouteSet = enabled;
170     }
171 
172     /**
173      * This is not implemented.
174      */
releaseWakeLock()175     public void releaseWakeLock() {
176     }
177 
178     private class MobileDataStateReceiver extends BroadcastReceiver {
179         @Override
onReceive(Context context, Intent intent)180         public void onReceive(Context context, Intent intent) {
181             if (intent.getAction().equals(TelephonyIntents.
182                     ACTION_ANY_DATA_CONNECTION_STATE_CHANGED)) {
183                 String apnType = intent.getStringExtra(Phone.DATA_APN_TYPE_KEY);
184                 if (VDBG) {
185                     log(String.format("Broadcast received: ACTION_ANY_DATA_CONNECTION_STATE_CHANGED"
186                         + "mApnType=%s %s received apnType=%s", mApnType,
187                         TextUtils.equals(apnType, mApnType) ? "==" : "!=", apnType));
188                 }
189                 if (!TextUtils.equals(apnType, mApnType)) {
190                     return;
191                 }
192                 mNetworkInfo.setSubtype(TelephonyManager.getDefault().getNetworkType(),
193                         TelephonyManager.getDefault().getNetworkTypeName());
194                 Phone.DataState state = Enum.valueOf(Phone.DataState.class,
195                         intent.getStringExtra(Phone.STATE_KEY));
196                 String reason = intent.getStringExtra(Phone.STATE_CHANGE_REASON_KEY);
197                 String apnName = intent.getStringExtra(Phone.DATA_APN_KEY);
198                 mNetworkInfo.setRoaming(intent.getBooleanExtra(Phone.DATA_NETWORK_ROAMING_KEY,
199                         false));
200                 if (VDBG) {
201                     log(mApnType + " setting isAvailable to " +
202                             intent.getBooleanExtra(Phone.NETWORK_UNAVAILABLE_KEY,false));
203                 }
204                 mNetworkInfo.setIsAvailable(!intent.getBooleanExtra(Phone.NETWORK_UNAVAILABLE_KEY,
205                         false));
206 
207                 if (DBG) {
208                     log("Received state=" + state + ", old=" + mMobileDataState +
209                         ", reason=" + (reason == null ? "(unspecified)" : reason));
210                 }
211                 if (mMobileDataState != state) {
212                     mMobileDataState = state;
213                     switch (state) {
214                         case DISCONNECTED:
215                             if(isTeardownRequested()) {
216                                 setTeardownRequested(false);
217                             }
218 
219                             setDetailedState(DetailedState.DISCONNECTED, reason, apnName);
220                             // can't do this here - ConnectivityService needs it to clear stuff
221                             // it's ok though - just leave it to be refreshed next time
222                             // we connect.
223                             //if (DBG) log("clearing mInterfaceName for "+ mApnType +
224                             //        " as it DISCONNECTED");
225                             //mInterfaceName = null;
226                             break;
227                         case CONNECTING:
228                             setDetailedState(DetailedState.CONNECTING, reason, apnName);
229                             break;
230                         case SUSPENDED:
231                             setDetailedState(DetailedState.SUSPENDED, reason, apnName);
232                             break;
233                         case CONNECTED:
234                             mLinkProperties = intent.getParcelableExtra(
235                                     Phone.DATA_LINK_PROPERTIES_KEY);
236                             if (mLinkProperties == null) {
237                                 loge("CONNECTED event did not supply link properties.");
238                                 mLinkProperties = new LinkProperties();
239                             }
240                             mLinkCapabilities = intent.getParcelableExtra(
241                                     Phone.DATA_LINK_CAPABILITIES_KEY);
242                             if (mLinkCapabilities == null) {
243                                 loge("CONNECTED event did not supply link capabilities.");
244                                 mLinkCapabilities = new LinkCapabilities();
245                             }
246                             setDetailedState(DetailedState.CONNECTED, reason, apnName);
247                             break;
248                     }
249                 } else {
250                     // There was no state change. Check if LinkProperties has been updated.
251                     if (TextUtils.equals(reason, Phone.REASON_LINK_PROPERTIES_CHANGED)) {
252                         mLinkProperties = intent.getParcelableExtra(Phone.DATA_LINK_PROPERTIES_KEY);
253                         if (mLinkProperties == null) {
254                             loge("No link property in LINK_PROPERTIES change event.");
255                             mLinkProperties = new LinkProperties();
256                         }
257                         // Just update reason field in this NetworkInfo
258                         mNetworkInfo.setDetailedState(mNetworkInfo.getDetailedState(), reason,
259                                                       mNetworkInfo.getExtraInfo());
260                         Message msg = mTarget.obtainMessage(EVENT_CONFIGURATION_CHANGED,
261                                                             mNetworkInfo);
262                         msg.sendToTarget();
263                     }
264                 }
265             } else if (intent.getAction().
266                     equals(TelephonyIntents.ACTION_DATA_CONNECTION_FAILED)) {
267                 String apnType = intent.getStringExtra(Phone.DATA_APN_TYPE_KEY);
268                 if (!TextUtils.equals(apnType, mApnType)) {
269                     if (DBG) {
270                         log(String.format(
271                                 "Broadcast received: ACTION_ANY_DATA_CONNECTION_FAILED ignore, " +
272                                 "mApnType=%s != received apnType=%s", mApnType, apnType));
273                     }
274                     return;
275                 }
276                 String reason = intent.getStringExtra(Phone.FAILURE_REASON_KEY);
277                 String apnName = intent.getStringExtra(Phone.DATA_APN_KEY);
278                 if (DBG) {
279                     log("Received " + intent.getAction() +
280                                 " broadcast" + reason == null ? "" : "(" + reason + ")");
281                 }
282                 setDetailedState(DetailedState.FAILED, reason, apnName);
283             } else if (intent.getAction().
284                     equals(DataConnectionTracker.ACTION_DATA_CONNECTION_TRACKER_MESSENGER)) {
285                 if (VDBG) log(mApnType + " got ACTION_DATA_CONNECTION_TRACKER_MESSENGER");
286                 mMessenger = intent.getParcelableExtra(DataConnectionTracker.EXTRA_MESSENGER);
287                 AsyncChannel ac = new AsyncChannel();
288                 ac.connect(mContext, MobileDataStateTracker.this.mHandler, mMessenger);
289             } else {
290                 if (DBG) log("Broadcast received: ignore " + intent.getAction());
291             }
292         }
293     }
294 
getPhoneService(boolean forceRefresh)295     private void getPhoneService(boolean forceRefresh) {
296         if ((mPhoneService == null) || forceRefresh) {
297             mPhoneService = ITelephony.Stub.asInterface(ServiceManager.getService("phone"));
298         }
299     }
300 
301     /**
302      * Report whether data connectivity is possible.
303      */
isAvailable()304     public boolean isAvailable() {
305         return mNetworkInfo.isAvailable();
306     }
307 
308     /**
309      * Return the system properties name associated with the tcp buffer sizes
310      * for this network.
311      */
getTcpBufferSizesPropName()312     public String getTcpBufferSizesPropName() {
313         String networkTypeStr = "unknown";
314         TelephonyManager tm = new TelephonyManager(mContext);
315         //TODO We have to edit the parameter for getNetworkType regarding CDMA
316         switch(tm.getNetworkType()) {
317         case TelephonyManager.NETWORK_TYPE_GPRS:
318             networkTypeStr = "gprs";
319             break;
320         case TelephonyManager.NETWORK_TYPE_EDGE:
321             networkTypeStr = "edge";
322             break;
323         case TelephonyManager.NETWORK_TYPE_UMTS:
324             networkTypeStr = "umts";
325             break;
326         case TelephonyManager.NETWORK_TYPE_HSDPA:
327             networkTypeStr = "hsdpa";
328             break;
329         case TelephonyManager.NETWORK_TYPE_HSUPA:
330             networkTypeStr = "hsupa";
331             break;
332         case TelephonyManager.NETWORK_TYPE_HSPA:
333             networkTypeStr = "hspa";
334             break;
335         case TelephonyManager.NETWORK_TYPE_CDMA:
336             networkTypeStr = "cdma";
337             break;
338         case TelephonyManager.NETWORK_TYPE_1xRTT:
339             networkTypeStr = "1xrtt";
340             break;
341         case TelephonyManager.NETWORK_TYPE_EVDO_0:
342             networkTypeStr = "evdo";
343             break;
344         case TelephonyManager.NETWORK_TYPE_EVDO_A:
345             networkTypeStr = "evdo";
346             break;
347         case TelephonyManager.NETWORK_TYPE_EVDO_B:
348             networkTypeStr = "evdo";
349             break;
350         case TelephonyManager.NETWORK_TYPE_IDEN:
351             networkTypeStr = "iden";
352             break;
353         case TelephonyManager.NETWORK_TYPE_LTE:
354             networkTypeStr = "lte";
355             break;
356         case TelephonyManager.NETWORK_TYPE_EHRPD:
357             networkTypeStr = "ehrpd";
358             break;
359         default:
360             loge("unknown network type: " + tm.getNetworkType());
361         }
362         return "net.tcp.buffersize." + networkTypeStr;
363     }
364 
365     /**
366      * Tear down mobile data connectivity, i.e., disable the ability to create
367      * mobile data connections.
368      * TODO - make async and return nothing?
369      */
teardown()370     public boolean teardown() {
371         setTeardownRequested(true);
372         return (setEnableApn(mApnType, false) != Phone.APN_REQUEST_FAILED);
373     }
374 
375     /**
376      * Record the detailed state of a network, and if it is a
377      * change from the previous state, send a notification to
378      * any listeners.
379      * @param state the new @{code DetailedState}
380      * @param reason a {@code String} indicating a reason for the state change,
381      * if one was supplied. May be {@code null}.
382      * @param extraInfo optional {@code String} providing extra information about the state change
383      */
setDetailedState(NetworkInfo.DetailedState state, String reason, String extraInfo)384     private void setDetailedState(NetworkInfo.DetailedState state, String reason,
385             String extraInfo) {
386         if (DBG) log("setDetailed state, old ="
387                 + mNetworkInfo.getDetailedState() + " and new state=" + state);
388         if (state != mNetworkInfo.getDetailedState()) {
389             boolean wasConnecting = (mNetworkInfo.getState() == NetworkInfo.State.CONNECTING);
390             String lastReason = mNetworkInfo.getReason();
391             /*
392              * If a reason was supplied when the CONNECTING state was entered, and no
393              * reason was supplied for entering the CONNECTED state, then retain the
394              * reason that was supplied when going to CONNECTING.
395              */
396             if (wasConnecting && state == NetworkInfo.DetailedState.CONNECTED && reason == null
397                     && lastReason != null)
398                 reason = lastReason;
399             mNetworkInfo.setDetailedState(state, reason, extraInfo);
400             Message msg = mTarget.obtainMessage(EVENT_STATE_CHANGED, new NetworkInfo(mNetworkInfo));
401             msg.sendToTarget();
402         }
403     }
404 
setTeardownRequested(boolean isRequested)405     public void setTeardownRequested(boolean isRequested) {
406         mTeardownRequested = isRequested;
407     }
408 
isTeardownRequested()409     public boolean isTeardownRequested() {
410         return mTeardownRequested;
411     }
412 
413     /**
414      * Re-enable mobile data connectivity after a {@link #teardown()}.
415      * TODO - make async and always get a notification?
416      */
reconnect()417     public boolean reconnect() {
418         boolean retValue = false; //connected or expect to be?
419         setTeardownRequested(false);
420         switch (setEnableApn(mApnType, true)) {
421             case Phone.APN_ALREADY_ACTIVE:
422                 // need to set self to CONNECTING so the below message is handled.
423                 retValue = true;
424                 break;
425             case Phone.APN_REQUEST_STARTED:
426                 // set IDLE here , avoid the following second FAILED not sent out
427                 mNetworkInfo.setDetailedState(DetailedState.IDLE, null, null);
428                 retValue = true;
429                 break;
430             case Phone.APN_REQUEST_FAILED:
431             case Phone.APN_TYPE_NOT_AVAILABLE:
432                 break;
433             default:
434                 loge("Error in reconnect - unexpected response.");
435                 break;
436         }
437         return retValue;
438     }
439 
440     /**
441      * Turn on or off the mobile radio. No connectivity will be possible while the
442      * radio is off. The operation is a no-op if the radio is already in the desired state.
443      * @param turnOn {@code true} if the radio should be turned on, {@code false} if
444      */
setRadio(boolean turnOn)445     public boolean setRadio(boolean turnOn) {
446         getPhoneService(false);
447         /*
448          * If the phone process has crashed in the past, we'll get a
449          * RemoteException and need to re-reference the service.
450          */
451         for (int retry = 0; retry < 2; retry++) {
452             if (mPhoneService == null) {
453                 loge("Ignoring mobile radio request because could not acquire PhoneService");
454                 break;
455             }
456 
457             try {
458                 return mPhoneService.setRadio(turnOn);
459             } catch (RemoteException e) {
460                 if (retry == 0) getPhoneService(true);
461             }
462         }
463 
464         loge("Could not set radio power to " + (turnOn ? "on" : "off"));
465         return false;
466     }
467 
468     @Override
setUserDataEnable(boolean enabled)469     public void setUserDataEnable(boolean enabled) {
470         if (DBG) log("setUserDataEnable: E enabled=" + enabled);
471         final AsyncChannel channel = mDataConnectionTrackerAc;
472         if (channel != null) {
473             channel.sendMessage(CMD_SET_USER_DATA_ENABLE, enabled ? ENABLED : DISABLED);
474             mUserDataEnabled = enabled;
475         }
476         if (VDBG) log("setUserDataEnable: X enabled=" + enabled);
477     }
478 
479     @Override
setPolicyDataEnable(boolean enabled)480     public void setPolicyDataEnable(boolean enabled) {
481         if (DBG) log("setPolicyDataEnable(enabled=" + enabled + ")");
482         final AsyncChannel channel = mDataConnectionTrackerAc;
483         if (channel != null) {
484             channel.sendMessage(CMD_SET_POLICY_DATA_ENABLE, enabled ? ENABLED : DISABLED);
485             mPolicyDataEnabled = enabled;
486         }
487     }
488 
489     /**
490      * carrier dependency is met/unmet
491      * @param met
492      */
setDependencyMet(boolean met)493     public void setDependencyMet(boolean met) {
494         Bundle bundle = Bundle.forPair(DataConnectionTracker.APN_TYPE_KEY, mApnType);
495         try {
496             if (DBG) log("setDependencyMet: E met=" + met);
497             Message msg = Message.obtain();
498             msg.what = DataConnectionTracker.CMD_SET_DEPENDENCY_MET;
499             msg.arg1 = (met ? DataConnectionTracker.ENABLED : DataConnectionTracker.DISABLED);
500             msg.setData(bundle);
501             mDataConnectionTrackerAc.sendMessage(msg);
502             if (VDBG) log("setDependencyMet: X met=" + met);
503         } catch (NullPointerException e) {
504             loge("setDependencyMet: X mAc was null" + e);
505         }
506     }
507 
508     @Override
toString()509     public String toString() {
510         final CharArrayWriter writer = new CharArrayWriter();
511         final PrintWriter pw = new PrintWriter(writer);
512         pw.print("Mobile data state: "); pw.println(mMobileDataState);
513         pw.print("Data enabled: user="); pw.print(mUserDataEnabled);
514         pw.print(", policy="); pw.println(mPolicyDataEnabled);
515         return writer.toString();
516     }
517 
518    /**
519      * Internal method supporting the ENABLE_MMS feature.
520      * @param apnType the type of APN to be enabled or disabled (e.g., mms)
521      * @param enable {@code true} to enable the specified APN type,
522      * {@code false} to disable it.
523      * @return an integer value representing the outcome of the request.
524      */
setEnableApn(String apnType, boolean enable)525     private int setEnableApn(String apnType, boolean enable) {
526         getPhoneService(false);
527         /*
528          * If the phone process has crashed in the past, we'll get a
529          * RemoteException and need to re-reference the service.
530          */
531         for (int retry = 0; retry < 2; retry++) {
532             if (mPhoneService == null) {
533                 loge("Ignoring feature request because could not acquire PhoneService");
534                 break;
535             }
536 
537             try {
538                 if (enable) {
539                     return mPhoneService.enableApnType(apnType);
540                 } else {
541                     return mPhoneService.disableApnType(apnType);
542                 }
543             } catch (RemoteException e) {
544                 if (retry == 0) getPhoneService(true);
545             }
546         }
547 
548         loge("Could not " + (enable ? "enable" : "disable") + " APN type \"" + apnType + "\"");
549         return Phone.APN_REQUEST_FAILED;
550     }
551 
networkTypeToApnType(int netType)552     public static String networkTypeToApnType(int netType) {
553         switch(netType) {
554             case ConnectivityManager.TYPE_MOBILE:
555                 return Phone.APN_TYPE_DEFAULT;  // TODO - use just one of these
556             case ConnectivityManager.TYPE_MOBILE_MMS:
557                 return Phone.APN_TYPE_MMS;
558             case ConnectivityManager.TYPE_MOBILE_SUPL:
559                 return Phone.APN_TYPE_SUPL;
560             case ConnectivityManager.TYPE_MOBILE_DUN:
561                 return Phone.APN_TYPE_DUN;
562             case ConnectivityManager.TYPE_MOBILE_HIPRI:
563                 return Phone.APN_TYPE_HIPRI;
564             case ConnectivityManager.TYPE_MOBILE_FOTA:
565                 return Phone.APN_TYPE_FOTA;
566             case ConnectivityManager.TYPE_MOBILE_IMS:
567                 return Phone.APN_TYPE_IMS;
568             case ConnectivityManager.TYPE_MOBILE_CBS:
569                 return Phone.APN_TYPE_CBS;
570             default:
571                 sloge("Error mapping networkType " + netType + " to apnType.");
572                 return null;
573         }
574     }
575 
576     /**
577      * @see android.net.NetworkStateTracker#getLinkProperties()
578      */
getLinkProperties()579     public LinkProperties getLinkProperties() {
580         return new LinkProperties(mLinkProperties);
581     }
582 
583     /**
584      * @see android.net.NetworkStateTracker#getLinkCapabilities()
585      */
getLinkCapabilities()586     public LinkCapabilities getLinkCapabilities() {
587         return new LinkCapabilities(mLinkCapabilities);
588     }
589 
log(String s)590     private void log(String s) {
591         Slog.d(TAG, mApnType + ": " + s);
592     }
593 
loge(String s)594     private void loge(String s) {
595         Slog.e(TAG, mApnType + ": " + s);
596     }
597 
sloge(String s)598     static private void sloge(String s) {
599         Slog.e(TAG, s);
600     }
601 }
602