This contains a squash of two changes
>>>>>>>>>>>>>>>>>>>>>>
aosp/1284588
Adjust permission of NetworkProvider related API
- Allow an app holds NETWORK_SETTINGS to acess registerNetworkProvier()
and unregisterNetworkProvider().
- To access declareNetworkRequestUnfulfillable(), allow an app holds
MANAGE_TEST_NETWORKS to declare a unfulfillable request that contains
TRANSPORT_TEST transport.
This makes easier to write cts to test.
>>>>>>>>>>>>>>>>>>>>>>
aosp/1285957
Add cts test for NetworkProvider
It will skip whole tests on Q device since NetworkProvider class
is introduced in R.
Result on Q device would be:
[1/1] android.net.NetworkProviderTest#skippedClassForDevSdkMismatch: IGNORED (3ms)
>>>>>>>>>>>>>>>>>>>>>>
Bug: 153614605
Bug: 153613690
Bug: 153612373
Test: atest FrameworksNetTests
atest CtsNetTestCases:android.net.NetworkProviderTest
Test: atest CtsNetTestCasesLatestSdk:android.net.NetworkProviderTest
Change-Id: Ib6f42b8f0e94e8c2715a030587e065864edff25b
Merged-In: Ic9809e731aa811a51c2f82d189372169d99a5ed9
Merged-In: If7bfc7fae503e3497c37754697d0b148ff4cab3b
(cherry picked from commit 10138d42a8f3892fcdb129a39409efe42873f6fe)
This commit is contained in:
@@ -2093,6 +2093,20 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||||||
NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK);
|
NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void enforceNetworkFactoryOrSettingsPermission() {
|
||||||
|
enforceAnyPermissionOf(
|
||||||
|
android.Manifest.permission.NETWORK_SETTINGS,
|
||||||
|
android.Manifest.permission.NETWORK_FACTORY,
|
||||||
|
NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void enforceNetworkFactoryOrTestNetworksPermission() {
|
||||||
|
enforceAnyPermissionOf(
|
||||||
|
android.Manifest.permission.MANAGE_TEST_NETWORKS,
|
||||||
|
android.Manifest.permission.NETWORK_FACTORY,
|
||||||
|
NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK);
|
||||||
|
}
|
||||||
|
|
||||||
private boolean checkSettingsPermission() {
|
private boolean checkSettingsPermission() {
|
||||||
return checkAnyPermissionOf(
|
return checkAnyPermissionOf(
|
||||||
android.Manifest.permission.NETWORK_SETTINGS,
|
android.Manifest.permission.NETWORK_SETTINGS,
|
||||||
@@ -5683,7 +5697,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int registerNetworkProvider(Messenger messenger, String name) {
|
public int registerNetworkProvider(Messenger messenger, String name) {
|
||||||
enforceNetworkFactoryPermission();
|
enforceNetworkFactoryOrSettingsPermission();
|
||||||
NetworkProviderInfo npi = new NetworkProviderInfo(name, messenger,
|
NetworkProviderInfo npi = new NetworkProviderInfo(name, messenger,
|
||||||
null /* asyncChannel */, nextNetworkProviderId(),
|
null /* asyncChannel */, nextNetworkProviderId(),
|
||||||
() -> unregisterNetworkProvider(messenger));
|
() -> unregisterNetworkProvider(messenger));
|
||||||
@@ -5693,7 +5707,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void unregisterNetworkProvider(Messenger messenger) {
|
public void unregisterNetworkProvider(Messenger messenger) {
|
||||||
enforceNetworkFactoryPermission();
|
enforceNetworkFactoryOrSettingsPermission();
|
||||||
mHandler.sendMessage(mHandler.obtainMessage(EVENT_UNREGISTER_NETWORK_PROVIDER, messenger));
|
mHandler.sendMessage(mHandler.obtainMessage(EVENT_UNREGISTER_NETWORK_PROVIDER, messenger));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5713,7 +5727,11 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void declareNetworkRequestUnfulfillable(NetworkRequest request) {
|
public void declareNetworkRequestUnfulfillable(NetworkRequest request) {
|
||||||
enforceNetworkFactoryPermission();
|
if (request.hasTransport(TRANSPORT_TEST)) {
|
||||||
|
enforceNetworkFactoryOrTestNetworksPermission();
|
||||||
|
} else {
|
||||||
|
enforceNetworkFactoryPermission();
|
||||||
|
}
|
||||||
mHandler.post(() -> handleReleaseNetworkRequest(request, Binder.getCallingUid(), true));
|
mHandler.post(() -> handleReleaseNetworkRequest(request, Binder.getCallingUid(), true));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
158
tests/net/common/java/android/net/NetworkProviderTest.kt
Normal file
158
tests/net/common/java/android/net/NetworkProviderTest.kt
Normal file
@@ -0,0 +1,158 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2020 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package android.net
|
||||||
|
|
||||||
|
import android.app.Instrumentation
|
||||||
|
import android.content.Context
|
||||||
|
import android.net.NetworkCapabilities.TRANSPORT_TEST
|
||||||
|
import android.os.Build
|
||||||
|
import android.os.HandlerThread
|
||||||
|
import android.os.Looper
|
||||||
|
import android.net.NetworkProviderTest.TestNetworkCallback.CallbackEntry.OnUnavailable
|
||||||
|
import android.net.NetworkProviderTest.TestNetworkProvider.CallbackEntry.OnNetworkRequested
|
||||||
|
import android.net.NetworkProviderTest.TestNetworkProvider.CallbackEntry.OnNetworkRequestWithdrawn
|
||||||
|
import androidx.test.InstrumentationRegistry
|
||||||
|
import com.android.testutils.ArrayTrackRecord
|
||||||
|
import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo
|
||||||
|
import com.android.testutils.DevSdkIgnoreRunner
|
||||||
|
import java.util.UUID
|
||||||
|
import kotlin.test.assertEquals
|
||||||
|
import kotlin.test.assertNotEquals
|
||||||
|
import org.junit.After
|
||||||
|
import org.junit.Before
|
||||||
|
import org.junit.Test
|
||||||
|
import org.junit.runner.RunWith
|
||||||
|
|
||||||
|
private const val DEFAULT_TIMEOUT_MS = 5000L
|
||||||
|
private val instrumentation: Instrumentation
|
||||||
|
get() = InstrumentationRegistry.getInstrumentation()
|
||||||
|
private val context: Context get() = InstrumentationRegistry.getContext()
|
||||||
|
private val PROVIDER_NAME = "NetworkProviderTest"
|
||||||
|
|
||||||
|
@RunWith(DevSdkIgnoreRunner::class)
|
||||||
|
@IgnoreUpTo(Build.VERSION_CODES.Q)
|
||||||
|
class NetworkProviderTest {
|
||||||
|
private val mCm = context.getSystemService(ConnectivityManager::class.java)
|
||||||
|
private val mHandlerThread = HandlerThread("${javaClass.simpleName} handler thread")
|
||||||
|
|
||||||
|
@Before
|
||||||
|
fun setUp() {
|
||||||
|
instrumentation.getUiAutomation().adoptShellPermissionIdentity()
|
||||||
|
mHandlerThread.start()
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
fun tearDown() {
|
||||||
|
mHandlerThread.quitSafely()
|
||||||
|
instrumentation.getUiAutomation().dropShellPermissionIdentity()
|
||||||
|
}
|
||||||
|
|
||||||
|
private class TestNetworkProvider(context: Context, looper: Looper) :
|
||||||
|
NetworkProvider(context, looper, PROVIDER_NAME) {
|
||||||
|
private val seenEvents = ArrayTrackRecord<CallbackEntry>().newReadHead()
|
||||||
|
|
||||||
|
sealed class CallbackEntry {
|
||||||
|
data class OnNetworkRequested(
|
||||||
|
val request: NetworkRequest,
|
||||||
|
val score: Int,
|
||||||
|
val id: Int
|
||||||
|
) : CallbackEntry()
|
||||||
|
data class OnNetworkRequestWithdrawn(val request: NetworkRequest) : CallbackEntry()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onNetworkRequested(request: NetworkRequest, score: Int, id: Int) {
|
||||||
|
seenEvents.add(OnNetworkRequested(request, score, id))
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onNetworkRequestWithdrawn(request: NetworkRequest) {
|
||||||
|
seenEvents.add(OnNetworkRequestWithdrawn(request))
|
||||||
|
}
|
||||||
|
|
||||||
|
inline fun <reified T : CallbackEntry> expectCallback(
|
||||||
|
crossinline predicate: (T) -> Boolean
|
||||||
|
) = seenEvents.poll(DEFAULT_TIMEOUT_MS) { it is T && predicate(it) }
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createNetworkProvider(): TestNetworkProvider {
|
||||||
|
return TestNetworkProvider(context, mHandlerThread.looper)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testOnNetworkRequested() {
|
||||||
|
val provider = createNetworkProvider()
|
||||||
|
assertEquals(provider.getProviderId(), NetworkProvider.ID_NONE)
|
||||||
|
mCm.registerNetworkProvider(provider)
|
||||||
|
assertNotEquals(provider.getProviderId(), NetworkProvider.ID_NONE)
|
||||||
|
|
||||||
|
val specifier = StringNetworkSpecifier(UUID.randomUUID().toString())
|
||||||
|
val nr: NetworkRequest = NetworkRequest.Builder()
|
||||||
|
.addTransportType(TRANSPORT_TEST)
|
||||||
|
.setNetworkSpecifier(specifier)
|
||||||
|
.build()
|
||||||
|
val cb = ConnectivityManager.NetworkCallback()
|
||||||
|
mCm.requestNetwork(nr, cb)
|
||||||
|
provider.expectCallback<OnNetworkRequested>() {
|
||||||
|
callback -> callback.request.getNetworkSpecifier() == specifier &&
|
||||||
|
callback.request.hasTransport(TRANSPORT_TEST)
|
||||||
|
}
|
||||||
|
|
||||||
|
mCm.unregisterNetworkCallback(cb)
|
||||||
|
provider.expectCallback<OnNetworkRequestWithdrawn>() {
|
||||||
|
callback -> callback.request.getNetworkSpecifier() == specifier &&
|
||||||
|
callback.request.hasTransport(TRANSPORT_TEST)
|
||||||
|
}
|
||||||
|
mCm.unregisterNetworkProvider(provider)
|
||||||
|
// Provider id should be ID_NONE after unregister network provider
|
||||||
|
assertEquals(provider.getProviderId(), NetworkProvider.ID_NONE)
|
||||||
|
// unregisterNetworkProvider should not crash even if it's called on an
|
||||||
|
// already unregistered provider.
|
||||||
|
mCm.unregisterNetworkProvider(provider)
|
||||||
|
}
|
||||||
|
|
||||||
|
private class TestNetworkCallback : ConnectivityManager.NetworkCallback() {
|
||||||
|
private val seenEvents = ArrayTrackRecord<CallbackEntry>().newReadHead()
|
||||||
|
sealed class CallbackEntry {
|
||||||
|
object OnUnavailable : CallbackEntry()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onUnavailable() {
|
||||||
|
seenEvents.add(OnUnavailable)
|
||||||
|
}
|
||||||
|
|
||||||
|
inline fun <reified T : CallbackEntry> expectCallback(
|
||||||
|
crossinline predicate: (T) -> Boolean
|
||||||
|
) = seenEvents.poll(DEFAULT_TIMEOUT_MS) { it is T && predicate(it) }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testDeclareNetworkRequestUnfulfillable() {
|
||||||
|
val provider = createNetworkProvider()
|
||||||
|
mCm.registerNetworkProvider(provider)
|
||||||
|
|
||||||
|
val specifier = StringNetworkSpecifier(UUID.randomUUID().toString())
|
||||||
|
val nr: NetworkRequest = NetworkRequest.Builder()
|
||||||
|
.addTransportType(TRANSPORT_TEST)
|
||||||
|
.setNetworkSpecifier(specifier)
|
||||||
|
.build()
|
||||||
|
|
||||||
|
val cb = TestNetworkCallback()
|
||||||
|
mCm.requestNetwork(nr, cb)
|
||||||
|
provider.declareNetworkRequestUnfulfillable(nr)
|
||||||
|
cb.expectCallback<OnUnavailable>() { nr.getNetworkSpecifier() == specifier }
|
||||||
|
mCm.unregisterNetworkProvider(provider)
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user