18. ConnectivityService网络管理原理

摘要

本文从Android Framework源码角度深度剖析ConnectivityService网络管理机制。ConnectivityService是Android网络管理的核心服务,负责网络连接状态监控、网络切换、VPN管理、网络评分机制等功能。文章详细解析网络架构、NetworkAgent机制、网络请求与评分算法、网络策略管理、以及网络监控实现,帮助开发者深入理解Android网络系统的底层运作。

关键词: ConnectivityService、NetworkAgent、网络评分、网络切换、VPN管理


1. ConnectivityService架构

1.1 系统架构

硬件层

网络层

Framework层

应用层

App

ConnectivityManager API

ConnectivityService

NetworkFactory

NetworkAgent

WiFiNetworkFactory

TelephonyNetworkFactory

EthernetNetworkFactory

WiFiNetworkAgent

MobileNetworkAgent

VpnNetworkAgent

WiFi驱动

Modem

1.2 核心职责

ConnectivityService

网络管理

网络连接

网络断开

网络切换

默认网络

网络请求

应用网络请求

网络能力匹配

网络评分

网络选择

网络监控

连接状态

网络质量

流量统计

网络事件

策略管理

数据节省模式

后台数据限制

VPN管理

网络策略


2. ConnectivityService启动流程

// frameworks/base/services/core/java/com/android/server/ConnectivityService.java
public class ConnectivityService extends IConnectivityManager.Stub
        implements PendingIntent.OnFinished {

    public ConnectivityService(Context context, INetworkManagementService netManager,
            INetworkStatsService statsService, INetworkPolicyManager policyManager) {

        mContext = context;
        mNetd = netManager;
        mStatsService = statsService;
        mPolicyManager = policyManager;

        // 1. 创建Handler
        mHandlerThread = new HandlerThread("ConnectivityServiceThread");
        mHandlerThread.start();
        mHandler = new InternalHandler(mHandlerThread.getLooper());

        // 2. 初始化网络追踪器
        mNetworkAgentInfos = new HashMap<>();
        mNetworkRequests = new HashMap<>();

        // 3. 创建默认网络请求
        mDefaultRequest = createDefaultNetworkRequest();
        mNetworkRequests.put(mDefaultRequest, new NetworkRequestInfo(
                null, mDefaultRequest, new Binder()));

        // 4. 注册NetworkFactory
        mNetworkFactoryInfos = new HashMap<>();

        // 5. 注册监听器
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(Intent.ACTION_USER_PRESENT);
        intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
        mContext.registerReceiverAsUser(new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                handleBroadcast(intent);
            }
        }, UserHandle.ALL, intentFilter, null, mHandler);

        // 6. 初始化VPN管理
        mVpns = new SparseArray<Vpn>();
    }

    private NetworkRequest createDefaultNetworkRequest() {
        NetworkRequest.Builder builder = new NetworkRequest.Builder();
        builder.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
        builder.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED);
        builder.addCapability(NetworkCapabilities.NET_CAPABILITY_TRUSTED);
        builder.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN);
        return builder.build();
    }
}

3. NetworkAgent机制

3.1 NetworkAgent注册流程

应用 ConnectivityService NetworkAgent WiFi服务 应用 ConnectivityService NetworkAgent WiFi服务 网络连接成功 new NetworkAgent() register() handleRegisterNetworkAgent() 评分和排序 选择最佳网络 onAvailable(network) sendNetworkInfo(CONNECTED) updateNetworkInfo() onCapabilitiesChanged()

3.2 核心代码

// frameworks/base/services/core/java/com/android/server/ConnectivityService.java
private void handleRegisterNetworkAgent(NetworkAgentInfo nai) {
    // 1. 添加到网络列表
    mNetworkAgentInfos.put(nai.messenger, nai);

    // 2. 分配网络ID
    synchronized (mNetworkForNetId) {
        int netId = mNextNetId++;
        mNetworkForNetId.put(netId, nai);
        nai.network = new Network(netId);
    }

    // 3. 通知NetworkFactory
    for (NetworkFactoryInfo nfi : mNetworkFactoryInfos.values()) {
        nfi.asyncChannel.sendMessage(NetworkFactory.CMD_REQUEST_NETWORK, nai.network);
    }

    // 4. 尝试满足网络请求
    rematchAllNetworksAndRequests(null, 0);
}

private void rematchAllNetworksAndRequests(NetworkAgentInfo changed, int oldScore) {
    // 1. 重新评估所有网络和请求
    ArrayList<NetworkAgentInfo> nais = new ArrayList<>(mNetworkAgentInfos.values());

    // 2. 对每个请求找到最佳网络
    for (NetworkRequestInfo nri : mNetworkRequests.values()) {
        NetworkAgentInfo bestNetwork = null;
        int bestScore = 0;

        for (NetworkAgentInfo nai : nais) {
            if (nai.satisfies(nri.request)) {
                int score = nai.getCurrentScore();
                if (score > bestScore) {
                    bestNetwork = nai;
                    bestScore = score;
                }
            }
        }

        // 3. 切换到最佳网络
        if (bestNetwork != nri.satisfier) {
            if (nri.satisfier != null) {
                notifyNetworkLost(nri.satisfier.network, nri.request.requestId);
            }
            if (bestNetwork != null) {
                notifyNetworkAvailable(bestNetwork.network, nri.request.requestId);
            }
            nri.satisfier = bestNetwork;
        }
    }
}

