• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2024 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.server
18 
19 import android.Manifest.permission.NETWORK_STACK
20 import android.content.Intent
21 import android.content.pm.PackageManager.PERMISSION_DENIED
22 import android.content.pm.PackageManager.PERMISSION_GRANTED
23 import android.net.CaptivePortal
24 import android.net.ConnectivityManager.ACTION_CAPTIVE_PORTAL_SIGN_IN
25 import android.net.ConnectivityManager.EXTRA_CAPTIVE_PORTAL
26 import android.net.IpPrefix
27 import android.net.LinkAddress
28 import android.net.LinkProperties
29 import android.net.NetworkCapabilities
30 import android.net.NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL
31 import android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET
32 import android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED
33 import android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING
34 import android.net.NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED
35 import android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED
36 import android.net.NetworkCapabilities.TRANSPORT_WIFI
37 import android.net.NetworkRequest
38 import android.net.NetworkScore
39 import android.net.NetworkScore.KEEP_CONNECTED_FOR_TEST
40 import android.net.NetworkStack
41 import android.net.RouteInfo
42 import android.os.Build
43 import android.os.Bundle
44 import androidx.test.filters.SmallTest
45 import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo
46 import com.android.testutils.DevSdkIgnoreRunner
47 import com.android.testutils.TestableNetworkCallback
48 import kotlin.test.assertEquals
49 import org.junit.Test
50 import org.junit.runner.RunWith
51 import org.mockito.ArgumentMatchers.anyInt
52 import org.mockito.Mockito.never
53 import org.mockito.Mockito.verify
54 
55 // This allows keeping all the networks connected without having to file individual requests
56 // for them.
keepScorenull57 private fun keepScore() = FromS(
58         NetworkScore.Builder().setKeepConnectedReason(KEEP_CONNECTED_FOR_TEST).build()
59 )
60 
61 private fun nc(transport: Int, vararg caps: Int) = NetworkCapabilities.Builder().apply {
62     addTransportType(transport)
63     caps.forEach {
64         addCapability(it)
65     }
66     // Useful capabilities for everybody
67     addCapability(NET_CAPABILITY_NOT_RESTRICTED)
68     addCapability(NET_CAPABILITY_NOT_SUSPENDED)
69     addCapability(NET_CAPABILITY_NOT_ROAMING)
70     addCapability(NET_CAPABILITY_NOT_VCN_MANAGED)
71 }.build()
72 
<lambda>null73 private fun lp(iface: String) = LinkProperties().apply {
74     interfaceName = iface
75     addLinkAddress(LinkAddress(LOCAL_IPV4_ADDRESS, 32))
76     addRoute(RouteInfo(IpPrefix("0.0.0.0/0"), null, null))
77 }
78 
79 @DevSdkIgnoreRunner.MonitorThreadLeak
80 @RunWith(DevSdkIgnoreRunner::class)
81 @SmallTest
82 @IgnoreUpTo(Build.VERSION_CODES.R)
83 class CSCaptivePortalAppTest : CSTest() {
84     private val WIFI_IFACE = "wifi0"
85     private val TEST_REDIRECT_URL = "http://example.com/firstPath"
86     private val TIMEOUT_MS = 2_000L
87 
88     @Test
testCaptivePortalApp_Reevaluate_Nopermissionnull89     fun testCaptivePortalApp_Reevaluate_Nopermission() {
90         val captivePortalCallback = TestableNetworkCallback()
91         val captivePortalRequest = NetworkRequest.Builder()
92                 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build()
93         cm.registerNetworkCallback(captivePortalRequest, captivePortalCallback)
94         val wifiAgent = createWifiAgent()
95         wifiAgent.connectWithCaptivePortal(TEST_REDIRECT_URL)
96         captivePortalCallback.expectAvailableCallbacksUnvalidated(wifiAgent)
97         val signInIntent = startCaptivePortalApp(wifiAgent)
98         // Remove the granted permissions
99         context.setPermission(
100             NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
101                 PERMISSION_DENIED
102         )
103         context.setPermission(NETWORK_STACK, PERMISSION_DENIED)
104         val captivePortal: CaptivePortal? = signInIntent.getParcelableExtra(EXTRA_CAPTIVE_PORTAL)
105         captivePortal?.reevaluateNetwork()
106         verify(wifiAgent.networkMonitor, never()).forceReevaluation(anyInt())
107     }
108 
createWifiAgentnull109     private fun createWifiAgent(): CSAgentWrapper {
110         return Agent(
111             score = keepScore(),
112             lp = lp(WIFI_IFACE),
113                 nc = nc(TRANSPORT_WIFI, NET_CAPABILITY_INTERNET)
114         )
115     }
116 
startCaptivePortalAppnull117     private fun startCaptivePortalApp(networkAgent: CSAgentWrapper): Intent {
118         val network = networkAgent.network
119         cm.startCaptivePortalApp(network)
120         waitForIdle()
121         verify(networkAgent.networkMonitor).launchCaptivePortalApp()
122 
123         val testBundle = Bundle()
124         val testKey = "testkey"
125         val testValue = "testvalue"
126         testBundle.putString(testKey, testValue)
127         context.setPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, PERMISSION_GRANTED)
128         cm.startCaptivePortalApp(network, testBundle)
129         val signInIntent: Intent = context.expectStartActivityIntent(TIMEOUT_MS)
130         assertEquals(ACTION_CAPTIVE_PORTAL_SIGN_IN, signInIntent.getAction())
131         assertEquals(testValue, signInIntent.getStringExtra(testKey))
132         return signInIntent
133     }
134 }
135