OkHttp之AndroidPlatform类分析

7 阅读5分钟

OkHttp之AndroidPlatform类分析

一、AndroidPlatform 类设计

1. 概述

AndroidPlatform 是 OkHttp 针对 Android 5 到 9(API 21 到 28)平台的特定实现类。它继承自 Platform 类,同时实现 ContextAwarePlatform 接口,为 Android 平台提供定制化的网络连接、SSL 配置和证书管理等功能。

2. 关键属性

  • applicationContext:应用上下文,用于访问 Android 系统服务和资源,实现 ContextAwarePlatform 接口的属性。
  • socketAdapters:用于处理 SSLSocket 的适配器列表,包含多种不同的 SocketAdapter 实例,会根据设备支持情况进行初始化和过滤。

3. 关键方法

  • connectSocket:连接指定的 Socket 到目标地址,针对 Android 8.0(API 26)的特定 bug 进行异常处理。
  • newSSLContext:创建新的 SSLContext 实例,标记该操作是慢操作后调用父类方法。
  • trustManager:从 SSLSocketFactory 中获取 X509TrustManager 实例,遍历 socketAdapters 列表查找匹配适配器。
  • configureTlsExtensions:配置 SSLSocket 的 TLS 扩展,遍历 socketAdapters 列表查找匹配适配器进行配置。
  • getSelectedProtocol:获取 SSLSocket 协商选定的协议,遍历 socketAdapters 列表查找匹配适配器获取协议。
  • isCleartextTrafficPermitted:根据 Android 系统 API 版本判断是否允许明文流量。
  • buildCertificateChainCleaner:尝试使用 AndroidCertificateChainCleaner 构建证书链清理器,失败则调用父类方法。
  • buildTrustRootIndex:尝试通过反射调用 X509TrustManager 的方法构建信任根索引,失败则调用父类方法。

4. 类关系图

classDiagram
    Platform <|-- AndroidPlatform
    AndroidPlatform ..|> ContextAwarePlatform
    AndroidPlatform "1" *-- "n" SocketAdapter : uses
    AndroidPlatform ..> AndroidCertificateChainCleaner
    AndroidPlatform ..> NetworkSecurityPolicy
    AndroidPlatform ..> SSLContext
    AndroidPlatform ..> X509TrustManager
    AndroidPlatform ..> SSLSocketFactory
    AndroidPlatform ..> SSLSocket
    AndroidPlatform ..> Socket
    
    class Platform {
        <<abstract>>
        +newSSLContext()
        +buildCertificateChainCleaner()
        +buildTrustRootIndex()
        +trustManager()
        +configureTlsExtensions()
        +getSelectedProtocol()
        +isCleartextTrafficPermitted()
        +log()
    }
    
    class ContextAwarePlatform {
        <<interface>>
        +applicationContext: Context?
    }
    
    class AndroidPlatform {
        +applicationContext: Context?
        -socketAdapters: List<SocketAdapter>
        +connectSocket()
        +newSSLContext()
        +trustManager()
        +configureTlsExtensions()
        +getSelectedProtocol()
        +isCleartextTrafficPermitted()
        +buildCertificateChainCleaner()
        +buildTrustRootIndex()
        +getHandshakeServerNames()
        +log()
        +CustomTrustRootIndex
        +buildIfSupported()
    }
    
    class SocketAdapter {
        <<interface>>
        +isSupported()
        +trustManager(sslSocketFactory)
        +matchesSocket(sslSocket)
        +matchesSocketFactory(sslSocketFactory)
        +configureTlsExtensions(sslSocket, hostname, protocols)
        +getSelectedProtocol(sslSocket)
    }
    
    class AndroidCertificateChainCleaner {
        +buildIfSupported()
    }
    
    class NetworkSecurityPolicy {
        +getInstance()
        +isCleartextTrafficPermitted()
    }

5. 平台选择流程图