4. 网络评分机制

4.1 评分算法

// frameworks/base/core/java/android/net/NetworkScore.java
public class NetworkScore {
    // 基础分数
    private static final int BASE_SCORE = 50;

    // 网络类型加分
    private static final int WIFI_SCORE = 60;
    private static final int ETHERNET_SCORE = 70;
    private static final int MOBILE_SCORE = 50;

    public static int calculateScore(NetworkCapabilities nc, boolean isDefault) {
        int score = BASE_SCORE;

        // 1. 网络类型评分
        if (nc.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET)) {
            score = ETHERNET_SCORE;
        } else if (nc.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {
            score = WIFI_SCORE;
        } else if (nc.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) {
            score = MOBILE_SCORE;
        }

        // 2. 信号强度加分(WiFi)
        int signalStrength = nc.getSignalStrength();
        if (signalStrength != SIGNAL_STRENGTH_UNSPECIFIED) {
            score += signalStrength;
        }

        // 3. 验证状态加分
        if (nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)) {
            score += 10;
        }

        // 4. 是否默认网络
        if (isDefault) {
            score += 10;
        }

        return score;
    }
}

4.2 网络验证

// frameworks/base/services/core/java/com/android/server/connectivity/NetworkMonitor.java
public class NetworkMonitor extends StateMachine {
    private static final String DEFAULT_HTTPS_URL = "https://www.google.com/generate_204";

    protected void validateInternetConnectivity() {
        // 1. HTTP探测
        int httpResult = isCaptivePortal();

        if (httpResult == 204) {
            // 验证通过
            mConnectivityServiceHandler.sendMessage(
                EVENT_NETWORK_TESTED,
                NETWORK_TEST_RESULT_VALID);
        } else if (httpResult >= 200 && httpResult <= 399) {
            // 可能是Captive Portal(需要认证的WiFi)
            mConnectivityServiceHandler.sendMessage(
                EVENT_NETWORK_TESTED,
                NETWORK_TEST_RESULT_PARTIAL);
        } else {
            // 验证失败
            mConnectivityServiceHandler.sendMessage(
                EVENT_NETWORK_TESTED,
                NETWORK_TEST_RESULT_INVALID);
        }
    }

    private int isCaptivePortal() {
        HttpURLConnection urlConnection = null;
        try {
            URL url = new URL(DEFAULT_HTTPS_URL);
            urlConnection = (HttpURLConnection) url.openConnection();
            urlConnection.setInstanceFollowRedirects(false);
            urlConnection.setConnectTimeout(10000);
            urlConnection.setReadTimeout(10000);
            urlConnection.setUseCaches(false);

            urlConnection.getInputStream();
            return urlConnection.getResponseCode();
        } catch (IOException e) {
            return 599;  // 网络错误
        } finally {
            if (urlConnection != null) {
                urlConnection.disconnect();
            }
        }
    }
}

5. 网络请求与切换

5.1 requestNetwork流程

// frameworks/base/services/core/java/com/android/server/ConnectivityService.java
@Override
public NetworkRequest requestNetwork(NetworkCapabilities networkCapabilities,
        Messenger messenger, int timeoutMs, IBinder binder, int legacyType) {

    // 1. 创建NetworkRequest
    NetworkRequest networkRequest = new NetworkRequest(networkCapabilities, legacyType,
            nextNetworkRequestId++, NetworkRequest.Type.REQUEST);

    // 2. 创建NetworkRequestInfo
    NetworkRequestInfo nri = new NetworkRequestInfo(messenger, networkRequest, binder);

    // 3. 添加到请求列表
    mNetworkRequests.put(networkRequest, nri);

    // 4. 尝试匹配现有网络
    rematchAllNetworksAndRequests(null, 0);

    // 5. 通知NetworkFactory创建网络
    for (NetworkFactoryInfo nfi : mNetworkFactoryInfos.values()) {
        nfi.asyncChannel.sendMessage(NetworkFactory.CMD_REQUEST_NETWORK, networkRequest);
    }

    // 6. 设置超时
    if (timeoutMs > 0) {
        mHandler.sendMessageDelayed(
            mHandler.obtainMessage(EVENT_TIMEOUT_NETWORK_REQUEST, nri),
            timeoutMs);
    }

    return networkRequest;
}

6. 实战案例

6.1 监听网络状态

public class NetworkMonitor {
    private ConnectivityManager mConnectivityManager;
    private ConnectivityManager.NetworkCallback mNetworkCallback;

