Android源码笔记--网络

Posted ljt2724960661

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android源码笔记--网络相关的知识,希望对你有一定的参考价值。

           这一节主要了解ConnectivityService,这个api在android网络里使用较常见,它是Android网络管理的中心,它是在SystemServer中创建的,代码如下:

 /frameworks/base/services/java/com/android/server/SystemServer.java

/**
     * Starts a miscellaneous grab bag of stuff that has yet to be refactored and organized.
     */
   private void startOtherServices(@NonNull TimingsTraceAndSlog t) 
     try 
                connectivity = new ConnectivityService(
                        context, networkManagement, networkStats, networkPolicy);
                ServiceManager.addService(Context.CONNECTIVITY_SERVICE, connectivity,
                        /* allowIsolated= */ false,
                        DUMP_FLAG_PRIORITY_HIGH | DUMP_FLAG_PRIORITY_NORMAL);
                networkPolicy.bindConnectivityManager(connectivity);
             catch (Throwable e) 
                reportWtf("starting Connectivity Service", e);
            
   
   

分析:初始化过程ConnectivityService的构造方法非常长,如下:

@VisibleForTesting
    protected ConnectivityService(Context context, INetworkManagementService netManager,
            INetworkStatsService statsService, INetworkPolicyManager policyManager,
            IDnsResolver dnsresolver, IpConnectivityLog logger, INetd netd, Dependencies deps) 
        if (DBG) log("ConnectivityService starting up");
...
        mDefaultRequest = createDefaultInternetRequestForTransport(-1, NetworkRequest.Type.REQUEST);
        mNetworkRanker = new NetworkRanker();
        NetworkRequestInfo defaultNRI = new NetworkRequestInfo(null, mDefaultRequest, new Binder());
        mNetworkRequests.put(mDefaultRequest, defaultNRI);
        mNetworkRequestInfoLogs.log("REGISTER " + defaultNRI);

        mDefaultMobileDataRequest = createDefaultInternetRequestForTransport(
                NetworkCapabilities.TRANSPORT_CELLULAR, NetworkRequest.Type.BACKGROUND_REQUEST);
...
        mDefaultWifiRequest = createDefaultInternetRequestForTransport(
                NetworkCapabilities.TRANSPORT_WIFI, NetworkRequest.Type.BACKGROUND_REQUEST);

        mHandlerThread = mDeps.makeHandlerThread();
        mHandlerThread.start();
        mHandler = new InternalHandler(mHandlerThread.getLooper());
        mTrackerHandler = new NetworkStateTrackerHandler(mHandlerThread.getLooper());
        mConnectivityDiagnosticsHandler =
                new ConnectivityDiagnosticsHandler(mHandlerThread.getLooper());

        mReleasePendingIntentDelayMs = Settings.Secure.getInt(context.getContentResolver(),
                Settings.Secure.CONNECTIVITY_RELEASE_PENDING_INTENT_DELAY_MS, 5_000);

        mLingerDelayMs = mSystemProperties.getInt(LINGER_DELAY_PROPERTY, DEFAULT_LINGER_DELAY_MS);

        mNMS = Objects.requireNonNull(netManager, "missing INetworkManagementService");
        mStatsService = Objects.requireNonNull(statsService, "missing INetworkStatsService");
        mPolicyManager = Objects.requireNonNull(policyManager, "missing INetworkPolicyManager");
        mPolicyManagerInternal = Objects.requireNonNull(
                LocalServices.getService(NetworkPolicyManagerInternal.class),
                "missing NetworkPolicyManagerInternal");
        mDnsResolver = Objects.requireNonNull(dnsresolver, "missing IDnsResolver");
        mProxyTracker = mDeps.makeProxyTracker(mContext, mHandler);

        mNetd = netd;
        mKeyStore = KeyStore.getInstance();
        mTelephonyManager = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
        mAppOpsManager = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
        mLocationPermissionChecker = new LocationPermissionChecker(mContext);
...
        try 
            mPolicyManager.registerListener(mPolicyListener);
         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];
...
        boolean wifiOnly = mSystemProperties.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) 
                   
                    continue;
                
                if (wifiOnly && ConnectivityManager.isNetworkTypeMobile(n.type)) 
                 
                    continue;
                
                if (mNetConfigs[n.type] != null) 
                   
                    continue;
                
                mLegacyTypeTracker.addSupportedType(n.type);

                mNetConfigs[n.type] = n;
                mNetworksDefined++;
             catch(Exception e) 
                // ignore it - leave the entry null
            
        

        if (mNetConfigs[TYPE_VPN] == null) 
           
            mLegacyTypeTracker.addSupportedType(TYPE_VPN);
            mNetworksDefined++;  // used only in the log() statement below.
        