flowchart TD
    A[Platform.buildPlatform] --> B{平台类型?}
    B -->|JVM| C[JvmPlatformRegistry.findPlatform]
    B -->|Android| D[AndroidPlatformRegistry.findPlatform]

    C --> C1{Conscrypt可用?}
    C1 -->|是| C2[ConscryptPlatform]
    C1 -->|否| C3{OpenJSSE可用?}

    C3 -->|是| C4[OpenJSSEPlatform]
    C3 -->|否| C5{BouncyCastle可用?}

    C5 -->|是| C6[BouncyCastlePlatform]
    C5 -->|否| C7{JDK 9+或JDK 8 build 252+?}

    C7 -->|是| C8[Jdk9Platform]
    C7 -->|否| C9{JDK 8?}

    C9 -->|是| C10[Jdk8WithJettyBootPlatform]
    C9 -->|否| C11[默认Platform]

    D --> D1{Android 10+?}
    D1 -->|是| D2[Android10Platform]
    D1 -->|否| D3{Android 5 - 9?}

    D3 -->|是| D4[AndroidPlatform]
    D4 --> D41{ConscryptSocketAdapter支持?}
    D41 -->|是| D42[使用ConscryptSocketAdapter]
    D41 -->|否| D43{BouncyCastleSocketAdapter支持?}
    D43 -->|是| D44[使用BouncyCastleSocketAdapter]
    D43 -->|否| D45{AndroidSocketAdapter支持?}
    D45 -->|是| D46[使用AndroidSocketAdapter]
    D45 -->|否| D47[使用默认SocketAdapter处理]
    
    D3 -->|否| D5{API版本=0?}

    D5 -->|是| D6[Jdk9Platform或默认Platform]
    D5 -->|否| D7[抛出异常]

二、SocketAdapter 扩展设计

1. 概述

SocketAdapter 是一个接口,旨在为不同的 SSLSocket 实现提供适配能力。通过实现该接口,开发者能轻松添加新的 SSLSocket 适配逻辑,而不影响现有代码。

2. 关键方法

  • isSupported() :判断当前平台是否支持该 SocketAdapter 实现。
  • trustManager(sslSocketFactory) :从 SSLSocketFactory 中获取 X509TrustManager 实例,默认返回 null
  • matchesSocket(sslSocket) :判断给定的 SSLSocket 是否与当前 SocketAdapter 匹配。
  • matchesSocketFactory(sslSocketFactory) :判断给定的 SSLSocketFactory 是否与当前 SocketAdapter 匹配,默认返回 false
  • configureTlsExtensions(sslSocket, hostname, protocols) :配置 SSLSocket 的 TLS 扩展。
  • getSelectedProtocol(sslSocket) :获取 SSLSocket 协商选定的协议。

3. 常见实现类

  • AndroidSocketAdapter:基于现代反射的 Socket 适配器,适用于 Conscrypt 类的 SSLSocket
  • Android10SocketAdapter:适用于 Android Q(API 级别 29)及以上版本的简单非反射 Socket 适配器。
  • ConscryptSocketAdapter:当 Conscrypt 作为应用依赖直接引入时,使用的简单非反射 Socket 适配器。
  • BouncyCastleSocketAdapter:适用于 Bouncy Castle 的简单非反射 Socket 适配器。

三、SocketAdapter 泛化分析

1. 泛化概念

SocketAdapter 接口的设计具备良好的泛化能力,不同的实现类可根据具体的 SSLSocket 实现(如 Conscrypt、Bouncy Castle 等)提供适配逻辑。这种设计使得 SocketAdapter 能够灵活应对多种 SSLSocket 实现,降低了代码的耦合度,提高了可扩展性。

2. 泛化类关系图