    public void startMonitoring(Context context) {
        mConnectivityManager = context.getSystemService(ConnectivityManager.class);

        mNetworkCallback = new ConnectivityManager.NetworkCallback() {
            @Override
            public void onAvailable(Network network) {
                // 网络可用
                NetworkCapabilities caps = mConnectivityManager.getNetworkCapabilities(network);
                boolean isWiFi = caps.hasTransport(NetworkCapabilities.TRANSPORT_WIFI);
                boolean isCellular = caps.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR);
                Log.d(TAG, "网络连接: WiFi=" + isWiFi + ", Cellular=" + isCellular);
            }

            @Override
            public void onLost(Network network) {
                // 网络断开
                Log.d(TAG, "网络断开");
            }

            @Override
            public void onCapabilitiesChanged(Network network, NetworkCapabilities caps) {
                // 网络能力变化
                boolean validated = caps.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED);
                int signalStrength = caps.getSignalStrength();
                Log.d(TAG, "网络质量: validated=" + validated + ", signal=" + signalStrength);
            }
        };

        // 注册监听
        NetworkRequest request = new NetworkRequest.Builder()
            .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
            .build();
        mConnectivityManager.registerNetworkCallback(request, mNetworkCallback);
    }

    public void stopMonitoring() {
        if (mConnectivityManager != null && mNetworkCallback != null) {
            mConnectivityManager.unregisterNetworkCallback(mNetworkCallback);
        }
    }
}

6.2 请求特定网络

public class NetworkRequester {
    private ConnectivityManager mConnectivityManager;
    private Network mWiFiNetwork;

    public void requestWiFiNetwork(Context context) {
        mConnectivityManager = context.getSystemService(ConnectivityManager.class);

        NetworkRequest request = new NetworkRequest.Builder()
            .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
            .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
            .build();

        ConnectivityManager.NetworkCallback callback = new ConnectivityManager.NetworkCallback() {
            @Override
            public void onAvailable(Network network) {
                mWiFiNetwork = network;
                // 绑定进程到WiFi网络
                mConnectivityManager.bindProcessToNetwork(network);
            }

            @Override
            public void onLost(Network network) {
                mWiFiNetwork = null;
                mConnectivityManager.bindProcessToNetwork(null);
            }
        };

        mConnectivityManager.requestNetwork(request, callback);
    }
}

6.3 检查网络连接

public class NetworkUtils {
    public static boolean isNetworkAvailable(Context context) {
        ConnectivityManager cm = context.getSystemService(ConnectivityManager.class);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            Network network = cm.getActiveNetwork();
            if (network == null) return false;

            NetworkCapabilities caps = cm.getNetworkCapabilities(network);
            return caps != null &&
                   caps.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) &&
                   caps.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED);
        } else {
            NetworkInfo info = cm.getActiveNetworkInfo();
            return info != null && info.isConnected();
        }
    }

    public static boolean isWiFiConnected(Context context) {
        ConnectivityManager cm = context.getSystemService(ConnectivityManager.class);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            Network network = cm.getActiveNetwork();
            if (network == null) return false;

            NetworkCapabilities caps = cm.getNetworkCapabilities(network);
            return caps != null && caps.hasTransport(NetworkCapabilities.TRANSPORT_WIFI);
        } else {
            NetworkInfo info = cm.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
            return info != null && info.isConnected();
        }
    }
}

7. 性能优化

7.1 最佳实践

// ✅ 推荐:使用NetworkCallback监听(高效)
cm.registerNetworkCallback(request, callback);

// ❌ 避免:轮询检查网络状态(低效)
while (true) {
    boolean connected = isNetworkAvailable(context);
    Thread.sleep(1000);
}

// ✅ 推荐:检查网络验证状态
boolean validated = caps.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED);

// ✅ 推荐:使用WorkManager处理网络约束
Constraints constraints = new Constraints.Builder()
    .setRequiredNetworkType(NetworkType.CONNECTED)
    .build();

8. 总结

8.1 核心架构

ConnectivityService

NetworkAgent管理

NetworkFactory管理

网络请求匹配

网络评分选择

WiFi/Mobile/VPN Agent

创建网络连接

满足应用需求

选择最佳网络

8.2 关键要点

  1. NetworkAgent机制:各网络类型注册Agent,统一管理
  2. 网络评分:综合网络类型、信号强度、验证状态评分
  3. 网络请求:应用提出需求,系统匹配最佳网络
  4. 网络切换:自动选择最优网络,无缝切换
  5. 网络验证:HTTP探测确认Internet连接

ConnectivityService是Android网络管理的大脑,理解其原理对于开发网络相关应用至关重要。


参考资料

  • Android源码:frameworks/base/services/core/java/com/android/server/ConnectivityService.java
  • Android源码:frameworks/base/core/java/android/net/ConnectivityManager.java
  • Android官方文档:Connectivity Manager
Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