Snap for 6424828 from 6e56c29e8d8d4dc8780640d65d53c1ebf2ad441c to rvc-release

Change-Id: Ifa15d610637210d36e7b8c3a9f0d807ffc2fb201
This commit is contained in:
android-build-team Robot
2020-04-24 01:14:27 +00:00
8 changed files with 281 additions and 147 deletions

View File

@@ -16,6 +16,7 @@ cc_library_shared {
name: "libnativedns_jni",
srcs: ["NativeDnsJni.c"],
sdk_version: "current",
shared_libs: [
"libnativehelper_compat_libc++",
@@ -35,6 +36,7 @@ cc_library_shared {
name: "libnativemultinetwork_jni",
srcs: ["NativeMultinetworkJni.cpp"],
sdk_version: "current",
cflags: [
"-Wall",
"-Werror",

View File

@@ -19,7 +19,12 @@
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <utils/Log.h>
#include <android/log.h>
#define LOG_TAG "NativeDns-JNI"
#define LOGD(fmt, ...) \
__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, fmt, ##__VA_ARGS__)
const char *GoogleDNSIpV4Address="8.8.8.8";
const char *GoogleDNSIpV4Address2="8.8.4.4";
@@ -33,7 +38,7 @@ JNIEXPORT jboolean Java_android_net_cts_DnsTest_testNativeDns(JNIEnv* env, jclas
struct addrinfo *answer;
int res = getaddrinfo(node, service, NULL, &answer);
ALOGD("getaddrinfo(www.google.com) gave res=%d (%s)", res, gai_strerror(res));
LOGD("getaddrinfo(www.google.com) gave res=%d (%s)", res, gai_strerror(res));
if (res != 0) return JNI_FALSE;
// check for v4 & v6
@@ -47,12 +52,12 @@ JNIEXPORT jboolean Java_android_net_cts_DnsTest_testNativeDns(JNIEnv* env, jclas
inet_ntop(current->ai_family, &((struct sockaddr_in *)current->ai_addr)->sin_addr,
buf, sizeof(buf));
foundv4 = 1;
ALOGD(" %s", buf);
LOGD(" %s", buf);
} else if (current->ai_addr->sa_family == AF_INET6) {
inet_ntop(current->ai_family, &((struct sockaddr_in6 *)current->ai_addr)->sin6_addr,
buf, sizeof(buf));
foundv6 = 1;
ALOGD(" %s", buf);
LOGD(" %s", buf);
}
current = current->ai_next;
}
@@ -60,14 +65,14 @@ JNIEXPORT jboolean Java_android_net_cts_DnsTest_testNativeDns(JNIEnv* env, jclas
freeaddrinfo(answer);
answer = NULL;
if (foundv4 != 1 && foundv6 != 1) {
ALOGD("getaddrinfo(www.google.com) didn't find either v4 or v6 address");
LOGD("getaddrinfo(www.google.com) didn't find either v4 or v6 address");
return JNI_FALSE;
}
}
node = "ipv6.google.com";
res = getaddrinfo(node, service, NULL, &answer);
ALOGD("getaddrinfo(ipv6.google.com) gave res=%d", res);
LOGD("getaddrinfo(ipv6.google.com) gave res=%d", res);
if (res != 0) return JNI_FALSE;
{
@@ -79,12 +84,12 @@ JNIEXPORT jboolean Java_android_net_cts_DnsTest_testNativeDns(JNIEnv* env, jclas
if (current->ai_addr->sa_family == AF_INET) {
inet_ntop(current->ai_family, &((struct sockaddr_in *)current->ai_addr)->sin_addr,
buf, sizeof(buf));
ALOGD(" %s", buf);
LOGD(" %s", buf);
foundv4 = 1;
} else if (current->ai_addr->sa_family == AF_INET6) {
inet_ntop(current->ai_family, &((struct sockaddr_in6 *)current->ai_addr)->sin6_addr,
buf, sizeof(buf));
ALOGD(" %s", buf);
LOGD(" %s", buf);
foundv6 = 1;
}
current = current->ai_next;
@@ -93,7 +98,7 @@ JNIEXPORT jboolean Java_android_net_cts_DnsTest_testNativeDns(JNIEnv* env, jclas
freeaddrinfo(answer);
answer = NULL;
if (foundv4 == 1 || foundv6 != 1) {
ALOGD("getaddrinfo(ipv6.google.com) didn't find only v6");
LOGD("getaddrinfo(ipv6.google.com) didn't find only v6");
return JNI_FALSE;
}
}
@@ -116,12 +121,12 @@ JNIEXPORT jboolean Java_android_net_cts_DnsTest_testNativeDns(JNIEnv* env, jclas
res = getnameinfo((const struct sockaddr*)&sa4, sizeof(sa4), buf, sizeof(buf), NULL, 0, flags);
if (res != 0) {
ALOGD("getnameinfo(%s (GoogleDNS) ) gave error %d (%s)", GoogleDNSIpV4Address, res,
LOGD("getnameinfo(%s (GoogleDNS) ) gave error %d (%s)", GoogleDNSIpV4Address, res,
gai_strerror(res));
return JNI_FALSE;
}
if (strstr(buf, "google.com") == NULL && strstr(buf, "dns.google") == NULL) {
ALOGD("getnameinfo(%s (GoogleDNS) ) didn't return google.com or dns.google: %s",
LOGD("getnameinfo(%s (GoogleDNS) ) didn't return google.com or dns.google: %s",
GoogleDNSIpV4Address, buf);
return JNI_FALSE;
}
@@ -129,12 +134,12 @@ JNIEXPORT jboolean Java_android_net_cts_DnsTest_testNativeDns(JNIEnv* env, jclas
memset(buf, 0, sizeof(buf));
res = getnameinfo((const struct sockaddr*)&sa6, sizeof(sa6), buf, sizeof(buf), NULL, 0, flags);
if (res != 0) {
ALOGD("getnameinfo(%s (GoogleDNS) ) gave error %d (%s)", GoogleDNSIpV6Address2,
LOGD("getnameinfo(%s (GoogleDNS) ) gave error %d (%s)", GoogleDNSIpV6Address2,
res, gai_strerror(res));
return JNI_FALSE;
}
if (strstr(buf, "google.com") == NULL && strstr(buf, "dns.google") == NULL) {
ALOGD("getnameinfo(%s (GoogleDNS) ) didn't return google.com or dns.google: %s",
LOGD("getnameinfo(%s (GoogleDNS) ) didn't return google.com or dns.google: %s",
GoogleDNSIpV6Address2, buf);
return JNI_FALSE;
}
@@ -142,11 +147,11 @@ JNIEXPORT jboolean Java_android_net_cts_DnsTest_testNativeDns(JNIEnv* env, jclas
// gethostbyname
struct hostent *my_hostent = gethostbyname("www.youtube.com");
if (my_hostent == NULL) {
ALOGD("gethostbyname(www.youtube.com) gave null response");
LOGD("gethostbyname(www.youtube.com) gave null response");
return JNI_FALSE;
}
if ((my_hostent->h_addr_list == NULL) || (*my_hostent->h_addr_list == NULL)) {
ALOGD("gethostbyname(www.youtube.com) gave 0 addresses");
LOGD("gethostbyname(www.youtube.com) gave 0 addresses");
return JNI_FALSE;
}
{
@@ -154,7 +159,7 @@ JNIEXPORT jboolean Java_android_net_cts_DnsTest_testNativeDns(JNIEnv* env, jclas
while (*current != NULL) {
char buf[256];
inet_ntop(my_hostent->h_addrtype, *current, buf, sizeof(buf));
ALOGD("gethostbyname(www.youtube.com) gave %s", buf);
LOGD("gethostbyname(www.youtube.com) gave %s", buf);
current++;
}
}
@@ -164,11 +169,11 @@ JNIEXPORT jboolean Java_android_net_cts_DnsTest_testNativeDns(JNIEnv* env, jclas
inet_pton(AF_INET6, GoogleDNSIpV6Address, addr6);
my_hostent = gethostbyaddr(addr6, sizeof(addr6), AF_INET6);
if (my_hostent == NULL) {
ALOGD("gethostbyaddr(%s (GoogleDNS) ) gave null response", GoogleDNSIpV6Address);
LOGD("gethostbyaddr(%s (GoogleDNS) ) gave null response", GoogleDNSIpV6Address);
return JNI_FALSE;
}
ALOGD("gethostbyaddr(%s (GoogleDNS) ) gave %s for name", GoogleDNSIpV6Address,
LOGD("gethostbyaddr(%s (GoogleDNS) ) gave %s for name", GoogleDNSIpV6Address,
my_hostent->h_name ? my_hostent->h_name : "null");
if (my_hostent->h_name == NULL) return JNI_FALSE;

View File

@@ -16,7 +16,6 @@
#define LOG_TAG "MultinetworkApiTest"
#include <utils/Log.h>
#include <arpa/inet.h>
#include <arpa/nameser.h>
@@ -34,9 +33,13 @@
#include <string>
#include <android/log.h>
#include <android/multinetwork.h>
#include <nativehelper/JNIHelp.h>
#define LOGD(fmt, ...) \
__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, fmt, ##__VA_ARGS__)
#define EXPECT_GE(env, actual, expected, msg) \
do { \
if (actual < expected) { \
@@ -138,7 +141,7 @@ int expectAnswersNotValid(JNIEnv* env, int fd, int expectedErrno) {
uint8_t buf[MAXPACKET] = {};
int res = getAsyncResponse(env, fd, TIMEOUT_MS, &rcode, buf, MAXPACKET);
if (res != expectedErrno) {
ALOGD("res:%d, expectedErrno = %d", res, expectedErrno);
LOGD("res:%d, expectedErrno = %d", res, expectedErrno);
return (res > 0) ? -EREMOTEIO : res;
}
return 0;
@@ -326,7 +329,7 @@ JNIEXPORT jint Java_android_net_cts_MultinetworkApiTest_runGetaddrinfoCheck(
const int saved_errno = errno;
freeaddrinfo(res);
ALOGD("android_getaddrinfofornetwork(%" PRIu64 ", %s) returned rval=%d errno=%d",
LOGD("android_getaddrinfofornetwork(%" PRIu64 ", %s) returned rval=%d errno=%d",
handle, kHostname, rval, saved_errno);
return rval == 0 ? 0 : -saved_errno;
}
@@ -339,7 +342,7 @@ JNIEXPORT jint Java_android_net_cts_MultinetworkApiTest_runSetprocnetwork(
errno = 0;
int rval = android_setprocnetwork(handle);
const int saved_errno = errno;
ALOGD("android_setprocnetwork(%" PRIu64 ") returned rval=%d errno=%d",
LOGD("android_setprocnetwork(%" PRIu64 ") returned rval=%d errno=%d",
handle, rval, saved_errno);
return rval == 0 ? 0 : -saved_errno;
}
@@ -352,14 +355,14 @@ JNIEXPORT jint Java_android_net_cts_MultinetworkApiTest_runSetsocknetwork(
errno = 0;
int fd = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
if (fd < 0) {
ALOGD("socket() failed, errno=%d", errno);
LOGD("socket() failed, errno=%d", errno);
return -errno;
}
errno = 0;
int rval = android_setsocknetwork(handle, fd);
const int saved_errno = errno;
ALOGD("android_setprocnetwork(%" PRIu64 ", %d) returned rval=%d errno=%d",
LOGD("android_setprocnetwork(%" PRIu64 ", %d) returned rval=%d errno=%d",
handle, fd, rval, saved_errno);
close(fd);
return rval == 0 ? 0 : -saved_errno;
@@ -404,7 +407,7 @@ JNIEXPORT jint Java_android_net_cts_MultinetworkApiTest_runDatagramCheck(
static const char kPort[] = "443";
int rval = android_getaddrinfofornetwork(handle, kHostname, kPort, &kHints, &res);
if (rval != 0) {
ALOGD("android_getaddrinfofornetwork(%llu, %s) returned rval=%d errno=%d",
LOGD("android_getaddrinfofornetwork(%llu, %s) returned rval=%d errno=%d",
handle, kHostname, rval, errno);
freeaddrinfo(res);
return -errno;
@@ -413,14 +416,14 @@ JNIEXPORT jint Java_android_net_cts_MultinetworkApiTest_runDatagramCheck(
// Rely upon getaddrinfo sorting the best destination to the front.
int fd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
if (fd < 0) {
ALOGD("socket(%d, %d, %d) failed, errno=%d",
LOGD("socket(%d, %d, %d) failed, errno=%d",
res->ai_family, res->ai_socktype, res->ai_protocol, errno);
freeaddrinfo(res);
return -errno;
}
rval = android_setsocknetwork(handle, fd);
ALOGD("android_setprocnetwork(%llu, %d) returned rval=%d errno=%d",
LOGD("android_setprocnetwork(%llu, %d) returned rval=%d errno=%d",
handle, fd, rval, errno);
if (rval != 0) {
close(fd);
@@ -430,7 +433,7 @@ JNIEXPORT jint Java_android_net_cts_MultinetworkApiTest_runDatagramCheck(
char addrstr[kSockaddrStrLen+1];
sockaddr_ntop(res->ai_addr, res->ai_addrlen, addrstr, sizeof(addrstr));
ALOGD("Attempting connect() to %s ...", addrstr);
LOGD("Attempting connect() to %s ...", addrstr);
rval = connect(fd, res->ai_addr, res->ai_addrlen);
if (rval != 0) {
@@ -447,7 +450,7 @@ JNIEXPORT jint Java_android_net_cts_MultinetworkApiTest_runDatagramCheck(
return -errno;
}
sockaddr_ntop((const struct sockaddr *)&src_addr, sizeof(src_addr), addrstr, sizeof(addrstr));
ALOGD("... from %s", addrstr);
LOGD("... from %s", addrstr);
// Don't let reads or writes block indefinitely.
const struct timeval timeo = { 2, 0 }; // 2 seconds
@@ -479,7 +482,7 @@ JNIEXPORT jint Java_android_net_cts_MultinetworkApiTest_runDatagramCheck(
sent = send(fd, quic_packet, sizeof(quic_packet), 0);
if (sent < (ssize_t)sizeof(quic_packet)) {
errnum = errno;
ALOGD("send(QUIC packet) returned sent=%zd, errno=%d", sent, errnum);
LOGD("send(QUIC packet) returned sent=%zd, errno=%d", sent, errnum);
close(fd);
return -errnum;
}
@@ -489,14 +492,14 @@ JNIEXPORT jint Java_android_net_cts_MultinetworkApiTest_runDatagramCheck(
break;
} else {
errnum = errno;
ALOGD("[%d/%d] recv(QUIC response) returned rcvd=%zd, errno=%d",
LOGD("[%d/%d] recv(QUIC response) returned rcvd=%zd, errno=%d",
i + 1, MAX_RETRIES, rcvd, errnum);
}
}
if (rcvd < 9) {
ALOGD("QUIC UDP %s: sent=%zd but rcvd=%zd, errno=%d", kPort, sent, rcvd, errnum);
LOGD("QUIC UDP %s: sent=%zd but rcvd=%zd, errno=%d", kPort, sent, rcvd, errnum);
if (rcvd <= 0) {
ALOGD("Does this network block UDP port %s?", kPort);
LOGD("Does this network block UDP port %s?", kPort);
}
close(fd);
return -EPROTO;
@@ -504,7 +507,7 @@ JNIEXPORT jint Java_android_net_cts_MultinetworkApiTest_runDatagramCheck(
int conn_id_cmp = memcmp(quic_packet + 1, response + 1, 8);
if (conn_id_cmp != 0) {
ALOGD("sent and received connection IDs do not match");
LOGD("sent and received connection IDs do not match");
close(fd);
return -EPROTO;
}

View File

@@ -18,15 +18,17 @@ package android.net.cts;
import static android.net.ConnectivityDiagnosticsManager.ConnectivityDiagnosticsCallback;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.fail;
import android.content.Context;
import android.net.ConnectivityDiagnosticsManager;
import android.net.NetworkRequest;
import android.os.Build;
import androidx.test.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo;
import com.android.testutils.DevSdkIgnoreRunner;
import org.junit.Before;
import org.junit.Test;
@@ -34,7 +36,8 @@ import org.junit.runner.RunWith;
import java.util.concurrent.Executor;
@RunWith(AndroidJUnit4.class)
@RunWith(DevSdkIgnoreRunner.class)
@IgnoreUpTo(Build.VERSION_CODES.Q) // ConnectivityDiagnosticsManager did not exist in Q
public class ConnectivityDiagnosticsManagerTest {
private static final Executor INLINE_EXECUTOR = x -> x.run();
private static final NetworkRequest DEFAULT_REQUEST = new NetworkRequest.Builder().build();

View File

@@ -180,7 +180,7 @@ class NetworkAgentTest {
}
private open class TestableNetworkAgent(
val looper: Looper,
looper: Looper,
val nc: NetworkCapabilities,
val lp: LinkProperties,
conf: NetworkAgentConfig

View File

@@ -29,9 +29,11 @@ import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import android.net.MacAddress;
import android.net.MatchAllNetworkSpecifier;
import android.net.NetworkCapabilities;
import android.net.NetworkRequest;
import android.net.NetworkSpecifier;
import android.net.TelephonyNetworkSpecifier;
import android.net.wifi.WifiNetworkSpecifier;
import android.os.Build;
import android.os.Process;
@@ -127,39 +129,54 @@ public class NetworkRequestTest {
@Test
@IgnoreUpTo(Build.VERSION_CODES.Q)
public void testCanBeSatisfiedBy() {
final WifiNetworkSpecifier specifier1 = new WifiNetworkSpecifier.Builder()
.setSsidPattern(new PatternMatcher(TEST_SSID, PatternMatcher.PATTERN_LITERAL))
.setBssidPattern(ARBITRARY_ADDRESS, ARBITRARY_ADDRESS)
final TelephonyNetworkSpecifier specifier1 = new TelephonyNetworkSpecifier.Builder()
.setSubscriptionId(1234 /* subId */)
.build();
final WifiNetworkSpecifier specifier2 = new WifiNetworkSpecifier.Builder()
.setSsidPattern(new PatternMatcher(OTHER_SSID, PatternMatcher.PATTERN_LITERAL))
.setBssidPattern(ARBITRARY_ADDRESS, ARBITRARY_ADDRESS)
final TelephonyNetworkSpecifier specifier2 = new TelephonyNetworkSpecifier.Builder()
.setSubscriptionId(5678 /* subId */)
.build();
final NetworkCapabilities cap = new NetworkCapabilities()
.addTransportType(TRANSPORT_WIFI)
.addCapability(NET_CAPABILITY_INTERNET);
final NetworkCapabilities capWithSp =
new NetworkCapabilities(cap).setNetworkSpecifier(specifier1);
final NetworkCapabilities cellCap = new NetworkCapabilities()
.addTransportType(TRANSPORT_CELLULAR)
.addCapability(NET_CAPABILITY_MMS)
.addCapability(NET_CAPABILITY_INTERNET);
final NetworkRequest request = new NetworkRequest.Builder()
.addTransportType(TRANSPORT_WIFI)
final NetworkCapabilities capDualTransport = new NetworkCapabilities(cap)
.addTransportType(TRANSPORT_VPN);
final NetworkCapabilities capWithSpecifier1 =
new NetworkCapabilities(cap).setNetworkSpecifier(specifier1);
final NetworkCapabilities capDiffTransportWithSpecifier1 = new NetworkCapabilities()
.addCapability(NET_CAPABILITY_INTERNET)
.addTransportType(TRANSPORT_VPN)
.setNetworkSpecifier(specifier1);
final NetworkRequest requestWithSpecifier1 = new NetworkRequest.Builder()
.addTransportType(TRANSPORT_CELLULAR)
.addCapability(NET_CAPABILITY_INTERNET)
.setNetworkSpecifier(specifier1)
.build();
assertFalse(request.canBeSatisfiedBy(null));
assertFalse(request.canBeSatisfiedBy(new NetworkCapabilities()));
assertTrue(request.canBeSatisfiedBy(cap));
assertTrue(request.canBeSatisfiedBy(
new NetworkCapabilities(cap).addTransportType(TRANSPORT_VPN)));
assertTrue(request.canBeSatisfiedBy(capWithSp));
assertFalse(request.canBeSatisfiedBy(
assertFalse(requestWithSpecifier1.canBeSatisfiedBy(null));
assertFalse(requestWithSpecifier1.canBeSatisfiedBy(new NetworkCapabilities()));
assertTrue(requestWithSpecifier1.canBeSatisfiedBy(new NetworkCapabilities(cap)
.setNetworkSpecifier(new MatchAllNetworkSpecifier())));
assertTrue(requestWithSpecifier1.canBeSatisfiedBy(cap));
assertTrue(requestWithSpecifier1.canBeSatisfiedBy(capWithSpecifier1));
assertTrue(requestWithSpecifier1.canBeSatisfiedBy(capDualTransport));
assertFalse(requestWithSpecifier1.canBeSatisfiedBy(
new NetworkCapabilities(cap).setNetworkSpecifier(specifier2)));
assertFalse(request.canBeSatisfiedBy(cellCap));
assertEquals(request.canBeSatisfiedBy(capWithSp),
new NetworkCapabilities(capWithSp).satisfiedByNetworkCapabilities(capWithSp));
final NetworkRequest request = new NetworkRequest.Builder()
.addTransportType(TRANSPORT_CELLULAR)
.addCapability(NET_CAPABILITY_INTERNET)
.build();
assertTrue(request.canBeSatisfiedBy(cap));
assertTrue(request.canBeSatisfiedBy(capWithSpecifier1));
assertTrue(request.canBeSatisfiedBy(
new NetworkCapabilities(cap).setNetworkSpecifier(specifier2)));
assertFalse(request.canBeSatisfiedBy(capDiffTransportWithSpecifier1));
assertTrue(request.canBeSatisfiedBy(capDualTransport));
assertEquals(requestWithSpecifier1.canBeSatisfiedBy(capWithSpecifier1),
new NetworkCapabilities(capWithSpecifier1)
.satisfiedByNetworkCapabilities(capWithSpecifier1));
}
@Test @IgnoreUpTo(Build.VERSION_CODES.Q)

View File

@@ -25,8 +25,10 @@ android_test {
],
static_libs: [
"TetheringCommonTests",
"TetheringIntegrationTestsLib",
"compatibility-device-util-axt",
"net-tests-utils",
"ctstestrunner-axt",
"junit",
"junit-params",

View File

@@ -15,20 +15,24 @@
*/
package android.tethering.test;
import static android.net.TetheringManager.TETHER_HARDWARE_OFFLOAD_FAILED;
import static android.net.TetheringManager.TETHER_HARDWARE_OFFLOAD_STARTED;
import static android.net.TetheringManager.TETHER_HARDWARE_OFFLOAD_STOPPED;
import static android.net.TetheringManager.TETHERING_USB;
import static android.net.TetheringManager.TETHERING_WIFI;
import static android.net.TetheringManager.TETHERING_WIFI_P2P;
import static android.net.TetheringManager.TETHER_ERROR_ENTITLEMENT_UNKNOWN;
import static android.net.TetheringManager.TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION;
import static android.net.TetheringManager.TETHER_ERROR_NO_ERROR;
import static android.net.TetheringManager.TETHER_HARDWARE_OFFLOAD_FAILED;
import static android.net.TetheringManager.TETHER_HARDWARE_OFFLOAD_STARTED;
import static android.net.TetheringManager.TETHER_HARDWARE_OFFLOAD_STOPPED;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import android.app.UiAutomation;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -48,6 +52,8 @@ import androidx.annotation.NonNull;
import androidx.test.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
import com.android.testutils.ArrayTrackRecord;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@@ -77,11 +83,21 @@ public class TetheringManagerTest {
private static final int DEFAULT_TIMEOUT_MS = 60_000;
private void adoptShellPermissionIdentity() {
final UiAutomation uiAutomation =
InstrumentationRegistry.getInstrumentation().getUiAutomation();
uiAutomation.adoptShellPermissionIdentity();
}
private void dropShellPermissionIdentity() {
final UiAutomation uiAutomation =
InstrumentationRegistry.getInstrumentation().getUiAutomation();
uiAutomation.dropShellPermissionIdentity();
}
@Before
public void setUp() throws Exception {
InstrumentationRegistry.getInstrumentation()
.getUiAutomation()
.adoptShellPermissionIdentity();
adoptShellPermissionIdentity();
mContext = InstrumentationRegistry.getContext();
mTM = (TetheringManager) mContext.getSystemService(Context.TETHERING_SERVICE);
mTetherChangeReceiver = new TetherChangeReceiver();
@@ -93,10 +109,9 @@ public class TetheringManagerTest {
@After
public void tearDown() throws Exception {
mTM.stopAllTethering();
mContext.unregisterReceiver(mTetherChangeReceiver);
InstrumentationRegistry.getInstrumentation()
.getUiAutomation()
.dropShellPermissionIdentity();
dropShellPermissionIdentity();
}
private class TetherChangeReceiver extends BroadcastReceiver {
@@ -202,15 +217,54 @@ public class TetheringManagerTest {
}
}
private class StartTetheringCallback implements TetheringManager.StartTetheringCallback {
private static class StartTetheringCallback implements TetheringManager.StartTetheringCallback {
private static int TIMEOUT_MS = 30_000;
public static class CallbackValue {
public final int error;
private CallbackValue(final int e) {
error = e;
}
public static class OnTetheringStarted extends CallbackValue {
OnTetheringStarted() { super(TETHER_ERROR_NO_ERROR); }
}
public static class OnTetheringFailed extends CallbackValue {
OnTetheringFailed(final int error) { super(error); }
}
@Override
public String toString() {
return String.format("%s(%d)", getClass().getSimpleName(), error);
}
}
private final ArrayTrackRecord<CallbackValue>.ReadHead mHistory =
new ArrayTrackRecord<CallbackValue>().newReadHead();
@Override
public void onTetheringStarted() {
// Do nothing, TetherChangeReceiver will wait until it receives the broadcast.
mHistory.add(new CallbackValue.OnTetheringStarted());
}
@Override
public void onTetheringFailed(final int error) {
fail("startTethering fail: " + error);
mHistory.add(new CallbackValue.OnTetheringFailed(error));
}
public void verifyTetheringStarted() {
final CallbackValue cv = mHistory.poll(TIMEOUT_MS, c -> true);
assertNotNull("No onTetheringStarted after " + TIMEOUT_MS + " ms", cv);
assertTrue("Fail start tethering:" + cv,
cv instanceof CallbackValue.OnTetheringStarted);
}
public void expectTetheringFailed(final int expected) throws InterruptedException {
final CallbackValue cv = mHistory.poll(TIMEOUT_MS, c -> true);
assertNotNull("No onTetheringFailed after " + TIMEOUT_MS + " ms", cv);
assertTrue("Expect fail with error code " + expected + ", but received: " + cv,
(cv instanceof CallbackValue.OnTetheringFailed) && (cv.error == expected));
}
}
@@ -244,8 +298,10 @@ public class TetheringManagerTest {
mTetherChangeReceiver.expectNoActiveTethering(0 /** timeout */);
final StartTetheringCallback startTetheringCallback = new StartTetheringCallback();
mTM.startTethering(new TetheringRequest.Builder(TETHERING_WIFI).build(), c -> c.run(),
startTetheringCallback);
mTM.startTethering(new TetheringRequest.Builder(TETHERING_WIFI).build(),
c -> c.run() /* executor */, startTetheringCallback);
startTetheringCallback.verifyTetheringStarted();
mTetherChangeReceiver.expectActiveTethering(wifiRegexs);
mTM.stopTethering(TETHERING_WIFI);
@@ -277,6 +333,7 @@ public class TetheringManagerTest {
// Must poll the callback before looking at the member.
private static class TestTetheringEventCallback implements TetheringEventCallback {
private static final int TIMEOUT_MS = 30_000;
public enum CallbackType {
ON_SUPPORTED,
ON_UPSTREAM,
@@ -299,7 +356,10 @@ public class TetheringManagerTest {
this.callbackParam2 = param2;
}
}
private final LinkedBlockingQueue<CallbackValue> mCallbacks = new LinkedBlockingQueue<>();
private final ArrayTrackRecord<CallbackValue>.ReadHead mHistory =
new ArrayTrackRecord<CallbackValue>().newReadHead();
private TetheringInterfaceRegexps mTetherableRegex;
private List<String> mTetherableIfaces;
@@ -307,108 +367,96 @@ public class TetheringManagerTest {
@Override
public void onTetheringSupported(boolean supported) {
mCallbacks.add(new CallbackValue(CallbackType.ON_SUPPORTED, null, 0));
mHistory.add(new CallbackValue(CallbackType.ON_SUPPORTED, null, 0));
}
@Override
public void onUpstreamChanged(Network network) {
mCallbacks.add(new CallbackValue(CallbackType.ON_UPSTREAM, network, 0));
mHistory.add(new CallbackValue(CallbackType.ON_UPSTREAM, network, 0));
}
@Override
public void onTetherableInterfaceRegexpsChanged(TetheringInterfaceRegexps reg) {
mTetherableRegex = reg;
mCallbacks.add(new CallbackValue(CallbackType.ON_TETHERABLE_REGEX, reg, 0));
mHistory.add(new CallbackValue(CallbackType.ON_TETHERABLE_REGEX, reg, 0));
}
@Override
public void onTetherableInterfacesChanged(List<String> interfaces) {
mTetherableIfaces = interfaces;
mCallbacks.add(new CallbackValue(CallbackType.ON_TETHERABLE_IFACES, interfaces, 0));
mHistory.add(new CallbackValue(CallbackType.ON_TETHERABLE_IFACES, interfaces, 0));
}
@Override
public void onTetheredInterfacesChanged(List<String> interfaces) {
mTetheredIfaces = interfaces;
mCallbacks.add(new CallbackValue(CallbackType.ON_TETHERED_IFACES, interfaces, 0));
mHistory.add(new CallbackValue(CallbackType.ON_TETHERED_IFACES, interfaces, 0));
}
@Override
public void onError(String ifName, int error) {
mCallbacks.add(new CallbackValue(CallbackType.ON_ERROR, ifName, error));
mHistory.add(new CallbackValue(CallbackType.ON_ERROR, ifName, error));
}
@Override
public void onClientsChanged(Collection<TetheredClient> clients) {
mCallbacks.add(new CallbackValue(CallbackType.ON_CLIENTS, clients, 0));
mHistory.add(new CallbackValue(CallbackType.ON_CLIENTS, clients, 0));
}
@Override
public void onOffloadStatusChanged(int status) {
mCallbacks.add(new CallbackValue(CallbackType.ON_OFFLOAD_STATUS, status, 0));
}
public CallbackValue pollCallback() {
try {
return mCallbacks.poll(DEFAULT_TIMEOUT_MS, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
fail("Callback not seen");
}
return null;
mHistory.add(new CallbackValue(CallbackType.ON_OFFLOAD_STATUS, status, 0));
}
public void expectTetherableInterfacesChanged(@NonNull List<String> regexs) {
while (true) {
final CallbackValue cv = pollCallback();
if (cv == null) fail("No expected tetherable ifaces callback");
if (cv.callbackType != CallbackType.ON_TETHERABLE_IFACES) continue;
final List<String> interfaces = (List<String>) cv.callbackParam;
if (isIfaceMatch(regexs, interfaces)) break;
}
assertNotNull("No expected tetherable ifaces callback", mHistory.poll(TIMEOUT_MS,
(cv) -> {
if (cv.callbackType != CallbackType.ON_TETHERABLE_IFACES) return false;
final List<String> interfaces = (List<String>) cv.callbackParam;
return isIfaceMatch(regexs, interfaces);
}));
}
public void expectTetheredInterfacesChanged(@NonNull List<String> regexs) {
while (true) {
final CallbackValue cv = pollCallback();
if (cv == null) fail("No expected tethered ifaces callback");
if (cv.callbackType != CallbackType.ON_TETHERED_IFACES) continue;
assertNotNull("No expected tethered ifaces callback", mHistory.poll(TIMEOUT_MS,
(cv) -> {
if (cv.callbackType != CallbackType.ON_TETHERED_IFACES) return false;
final List<String> interfaces = (List<String>) cv.callbackParam;
final List<String> interfaces = (List<String>) cv.callbackParam;
// Null regexs means no active tethering.
if (regexs == null) {
if (interfaces.size() == 0) break;
} else if (isIfaceMatch(regexs, interfaces)) {
break;
}
}
// Null regexs means no active tethering.
if (regexs == null) return interfaces.isEmpty();
return isIfaceMatch(regexs, interfaces);
}));
}
public void expectCallbackStarted() {
int receivedBitMap = 0;
// The each bit represent a type from CallbackType.ON_*.
// Expect all of callbacks except for ON_ERROR.
final int expectedBitMap = 0x7f ^ (1 << CallbackType.ON_ERROR.ordinal());
int receivedBitMap = 0;
while (receivedBitMap != expectedBitMap) {
final CallbackValue cv = pollCallback();
final int expectedBitMap = 0xff ^ (1 << CallbackType.ON_ERROR.ordinal());
// Receive ON_ERROR on started callback is not matter. It just means tethering is
// failed last time, should able to continue the test this time.
while ((receivedBitMap & expectedBitMap) != expectedBitMap) {
final CallbackValue cv = mHistory.poll(TIMEOUT_MS, c -> true);
if (cv == null) {
fail("No expected callbacks, " + "expected bitmap: "
+ expectedBitMap + ", actual: " + receivedBitMap);
}
receivedBitMap = receivedBitMap | (1 << cv.callbackType.ordinal());
receivedBitMap |= (1 << cv.callbackType.ordinal());
}
}
public void expectOneOfOffloadStatusChanged(int... offloadStatuses) {
while (true) {
final CallbackValue cv = pollCallback();
if (cv == null) fail("No expected offload status change callback");
if (cv.callbackType != CallbackType.ON_OFFLOAD_STATUS) continue;
assertNotNull("No offload status changed", mHistory.poll(TIMEOUT_MS, (cv) -> {
if (cv.callbackType != CallbackType.ON_OFFLOAD_STATUS) return false;
final int status = (int) cv.callbackParam;
for (int offloadStatus : offloadStatuses) if (offloadStatus == status) return;
}
for (int offloadStatus : offloadStatuses) if (offloadStatus == status) return true;
return false;
}));
}
public TetheringInterfaceRegexps getTetheringInterfaceRegexps() {
@@ -424,52 +472,78 @@ public class TetheringManagerTest {
}
}
@Test
public void testRegisterTetheringEventCallback() throws Exception {
if (!mTM.isTetheringSupported()) return;
private TestTetheringEventCallback registerTetheringEventCallback() {
final TestTetheringEventCallback tetherEventCallback = new TestTetheringEventCallback();
mTM.registerTetheringEventCallback(c -> c.run(), tetherEventCallback);
mTM.registerTetheringEventCallback(c -> c.run() /* executor */, tetherEventCallback);
tetherEventCallback.expectCallbackStarted();
tetherEventCallback.expectOneOfOffloadStatusChanged(TETHER_HARDWARE_OFFLOAD_STOPPED);
final TetheringInterfaceRegexps tetherableRegexs =
tetherEventCallback.getTetheringInterfaceRegexps();
final List<String> wifiRegexs = tetherableRegexs.getTetherableWifiRegexs();
if (wifiRegexs.size() == 0) return;
return tetherEventCallback;
}
private void unregisterTetheringEventCallback(final TestTetheringEventCallback callback) {
mTM.unregisterTetheringEventCallback(callback);
}
private List<String> getWifiTetherableInterfaceRegexps(
final TestTetheringEventCallback callback) {
return callback.getTetheringInterfaceRegexps().getTetherableWifiRegexs();
}
private boolean isWifiTetheringSupported(final TestTetheringEventCallback callback) {
return !getWifiTetherableInterfaceRegexps(callback).isEmpty();
}
private void startWifiTethering(final TestTetheringEventCallback callback)
throws InterruptedException {
final List<String> wifiRegexs = getWifiTetherableInterfaceRegexps(callback);
final boolean isIfaceAvailWhenNoTethering =
isIfaceMatch(wifiRegexs, tetherEventCallback.getTetherableInterfaces());
isIfaceMatch(wifiRegexs, callback.getTetherableInterfaces());
mTM.startTethering(new TetheringRequest.Builder(TETHERING_WIFI).build(), c -> c.run(),
new StartTetheringCallback());
final StartTetheringCallback startTetheringCallback = new StartTetheringCallback();
mTM.startTethering(new TetheringRequest.Builder(TETHERING_WIFI).build(),
c -> c.run() /* executor */, startTetheringCallback);
startTetheringCallback.verifyTetheringStarted();
// If interface is already available before starting tethering, the available callback may
// not be sent after tethering enabled.
if (!isIfaceAvailWhenNoTethering) {
tetherEventCallback.expectTetherableInterfacesChanged(wifiRegexs);
callback.expectTetherableInterfacesChanged(wifiRegexs);
}
tetherEventCallback.expectTetheredInterfacesChanged(wifiRegexs);
tetherEventCallback.expectOneOfOffloadStatusChanged(
callback.expectTetheredInterfacesChanged(wifiRegexs);
callback.expectOneOfOffloadStatusChanged(
TETHER_HARDWARE_OFFLOAD_STARTED,
TETHER_HARDWARE_OFFLOAD_FAILED);
}
private void stopWifiTethering(final TestTetheringEventCallback callback) {
mTM.stopTethering(TETHERING_WIFI);
callback.expectTetheredInterfacesChanged(null);
callback.expectOneOfOffloadStatusChanged(TETHER_HARDWARE_OFFLOAD_STOPPED);
}
tetherEventCallback.expectTetheredInterfacesChanged(null);
tetherEventCallback.expectOneOfOffloadStatusChanged(TETHER_HARDWARE_OFFLOAD_STOPPED);
mTM.unregisterTetheringEventCallback(tetherEventCallback);
@Test
public void testRegisterTetheringEventCallback() throws Exception {
if (!mTM.isTetheringSupported()) return;
final TestTetheringEventCallback tetherEventCallback = registerTetheringEventCallback();
if (!isWifiTetheringSupported(tetherEventCallback)) return;
startWifiTethering(tetherEventCallback);
stopWifiTethering(tetherEventCallback);
unregisterTetheringEventCallback(tetherEventCallback);
}
@Test
public void testGetTetherableInterfaceRegexps() {
if (!mTM.isTetheringSupported()) return;
final TestTetheringEventCallback tetherEventCallback = new TestTetheringEventCallback();
mTM.registerTetheringEventCallback(c -> c.run(), tetherEventCallback);
tetherEventCallback.expectCallbackStarted();
final TestTetheringEventCallback tetherEventCallback = registerTetheringEventCallback();
final TetheringInterfaceRegexps tetherableRegexs =
tetherEventCallback.getTetheringInterfaceRegexps();
@@ -486,7 +560,35 @@ public class TetheringManagerTest {
wifiRegexs.forEach(s -> assertFalse(btRegexs.contains(s)));
usbRegexs.forEach(s -> assertFalse(btRegexs.contains(s)));
mTM.unregisterTetheringEventCallback(tetherEventCallback);
unregisterTetheringEventCallback(tetherEventCallback);
}
@Test
public void testStopAllTethering() throws Exception {
if (!mTM.isTetheringSupported()) return;
final TestTetheringEventCallback tetherEventCallback = registerTetheringEventCallback();
if (!isWifiTetheringSupported(tetherEventCallback)) return;
// TODO: start ethernet tethering here when TetheringManagerTest is moved to
// TetheringIntegrationTest.
startWifiTethering(tetherEventCallback);
mTM.stopAllTethering();
tetherEventCallback.expectTetheredInterfacesChanged(null);
unregisterTetheringEventCallback(tetherEventCallback);
}
@Test
public void testEnableTetheringPermission() throws Exception {
dropShellPermissionIdentity();
final StartTetheringCallback startTetheringCallback = new StartTetheringCallback();
mTM.startTethering(new TetheringRequest.Builder(TETHERING_WIFI).build(),
c -> c.run() /* executor */, startTetheringCallback);
startTetheringCallback.expectTetheringFailed(TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION);
}
private class EntitlementResultListener implements OnTetheringEntitlementResultListener {