classDiagram
    SocketAdapter <|-- AndroidSocketAdapter
    SocketAdapter <|-- Android10SocketAdapter
    SocketAdapter <|-- ConscryptSocketAdapter
    SocketAdapter <|-- BouncyCastleSocketAdapter
    SocketAdapter <|-- CustomSocketAdapter
    
    class SocketAdapter {
        <<interface>>
        +isSupported()
        +trustManager(sslSocketFactory)
        +matchesSocket(sslSocket)
        +matchesSocketFactory(sslSocketFactory)
        +configureTlsExtensions(sslSocket, hostname, protocols)
        +getSelectedProtocol(sslSocket)
    }
    
    class AndroidSocketAdapter {
        +isSupported()
        +trustManager(sslSocketFactory)
        +matchesSocket(sslSocket)
        +matchesSocketFactory(sslSocketFactory)
        +configureTlsExtensions(sslSocket, hostname, protocols)
        +getSelectedProtocol(sslSocket)
    }
    
    class Android10SocketAdapter {
        +isSupported()
        +trustManager(sslSocketFactory)
        +matchesSocket(sslSocket)
        +matchesSocketFactory(sslSocketFactory)
        +configureTlsExtensions(sslSocket, hostname, protocols)
        +getSelectedProtocol(sslSocket)
    }
    
    class ConscryptSocketAdapter {
        +isSupported()
        +trustManager(sslSocketFactory)
        +matchesSocket(sslSocket)
        +matchesSocketFactory(sslSocketFactory)
        +configureTlsExtensions(sslSocket, hostname, protocols)
        +getSelectedProtocol(sslSocket)
    }
    
    class BouncyCastleSocketAdapter {
        +isSupported()
        +trustManager(sslSocketFactory)
        +matchesSocket(sslSocket)
        +matchesSocketFactory(sslSocketFactory)
        +configureTlsExtensions(sslSocket, hostname, protocols)
        +getSelectedProtocol(sslSocket)
    }
    
    class CustomSocketAdapter {
        +isSupported()
        +trustManager(sslSocketFactory)
        +matchesSocket(sslSocket)
        +matchesSocketFactory(sslSocketFactory)
        +configureTlsExtensions(sslSocket, hostname, protocols)
        +getSelectedProtocol(sslSocket)
    }

从图中可以看出,SocketAdapter 作为接口,多个具体的适配器类实现了该接口。CustomSocketAdapter 表示开发者可以自定义的适配器类,体现了 SocketAdapter 接口的泛化能力,开发者能根据需求添加新的适配器实现。

四、AndroidPlatform 与 SocketAdapter 的关系

1. 依赖关系

AndroidPlatform 依赖 SocketAdapter 来处理 SSLSocket 相关操作。AndroidPlatform 持有一个 socketAdapters 列表,在进行 SSLSocket 相关操作时,会遍历该列表,找到匹配的 SocketAdapter 并调用其方法。

2. 协作流程

以 trustManager 方法为例
sequenceDiagram
    participant Client
    participant AndroidPlatform
    participant SocketAdapter
    
    Client->>AndroidPlatform: trustManager(sslSocketFactory)
    AndroidPlatform->>AndroidPlatform: Iterate socketAdapters
    loop For each SocketAdapter
        AndroidPlatform->>SocketAdapter: matchesSocketFactory(sslSocketFactory)
        alt Match found
            SocketAdapter-->>AndroidPlatform: true
            AndroidPlatform->>SocketAdapter: trustManager(sslSocketFactory)
            SocketAdapter-->>AndroidPlatform: X509TrustManager
            AndroidPlatform-->>Client: X509TrustManager
        else No match
            SocketAdapter-->>AndroidPlatform: false
        end
    end
    alt No match found
        AndroidPlatform-->>Client: null
    end
以 configureTlsExtensions 方法为例
sequenceDiagram
    participant Client
    participant AndroidPlatform
    participant SocketAdapter
    
    Client->>AndroidPlatform: configureTlsExtensions(sslSocket, hostname, protocols)
    AndroidPlatform->>AndroidPlatform: Iterate socketAdapters
    loop For each SocketAdapter
        AndroidPlatform->>SocketAdapter: matchesSocket(sslSocket)
        alt Match found
            SocketAdapter-->>AndroidPlatform: true
            AndroidPlatform->>SocketAdapter: configureTlsExtensions(sslSocket, hostname, protocols)
            SocketAdapter-->>AndroidPlatform: Operation completed
            AndroidPlatform-->>Client: Operation completed
        else No match
            SocketAdapter-->>AndroidPlatform: false
        end
    end
    alt No match found
        AndroidPlatform-->>Client: No suitable adapter found
    end

AndroidPlatform 通过 SocketAdapter 泛化最终实现了与 JVM 平台类似的降级策略,下面从多个方面详细分析:

降级策略概念

降级策略通常是指在系统运行过程中,当某些高级功能无法正常使用或者资源不足时,系统会自动切换到次优方案,以保证基本功能的正常运行。在网络通信场景中,可能表现为当无法使用最新的安全协议或加密算法时,退而使用较旧但仍可用的协议或算法。

AndroidPlatform 与 SocketAdapter 实现降级策略的方式

1. 多 SocketAdapter 实现

SocketAdapter 是一个接口,有多种实现类,如 AndroidSocketAdapterConscryptSocketAdapterBouncyCastleSocketAdapter 等。每个实现类对应不同的 SSLSocket 实现或不同的 Android 平台版本,这就为降级提供了多种备选方案。

classDiagram
    SocketAdapter <|-- AndroidSocketAdapter
    SocketAdapter <|-- ConscryptSocketAdapter
    SocketAdapter <|-- BouncyCastleSocketAdapter
    SocketAdapter <|-- Android10SocketAdapter

    class SocketAdapter {
        <<interface>>
        +isSupported()
        +trustManager(sslSocketFactory)
        +matchesSocket(sslSocket)
        +matchesSocketFactory(sslSocketFactory)
        +configureTlsExtensions(sslSocket, hostname, protocols)
        +getSelectedProtocol(sslSocket)
    }

2. 动态选择适配器

AndroidPlatform 持有一个 socketAdapters 列表,在进行 SSLSocket 相关操作时,会遍历该列表,依次调用每个 SocketAdapter 的 isSupported() 和 matchesSocket() 等方法,找到第一个匹配且支持的 SocketAdapter 来处理操作。如果当前的适配器不支持,就尝试下一个,直到找到合适的适配器或者遍历完所有适配器。

sequenceDiagram
    participant Client
    participant AndroidPlatform
    participant Adapter1
    participant Adapter2
    participant Adapter3

    Client->>AndroidPlatform: configureTlsExtensions(sslSocket, ...)
    AndroidPlatform->>Adapter1: isSupported()
    Adapter1-->>AndroidPlatform: false
    AndroidPlatform->>Adapter2: isSupported()
    Adapter2-->>AndroidPlatform: true
    AndroidPlatform->>Adapter2: matchesSocket(sslSocket)
    Adapter2-->>AndroidPlatform: true
    AndroidPlatform->>Adapter2: configureTlsExtensions(sslSocket, ...)
    Adapter2-->>AndroidPlatform: Success
    AndroidPlatform-->>Client: Success

3. 降级效果

当系统环境发生变化,比如 Android 版本升级、依赖库缺失等,导致某些 SocketAdapter 不再支持时,AndroidPlatform 会自动选择其他可用的 SocketAdapter,从而保证网络通信功能的正常运行。这与 JVM 平台的降级策略类似,JVM 平台在遇到安全协议不支持、证书验证失败等问题时,也会尝试使用其他方案来保证通信的基本功能。

与 JVM 平台降级策略的相似性

  • 多方案选择:JVM 平台也有多种安全协议、加密算法和网络库的实现可供选择。当首选方案不可用时,会尝试其他方案。例如,当 TLS 1.3 不可用时,会降级到 TLS 1.2。AndroidPlatform 同样通过 SocketAdapter 提供了多种适配方案,根据实际情况选择合适的适配器。
  • 自动降级:JVM 平台和 AndroidPlatform 都能自动检测环境变化,在发现当前方案不可行时,自动切换到备用方案,无需人工干预。

综上所述,AndroidPlatform 通过 SocketAdapter 泛化实现了与 JVM 平台类似的降级策略,提高了系统的健壮性和兼容性。

五、总结

AndroidPlatform 通过组合多个 SocketAdapter 实例,实现了对不同 SSLSocket 实现的灵活支持。SocketAdapter 接口的泛化设计使得新的 SSLSocket 适配逻辑可以方便地扩展,提高了代码的可维护性和可扩展性。这种设计模式符合开闭原则,对扩展开放,对修改关闭。开发者可以根据具体需求实现新的 SocketAdapter 类,以支持更多类型的 SSLSocket 实现。