Merge master@5406228 into qt-dev.
Change-Id: I3e6583f250f2eddba9c7c893acbfd0e3dd6c8d08 BUG: 129345239
This commit is contained in:
@@ -19,6 +19,7 @@ LOCAL_MODULE_TAGS := tests
|
||||
LOCAL_SDK_VERSION := current
|
||||
LOCAL_SRC_FILES := \
|
||||
com/android/cts/net/hostside/IMyService.aidl \
|
||||
com/android/cts/net/hostside/INetworkCallback.aidl \
|
||||
com/android/cts/net/hostside/INetworkStateObserver.aidl \
|
||||
com/android/cts/net/hostside/IRemoteSocketFactory.aidl
|
||||
LOCAL_MODULE := CtsHostsideNetworkTestsAidl
|
||||
|
||||
@@ -16,10 +16,13 @@
|
||||
|
||||
package com.android.cts.net.hostside;
|
||||
|
||||
import com.android.cts.net.hostside.INetworkCallback;
|
||||
|
||||
interface IMyService {
|
||||
void registerBroadcastReceiver();
|
||||
int getCounters(String receiverName, String action);
|
||||
String checkNetworkStatus();
|
||||
String getRestrictBackgroundStatus();
|
||||
void sendNotification(int notificationId, String notificationType);
|
||||
void registerNetworkCallback(in INetworkCallback cb);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright (C) 2019 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 com.android.cts.net.hostside;
|
||||
|
||||
import android.net.Network;
|
||||
|
||||
interface INetworkCallback {
|
||||
void onBlockedStatusChanged(in Network network, boolean blocked);
|
||||
void onAvailable(in Network network);
|
||||
void onLost(in Network network);
|
||||
}
|
||||
@@ -372,6 +372,23 @@ abstract class AbstractRestrictBackgroundNetworkTestCase extends Instrumentation
|
||||
fail("App2 is not on foreground service state after " + maxTries + " attempts: " + state );
|
||||
}
|
||||
|
||||
/**
|
||||
* As per CDD requirements, if the device doesn't support data saver mode then
|
||||
* ConnectivityManager.getRestrictBackgroundStatus() will always return
|
||||
* RESTRICT_BACKGROUND_STATUS_DISABLED. So, enable the data saver mode and check if
|
||||
* ConnectivityManager.getRestrictBackgroundStatus() for an app in background returns
|
||||
* RESTRICT_BACKGROUND_STATUS_DISABLED or not.
|
||||
*/
|
||||
protected boolean isDataSaverSupported() throws Exception {
|
||||
assertMyRestrictBackgroundStatus(RESTRICT_BACKGROUND_STATUS_DISABLED);
|
||||
try {
|
||||
setRestrictBackground(true);
|
||||
return !isMyRestrictBackgroundStatus(RESTRICT_BACKGROUND_STATUS_DISABLED);
|
||||
} finally {
|
||||
setRestrictBackground(false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether an app state should be considered "background" for restriction purposes.
|
||||
*/
|
||||
@@ -979,6 +996,10 @@ abstract class AbstractRestrictBackgroundNetworkTestCase extends Instrumentation
|
||||
fail("app2 receiver is not ready");
|
||||
}
|
||||
|
||||
protected void registerNetworkCallback(INetworkCallback cb) throws Exception {
|
||||
mServiceClient.registerNetworkCallback(cb);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a {@link NotificationListenerService} implementation that will execute the
|
||||
* notification actions right after the notification is sent.
|
||||
|
||||
@@ -73,23 +73,6 @@ public class DataSaverModeTest extends AbstractRestrictBackgroundNetworkTestCase
|
||||
return mIsDataSaverSupported && super.isSupported();
|
||||
}
|
||||
|
||||
/**
|
||||
* As per CDD requirements, if the device doesn't support data saver mode then
|
||||
* ConnectivityManager.getRestrictBackgroundStatus() will always return
|
||||
* RESTRICT_BACKGROUND_STATUS_DISABLED. So, enable the data saver mode and check if
|
||||
* ConnectivityManager.getRestrictBackgroundStatus() for an app in background returns
|
||||
* RESTRICT_BACKGROUND_STATUS_DISABLED or not.
|
||||
*/
|
||||
private boolean isDataSaverSupported() throws Exception {
|
||||
assertMyRestrictBackgroundStatus(RESTRICT_BACKGROUND_STATUS_DISABLED);
|
||||
try {
|
||||
setRestrictBackground(true);
|
||||
return !isMyRestrictBackgroundStatus(RESTRICT_BACKGROUND_STATUS_DISABLED);
|
||||
} finally {
|
||||
setRestrictBackground(false);
|
||||
}
|
||||
}
|
||||
|
||||
public void testGetRestrictBackgroundStatus_disabled() throws Exception {
|
||||
if (!isSupported()) return;
|
||||
|
||||
|
||||
@@ -26,8 +26,6 @@ import android.os.RemoteException;
|
||||
|
||||
import com.android.cts.net.hostside.IMyService;
|
||||
|
||||
import java.io.FileDescriptor;
|
||||
|
||||
public class MyServiceClient {
|
||||
private static final int TIMEOUT_MS = 5000;
|
||||
private static final String PACKAGE = MyServiceClient.class.getPackage().getName();
|
||||
@@ -98,4 +96,8 @@ public class MyServiceClient {
|
||||
public void sendNotification(int notificationId, String notificationType) throws RemoteException {
|
||||
mService.sendNotification(notificationId, notificationType);
|
||||
}
|
||||
|
||||
public void registerNetworkCallback(INetworkCallback cb) throws RemoteException {
|
||||
mService.registerNetworkCallback(cb);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,241 @@
|
||||
/*
|
||||
* Copyright (C) 2019 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 com.android.cts.net.hostside;
|
||||
|
||||
import android.net.Network;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class NetworkCallbackTest extends AbstractRestrictBackgroundNetworkTestCase {
|
||||
|
||||
private boolean mIsDataSaverSupported;
|
||||
private Network mNetwork;
|
||||
private final TestNetworkCallback mTestNetworkCallback = new TestNetworkCallback();
|
||||
|
||||
enum CallbackState {
|
||||
NONE,
|
||||
AVAILABLE,
|
||||
LOST,
|
||||
BLOCKED_STATUS
|
||||
}
|
||||
|
||||
private static class CallbackInfo {
|
||||
public final CallbackState state;
|
||||
public final Network network;
|
||||
public final Object arg;
|
||||
|
||||
CallbackInfo(CallbackState s, Network n, Object o) {
|
||||
state = s; network = n; arg = o;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return String.format("%s (%s) (%s)", state, network, arg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (!(o instanceof CallbackInfo)) return false;
|
||||
// Ignore timeMs, since it's unpredictable.
|
||||
final CallbackInfo other = (CallbackInfo) o;
|
||||
return (state == other.state) && Objects.equals(network, other.network)
|
||||
&& Objects.equals(arg, other.arg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(state, network, arg);
|
||||
}
|
||||
}
|
||||
|
||||
private class TestNetworkCallback extends INetworkCallback.Stub {
|
||||
private static final int TEST_CALLBACK_TIMEOUT_MS = 200;
|
||||
|
||||
private final LinkedBlockingQueue<CallbackInfo> mCallbacks = new LinkedBlockingQueue<>();
|
||||
|
||||
protected void setLastCallback(CallbackState state, Network network, Object o) {
|
||||
mCallbacks.offer(new CallbackInfo(state, network, o));
|
||||
}
|
||||
|
||||
CallbackInfo nextCallback(int timeoutMs) {
|
||||
CallbackInfo cb = null;
|
||||
try {
|
||||
cb = mCallbacks.poll(timeoutMs, TimeUnit.MILLISECONDS);
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
if (cb == null) {
|
||||
fail("Did not receive callback after " + timeoutMs + "ms");
|
||||
}
|
||||
return cb;
|
||||
}
|
||||
|
||||
CallbackInfo expectCallback(CallbackState state, Network expectedNetwork, Object o) {
|
||||
final CallbackInfo expected = new CallbackInfo(state, expectedNetwork, o);
|
||||
final CallbackInfo actual = nextCallback(TEST_CALLBACK_TIMEOUT_MS);
|
||||
assertEquals("Unexpected callback:", expected, actual);
|
||||
return actual;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAvailable(Network network) {
|
||||
setLastCallback(CallbackState.AVAILABLE, network, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLost(Network network) {
|
||||
setLastCallback(CallbackState.LOST, network, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBlockedStatusChanged(Network network, boolean blocked) {
|
||||
setLastCallback(CallbackState.BLOCKED_STATUS, network, blocked);
|
||||
}
|
||||
|
||||
public void expectLostCallback(Network expectedNetwork) {
|
||||
expectCallback(CallbackState.LOST, expectedNetwork, null);
|
||||
}
|
||||
|
||||
public void expectAvailableCallback(Network expectedNetwork) {
|
||||
expectCallback(CallbackState.AVAILABLE, expectedNetwork, null);
|
||||
}
|
||||
|
||||
public void expectBlockedStatusCallback(Network expectedNetwork, boolean expectBlocked) {
|
||||
expectCallback(CallbackState.BLOCKED_STATUS, expectedNetwork,
|
||||
expectBlocked);
|
||||
}
|
||||
|
||||
void assertNoCallback() {
|
||||
CallbackInfo cb = null;
|
||||
try {
|
||||
cb = mCallbacks.poll(TEST_CALLBACK_TIMEOUT_MS, TimeUnit.MILLISECONDS);
|
||||
} catch (InterruptedException e) {
|
||||
// Expected.
|
||||
}
|
||||
if (cb != null) {
|
||||
assertNull("Unexpected callback: " + cb, cb);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setUp() throws Exception {
|
||||
super.setUp();
|
||||
|
||||
mIsDataSaverSupported = isDataSaverSupported();
|
||||
|
||||
mNetwork = mCm.getActiveNetwork();
|
||||
|
||||
// Set initial state.
|
||||
setBatterySaverMode(false);
|
||||
registerBroadcastReceiver();
|
||||
|
||||
if (!mIsDataSaverSupported) return;
|
||||
setRestrictBackground(false);
|
||||
removeRestrictBackgroundWhitelist(mUid);
|
||||
removeRestrictBackgroundBlacklist(mUid);
|
||||
assertRestrictBackgroundChangedReceived(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void tearDown() throws Exception {
|
||||
super.tearDown();
|
||||
|
||||
if (!mIsDataSaverSupported) return;
|
||||
|
||||
try {
|
||||
resetMeteredNetwork();
|
||||
} finally {
|
||||
setRestrictBackground(false);
|
||||
}
|
||||
}
|
||||
|
||||
public void testOnBlockedStatusChanged_data_saver() throws Exception {
|
||||
if (!mIsDataSaverSupported) return;
|
||||
|
||||
// Prepare metered wifi
|
||||
if (!setMeteredNetwork()) return;
|
||||
|
||||
// Register callback
|
||||
registerNetworkCallback((INetworkCallback.Stub) mTestNetworkCallback);
|
||||
mTestNetworkCallback.expectAvailableCallback(mNetwork);
|
||||
mTestNetworkCallback.expectBlockedStatusCallback(mNetwork, false);
|
||||
|
||||
// Enable restrict background
|
||||
setRestrictBackground(true);
|
||||
assertBackgroundNetworkAccess(false);
|
||||
mTestNetworkCallback.expectBlockedStatusCallback(mNetwork, true);
|
||||
|
||||
// Add to whitelist
|
||||
addRestrictBackgroundWhitelist(mUid);
|
||||
assertBackgroundNetworkAccess(true);
|
||||
mTestNetworkCallback.expectBlockedStatusCallback(mNetwork, false);
|
||||
|
||||
// Remove from whitelist
|
||||
removeRestrictBackgroundWhitelist(mUid);
|
||||
assertBackgroundNetworkAccess(false);
|
||||
mTestNetworkCallback.expectBlockedStatusCallback(mNetwork, true);
|
||||
|
||||
// Set to non-metered network
|
||||
setUnmeteredNetwork();
|
||||
assertBackgroundNetworkAccess(true);
|
||||
mTestNetworkCallback.expectBlockedStatusCallback(mNetwork, false);
|
||||
|
||||
// Disable restrict background, should not trigger callback
|
||||
setRestrictBackground(false);
|
||||
assertBackgroundNetworkAccess(true);
|
||||
mTestNetworkCallback.assertNoCallback();
|
||||
}
|
||||
|
||||
|
||||
public void testOnBlockedStatusChanged_power_saver() throws Exception {
|
||||
// Prepare metered wifi
|
||||
if (!setMeteredNetwork()) return;
|
||||
|
||||
// Register callback
|
||||
registerNetworkCallback((INetworkCallback.Stub) mTestNetworkCallback);
|
||||
mTestNetworkCallback.expectAvailableCallback(mNetwork);
|
||||
mTestNetworkCallback.expectBlockedStatusCallback(mNetwork, false);
|
||||
|
||||
// Enable Power Saver
|
||||
setBatterySaverMode(true);
|
||||
assertBackgroundNetworkAccess(false);
|
||||
mTestNetworkCallback.expectBlockedStatusCallback(mNetwork, true);
|
||||
|
||||
// Disable Power Saver
|
||||
setBatterySaverMode(false);
|
||||
assertBackgroundNetworkAccess(true);
|
||||
mTestNetworkCallback.expectBlockedStatusCallback(mNetwork, false);
|
||||
|
||||
// Set to non-metered network
|
||||
setUnmeteredNetwork();
|
||||
mTestNetworkCallback.assertNoCallback();
|
||||
|
||||
// Enable Power Saver
|
||||
setBatterySaverMode(true);
|
||||
assertBackgroundNetworkAccess(false);
|
||||
mTestNetworkCallback.expectBlockedStatusCallback(mNetwork, true);
|
||||
|
||||
// Disable Power Saver
|
||||
setBatterySaverMode(false);
|
||||
assertBackgroundNetworkAccess(true);
|
||||
mTestNetworkCallback.expectBlockedStatusCallback(mNetwork, false);
|
||||
}
|
||||
|
||||
// TODO: 1. test against VPN lockdown.
|
||||
// 2. test against multiple networks.
|
||||
}
|
||||
@@ -16,6 +16,7 @@
|
||||
package com.android.cts.net.hostside.app2;
|
||||
|
||||
import static android.net.ConnectivityManager.ACTION_RESTRICT_BACKGROUND_CHANGED;
|
||||
|
||||
import static com.android.cts.net.hostside.app2.Common.ACTION_RECEIVER_READY;
|
||||
import static com.android.cts.net.hostside.app2.Common.DYNAMIC_RECEIVER;
|
||||
import static com.android.cts.net.hostside.app2.Common.TAG;
|
||||
@@ -26,13 +27,16 @@ import android.app.Service;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.SharedPreferences;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.net.Network;
|
||||
import android.net.NetworkCapabilities;
|
||||
import android.net.NetworkRequest;
|
||||
import android.os.IBinder;
|
||||
import android.os.Looper;
|
||||
import android.os.RemoteException;
|
||||
import android.util.Log;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.android.cts.net.hostside.IMyService;
|
||||
import com.android.cts.net.hostside.INetworkCallback;
|
||||
|
||||
/**
|
||||
* Service used to dynamically register a broadcast receiver.
|
||||
@@ -40,7 +44,10 @@ import com.android.cts.net.hostside.IMyService;
|
||||
public class MyService extends Service {
|
||||
private static final String NOTIFICATION_CHANNEL_ID = "MyService";
|
||||
|
||||
ConnectivityManager mCm;
|
||||
|
||||
private MyBroadcastReceiver mReceiver;
|
||||
private ConnectivityManager.NetworkCallback mNetworkCallback;
|
||||
|
||||
// TODO: move MyBroadcast static functions here - they were kept there to make git diff easier.
|
||||
|
||||
@@ -81,8 +88,67 @@ public class MyService extends Service {
|
||||
MyBroadcastReceiver .sendNotification(getApplicationContext(), NOTIFICATION_CHANNEL_ID,
|
||||
notificationId, notificationType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerNetworkCallback(INetworkCallback cb) {
|
||||
if (mNetworkCallback != null) {
|
||||
Log.d(TAG, "unregister previous network callback: " + mNetworkCallback);
|
||||
unregisterNetworkCallback();
|
||||
}
|
||||
Log.d(TAG, "registering network callback");
|
||||
|
||||
mNetworkCallback = new ConnectivityManager.NetworkCallback() {
|
||||
@Override
|
||||
public void onBlockedStatusChanged(Network network, boolean blocked) {
|
||||
try {
|
||||
cb.onBlockedStatusChanged(network, blocked);
|
||||
} catch (RemoteException e) {
|
||||
Log.d(TAG, "Cannot send onBlockedStatusChanged: " + e);
|
||||
unregisterNetworkCallback();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAvailable(Network network) {
|
||||
try {
|
||||
cb.onAvailable(network);
|
||||
} catch (RemoteException e) {
|
||||
Log.d(TAG, "Cannot send onAvailable: " + e);
|
||||
unregisterNetworkCallback();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLost(Network network) {
|
||||
try {
|
||||
cb.onLost(network);
|
||||
} catch (RemoteException e) {
|
||||
Log.d(TAG, "Cannot send onLost: " + e);
|
||||
unregisterNetworkCallback();
|
||||
}
|
||||
}
|
||||
};
|
||||
mCm.registerNetworkCallback(makeWifiNetworkRequest(), mNetworkCallback);
|
||||
try {
|
||||
cb.asBinder().linkToDeath(() -> unregisterNetworkCallback(), 0);
|
||||
} catch (RemoteException e) {
|
||||
unregisterNetworkCallback();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private void unregisterNetworkCallback() {
|
||||
Log.d(TAG, "unregistering network callback");
|
||||
mCm.unregisterNetworkCallback(mNetworkCallback);
|
||||
mNetworkCallback = null;
|
||||
}
|
||||
|
||||
private NetworkRequest makeWifiNetworkRequest() {
|
||||
return new NetworkRequest.Builder()
|
||||
.addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBinder onBind(Intent intent) {
|
||||
return mBinder;
|
||||
@@ -94,6 +160,8 @@ public class MyService extends Service {
|
||||
((NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE))
|
||||
.createNotificationChannel(new NotificationChannel(NOTIFICATION_CHANNEL_ID,
|
||||
NOTIFICATION_CHANNEL_ID, NotificationManager.IMPORTANCE_DEFAULT));
|
||||
mCm = (ConnectivityManager) getApplicationContext()
|
||||
.getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright (C) 2019 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 com.android.cts.net;
|
||||
public class HostsideNetworkCallbackTests extends HostsideNetworkTestCase {
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
uninstallPackage(TEST_APP2_PKG, false);
|
||||
installPackage(TEST_APP2_APK);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void tearDown() throws Exception {
|
||||
super.tearDown();
|
||||
uninstallPackage(TEST_APP2_PKG, true);
|
||||
}
|
||||
|
||||
public void testOnBlockedStatusChanged_data_saver() throws Exception {
|
||||
runDeviceTests(TEST_PKG,
|
||||
TEST_PKG + ".NetworkCallbackTest", "testOnBlockedStatusChanged_data_saver");
|
||||
}
|
||||
|
||||
public void testOnBlockedStatusChanged_power_saver() throws Exception {
|
||||
runDeviceTests(TEST_PKG,
|
||||
TEST_PKG + ".NetworkCallbackTest", "testOnBlockedStatusChanged_power_saver");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
<configuration description="Config for CTS Native Network dns test cases">
|
||||
<option name="test-suite-tag" value="cts" />
|
||||
<option name="config-descriptor:metadata" key="component" value="networking" />
|
||||
<option name="config-descriptor:metadata" key="parameter" value="instant_app" />
|
||||
<option name="config-descriptor:metadata" key="parameter" value="multi_abi" />
|
||||
<target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
|
||||
<option name="cleanup" value="true" />
|
||||
<option name="push" value="CtsNativeNetDnsTestCases->/data/local/tmp/CtsNativeNetDnsTestCases" />
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
<configuration description="Config for CTS Native Network xt_qtaguid test cases">
|
||||
<option name="test-suite-tag" value="cts" />
|
||||
<option name="config-descriptor:metadata" key="component" value="networking" />
|
||||
<option name="config-descriptor:metadata" key="parameter" value="instant_app" />
|
||||
<option name="config-descriptor:metadata" key="parameter" value="multi_abi" />
|
||||
<target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
|
||||
<option name="cleanup" value="true" />
|
||||
<option name="push" value="CtsNativeNetTestCases->/data/local/tmp/CtsNativeNetTestCases" />
|
||||
|
||||
@@ -17,9 +17,11 @@
|
||||
package android.net.cts;
|
||||
|
||||
import static android.net.DnsResolver.CLASS_IN;
|
||||
import static android.net.DnsResolver.FLAG_EMPTY;
|
||||
import static android.net.DnsResolver.FLAG_NO_CACHE_LOOKUP;
|
||||
import static android.net.DnsResolver.TYPE_A;
|
||||
import static android.net.DnsResolver.TYPE_AAAA;
|
||||
import static android.system.OsConstants.EBADF;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
@@ -30,6 +32,7 @@ import android.net.DnsResolver;
|
||||
import android.net.Network;
|
||||
import android.net.NetworkCapabilities;
|
||||
import android.net.ParseException;
|
||||
import android.os.CancellationSignal;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.system.ErrnoException;
|
||||
@@ -50,6 +53,7 @@ public class DnsResolverTest extends AndroidTestCase {
|
||||
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
|
||||
};
|
||||
static final int TIMEOUT_MS = 12_000;
|
||||
static final int CANCEL_RETRY_TIMES = 5;
|
||||
|
||||
private ConnectivityManager mCM;
|
||||
private Executor mExecutor;
|
||||
@@ -118,7 +122,7 @@ public class DnsResolverTest extends AndroidTestCase {
|
||||
}
|
||||
};
|
||||
mDns.query(network, dname, CLASS_IN, TYPE_A, FLAG_NO_CACHE_LOOKUP,
|
||||
mExecutor, callback);
|
||||
mExecutor, null, callback);
|
||||
try {
|
||||
assertTrue(msg + " but no valid answer after " + TIMEOUT_MS + "ms.",
|
||||
latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
|
||||
@@ -174,12 +178,19 @@ public class DnsResolverTest extends AndroidTestCase {
|
||||
class RawAnswerCallbackImpl extends DnsResolver.RawAnswerCallback {
|
||||
private final CountDownLatch mLatch = new CountDownLatch(1);
|
||||
private final String mMsg;
|
||||
RawAnswerCallbackImpl(String msg) {
|
||||
private final int mTimeout;
|
||||
|
||||
RawAnswerCallbackImpl(@NonNull String msg, int timeout) {
|
||||
this.mMsg = msg;
|
||||
this.mTimeout = timeout;
|
||||
}
|
||||
|
||||
RawAnswerCallbackImpl(@NonNull String msg) {
|
||||
this(msg, TIMEOUT_MS);
|
||||
}
|
||||
|
||||
public boolean waitForAnswer() throws InterruptedException {
|
||||
return mLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS);
|
||||
return mLatch.await(mTimeout, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -210,7 +221,7 @@ public class DnsResolverTest extends AndroidTestCase {
|
||||
for (Network network : getTestableNetworks()) {
|
||||
final RawAnswerCallbackImpl callback = new RawAnswerCallbackImpl(msg);
|
||||
mDns.query(network, dname, CLASS_IN, TYPE_AAAA, FLAG_NO_CACHE_LOOKUP,
|
||||
mExecutor, callback);
|
||||
mExecutor, null, callback);
|
||||
try {
|
||||
assertTrue(msg + " but no answer after " + TIMEOUT_MS + "ms.",
|
||||
callback.waitForAnswer());
|
||||
@@ -238,7 +249,7 @@ public class DnsResolverTest extends AndroidTestCase {
|
||||
final String msg = "Query with RawAnswerCallback " + byteArrayToHexString(blob);
|
||||
for (Network network : getTestableNetworks()) {
|
||||
final RawAnswerCallbackImpl callback = new RawAnswerCallbackImpl(msg);
|
||||
mDns.query(network, blob, FLAG_NO_CACHE_LOOKUP, mExecutor, callback);
|
||||
mDns.query(network, blob, FLAG_NO_CACHE_LOOKUP, mExecutor, null, callback);
|
||||
try {
|
||||
assertTrue(msg + " but no answer after " + TIMEOUT_MS + "ms.",
|
||||
callback.waitForAnswer());
|
||||
@@ -276,7 +287,7 @@ public class DnsResolverTest extends AndroidTestCase {
|
||||
}
|
||||
};
|
||||
mDns.query(network, dname, CLASS_IN, TYPE_AAAA, FLAG_NO_CACHE_LOOKUP,
|
||||
mExecutor, callback);
|
||||
mExecutor, null, callback);
|
||||
try {
|
||||
assertTrue(msg + "but no answer after " + TIMEOUT_MS + "ms.",
|
||||
latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
|
||||
@@ -313,7 +324,7 @@ public class DnsResolverTest extends AndroidTestCase {
|
||||
}
|
||||
};
|
||||
mDns.query(network, dname, CLASS_IN, TYPE_AAAA, FLAG_NO_CACHE_LOOKUP,
|
||||
mExecutor, callback);
|
||||
mExecutor, null, callback);
|
||||
try {
|
||||
assertTrue(msg + " but no answer after " + TIMEOUT_MS + "ms.",
|
||||
latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
|
||||
@@ -322,4 +333,141 @@ public class DnsResolverTest extends AndroidTestCase {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A query callback that ensures that the query is cancelled and that onAnswer is never
|
||||
* called. If the query succeeds before it is cancelled, needRetry will return true so the
|
||||
* test can retry.
|
||||
*/
|
||||
class VerifyCancelCallback extends DnsResolver.RawAnswerCallback {
|
||||
private static final int CANCEL_TIMEOUT = 3_000;
|
||||
|
||||
private final CountDownLatch mLatch = new CountDownLatch(1);
|
||||
private final String mMsg;
|
||||
private final CancellationSignal mCancelSignal;
|
||||
|
||||
VerifyCancelCallback(@NonNull String msg, @NonNull CancellationSignal cancelSignal) {
|
||||
this.mMsg = msg;
|
||||
this.mCancelSignal = cancelSignal;
|
||||
}
|
||||
|
||||
public boolean needRetry() throws InterruptedException {
|
||||
return mLatch.await(CANCEL_TIMEOUT, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnswer(@NonNull byte[] answer) {
|
||||
if (mCancelSignal.isCanceled()) {
|
||||
fail(mMsg + " should not have returned any answers");
|
||||
}
|
||||
mLatch.countDown();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onParseException(@NonNull ParseException e) {
|
||||
fail(mMsg + e.getMessage());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onQueryException(@NonNull ErrnoException e) {
|
||||
if (mCancelSignal.isCanceled() && e.errno == EBADF) return;
|
||||
fail(mMsg + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public void testQueryCancel() throws ErrnoException {
|
||||
final String dname = "www.google.com";
|
||||
final String msg = "Test cancel query " + dname;
|
||||
// Start a DNS query and the cancel it immediately. Use VerifyCancelCallback to expect
|
||||
// that the query is cancelled before it succeeds. If it is not cancelled before it
|
||||
// succeeds, retry the until it is.
|
||||
for (Network network : getTestableNetworks()) {
|
||||
boolean retry = false;
|
||||
int round = 0;
|
||||
do {
|
||||
if (++round > CANCEL_RETRY_TIMES) {
|
||||
fail(msg + " cancel failed " + CANCEL_RETRY_TIMES + " times");
|
||||
}
|
||||
final CountDownLatch latch = new CountDownLatch(1);
|
||||
final CancellationSignal cancelSignal = new CancellationSignal();
|
||||
final VerifyCancelCallback callback = new VerifyCancelCallback(msg, cancelSignal);
|
||||
mDns.query(network, dname, CLASS_IN, TYPE_AAAA, FLAG_EMPTY,
|
||||
mExecutor, cancelSignal, callback);
|
||||
mExecutor.execute(() -> {
|
||||
cancelSignal.cancel();
|
||||
latch.countDown();
|
||||
});
|
||||
try {
|
||||
retry = callback.needRetry();
|
||||
assertTrue(msg + " query was not cancelled",
|
||||
latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
|
||||
} catch (InterruptedException e) {
|
||||
fail(msg + "Waiting for DNS lookup was interrupted");
|
||||
}
|
||||
} while (retry);
|
||||
}
|
||||
}
|
||||
|
||||
public void testQueryBlobCancel() throws ErrnoException {
|
||||
final byte[] blob = new byte[]{
|
||||
/* Header */
|
||||
0x55, 0x66, /* Transaction ID */
|
||||
0x01, 0x00, /* Flags */
|
||||
0x00, 0x01, /* Questions */
|
||||
0x00, 0x00, /* Answer RRs */
|
||||
0x00, 0x00, /* Authority RRs */
|
||||
0x00, 0x00, /* Additional RRs */
|
||||
/* Queries */
|
||||
0x03, 0x77, 0x77, 0x77, 0x06, 0x67, 0x6F, 0x6F, 0x67, 0x6c, 0x65,
|
||||
0x03, 0x63, 0x6f, 0x6d, 0x00, /* Name */
|
||||
0x00, 0x01, /* Type */
|
||||
0x00, 0x01 /* Class */
|
||||
};
|
||||
final String msg = "Test cancel raw Query " + byteArrayToHexString(blob);
|
||||
// Start a DNS query and the cancel it immediately. Use VerifyCancelCallback to expect
|
||||
// that the query is cancelled before it succeeds. If it is not cancelled before it
|
||||
// succeeds, retry the until it is.
|
||||
for (Network network : getTestableNetworks()) {
|
||||
boolean retry = false;
|
||||
int round = 0;
|
||||
do {
|
||||
if (++round > CANCEL_RETRY_TIMES) {
|
||||
fail(msg + " cancel failed " + CANCEL_RETRY_TIMES + " times");
|
||||
}
|
||||
final CountDownLatch latch = new CountDownLatch(1);
|
||||
final CancellationSignal cancelSignal = new CancellationSignal();
|
||||
final VerifyCancelCallback callback = new VerifyCancelCallback(msg, cancelSignal);
|
||||
mDns.query(network, blob, FLAG_EMPTY, mExecutor, cancelSignal, callback);
|
||||
mExecutor.execute(() -> {
|
||||
cancelSignal.cancel();
|
||||
latch.countDown();
|
||||
});
|
||||
try {
|
||||
retry = callback.needRetry();
|
||||
assertTrue(msg + " cancel is not done",
|
||||
latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
|
||||
} catch (InterruptedException e) {
|
||||
fail(msg + " Waiting for DNS lookup was interrupted");
|
||||
}
|
||||
} while (retry);
|
||||
}
|
||||
}
|
||||
|
||||
public void testCancelBeforeQuery() throws ErrnoException {
|
||||
final String dname = "www.google.com";
|
||||
final String msg = "Test cancelled query " + dname;
|
||||
for (Network network : getTestableNetworks()) {
|
||||
final RawAnswerCallbackImpl callback = new RawAnswerCallbackImpl(msg, 3_000);
|
||||
final CancellationSignal cancelSignal = new CancellationSignal();
|
||||
cancelSignal.cancel();
|
||||
mDns.query(network, dname, CLASS_IN, TYPE_AAAA, FLAG_EMPTY,
|
||||
mExecutor, cancelSignal, callback);
|
||||
try {
|
||||
assertTrue(msg + " should not return any answers",
|
||||
!callback.waitForAnswer());
|
||||
} catch (InterruptedException e) {
|
||||
fail(msg + " Waiting for DNS lookup was interrupted");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -287,7 +287,7 @@ public class DnsTest extends AndroidTestCase {
|
||||
final NetworkCallback callback = new NetworkCallback() {
|
||||
@Override
|
||||
public void onLinkPropertiesChanged(Network network, LinkProperties lp) {
|
||||
if (lp.hasGlobalIPv6Address()) {
|
||||
if (lp.hasGlobalIpv6Address()) {
|
||||
latch.countDown();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,9 +21,9 @@ import android.net.wifi.WifiManager;
|
||||
import android.net.wifi.WifiManager.WifiLock;
|
||||
import android.test.AndroidTestCase;
|
||||
|
||||
public class WifiManager_WifiLockTest extends AndroidTestCase {
|
||||
public class WifiLockTest extends AndroidTestCase {
|
||||
|
||||
private static final String WIFI_TAG = "WifiManager_WifiLockTest";
|
||||
private static final String WIFI_TAG = "WifiLockTest";
|
||||
|
||||
/**
|
||||
* Verify acquire and release of High Performance wifi locks
|
||||
@@ -82,7 +82,7 @@ public class WifiManager_WifiLockTest extends AndroidTestCase {
|
||||
wl.release();
|
||||
assertFalse(wl.isHeld());
|
||||
assertNotNull(wl.toString());
|
||||
// should be ignored
|
||||
// releasing again after release: but ignored for non-referenced locks
|
||||
wl.release();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user