...
        if (mNetConfigs[TYPE_ETHERNET] == null && mDeps.hasService(Context.ETHERNET_SERVICE)) 
            mLegacyTypeTracker.addSupportedType(TYPE_ETHERNET);
            mNetworksDefined++;
        

        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);
            
        

        mWolSupportedInterfaces = new ArraySet(
                mContext.getResources().getStringArray(
                        com.android.internal.R.array.config_wakeonlan_supported_interfaces));

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

        mPermissionMonitor = new PermissionMonitor(mContext, mNetd);
...
        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(
                mIntentReceiver,
                UserHandle.ALL,
                intentFilter,
                null /* broadcastPermission */,
                mHandler);
        mContext.registerReceiverAsUser(mUserPresentReceiver, UserHandle.SYSTEM,
                new IntentFilter(Intent.ACTION_USER_PRESENT), null, null);

        // Listen to package add and removal events for all users.
        intentFilter = new IntentFilter();
        intentFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
        intentFilter.addAction(Intent.ACTION_PACKAGE_REPLACED);
        intentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
        intentFilter.addDataScheme("package");
        mContext.registerReceiverAsUser(
                mIntentReceiver,
                UserHandle.ALL,
                intentFilter,
                null /* broadcastPermission */,
                mHandler);

        try 
            mNMS.registerObserver(mDataActivityObserver);
         catch (RemoteException e) 
            loge("Error registering observer :" + e);
        

        mSettingsObserver = new SettingsObserver(mContext, mHandler);
        registerSettingsCallbacks();

        final DataConnectionStats dataConnectionStats = new DataConnectionStats(mContext, mHandler);
        dataConnectionStats.startMonitoring();

        mKeepaliveTracker = new KeepaliveTracker(mContext, 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);

        mMultinetworkPolicyTracker = mDeps.makeMultinetworkPolicyTracker(
                mContext, mHandler, () -> rematchForAvoidBadWifiUpdate());
        mMultinetworkPolicyTracker.start();

        mMultipathPolicyTracker = new MultipathPolicyTracker(mContext, mHandler);

        mDnsManager = new DnsManager(mContext, mDnsResolver, mSystemProperties);
        registerPrivateDnsSettingsCallbacks();
    

执行过程大体如下:

     (1)创建处理消息的线程并启动。
  (2)创建处理消息的Handle对象mHandler、mTrackerHandler。
  (3)创建DefaultNetworkFactory 对象,用来创建各种NetworkStateTracker对象。
  (4)使用Android的ID设置net.hostname属性。这个属性将作为网络传输中的主机名。
  (5)从Setting 中或者系统资源Config.xml 的config_default_dns_server 项中得到DNS 服务器的IP地址,保存到变量mDefaultDns 中。
  (6)保存对其他系统服务的引用,包括NetworkManagementService、NetworkPolicyManagerService、PowerManagerService 和 PhoneInterfaceManager。
  (7)创建 wakelock对象mNetTransitionWakeLock,在网络有数据传输时用来防止休眠。
  (8)创建NetworkStateTracker对象的数组。
   (9)从系统资源Config.xml读取RadioAttributes、networkAttributes、config_protectedNetworks数组的值,分别用来初始化数组变量mRadioAttributes、mNetConfigs和mProtectedNetworks。
  (10)根据mNetConfigs数组,计算各种网络类型的优先级,保存在mPriorityList列表中。
  (11)变量mNetworkPreference表示系统中优先使用的网络,如果用户在Setting程序中设置了优先网络,则使用用户设置的值;用户没有设置,则从mPriorityList列表按照从先到后的顺序
  挑选当前有效的网络类型。
  (12)创建各种网络连接的NetworkState Tracker对象,填充mNetTrackers数组。
  (13)创建Tethering对象mTethering,用来共享网络。
  (14)创建监听用户状态变化 Intent的Receiver对象。
  (15)创建Nat464Xlat对象mClat,用于IPV4和IPV6地址的转换。

网络经常会用到的场景是获取当前网络类型,一般使用如下:

 public static int getNetworkState(Context context) 
        ConnectivityManager connManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); // 获取网络服务
        if (null == connManager)  // 为空则认为无网络
            return NETWORK_NONE;
        
        // 获取网络类型,如果为空,返回无网络
        NetworkInfo activeNetInfo = connManager.getActiveNetworkInfo();
        if (activeNetInfo == null || !activeNetInfo.isAvailable()) 
            return NETWORK_NONE;
        
       return activeNetInfo.getType();

