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.