finaldata使用教程 ()

ConnectivityManager 提供访问ConnectivityService的接口,与ConnectivityService通过binder进行通信

ConnectivityService 管理NetworkAgent

NetworkFactory

NetworkAgent 用于DataConnection和ConnectivityService进行通信

NetworkAgentInfo

NetworkInfo

NetworkManagementService

NetworkCapabilities 用于描述一个网络的能力,用来指定ConnectivityManager的需求以及检查网络。

NetworkRequest 定义一个网络请求。

NetworkStatsService 统计网络传输数据,供其他系统服务使用。

NetworkMonitor

TelephonyManager.java

路径:frameworks/base/telephony/java/android/telephony/

功能:为App提供获取Telephony信息的接口。App也可注册监听器来接收Telephony状态的变化。

其中很多接口都是通过AIDL调用其他相关程序得到的,用到的AIDL接口及对应实现包括:

ITelecomService --> TelecomServiceImpl.mBinderImpl --> Telecomm Service

IPhoneSubInfo --> PhoneSubInfoController

ITelephony --> PhoneInterfaceManager --> Telephony Service

ITelephonyRegistry --> TelephonyRegistry

DcTracker

Platform:Android-7.1.1_r22

public class DcTracker extends Handler {

// 一直为false,DcController.DccDefaultState.onDataStateChanged()中会用到,

// onDataStateChanged()是监听UNSOL_DATA_CALL_LIST_CHANGED的

public AtomicBoolean isCleanupRequired = new AtomicBoolean(false);

// 用于任务调度

private final AlarmManager mAlarmManager;

// 感觉没啥用

/* Currently requested APN type (TODO: This should probably be a parameter not a member) */

private String mRequestedApnType = PhoneConstants.APN_TYPE_DEFAULT;

// 持有不同数据开/关的设置状态

// All data enabling/disabling related settings

private final DataEnabledSettings mDataEnabledSettings = new DataEnabledSettings();

// 不能建立data的原因

public enum DataAllowFailReasonType {

NOT_ATTACHED(\" - Not attached\"),

RECORD_NOT_LOADED(\" - SIM not loaded\"),

ROAMING_DISABLED(\" - Roaming and data roaming not enabled\"),

INVALID_PHONE_STATE(\" - PhoneState is not idle\"),

CONCURRENT_VOICE_DATA_NOT_ALLOWED(\" - Concurrent voice and data not allowed\"),

PS_RESTRICTED(\" - mIsPsRestricted= true\"),

UNDESIRED_POWER_STATE(\" - desiredPowerState= false\"),

INTERNAL_DATA_DISABLED(\" - mInternalDataEnabled= false\"),

DEFAULT_DATA_UNSELECTED(\" - defaultDataSelected= false\"),

RADIO_DISABLED_BY_CARRIER(\" - powerStateFromCarrier= false\");

......

}

// 用于测试人员指定bingUp失败的次数及原因。

/**

* A package level call that causes all DataConnection bringUp calls to fail a specific

* number of times. Here is an example that sets counter to 2 and cause to -3 for all instances:

* adb shell am broadcast -a com.android.internal.telephony.dataconnection.action_fail_bringup \

* --ei counter 2 --ei fail_cause -3

*

* Also you can add a suggested retry time if desired:

* --ei suggested_retry_time 5000

*

* The fail_cause is one of {@link DcFailCause}

*/

private DcTesterFailBringUpAll mDcTesterFailBringUpAll;

// 新建DataConnection对象时会作为参数传入

private DcController mDcc;

// 按优先级排序的ApnContext队列,会在DcTracker的构造函数中进行初始化。

// 初始值是从frameworks/base/core/res/res/values/config.xml中的networkAttributes读取的,

// 一般情况下厂商会overlay。

/** kept in sync with mApnContexts

* Higher numbers are higher priority and sorted so highest priority is first */

private final PriorityQueue<ApnContext>mPrioritySortedApnContexts

// mAllApnSettings的内容是从telephony.db->carriers中读取的。

// telephony.db->carriers则是用apns.xml和apns-conf.xml中的内容进行初始化,

// 祥见TelephonyProvider.DatabaseHelper.initDatabase()

/** allApns holds all apns */

private ArrayList<ApnSetting> mAllApnSettings = null;

// ????????

/** emergency apn Setting*/

private ApnSetting mEmergencyApn = null;

// 关于provision apn,在config.xml中的\"mobile_provisioning_apn\"进行了定义,但还是不知道是做啥的

// ????????

/* Set to true with CMD_ENABLE_MOBILE_PROVISIONING */

private boolean mIsProvisioning = false;

// ????????

/* The Url passed as object parameter in CMD_ENABLE_MOBILE_PROVISIONING */

private String mProvisioningUrl = null;

// ????????

/* The provision apn alarm intent used to disable the provisioning apn */

private PendingIntent mProvisioningApnAlarmIntent = null;

// ????????

/* Used to track stale provisioning apn alarms */

private int mProvisioningApnAlarmTag = (int) SystemClock.elapsedRealtime();

// ????????

private AsyncChannel mReplyAc = new AsyncChannel();

// 处理以下广播:

// ACTION_SCREEN_ON

// ACTION_SCREEN_OFF

// INTENT_RECONNECT_ALARM

// INTENT_DATA_STALL_ALARM

// INTENT_PROVISIONING_APN_ALARM

// NETWORK_STATE_CHANGED_ACTION

// WIFI_STATE_CHANGED_ACTION

private final BroadcastReceiver mIntentReceiver = new BroadcastReceiver () {

// 统计每个周期内上下行数据的任务,状态栏上数据上下行图标就是用的这个结果

private final Runnable mPollNetStat = new Runnable() {

// 监听Subscription变化

private final OnSubscriptionsChangedListener mOnSubscriptionsChangedListener =

// 监听以下设置的变化:

// DATA_ROAMING

// DEVICE_PROVISIONED

// DEVICE_PROVISIONING_MOBILE_DATA_ENABLED

private final SettingsObserver mSettingsObserver;

/**

* List of messages that are waiting to be posted, when data call disconnect

* is complete

*/

private ArrayList<Message> mDisconnectAllCompleteMsgList = new ArrayList<Message>();

// member variables

private final Phone mPhone;

private final UiccController mUiccController;

private final AtomicReference<IccRecords> mIccRecords = new AtomicReference<IccRecords>();

// 以下几个是数据上下行图标相关的

private DctConstants.Activity mActivity = DctConstants.Activity.NONE;

private long mTxPkts;

private long mRxPkts;

private int mNetStatPollPeriod;

private boolean mNetStatPollEnabled = false;

// 以下几个是检测数据连接是否正常的

private TxRxSum mDataStallTxRxSum = new TxRxSum(0, 0);

// Used to track stale data stall alarms.

private int mDataStallAlarmTag = (int) SystemClock.elapsedRealtime();

// The current data stall alarm intent

private PendingIntent mDataStallAlarmIntent = null;

// Number of packets sent since the last received packet

private long mSentSinceLastRecv;

// Controls when a simple recovery attempt it to be tried

private int mNoRecvPollCount = 0;

// Reference counter for enabling fail fast

private static int sEnableFailFastRefCounter = 0;

// True if data stall detection is enabled

private volatile boolean mDataStallDetectionEnabled = true;

// Data retry时,如果此属性为true,就会使用一个较短的间隔时间

private volatile boolean mFailFast = false;

// True when in voice call

private boolean mInVoiceCall = false;

// wifi connection status will be updated by sticky intent

private boolean mIsWifiConnected = false;

// 感觉没啥用

// When false we will not auto attach and manually attaching is required.

private boolean mAutoAttachOnCreationConfig = false;

private AtomicBoolean mAutoAttachOnCreation = new AtomicBoolean(false);

// MVNO是虚拟运营商

// Indicates if we found mvno-specific APNs in the full APN list.

// used to determine if we can accept mno-specific APN for tethering.

private boolean mMvnoMatched = false;

// 每个DataConnection对象对应的唯一的Id号

/** Allows the generation of unique Id's for DataConnection objects */

private AtomicInteger mUniqueIdGenerator = new AtomicInteger(0);

// 跟mPrioritySortedApnContexts差不多,保存各种类型的ApnContext

/** Phone.APN_TYPE_* ===> ApnContext */

private final ConcurrentHashMap<String, ApnContext> mApnContexts =

new ConcurrentHashMap<String, ApnContext>();

// 跟mApnContexts差不多,只是key变成了整数

private final SparseArray<ApnContext> mApnContextsById = new SparseArray<ApnContext>();

// 感觉没啥用

private boolean mReregisterOnReconnectFailure = false;

// 只要读取preferedApn返回的Cursor对象不为null,则置为true,即使Cursor中啥都没有。

// 所以这个值一般都为true。

private boolean mCanSetPreferApn = false;

// 是否注上PS

private AtomicBoolean mAttached = new AtomicBoolean(false);

// 监控Telephony.db->carriers的变化

/** Watches for changes to the APN db. */

private ApnChangeObserver mApnObserver;

// ?????

private final String mProvisionActionName;

private BroadcastReceiver mProvisionBroadcastReceiver;

private ProgressDialog mProvisioningSpinner;

// 电脑 似乎没地方用啊!

public boolean mImsRegistrationState = false;

}

ApnContext

Platform:Android-7.1.1_r22

APN上下文,维护着apn的状态、设置等。

每个类型的apn对应一个ApnContext。

// 来自ActivePhoneSwitch/DEFAULT_SUBSCRIPTION_CHANGED等的网络请求

private final ArrayList<NetworkRequest> mNetworkRequests = new ArrayList<>();

// 会从frameworks/base/core/res/res/values/config.xml读取config_cell_retries_per_error_code来初始化,

// 这个值应该会被overlay,这是一个Map列表,其中每一个Map的Key为建立Data时返回的错误类型,

// Value为重试次数,若重试Value次后还是不能成功建立Data连接,则在其它条件满足时就会重启modem。

private final SparseIntArray mRetriesLeftPerErrorCode = new SparseIntArray();

private final RetryManager mRetryManager;

DataConnection

Platform:Android-7.1.1_r22

是一个状态机。

一个DataConnection维护一个数据连接。

public class DataConnection extends StateMachine {

// 从DcTracker传过来的

// The data connection controller

private 电脑 DcController mDcController;

// 从DcTracker传过来的

// The Tester for failing all bringup's

private DcTesterFailBringUpAll mDcTesterFailBringUpAll;

// DataConnection实例的数量

private static AtomicInteger mInstanceNumber = new AtomicInteger(0);

// 用于和其它Handler进行通信

private AsyncChannel mAc;

// 新建对象时传进来的DcTracker对象

// The DCT that's talking to us, we only support one!

private DcTracker mDct = null;

// Data建立成功后用来保存P-CSCF地址

protected String[] mPcscfAddr;

// 当前连接的apn设置

private ApnSetting mApnSetting;

// 连接参数

private ConnectionParams mConnectionParams;

//断开参数

private DisconnectParams mDisconnectParams;

// 建立连接失败的原因(SETUP_DATA_CALL返回错误)

private DcFailCause mDcFailCause;

// 描述数据连接的连接属性

private LinkProperties mLinkProperties = new LinkProperties();

// 数据连接建立成功的时间点

private long mCreateTime;

// 上次数据连接建立失败的时间点

private long mLastFailTime;电脑

// 上次数据连接建立失败的原因(尚未发起SETUP_DATA_CALL)

private DcFailCause mLastFailCause;

// 没有用

private Object mUserData;

// 保存Data的RAT

private int mRilRat = Integer.MAX_VALUE;

// Data的注册状态

private int mDataRegState = Integer.MAX_VALUE;

// 描述网络接口的状态

private NetworkInfo mNetworkInfo;

// 一个工具类,用来和Connectivity通信的

private NetworkAgent mNetworkAgent;

// 没大明白做啥的,应该是充当一个标识作用之类的吧

int mTag;

// 连接的id号,从modem传上来的

public int mCid;

// 存储连接的ApnContext与ConnectionParams的映射

public HashMap<ApnContext, ConnectionParams> mApnContexts = null;

// 没有用

PendingIntent mReconnectIntent = null;

// 没搞懂

/**

* Indicates if when this connection was established we had a restricted/privileged

* NetworkRequest and needed it to overcome data-enabled limitations.

*

* This gets set once per connection setup and is based on conditions at that time.

* We could theoretically have dynamic capabilities but now is not a good time to

* experiement with that.

*

* This flag overrides the APN-based restriction capability, restricting the network

* based on both having a NetworkRequest with restricted AND needing a restricted

* bit to overcome user-disabled status. This allows us to handle the common case

* of having both restricted requests and unrestricted requests for the same apn:

* if conditions require a restricted network to overcome user-disabled then it must

* be restricted, otherwise it is unrestricted (or restricted based on APN type).

*

* Because we're not supporting dynamic capabilities, if conditions change and we go from

* data-enabled to not or vice-versa we will need to tear down networks to deal with it

* at connection setup time with the new state.

*

* This supports a privileged app bringing up a network without general apps having access

* to it when the network is otherwise unavailable (hipri). The first use case is

* pre-paid SIM reprovisioning over internet, where the carrier insists on no traffic

* other than from the privileged carrier-app.

*/

private boolean mRestrictedNetworkOverride = false;

// 数据连接的六种状态

private DcDefaultState mDefaultState = new DcDefaultState();

private DcInactiveState mInactiveState = new DcInactiveState();

private DcActivatingState mActivatingState = new DcActivatingState();

private DcActiveState mActiveState = new DcActiveState();

private DcDisconnectingState mDisconnectingState = new DcDisconnectingState();

private DcDisconnectionErrorCreatingConnection mDisconnectingErrorCreatingConnection =

}

DcController

Platform:Android-7.1.1_r22

/**

* Data Connection Controller which is a package visible class and controls

* multiple data connections. For instance listening for unsolicited messages

* and then demultiplexing them to the appropriate DC.

*/

public class DcController extends StateMachine {

RetryManager

Platform:Android-7.1.1_r22

RetryManager管理着重试次数、重试间隔时间等配置。

RetryManager对象的建立是在ApnContext的构造函数的完成的。

public ApnContext(Phone phone, String apnType, String logTag, NetworkConfig config,

DcTracker tracker) {

......

mRetryManager = new RetryManager(phone, apnType);

}

而Retry所需要使用的apn及间隔时间是在DcTracker中通过trySetupData() -> ApnContext.setWaitingApns() -> RetryManager.setWaitingApns()进行设置的,且只有当ApnContext为IDLE时才会设置。

DcTracker.java

private boolean trySetupData(ApnContext apnContext, ArrayList<ApnSetting> waitingApns) {

......

if (apnContext.getState() == DctConstants.State.IDLE) {

if (waitingApns == null) {

waitingApns = buildWaitingApns(apnContext.getApnType(), radioTech);

}

if (waitingApns.isEmpty()) {

......

return false;

} else {

apnContext.setWaitingApns(waitingApns);

if (DBG) {

log (\"trySetupData: Create from mAllApnSettings : \"

+ apnListToString(mAllApnSettings));

}

}

}

......

}

RetryManager.java

public void setWaitingApns(ArrayList<ApnSetting> waitingApns) {

......

mWaitingApns = waitingApns; // 保存WaitingApns,通常情况下只有一个apn

// Since we replace the entire waiting APN list, we need to re-config this retry manager.

configureRetry(); // 配置Retry的间隔时间

for (ApnSetting apn : mWaitingApns) {

apn.permanentFailed = false;

}

}

配置重试次数、重试间隔时间。

private void configureRetry() {

......

// 初始化一个WaitingApns周期内的重试间隔时间(针对WaitingApns中有多个apn的情况)

mInterApnDelay = b.getLong(

CarrierConfigManager.KEY_CARRIER_DATA_CALL_APN_DELAY_DEFAULT_LONG,

DEFAULT_INTER_APN_DELAY);

// 初始化FailFast模式下的重试间隔时间

mFailFastInterApnDelay = b.getLong(

CarrierConfigManager.KEY_CARRIER_DATA_CALL_APN_DELAY_FASTER_LONG,

DEFAULT_INTER_APN_DELAY_FOR_PROVISIONING);

// 初始化通常情况下不同APN的重试间隔时间及次数;

// 若当前APN的配置不为空,则使用当前APN的配置;

// 若当前APN的配置为空且其他APN的配置不为空,则使用其他APN的配置;

// 若当前APN和其他APN的配置都为空,则使用默认配置

// Load all retry patterns for all different APNs.

String[] allConfigStrings = b.getStringArray(

CarrierConfigManager.KEY_CARRIER_DATA_CALL_RETRY_CONFIG_STRINGS);

......

// 解析配置

configure(configString);

}

这里我们就不分析configure()的代码了,直接用CarrierConfigManager中的默认配置来说明。

sDefaults.putStringArray(KEY_CARRIER_DATA_CALL_RETRY_CONFIG_STRINGS, new String[]{

\"default:default_randomization=2000,5000,10000,20000,40000,80000:5000,160000:5000,\"

+ \"320000:5000,640000:5000,1280000:5000,1800000:5000\",

\"mms:default_randomization=2000,5000,10000,20000,40000,80000:5000,160000:5000,\"

+ \"320000:5000,640000:5000,1280000:5000,1800000:5000\",

\"others:max_retries=3, 5000, 5000, 5000\"});

这个配置包含了3个字符串,分别对default_apn、mms_apn及其它apn进行配置。

每个配置的格式可表示为:

apn_type:[default_randomization=2000 | max_retries=3], 5000,10000,20000,40000,80000:5000,160000:5000

apn_type表示apn的类型;

default_randomization表示默认随机值边界;

max_retries表示最大重试次数,\"infinite\"表示无限次;

如果配置的最大重试次数小于实际配置的次数,则取实际配置的次数;

例如下面这种,虽然配置的最大重试次数为3,但后面配置了4个重试值,则实际的重试次数为4;

\"others:max_retries=3, 5000, 5000, 5000, 5000\"

如果配置的最大重试次数大于实际配置的次数,则后面几次未配置的值则使用最后一个配置值;

例如下面这种,配置的重试次数为5次,但只配置了3个值,则第4次和第5次就使用最后一个配置值,即3s;

\"others:max_retries=5, 1000, 2000, 3000\"

80000:5000表示间隔时间为80s,随机值边界为5s。

配置中的随机值,是用来加在配置的间隔时间上的,例如配置的间隔时间为\"80000:5000\",那么实际上的间隔时间则为80s再加上一个0~5s之间的随机值。之所以加上一个随机值,是为了防止基站周围的大量设备在同一时间发起重试请求。

ConnectivityManager

Platform:Android-7.1.1_r22

ConnectivityManager提供访问ConnectivityService的接口,与ConnectivityService通过binder进行通信

主要作用:

1.监视网络连接(WiFi、GPRS、UMTS等)

2.当网络连接变化时发送广播

3.当一个连接断开时切换到另一个连接

4.为App提供查询可用网络的粗略/详细状态的接口

5.为App提供请求及选择一个网络来进行数据传输的接口

/**

* Class that answers queries about the state of network connectivity. It also

* notifies applications when network connectivity changes. Get an instance

* of this class by calling

* {@link android.content.Context#getSystemService(String) Context.getSystemService(Context.CONNECTIVITY_SERVICE)}.

* <p>

* The primary responsibilities of this class are to:

* <ol>

* <li>Monitor network connections (Wi-Fi, GPRS, UMTS, etc.)</li>

* <li>Send broadcast intents when network connectivity changes</li>

* <li>Attempt to \"fail over\" to another network when connectivity to a network

* is lost</li>

* <li>Provide an API that allows applications to query the coarse-grained or fine-grained

* state of the available networks</li>

* <li>Provide an API that allows applications to request and select networks for their data

* traffic</li>

* </ol>

*/

ConnectivityService

Platform:Android-7.1.1_r22

由Zygote创建的SystemServer启动的。

SystemServer.startOtherServices() {

......

connectivity = new ConnectivityService(

context, networkManagement, networkStats, networkPolicy);

ServiceManager.addService(Context.CONNECTIVITY_SERVICE, connectivity);

networkStats.bindConnectivityManager(connectivity);

networkPolicy.bindConnectivityManager(connectivity);

......

}

启动ConnectivityService时会创建2个NetworkRequest对象

mDefaultRequest:

类型为REQUEST,transport为空,创建好后马上加入到mNetworkRequests。

mDefaultMobileDataRequest:

BACKGROUND_REQUEST,transport为CELLULAR,创建好后先不会加入到mNetworkRequests,

handleRegisterNetworkRequest()中加入到mNetworkRequests,

handleReleaseNetworkRequest()中再从mNetworkRequests移除。

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

属性值:

protected int mLingerDelayMs;

// How long to delay to removal of a pending intent based request.

// See Settings.Secure.CONNECTIVITY_RELEASE_PENDING_INTENT_DELAY_MS

private final int mReleasePendingIntentDelayMs;

private Tethering mTethering;

private final PermissionMonitor mPermissionMonitor;

private KeyStore mKeyStore;

@GuardedBy(\"mVpns\")

private final SparseArray<Vpn> mVpns = new SparseArray<Vpn>();

private boolean mLockdownEnabled;

private LockdownVpnTracker mLockdownTracker;

/** Lock around {@link #mUidRules} and {@link #mMeteredIfaces}. */

private Object mRulesLock = new Object();

/** Currently active network rules by UID. */

@GuardedBy(\"mRulesLock\")

private SparseIntArray mUidRules = new SparseIntArray();

/** Set of ifaces that are costly. */

@GuardedBy(\"mRulesLock\")

private ArraySet<String> mMeteredIfaces = new ArraySet<>();

/** Flag indicating if background data is restricted. */

@GuardedBy(\"mRulesLock\")

private boolean mRestrictBackground;

final private Context mContext;

private int mNetworkPreference;

// 0 is full bad, 100 is full good

private int mDefaultInetConditionPublished = 0;

private int mNumDnsEntries;

private boolean mTestMode;

private static ConnectivityService sServiceInstance;

private INetworkManagementService mNetd;

private INetworkStatsService mStatsService;

private INetworkPolicyManager mPolicyManager;

private String mCurrentTcpBufferSizes;

private static final SparseArray<String> sMagicDecoderRing

/**

* used internally to change our mobile data enabled flag

*/

private static final int EVENT_CHANGE_MOBILE_DATA_ENABLED = 2;

/**

* used internally to clear a wakelock when transitioning

* from one net to another. Clear happens when we get a new

* network - EVENT_EXPIRE_NET_TRANSITION_WAKELOCK happens

* after a timeout if no network is found (typically 1 min).

*/

private static final int EVENT_CLEAR_NET_TRANSITION_WAKELOCK = 8;

/**

* used internally to reload global proxy settings

*/

private static final int EVENT_APPLY_GLOBAL_HTTP_PROXY = 9;

/**

* PAC manager has received new port.

*/

private static final int EVENT_PROXY_HAS_CHANGED = 16;

/**

* used internally when registering NetworkFactories

* obj = NetworkFactoryInfo

*/

private static final int EVENT_REGISTER_NETWORK_FACTORY = 17;

/**

* used internally when registering NetworkAgents

* obj = Messenger

*/

private static final int EVENT_REGISTER_NETWORK_AGENT = 18;

/**

* used to add a network request

* includes a NetworkRequestInfo

*/

private static final int EVENT_REGISTER_NETWORK_REQUEST = 19;

/**

* indicates a timeout period is over - check if we had a network yet or not

* and if not, call the timeout callback (but leave the request live until they

* cancel it.

* includes a NetworkRequestInfo

*/

private static final int EVENT_TIMEOUT_NETWORK_REQUEST = 20;

/**

* used to add a network listener - no request

* includes a NetworkRequestInfo

*/

private static final int EVENT_REGISTER_NETWORK_LISTENER = 21;

/**

* used to remove a network request, either a listener or a real request

* arg1 = UID of caller

* obj = NetworkRequest

*/

private static final int EVENT_RELEASE_NETWORK_REQUEST = 22;

/**

* used internally when registering NetworkFactories

* obj = Messenger

*/

private static final int EVENT_UNREGISTER_NETWORK_FACTORY = 23;

/**

* used internally to expire a wakelock when transitioning

* from one net to another. Expire happens when we fail to find

* a new network (typically after 1 minute) -

* EVENT_CLEAR_NET_TRANSITION_WAKELOCK happens if we had found

* a replacement network.

*/

private static final int EVENT_EXPIRE_NET_TRANSITION_WAKELOCK = 24;

/**

* Used internally to indicate the system is ready.

*/

private static final int EVENT_SYSTEM_READY = 25;

/**

* used to add a network request with a pending intent

* obj = NetworkRequestInfo

*/

private static final int EVENT_REGISTER_NETWORK_REQUEST_WITH_INTENT = 26;

/**

* used to remove a pending intent and its associated network request.

* arg1 = UID of caller

* obj = PendingIntent

*/

private static final int EVENT_RELEASE_NETWORK_REQUEST_WITH_INTENT = 27;

/**

* used to specify whether a network should be used even if unvalidated.

* arg1 = whether to accept the network if it's unvalidated (1 or 0)

* arg2 = whether to remember this choice in the future (1 or 0)

* obj = network

*/

private static final int EVENT_SET_ACCEPT_UNVALIDATED = 28;

/**

* used to specify whether a network should not be penalized when it becomes unvalidated.

*/

private static final int EVENT_SET_AVOID_UNVALIDATED = 35;

/**

* used to ask the user to confirm a connection to an unvalidated network.

* obj = network

*/

private static final int EVENT_PROMPT_UNVALIDATED = 29;

/**

* used internally to (re)configure mobile data always-on settings.

*/

private static final int EVENT_CONFIGURE_MOBILE_DATA_ALWAYS_ON = 30;

/**

* used to add a network listener with a pending intent

* obj = NetworkRequestInfo

*/

private static final int EVENT_REGISTER_NETWORK_LISTENER_WITH_INTENT = 31;

/**

* Indicates a caller has requested to have its callback invoked with

* the latest LinkProperties or NetworkCapabilities.

*

* arg1 = UID of caller

* obj = NetworkRequest

*/

private static final int EVENT_REQUEST_LINKPROPERTIES = 32;

private static final int EVENT_REQUEST_NETCAPABILITIES = 33;

/** Handler thread used for both of the handlers below. */

@VisibleForTesting

protected final HandlerThread mHandlerThread;

/** Handler used for internal events. */

final private InternalHandler mHandler;

/** Handler used for incoming {@link NetworkStateTracker} events. */

final private NetworkStateTrackerHandler mTrackerHandler;

private boolean mSystemReady;

private Intent mInitialBroadcast;

private PowerManager.WakeLock mNetTransitionWakeLock;

private String mNetTransitionWakeLockCausedBy = \"\";

private int mNetTransitionWakeLockSerialNumber;

private int mNetTransitionWakeLockTimeout;

private final PowerManager.WakeLock mPendingIntentWakeLock;

// used in DBG mode to track inet condition reports

private static final int INET_CONDITION_LOG_MAX_SIZE = 15;

private ArrayList mInetLog;

// track the current default http proxy - tell the world if we get a new one (real change)

private volatile ProxyInfo mDefaultProxy = null;

private Object mProxyLock = new Object();

private boolean mDefaultProxyDisabled = false;

// track the global proxy.

private ProxyInfo mGlobalProxy = null;

private PacManager mPacManager = null;

final private SettingsObserver mSettingsObserver;

private UserManager mUserManager;

NetworkConfig[] mNetConfigs;

int mNetworksDefined;

// the set of network types that can only be enabled by system/sig apps

List mProtectedNetworks;

private DataConnectionStats mDataConnectionStats;

TelephonyManager mTelephonyManager;

private KeepaliveTracker mKeepaliveTracker;

private NetworkNotificationManager mNotifier;

private LingerMonitor mLingerMonitor;

// sequence number for Networks; keep in sync with system/netd/NetworkController.cpp

private final static int MIN_NET_ID = 100; // some reserved marks

private final static int MAX_NET_ID = 65535;

private int mNextNetId = MIN_NET_ID;

// sequence number of NetworkRequests

private int mNextNetworkRequestId = 1;

private final IpConnectivityLog mMetricsLog;

@VisibleForTesting

final AvoidBadWifiTracker mAvoidBadWifiTracker;

private INetworkManagementEventObserver mDataActivityObserver

private INetworkPolicyListener mPolicyListener

private final HashMap<Messenger, NetworkFactoryInfo> mNetworkFactoryInfos =

private final HashMap<NetworkRequest, NetworkRequestInfo> mNetworkRequests =

private static final int MAX_NETWORK_REQUESTS_PER_UID = 100;

// Map from UID to number of NetworkRequests that UID has filed.

@GuardedBy(\"mUidToNetworkRequestCount\")

private final SparseIntArray mUidToNetworkRequestCount = new SparseIntArray();

private final SparseArray<NetworkAgentInfo> mNetworkForRequestId =

private final SparseArray<NetworkAgentInfo> mNetworkForNetId =

private final SparseBooleanArray mNetIdInUse = new SparseBooleanArray();

private final HashMap<Messenger, NetworkAgentInfo> mNetworkAgentInfos =

private final HashSet<Integer> mBlockedAppUids = new HashSet();

// Note: if mDefaultRequest is changed, NetworkMonitor needs to be updated.

private final NetworkRequest mDefaultRequest;

// Request used to optionally keep mobile data active even when higher

// priority networks like Wi-Fi are active.

private final NetworkRequest mDefaultMobileDataRequest;

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

构造方法:

protected ConnectivityService(Context context, INetworkManagementService netManager,

INetworkStatsService statsService, INetworkPolicyManager policyManager,

IpConnectivityLog logger) {

if (DBG) log(\"ConnectivityService starting up\");

mMetricsLog = logger;

mDefaultRequest = createInternetRequestForTransport(-1, NetworkRequest.Type.REQUEST);

NetworkRequestInfo defaultNRI = new NetworkRequestInfo(null, mDefaultRequest, new Binder());

mNetworkRequests.put(mDefaultRequest, defaultNRI);

mNetworkRequestInfoLogs.log(\"REGISTER \" + defaultNRI);

mDefaultMobileDataRequest = createInternetRequestForTransport(

NetworkCapabilities.TRANSPORT_CELLULAR, NetworkRequest.Type.BACKGROUND_REQUEST);

mHandlerThread = createHandlerThread();

mHandlerThread.start();

mHandler = new InternalHandler(mHandlerThread.getLooper());

mTrackerHandler = new NetworkStateTrackerHandler(mHandlerThread.getLooper());

// setup our unique device name

if (TextUtils.isEmpty(SystemProperties.get(\"net.hostname\"))) {

String id = Settings.Secure.getString(context.getContentResolver(),

Settings.Secure.ANDROID_ID);

if (id != null && id.length() > 0) {

String name = new String(\"android-\").concat(id);

SystemProperties.set(\"net.hostname\", name);

}

}

mReleasePendingIntentDelayMs = Settings.Secure.getInt(context.getContentResolver(),

Settings.Secure.CONNECTIVITY_RELEASE_PENDING_INTENT_DELAY_MS, 5_000);

mLingerDelayMs = SystemProperties.getInt(LINGER_DELAY_PROPERTY, DEFAULT_LINGER_DELAY_MS);

mContext = checkNotNull(context, \"missing Context\");

mNetd = checkNotNull(netManager, \"missing INetworkManagementService\");

mStatsService = checkNotNull(statsService, \"missing INetworkStatsService\");

mPolicyManager = checkNotNull(policyManager, \"missing INetworkPolicyManager\");

mKeyStore = KeyStore.getInstance();

mTelephonyManager = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);

try {

mPolicyManager.setConnectivityListener(mPolicyListener);

mRestrictBackground = mPolicyManager.getRestrictBackground();

} catch (RemoteException e) {

// ouch, no rules updates means some processes may never get network

loge(\"unable to register INetworkPolicyListener\" + e);

}

final PowerManager powerManager = (PowerManager) context.getSystemService(

Context.POWER_SERVICE);

mNetTransitionWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);

mNetTransitionWakeLockTimeout = mContext.getResources().getInteger(

com.android.internal.R.integer.config_networkTransitionTimeout);

mPendingIntentWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);

mNetConfigs = new NetworkConfig[ConnectivityManager.MAX_NETWORK_TYPE+1];

// TODO: What is the \"correct\" way to do determine if this is a wifi only device?

boolean wifiOnly = SystemProperties.getBoolean(\"ro.radio.noril\", false);

log(\"wifiOnly=\" + wifiOnly);

String[] naStrings = context.getResources().getStringArray(

com.android.internal.R.array.networkAttributes);

for (String naString : naStrings) {

try {

NetworkConfig n = new NetworkConfig(naString);

if (VDBG) log(\"naString=\" + naString + \" config=\" + n);

if (n.type > ConnectivityManager.MAX_NETWORK_TYPE) {

loge(\"Error in networkAttributes - ignoring attempt to define type \" +

n.type);

continue;

}

if (wifiOnly && ConnectivityManager.isNetworkTypeMobile(n.type)) {

log(\"networkAttributes - ignoring mobile as this dev is wifiOnly \" +

n.type);

continue;

}

if (mNetConfigs[n.type] != null) {

loge(\"Error in networkAttributes - ignoring attempt to redefine type \" +

n.type);

continue;

}

mLegacyTypeTracker.addSupportedType(n.type);

mNetConfigs[n.type] = n;

mNetworksDefined++;

} catch(Exception e) {

// ignore it - leave the entry null

}

}

// Forcibly add TYPE_VPN as a supported type, if it has not already been added via config.

if (mNetConfigs[TYPE_VPN] == null) {

// mNetConfigs is used only for \"restore time\", which isn't applicable to VPNs, so we

// don't need to add TYPE_VPN to mNetConfigs.

mLegacyTypeTracker.addSupportedType(TYPE_VPN);

mNetworksDefined++; // used only in the log() statement below.

}

if (VDBG) log(\"mNetworksDefined=\" + mNetworksDefined);

mProtectedNetworks = new ArrayList<Integer>();

int[] protectedNetworks = context.getResources().getIntArray(

com.android.internal.R.array.config_protectedNetworks);

for (int p : protectedNetworks) {

if ((mNetConfigs[p] != null) && (mProtectedNetworks.contains(p) == false)) {

mProtectedNetworks.add(p);

} else {

if (DBG) loge(\"Ignoring protectedNetwork \" + p);

}

}

mTestMode = SystemProperties.get(\"cm.test.mode\").equals(\"true\")

&& SystemProperties.get(\"ro.build.type\").equals(\"eng\");

mTethering = new Tethering(mContext, mNetd, statsService, mPolicyManager);

mPermissionMonitor = new PermissionMonitor(mContext, mNetd);

//set up the listener for user state for creating user VPNs

IntentFilter intentFilter = new IntentFilter();

intentFilter.addAction(Intent.ACTION_USER_STARTED);

intentFilter.addAction(Intent.ACTION_USER_STOPPED);

intentFilter.addAction(Intent.ACTION_USER_ADDED);

intentFilter.addAction(Intent.ACTION_USER_REMOVED);

intentFilter.addAction(Intent.ACTION_USER_UNLOCKED);

mContext.registerReceiverAsUser(

mUserIntentReceiver, UserHandle.ALL, intentFilter, null, null);

try {

mNetd.registerObserver(mTethering);

mNetd.registerObserver(mDataActivityObserver);

} catch (RemoteException e) {

loge(\"Error registering observer :\" + e);

}

if (DBG) {

mInetLog = new ArrayList();

}

mSettingsObserver = new SettingsObserver(mContext, mHandler);

registerSettingsCallbacks();

mDataConnectionStats = new DataConnectionStats(mContext);

mDataConnectionStats.startMonitoring();

mPacManager = new PacManager(mContext, mHandler, EVENT_PROXY_HAS_CHANGED);

mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);

mKeepaliveTracker = new KeepaliveTracker(mHandler);

mNotifier = new NetworkNotificationManager(mContext, mTelephonyManager,

mContext.getSystemService(NotificationManager.class));

final int dailyLimit = Settings.Global.getInt(mContext.getContentResolver(),

Settings.Global.NETWORK_SWITCH_NOTIFICATION_DAILY_LIMIT,

LingerMonitor.DEFAULT_NOTIFICATION_DAILY_LIMIT);

final long rateLimit = Settings.Global.getLong(mContext.getContentResolver(),

Settings.Global.NETWORK_SWITCH_NOTIFICATION_RATE_LIMIT_MILLIS,

LingerMonitor.DEFAULT_NOTIFICATION_RATE_LIMIT_MILLIS);

mLingerMonitor = new LingerMonitor(mContext, mNotifier, dailyLimit, rateLimit);

mAvoidBadWifiTracker = createAvoidBadWifiTracker(

mContext, mHandler, () -> rematchForAvoidBadWifiUpdate());

}

frameworks/base/core/res/res/values/config.xml

<string-array translatable=\"false\" name=\"networkAttributes\">

name type radio priority restoreTime dependencyMet

<item>\"wifi, 1, 1, 1, -1, true\"</item>

<item>\"mobile, 0, 0, 0, -1, true\"</item>

<item>\"mobile_mms, 2, 0, 4, 60000, true\"</item>

<item>\"mobile_supl, 3, 0, 2, 60000, true\"</item>

<item>\"mobile_dun, 4, 0, 2, 60000, true\"</item>

<item>\"mobile_hipri, 5, 0, 3, 60000, true\"</item>

<item>\"mobile_fota, 10, 0, 2, 60000, true\"</item>

<item>\"mobile_ims, 11, 0, 2, 60000, true\"</item>

<item>\"mobile_cbs, 12, 0, 2, 60000, true\"</item>

<item>\"bluetooth, 7, 7, 2, -1, true\"</item>

<item>\"mobile_emergency, 15, 0, 5, -1, true\"</item>

</string-array>

NetworkAgent

用于特定承载代码和ConnectivityService通信的工具类。

如:DataConnection.java、Vpn.java、WifiStateMachine.java等与ConnectivityService通信

NetworkCapabilities

用于描述一个网络的能力,用来指定ConnectivityManager的需求以及检查网络。

/**

* This class represents the capabilities of a network. This is used both to specify

* needs to {@link ConnectivityManager} and when inspecting a network.

*

* Note that this replaces the old {@link ConnectivityManager#TYPE_MOBILE} method

* of network selection. Rather than indicate a need for Wi-Fi because an application

* needs high bandwidth and risk obsolescence when a new, fast network appears (like LTE),

* the application should specify it needs high bandwidth. Similarly if an application

* needs an unmetered network for a bulk transfer it can specify that rather than assuming

* all cellular based connections are metered and all Wi-Fi based connections are not.

*/

NetworkRequest

Platform:Android-7.1.1_r22

定义一个网络请求。

通过ConnectivityManager#requestNetwork请求一个网络;

通过ConnectivityManager#registerNetworkCallback监听网络变化。

/**

* Defines a request for a network, made through {@link NetworkRequest.Builder} and used

* to request a network via {@link ConnectivityManager#requestNetwork} or listen for changes

* via {@link ConnectivityManager#registerNetworkCallback}.

*/

public class NetworkRequest implements Parcelable {

public final NetworkCapabilities networkCapabilities;

// 请求id,ConnectivityService.mNextNetworkRequestId维护

/**

* Identifies the request. NetworkRequests should only be constructed by

* the Framework and given out to applications as tokens to be used to identify

* the request.

* @hide

*/

public final int requestId;

/**

* Set for legacy requests and the default. Set to TYPE_NONE for none.

* Causes CONNECTIVITY_ACTION broadcasts to be sent.

* @hide

*/

public final int legacyType;

/**

* A NetworkRequest as used by the system can be one of the following types:

*

* - LISTEN, for which the framework will issue callbacks about any

* and all networks that match the specified NetworkCapabilities,

*

* - REQUEST, capable of causing a specific network to be created

* first (e.g. a telephony DUN request), the framework will issue

* callbacks about the single, highest scoring current network

* (if any) that matches the specified NetworkCapabilities, or

*

* - TRACK_DEFAULT, a hybrid of the two designed such that the

* framework will issue callbacks for the single, highest scoring

* current network (if any) that matches the capabilities of the

* default Internet request (mDefaultRequest), but which cannot cause

* the framework to either create or retain the existence of any

* specific network. Note that from the point of view of the request

* matching code, TRACK_DEFAULT is identical to REQUEST: its special

* behaviour is not due to different semantics, but to the fact that

* the system will only ever create a TRACK_DEFAULT with capabilities

* that are identical to the default request's capabilities, thus

* causing it to share fate in every way with the default request.

*

* - BACKGROUND_REQUEST, like REQUEST but does not cause any networks

* to retain the NET_CAPABILITY_FOREGROUND capability. A network with

* no foreground requests is in the background. A network that has

* one or more background requests and loses its last foreground

* request to a higher-scoring network will not go into the

* background immediately, but will linger and go into the background

* after the linger timeout.

*

* - The value NONE is used only by applications. When an application

* creates a NetworkRequest, it does not have a type; the type is set

* by the system depending on the method used to file the request

* (requestNetwork, registerNetworkCallback, etc.).

*

* @hide

*/

public static enum Type {

NONE,

LISTEN,

TRACK_DEFAULT,

REQUEST,

BACKGROUND_REQUEST,

};

/**

* The type of the request. This is only used by the system and is always NONE elsewhere.

*

* @hide

*/

public final Type type;

NetworkStatsService

Platform:Android-7.1.1_r22

统计网络传输数据,供其他系统服务使用。

/**

* Collect and persist detailed network statistics, and provide this data to

* other system services.