看看源码:

/frameworks/base/core/java/android/net/ConnectivityManager.java

  private final IConnectivityManager mService;

   @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE)
    @Nullable
    public Network getActiveNetwork() 
        try 
            return mService.getActiveNetwork();
         catch (RemoteException e) 
            throw e.rethrowFromSystemServer();
        
    
/frameworks/base/core/java/android/net/IConnectivityManager.aidl

interface IConnectivityManager

    Network getActiveNetwork();
    Network getActiveNetworkForUid(int uid, boolean ignoreBlocked);
    @UnsupportedAppUsage
    NetworkInfo getActiveNetworkInfo();
    NetworkInfo getActiveNetworkInfoForUid(int uid, boolean ignoreBlocked);
    @UnsupportedAppUsage(maxTargetSdk = 28)
    NetworkInfo getNetworkInfo(int networkType);
/frameworks/base/services/core/java/com/android/server/ConnectivityService.java

   @Override
    public NetworkInfo getNetworkInfo(int networkType) 
        enforceAccessPermission();
        final int uid = Binder.getCallingUid();
        if (getVpnUnderlyingNetworks(uid) != null) 
            // A VPN is active, so we may need to return one of its underlying networks. This
            // information is not available in LegacyTypeTracker, so we have to get it from
            // getUnfilteredActiveNetworkState.
            final NetworkState state = getUnfilteredActiveNetworkState(uid);
            if (state.networkInfo != null && state.networkInfo.getType() == networkType) 
                filterNetworkStateForUid(state, uid, false);
                return state.networkInfo;
            
        
        final NetworkState state = getFilteredNetworkState(networkType, uid);
        return state.networkInfo;
    
	
	

    private NetworkState getFilteredNetworkState(int networkType, int uid) 
        if (mLegacyTypeTracker.isTypeSupported(networkType)) 
            final NetworkAgentInfo nai = mLegacyTypeTracker.getNetworkForType(networkType);
            final NetworkState state;
            if (nai != null) 
                state = nai.getNetworkState();
                state.networkInfo.setType(networkType);
             else 
                final NetworkInfo info = new NetworkInfo(networkType, 0,
                        getNetworkTypeName(networkType), "");
                info.setDetailedState(NetworkInfo.DetailedState.DISCONNECTED, null, null);
                info.setIsAvailable(true);
                final NetworkCapabilities capabilities = new NetworkCapabilities();
                capabilities.setCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING,
                        !info.isRoaming());
                state = new NetworkState(info, new LinkProperties(), capabilities,
                        null, null, null);
            
            filterNetworkStateForUid(state, uid, false);
            return state;
         else 
            return NetworkState.EMPTY;
        
    	
	/frameworks/base/core/java/android/net/LinkProperties.java
	//网络连接相关属性在此设置
	
	public final class LinkProperties implements Parcelable 
	   @TestApi
    public LinkProperties(@Nullable LinkProperties source, boolean parcelSensitiveFields) 
        mParcelSensitiveFields = parcelSensitiveFields;
        if (source == null) return;
        mIfaceName = source.mIfaceName;
        mLinkAddresses.addAll(source.mLinkAddresses);
        mDnses.addAll(source.mDnses);
        mValidatedPrivateDnses.addAll(source.mValidatedPrivateDnses);
        mUsePrivateDns = source.mUsePrivateDns;
        mPrivateDnsServerName = source.mPrivateDnsServerName;
        mPcscfs.addAll(source.mPcscfs);
        mDomains = source.mDomains;
        mRoutes.addAll(source.mRoutes);
        mHttpProxy = (source.mHttpProxy == null) ? null : new ProxyInfo(source.mHttpProxy);
        for (LinkProperties l: source.mStackedLinks.values()) 
            addStackedLink(l);
        
        setMtu(source.mMtu);
        setDhcpServerAddress(source.getDhcpServerAddress());
        mTcpBufferSizes = source.mTcpBufferSizes;
        mNat64Prefix = source.mNat64Prefix;
        mWakeOnLanSupported = source.mWakeOnLanSupported;
        mCaptivePortalApiUrl = source.mCaptivePortalApiUrl;
        mCaptivePortalData = source.mCaptivePortalData;
    

以上是关于Android源码笔记--网络的主要内容,如果未能解决你的问题,请参考以下文章

笔记 android网络框架源码解析及对比(待续)

Android源码笔记--网络

Android源码笔记--网络

Android源码笔记--恢复出厂设置

Android源码笔记--恢复出厂设置

Android源码笔记——Camera系统架构