summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2023-01-15 21:44:56 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2023-01-15 21:44:56 +0000
commit8e11ea226c6d3e3a92da7e2cde11e33868ebf0b7 (patch)
tree1fba5a35f2903295820aba0acfc40f9bed358ca5
parenta86947bd57dde335601337b066de5b3942db5a30 (diff)
parent33375336400cc9d5262a8a9be512dc90f4ec9f7c (diff)
downloadcts-sparse-9492874-L70600000958413829.tar.gz
Merge "Snap for 9491998 from b02bdb209055b85ab3c85b0a485f683e9efc10f5 to android13-tests-release" into android13-tests-releasesparse-9492874-L70600000958413829
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioTap2ToneActivity.java56
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsTestActivity.java2
-rw-r--r--hostsidetests/hdmicec/src/android/hdmicec/cts/HdmiCecClientWrapper.java12
-rw-r--r--hostsidetests/hdmicec/src/android/hdmicec/cts/common/HdmiCecGeneralProtocolTest.java38
-rw-r--r--hostsidetests/media/Android.bp5
-rw-r--r--hostsidetests/media/app/MediaMetricsTest/Android.bp1
-rw-r--r--hostsidetests/media/app/MediaMetricsTest/src/android/media/metrics/cts/MediaMetricsAtomHostSideTests.java26
-rw-r--r--hostsidetests/media/src/android/media/metrics/cts/MediaMetricsAtomTests.java214
-rw-r--r--tests/JobScheduler/src/android/jobscheduler/cts/ConnectivityConstraintTest.java326
-rw-r--r--tests/JobScheduler/src/android/jobscheduler/cts/JobThrottlingTest.java186
-rw-r--r--tests/JobScheduler/src/android/jobscheduler/cts/NetworkingHelper.java432
-rw-r--r--tests/mediapc/common/Android.bp5
-rw-r--r--tests/mediapc/common/src/android/mediapc/cts/common/PerformanceClassEvaluator.java105
-rw-r--r--tests/mediapc/common/src/android/mediapc/cts/common/RequiredMeasurement.java5
-rw-r--r--tests/mediapc/common/src/android/mediapc/cts/common/Requirement.java10
-rw-r--r--tests/mediapc/common/src/android/mediapc/cts/common/RequirementConstants.java1
-rw-r--r--tests/mediapc/common/tests/src/android/mediapc/cts/common/RequirementTest.java5
-rwxr-xr-xtests/tests/permission3/src/android/permission3/cts/BaseUsePermissionTest.kt4
18 files changed, 827 insertions, 606 deletions
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioTap2ToneActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioTap2ToneActivity.java
index 8ff23588889..cf09a74e062 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioTap2ToneActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioTap2ToneActivity.java
@@ -16,6 +16,11 @@
package com.android.cts.verifier.audio;
+import static com.android.cts.verifier.TestListActivity.sCurrentDisplayMode;
+import static com.android.cts.verifier.TestListAdapter.setTestNameSuffix;
+
+import android.mediapc.cts.common.PerformanceClassEvaluator;
+
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
@@ -46,6 +51,7 @@ import org.hyphonate.megaaudio.player.JavaSourceProxy;
import org.hyphonate.megaaudio.recorder.AudioSinkProvider;
import org.hyphonate.megaaudio.recorder.sinks.AppCallback;
import org.hyphonate.megaaudio.recorder.sinks.AppCallbackAudioSinkProvider;
+import org.junit.rules.TestName;
/**
* CtsVerifier test to measure tap-to-tone latency.
@@ -144,6 +150,8 @@ public class AudioTap2ToneActivity
private static final String KEY_LATENCY_AVE = "latency_max_";
private static final String KEY_LATENCY_NUM_MEASUREMENTS = "latency_num_measurements_";
+ public final TestName testName = new TestName();
+
@Override
protected void onCreate(Bundle savedInstanceState) {
setContentView(R.layout.audio_tap2tone_activity);
@@ -505,6 +513,54 @@ public class AudioTap2ToneActivity
super.setTestResultAndFinish(passed);
}
+ private void reportTestResultForApi(int api) {
+ CtsVerifierReportLog reportLog = getReportLog();
+ reportLog.addValue(
+ KEY_LATENCY_MIN + api,
+ mLatencyMin[api],
+ ResultType.NEUTRAL,
+ ResultUnit.NONE);
+ reportLog.addValue(
+ KEY_LATENCY_MAX + api,
+ mLatencyMax[api],
+ ResultType.NEUTRAL,
+ ResultUnit.NONE);
+ reportLog.addValue(
+ KEY_LATENCY_AVE + api,
+ mLatencyAve[api],
+ ResultType.NEUTRAL,
+ ResultUnit.NONE);
+ reportLog.addValue(
+ KEY_LATENCY_NUM_MEASUREMENTS + api,
+ mNumMeasurements[api],
+ ResultType.NEUTRAL,
+ ResultUnit.NONE);
+ }
+
+ /** Records perf class results and returns if mpc is met */
+ private void recordPerfClassResults() {
+ PerformanceClassEvaluator pce = new PerformanceClassEvaluator(testName);
+ PerformanceClassEvaluator.AudioTap2ToneLatencyRequirement r5_6__h_1_1 =
+ pce.addR5_6__H_1_1();
+
+ r5_6__h_1_1.setNativeLatency(mLatencyAve[TEST_API_NATIVE]);
+ r5_6__h_1_1.setJavaLatency(mLatencyAve[TEST_API_JAVA]);
+
+ pce.submitAndVerify();
+ }
+
+ @Override
+ public void recordTestResults() {
+ Log.i(TAG, "recordTestResults()");
+
+ reportTestResultForApi(TEST_API_NATIVE);
+ reportTestResultForApi(TEST_API_JAVA);
+
+ getReportLog().submit();
+
+ recordPerfClassResults();
+ }
+
//
// AppCallback overrides
//
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsTestActivity.java
index 692538a81c3..9f43e8514bd 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsTestActivity.java
@@ -392,7 +392,7 @@ public class ItsTestActivity extends DialogTestListActivity {
// Save MPC info once both front primary and rear primary data are collected.
if (mExecutedMpcTests.size() == 4) {
- mPce.submit();
+ mPce.submitAndVerify();
}
return true;
}
diff --git a/hostsidetests/hdmicec/src/android/hdmicec/cts/HdmiCecClientWrapper.java b/hostsidetests/hdmicec/src/android/hdmicec/cts/HdmiCecClientWrapper.java
index ad8e5067089..5f445d491db 100644
--- a/hostsidetests/hdmicec/src/android/hdmicec/cts/HdmiCecClientWrapper.java
+++ b/hostsidetests/hdmicec/src/android/hdmicec/cts/HdmiCecClientWrapper.java
@@ -795,7 +795,7 @@ public final class HdmiCecClientWrapper extends ExternalResource {
throw new CecClientWrapperException(ErrorCodes.CecMessageNotFound, expectedMessage.name());
}
- public void checkNoMessagesSentFromDevice(int timeoutMillis)
+ public void checkNoMessagesSentFromDevice(int timeoutMillis, List<CecOperand> excludeOperands)
throws CecClientWrapperException {
checkCecClient();
long startTime = System.currentTimeMillis();
@@ -810,6 +810,10 @@ public final class HdmiCecClientWrapper extends ExternalResource {
if (mInputConsole.ready()) {
String line = mInputConsole.readLine();
if (pattern.matcher(line).matches()) {
+ CecOperand operand = CecMessage.getOperand(line);
+ if(excludeOperands.contains(operand)){
+ continue;
+ }
CLog.v("Found unexpected message in " + line);
throw new CecClientWrapperException(
ErrorCodes.CecMessageFound,
@@ -827,6 +831,12 @@ public final class HdmiCecClientWrapper extends ExternalResource {
}
}
+ public void checkNoMessagesSentFromDevice(int timeoutMillis)
+ throws CecClientWrapperException {
+ List<CecOperand> excludeOperands = new ArrayList<>();
+ checkNoMessagesSentFromDevice(timeoutMillis, excludeOperands);
+ }
+
/**
* Looks for the CEC message incorrectMessage sent to CEC device toDevice on the cec-client
* communication channel and throws an CecClientWrapperException if it finds the line that
diff --git a/hostsidetests/hdmicec/src/android/hdmicec/cts/common/HdmiCecGeneralProtocolTest.java b/hostsidetests/hdmicec/src/android/hdmicec/cts/common/HdmiCecGeneralProtocolTest.java
index c62ce8f2a64..19d2c757d0e 100644
--- a/hostsidetests/hdmicec/src/android/hdmicec/cts/common/HdmiCecGeneralProtocolTest.java
+++ b/hostsidetests/hdmicec/src/android/hdmicec/cts/common/HdmiCecGeneralProtocolTest.java
@@ -33,6 +33,9 @@ import org.junit.Test;
import org.junit.rules.RuleChain;
import org.junit.runner.RunWith;
+import java.util.ArrayList;
+import java.util.List;
+
/** HDMI CEC 2.0 general protocol tests */
@RunWith(DeviceJUnit4ClassRunner.class)
public final class HdmiCecGeneralProtocolTest extends BaseHdmiCecCtsTest {
@@ -52,30 +55,34 @@ public final class HdmiCecGeneralProtocolTest extends BaseHdmiCecCtsTest {
@Test
public void cect_4_2_2_ignoreMessagesFromAddressF() throws Exception {
setCec20();
- sendMessageAndVerifyNoMessageSentFromDevice(CecOperand.GIVE_TUNER_DEVICE_STATUS, "01");
+ // get cec reinit messages
+ hdmiCecClient.getAllMessages(mDutLogicalAddresses,
+ HdmiCecConstants.TIMEOUT_CEC_REINIT_SECONDS);
+
+ sendMessageAndVerifyNoMessageSentFromDevice(CecOperand.GIVE_TUNER_DEVICE_STATUS, ":01");
sendMessageAndVerifyNoMessageSentFromDevice(CecOperand.RECORD_ON);
sendMessageAndVerifyNoMessageSentFromDevice(CecOperand.RECORD_OFF);
sendMessageAndVerifyNoMessageSentFromDevice(CecOperand.RECORD_TV_SCREEN);
- sendMessageAndVerifyNoMessageSentFromDevice(CecOperand.GIVE_DECK_STATUS, "01");
+ sendMessageAndVerifyNoMessageSentFromDevice(CecOperand.GIVE_DECK_STATUS, ":01");
sendMessageAndVerifyNoMessageSentFromDevice(
- CecOperand.CLEAR_ANALOG_TIMER, "02:02:02:02:02:02:00:00:00:02:00");
+ CecOperand.CLEAR_ANALOG_TIMER, ":02:02:02:02:02:02:00:00:00:02:00");
sendMessageAndVerifyNoMessageSentFromDevice(
- CecOperand.SET_ANALOG_TIMER, "02:02:02:02:02:02:00:00:00:02:00");
- sendMessageAndVerifyNoMessageSentFromDevice(CecOperand.PLAY, "05");
- sendMessageAndVerifyNoMessageSentFromDevice(CecOperand.DECK_CONTROL, "01");
+ CecOperand.SET_ANALOG_TIMER, ":02:02:02:02:02:02:00:00:00:02:00");
+ sendMessageAndVerifyNoMessageSentFromDevice(CecOperand.PLAY, ":05");
+ sendMessageAndVerifyNoMessageSentFromDevice(CecOperand.DECK_CONTROL, ":01");
sendMessageAndVerifyNoMessageSentFromDevice(CecOperand.GIVE_OSD_NAME);
sendMessageAndVerifyNoMessageSentFromDevice(CecOperand.GIVE_AUDIO_STATUS);
sendMessageAndVerifyNoMessageSentFromDevice(CecOperand.GIVE_SYSTEM_AUDIO_MODE_STATUS);
- sendMessageAndVerifyNoMessageSentFromDevice(CecOperand.VENDOR_COMMAND, "00:01");
- sendMessageAndVerifyNoMessageSentFromDevice(CecOperand.MENU_REQUEST, "00");
+ sendMessageAndVerifyNoMessageSentFromDevice(CecOperand.VENDOR_COMMAND, ":00:01");
+ sendMessageAndVerifyNoMessageSentFromDevice(CecOperand.MENU_REQUEST, ":00");
sendMessageAndVerifyNoMessageSentFromDevice(CecOperand.GIVE_POWER_STATUS);
sendMessageAndVerifyNoMessageSentFromDevice(
- CecOperand.SET_DIGITAL_TIMER, "02:02:02:02:02:02:00:00:00:02:00");
+ CecOperand.SET_DIGITAL_TIMER, ":02:02:02:02:02:02:00:00:00:02:00");
sendMessageAndVerifyNoMessageSentFromDevice(
- CecOperand.CLEAR_DIGITAL_TIMER, "02:02:02:02:02:02:00:00:00:02:00");
+ CecOperand.CLEAR_DIGITAL_TIMER, ":02:02:02:02:02:02:00:00:00:02:00");
sendMessageAndVerifyNoMessageSentFromDevice(CecOperand.GET_CEC_VERSION);
sendMessageAndVerifyNoMessageSentFromDevice(
- CecOperand.CLEAR_EXTERNAL_TIMER, "02:02:02:02:02:02:00:10:02");
+ CecOperand.CLEAR_EXTERNAL_TIMER, ":02:02:02:02:02:02:00:10:02");
sendMessageAndVerifyNoMessageSentFromDevice(CecOperand.REQUEST_SHORT_AUDIO_DESCRIPTOR);
sendMessageAndVerifyNoMessageSentFromDevice(CecOperand.INITIATE_ARC);
sendMessageAndVerifyNoMessageSentFromDevice(CecOperand.REQUEST_ARC_INITIATION);
@@ -86,10 +93,17 @@ public final class HdmiCecGeneralProtocolTest extends BaseHdmiCecCtsTest {
public void sendMessageAndVerifyNoMessageSentFromDevice(CecOperand message, String params)
throws Exception {
+ // DeviceDiscoveryAction will send GIVE_OSD_NAME and GIVE_DEVICE_VENDOR_ID
+ // HotplugDetectionAction will send GIVE_PHYSICAL_ADDRESS
+ List<CecOperand> excludeOperands = new ArrayList<>();
+ excludeOperands.add(CecOperand.GIVE_PHYSICAL_ADDRESS);
+ excludeOperands.add(CecOperand.GIVE_DEVICE_VENDOR_ID);
+ excludeOperands.add(CecOperand.GIVE_OSD_NAME);
+
hdmiCecClient.sendCecMessage(message, params);
// Default timeout for the incoming command to arrive in response to a request is 2 secs
// Thus test ensures no messages are sent from DUT for a spacing of 3 secs
- hdmiCecClient.checkNoMessagesSentFromDevice(3000);
+ hdmiCecClient.checkNoMessagesSentFromDevice(3000, excludeOperands);
}
public void sendMessageAndVerifyNoMessageSentFromDevice(CecOperand message) throws Exception {
diff --git a/hostsidetests/media/Android.bp b/hostsidetests/media/Android.bp
index 7f174a2a891..02d666c0c3c 100644
--- a/hostsidetests/media/Android.bp
+++ b/hostsidetests/media/Android.bp
@@ -41,6 +41,11 @@ java_test_host {
"cts-host-utils",
"cts-statsd-atom-host-test-utils",
],
+ data: [
+ ":CtsMediaMetricsHostTestApp",
+ ":CtsMediaSessionHostTestApp",
+ ":CtsMediaSessionTestHelper",
+ ],
}
filegroup {
diff --git a/hostsidetests/media/app/MediaMetricsTest/Android.bp b/hostsidetests/media/app/MediaMetricsTest/Android.bp
index ebab6b4a53f..6278f364e4c 100644
--- a/hostsidetests/media/app/MediaMetricsTest/Android.bp
+++ b/hostsidetests/media/app/MediaMetricsTest/Android.bp
@@ -50,6 +50,7 @@ android_test_helper_app {
],
static_libs: [
"androidx.test.rules",
+ "collector-device-lib",
"compatibility-device-util-axt",
"truth-prebuilt",
],
diff --git a/hostsidetests/media/app/MediaMetricsTest/src/android/media/metrics/cts/MediaMetricsAtomHostSideTests.java b/hostsidetests/media/app/MediaMetricsTest/src/android/media/metrics/cts/MediaMetricsAtomHostSideTests.java
index 8c91c5bc52d..3d0edfc3747 100644
--- a/hostsidetests/media/app/MediaMetricsTest/src/android/media/metrics/cts/MediaMetricsAtomHostSideTests.java
+++ b/hostsidetests/media/app/MediaMetricsTest/src/android/media/metrics/cts/MediaMetricsAtomHostSideTests.java
@@ -19,6 +19,7 @@ package android.media.metrics.cts;
import static com.google.common.truth.Truth.assertThat;
import android.content.Context;
+import android.device.collectors.util.SendToInstrumentation;
import android.media.metrics.BundleSession;
import android.media.metrics.EditingSession;
import android.media.metrics.LogSessionId;
@@ -44,10 +45,6 @@ import com.android.compatibility.common.util.SystemUtil;
import org.junit.Test;
import org.junit.runner.RunWith;
-import java.io.File;
-import java.io.FileWriter;
-import java.io.IOException;
-
@RunWith(AndroidJUnit4.class)
public class MediaMetricsAtomHostSideTests {
private static final String TAG = "MediaMetricsAtomHostSideTests";
@@ -300,7 +297,7 @@ public class MediaMetricsAtomHostSideTests {
.setNetworkBytesRead(102400)
.setLocalBytesRead(2000)
.setNetworkTransferDurationMillis(6000)
- .setDrmSessionId(new byte[] {2, 3, 3, 10})
+ .setDrmSessionId(new byte[]{2, 3, 3, 10})
.setMetricsBundle(new Bundle())
.addExperimentId(123)
.build();
@@ -443,7 +440,7 @@ public class MediaMetricsAtomHostSideTests {
.setNetworkBytesRead(102400)
.setLocalBytesRead(2000)
.setNetworkTransferDurationMillis(6000)
- .setDrmSessionId(new byte[] {2, 3, 3, 10})
+ .setDrmSessionId(new byte[]{2, 3, 3, 10})
.setMetricsBundle(new Bundle())
.addExperimentId(123)
.build();
@@ -507,7 +504,7 @@ public class MediaMetricsAtomHostSideTests {
.setNetworkBytesRead(102400)
.setLocalBytesRead(2000)
.setNetworkTransferDurationMillis(6000)
- .setDrmSessionId(new byte[] {2, 3, 3, 10})
+ .setDrmSessionId(new byte[]{2, 3, 3, 10})
.setMetricsBundle(new Bundle())
.addExperimentId(123)
.build();
@@ -540,16 +537,11 @@ public class MediaMetricsAtomHostSideTests {
@Test
public native void testAAudioLegacyInputStream();
- private void writeSessionIdToFile(String stringId) throws IOException {
- // TODO(b/259258249): Name session id after the test.
- Context context = InstrumentationRegistry.getInstrumentation().getContext();
+ private void writeSessionIdToFile(String stringId) {
Log.i(TAG, "log_session_id=" + stringId);
- File logDir = context.getExternalFilesDir(null);
- File logFile = new File(logDir, "log_session_id.txt");
- logFile.createNewFile();
- FileWriter fw = new FileWriter(logFile.getAbsolutePath());
- fw.write(stringId);
- fw.close();
- Log.i(TAG, "Logged to " + logFile.getAbsolutePath());
+ Bundle b = new Bundle();
+ // TODO(b/265311058): use a common constant for metrics keys.
+ b.putString("log_session_id", stringId);
+ SendToInstrumentation.sendBundle(InstrumentationRegistry.getInstrumentation(), b);
}
}
diff --git a/hostsidetests/media/src/android/media/metrics/cts/MediaMetricsAtomTests.java b/hostsidetests/media/src/android/media/metrics/cts/MediaMetricsAtomTests.java
index fe2ac25be0d..77cc851ebc3 100644
--- a/hostsidetests/media/src/android/media/metrics/cts/MediaMetricsAtomTests.java
+++ b/hostsidetests/media/src/android/media/metrics/cts/MediaMetricsAtomTests.java
@@ -24,23 +24,38 @@ import android.cts.statsdatom.lib.ConfigUtils;
import android.cts.statsdatom.lib.DeviceUtils;
import android.cts.statsdatom.lib.ReportUtils;
+import com.android.ddmlib.testrunner.RemoteAndroidTestRunner;
import com.android.os.AtomsProto;
import com.android.os.StatsLog;
import com.android.tradefed.build.IBuildInfo;
import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.log.LogUtil;
+import com.android.tradefed.metrics.proto.MetricMeasurement;
+import com.android.tradefed.result.CollectingTestListener;
+import com.android.tradefed.result.TestDescription;
+import com.android.tradefed.result.TestResult;
+import com.android.tradefed.result.TestRunResult;
import com.android.tradefed.testtype.DeviceTestCase;
import com.android.tradefed.testtype.IBuildReceiver;
import com.google.common.truth.Correspondence;
import java.util.Arrays;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
+import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
public class MediaMetricsAtomTests extends DeviceTestCase implements IBuildReceiver {
+
+ private static final String TEST_RUNNER = "androidx.test.runner.AndroidJUnitRunner";
private static final String TAG = "MediaMetricsAtomTests";
public static final String TEST_APK = "CtsMediaMetricsHostTestApp.apk";
public static final String TEST_PKG = "android.media.metrics.cts";
@@ -75,9 +90,9 @@ public class MediaMetricsAtomTests extends DeviceTestCase implements IBuildRecei
public void testPlaybackStateEvent_default() throws Exception {
ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG,
AtomsProto.Atom.MEDIA_PLAYBACK_STATE_CHANGED_FIELD_NUMBER);
- DeviceUtils.runDeviceTests(getDevice(), TEST_PKG,
+ runDeviceTests(getDevice(), TEST_PKG,
"android.media.metrics.cts.MediaMetricsAtomHostSideTests",
- "testPlaybackStateEvent_default");
+ "testPlaybackStateEvent_default", new LogSessionIdListener());
Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice());
@@ -93,9 +108,9 @@ public class MediaMetricsAtomTests extends DeviceTestCase implements IBuildRecei
public void testPlaybackStateEvent() throws Exception {
ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG,
AtomsProto.Atom.MEDIA_PLAYBACK_STATE_CHANGED_FIELD_NUMBER);
- DeviceUtils.runDeviceTests(getDevice(), TEST_PKG,
+ runDeviceTests(getDevice(), TEST_PKG,
"android.media.metrics.cts.MediaMetricsAtomHostSideTests",
- "testPlaybackStateEvent");
+ "testPlaybackStateEvent", new LogSessionIdListener());
Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice());
@@ -112,9 +127,9 @@ public class MediaMetricsAtomTests extends DeviceTestCase implements IBuildRecei
public void testBundleSessionPlaybackStateEvent() throws Exception {
ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG,
AtomsProto.Atom.MEDIA_PLAYBACK_STATE_CHANGED_FIELD_NUMBER);
- DeviceUtils.runDeviceTests(getDevice(), TEST_PKG,
+ runDeviceTests(getDevice(), TEST_PKG,
"android.media.metrics.cts.MediaMetricsAtomHostSideTests",
- "testBundleSessionPlaybackStateEvent");
+ "testBundleSessionPlaybackStateEvent", new LogSessionIdListener());
Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice());
@@ -131,9 +146,9 @@ public class MediaMetricsAtomTests extends DeviceTestCase implements IBuildRecei
public void testPlaybackErrorEvent_default() throws Exception {
ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG,
AtomsProto.Atom.MEDIA_PLAYBACK_ERROR_REPORTED_FIELD_NUMBER);
- DeviceUtils.runDeviceTests(getDevice(), TEST_PKG,
+ runDeviceTests(getDevice(), TEST_PKG,
"android.media.metrics.cts.MediaMetricsAtomHostSideTests",
- "testPlaybackErrorEvent_default");
+ "testPlaybackErrorEvent_default", new LogSessionIdListener());
Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice());
@@ -154,9 +169,9 @@ public class MediaMetricsAtomTests extends DeviceTestCase implements IBuildRecei
public void testPlaybackErrorEvent() throws Exception {
ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG,
AtomsProto.Atom.MEDIA_PLAYBACK_ERROR_REPORTED_FIELD_NUMBER);
- DeviceUtils.runDeviceTests(getDevice(), TEST_PKG,
+ runDeviceTests(getDevice(), TEST_PKG,
"android.media.metrics.cts.MediaMetricsAtomHostSideTests",
- "testPlaybackErrorEvent");
+ "testPlaybackErrorEvent", new LogSessionIdListener());
Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice());
@@ -177,9 +192,9 @@ public class MediaMetricsAtomTests extends DeviceTestCase implements IBuildRecei
public void testTrackChangeEvent_default() throws Exception {
ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG,
AtomsProto.Atom.MEDIA_PLAYBACK_TRACK_CHANGED_FIELD_NUMBER);
- DeviceUtils.runDeviceTests(getDevice(), TEST_PKG,
+ runDeviceTests(getDevice(), TEST_PKG,
"android.media.metrics.cts.MediaMetricsAtomHostSideTests",
- "testTrackChangeEvent_default");
+ "testTrackChangeEvent_default", new LogSessionIdListener());
Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice());
@@ -206,9 +221,9 @@ public class MediaMetricsAtomTests extends DeviceTestCase implements IBuildRecei
public void testTrackChangeEvent_text() throws Exception {
ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG,
AtomsProto.Atom.MEDIA_PLAYBACK_TRACK_CHANGED_FIELD_NUMBER);
- DeviceUtils.runDeviceTests(getDevice(), TEST_PKG,
+ runDeviceTests(getDevice(), TEST_PKG,
"android.media.metrics.cts.MediaMetricsAtomHostSideTests",
- "testTrackChangeEvent_text");
+ "testTrackChangeEvent_text", new LogSessionIdListener());
Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice());
@@ -233,9 +248,9 @@ public class MediaMetricsAtomTests extends DeviceTestCase implements IBuildRecei
public void testTrackChangeEvent_audio() throws Exception {
ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG,
AtomsProto.Atom.MEDIA_PLAYBACK_TRACK_CHANGED_FIELD_NUMBER);
- DeviceUtils.runDeviceTests(getDevice(), TEST_PKG,
+ runDeviceTests(getDevice(), TEST_PKG,
"android.media.metrics.cts.MediaMetricsAtomHostSideTests",
- "testTrackChangeEvent_audio");
+ "testTrackChangeEvent_audio", new LogSessionIdListener());
Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice());
@@ -262,9 +277,9 @@ public class MediaMetricsAtomTests extends DeviceTestCase implements IBuildRecei
public void testTrackChangeEvent_video() throws Exception {
ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG,
AtomsProto.Atom.MEDIA_PLAYBACK_TRACK_CHANGED_FIELD_NUMBER);
- DeviceUtils.runDeviceTests(getDevice(), TEST_PKG,
+ runDeviceTests(getDevice(), TEST_PKG,
"android.media.metrics.cts.MediaMetricsAtomHostSideTests",
- "testTrackChangeEvent_video");
+ "testTrackChangeEvent_video", new LogSessionIdListener());
Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice());
@@ -292,9 +307,9 @@ public class MediaMetricsAtomTests extends DeviceTestCase implements IBuildRecei
public void testNetworkEvent_default() throws Exception {
ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG,
AtomsProto.Atom.MEDIA_NETWORK_INFO_CHANGED_FIELD_NUMBER);
- DeviceUtils.runDeviceTests(getDevice(), TEST_PKG,
+ runDeviceTests(getDevice(), TEST_PKG,
"android.media.metrics.cts.MediaMetricsAtomHostSideTests",
- "testNetworkEvent_default");
+ "testNetworkEvent_default", new LogSessionIdListener());
Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice());
@@ -311,8 +326,9 @@ public class MediaMetricsAtomTests extends DeviceTestCase implements IBuildRecei
public void testNetworkEvent() throws Exception {
ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG,
AtomsProto.Atom.MEDIA_NETWORK_INFO_CHANGED_FIELD_NUMBER);
- DeviceUtils.runDeviceTests(getDevice(), TEST_PKG,
- "android.media.metrics.cts.MediaMetricsAtomHostSideTests", "testNetworkEvent");
+ runDeviceTests(getDevice(), TEST_PKG,
+ "android.media.metrics.cts.MediaMetricsAtomHostSideTests", "testNetworkEvent",
+ new LogSessionIdListener());
Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice());
@@ -329,9 +345,9 @@ public class MediaMetricsAtomTests extends DeviceTestCase implements IBuildRecei
public void testPlaybackMetrics_default() throws Exception {
ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG,
AtomsProto.Atom.MEDIAMETRICS_PLAYBACK_REPORTED_FIELD_NUMBER);
- DeviceUtils.runDeviceTests(getDevice(), TEST_PKG,
+ runDeviceTests(getDevice(), TEST_PKG,
"android.media.metrics.cts.MediaMetricsAtomHostSideTests",
- "testPlaybackMetrics_default");
+ "testPlaybackMetrics_default", new LogSessionIdListener());
Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice());
@@ -364,8 +380,9 @@ public class MediaMetricsAtomTests extends DeviceTestCase implements IBuildRecei
public void testPlaybackMetrics() throws Exception {
ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG,
AtomsProto.Atom.MEDIAMETRICS_PLAYBACK_REPORTED_FIELD_NUMBER);
- DeviceUtils.runDeviceTests(getDevice(), TEST_PKG,
- "android.media.metrics.cts.MediaMetricsAtomHostSideTests", "testPlaybackMetrics");
+ runDeviceTests(getDevice(), TEST_PKG,
+ "android.media.metrics.cts.MediaMetricsAtomHostSideTests", "testPlaybackMetrics",
+ new LogSessionIdListener());
Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice());
@@ -400,8 +417,9 @@ public class MediaMetricsAtomTests extends DeviceTestCase implements IBuildRecei
public void testSessionId() throws Exception {
ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG,
AtomsProto.Atom.MEDIAMETRICS_PLAYBACK_REPORTED_FIELD_NUMBER);
- DeviceUtils.runDeviceTests(getDevice(), TEST_PKG,
- "android.media.metrics.cts.MediaMetricsAtomHostSideTests", "testSessionId");
+ runDeviceTests(getDevice(), TEST_PKG,
+ "android.media.metrics.cts.MediaMetricsAtomHostSideTests", "testSessionId",
+ new LogSessionIdListener());
Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice());
@@ -411,8 +429,9 @@ public class MediaMetricsAtomTests extends DeviceTestCase implements IBuildRecei
public void testRecordingSession() throws Exception {
ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG,
AtomsProto.Atom.MEDIAMETRICS_PLAYBACK_REPORTED_FIELD_NUMBER);
- DeviceUtils.runDeviceTests(getDevice(), TEST_PKG,
- "android.media.metrics.cts.MediaMetricsAtomHostSideTests", "testRecordingSession");
+ runDeviceTests(getDevice(), TEST_PKG,
+ "android.media.metrics.cts.MediaMetricsAtomHostSideTests", "testRecordingSession",
+ new LogSessionIdListener());
Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice());
@@ -422,8 +441,9 @@ public class MediaMetricsAtomTests extends DeviceTestCase implements IBuildRecei
public void testEditingSession() throws Exception {
ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG,
AtomsProto.Atom.MEDIAMETRICS_PLAYBACK_REPORTED_FIELD_NUMBER);
- DeviceUtils.runDeviceTests(getDevice(), TEST_PKG,
- "android.media.metrics.cts.MediaMetricsAtomHostSideTests", "testEditingSession");
+ runDeviceTests(getDevice(), TEST_PKG,
+ "android.media.metrics.cts.MediaMetricsAtomHostSideTests", "testEditingSession",
+ new LogSessionIdListener());
Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice());
@@ -433,9 +453,9 @@ public class MediaMetricsAtomTests extends DeviceTestCase implements IBuildRecei
public void testTranscodingSession() throws Exception {
ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG,
AtomsProto.Atom.MEDIAMETRICS_PLAYBACK_REPORTED_FIELD_NUMBER);
- DeviceUtils.runDeviceTests(getDevice(), TEST_PKG,
+ runDeviceTests(getDevice(), TEST_PKG,
"android.media.metrics.cts.MediaMetricsAtomHostSideTests",
- "testTranscodingSession");
+ "testTranscodingSession", new LogSessionIdListener());
Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice());
@@ -445,8 +465,9 @@ public class MediaMetricsAtomTests extends DeviceTestCase implements IBuildRecei
public void testBundleSession() throws Exception {
ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG,
AtomsProto.Atom.MEDIAMETRICS_PLAYBACK_REPORTED_FIELD_NUMBER);
- DeviceUtils.runDeviceTests(getDevice(), TEST_PKG,
- "android.media.metrics.cts.MediaMetricsAtomHostSideTests", "testBundleSession");
+ runDeviceTests(getDevice(), TEST_PKG,
+ "android.media.metrics.cts.MediaMetricsAtomHostSideTests", "testBundleSession",
+ new LogSessionIdListener());
Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice());
@@ -456,11 +477,14 @@ public class MediaMetricsAtomTests extends DeviceTestCase implements IBuildRecei
public void testAppBlocklist() throws Exception {
ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG,
AtomsProto.Atom.MEDIA_PLAYBACK_STATE_CHANGED_FIELD_NUMBER);
- DeviceUtils.runDeviceTests(getDevice(), TEST_PKG,
- "android.media.metrics.cts.MediaMetricsAtomHostSideTests", "testAppBlocklist");
+ LogSessionIdListener listener = new LogSessionIdListener();
+ runDeviceTests(getDevice(),
+ TEST_PKG,
+ "android.media.metrics.cts.MediaMetricsAtomHostSideTests", "testAppBlocklist",
+ listener);
+ String logSessionId = listener.getLogSessionId();
Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
- String logSessionId = getLogSessionId();
assertWithMessage("log session id").that(logSessionId).isNotEmpty();
List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice());
List<AtomsProto.MediametricsPlaybackReported> playbackReportedList = toMyAtoms(data,
@@ -474,13 +498,14 @@ public class MediaMetricsAtomTests extends DeviceTestCase implements IBuildRecei
public void testAttributionBlocklist() throws Exception {
ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG,
AtomsProto.Atom.MEDIAMETRICS_PLAYBACK_REPORTED_FIELD_NUMBER);
- DeviceUtils.runDeviceTests(getDevice(), TEST_PKG,
+ LogSessionIdListener listener = new LogSessionIdListener();
+ runDeviceTests(getDevice(), TEST_PKG,
"android.media.metrics.cts.MediaMetricsAtomHostSideTests",
- "testAttributionBlocklist");
+ "testAttributionBlocklist", listener);
+ String logSessionId = listener.getLogSessionId();
Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice());
- String logSessionId = getLogSessionId();
assertWithMessage("log session id").that(logSessionId).isNotEmpty();
List<AtomsProto.MediametricsPlaybackReported> playbackReportedList = toMyAtoms(data,
AtomsProto.Atom::getMediametricsPlaybackReported);
@@ -511,12 +536,14 @@ public class MediaMetricsAtomTests extends DeviceTestCase implements IBuildRecei
public void testAppAllowlist() throws Exception {
ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG,
AtomsProto.Atom.MEDIA_PLAYBACK_STATE_CHANGED_FIELD_NUMBER);
- DeviceUtils.runDeviceTests(getDevice(), TEST_PKG,
- "android.media.metrics.cts.MediaMetricsAtomHostSideTests", "testAppAllowlist");
+ LogSessionIdListener listener = new LogSessionIdListener();
+ runDeviceTests(getDevice(), TEST_PKG,
+ "android.media.metrics.cts.MediaMetricsAtomHostSideTests",
+ "testAppAllowlist", listener);
+ String logSessionId = listener.getLogSessionId();
Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice());
- String logSessionId = getLogSessionId();
assertWithMessage("log session id").that(logSessionId).isNotEmpty();
List<AtomsProto.MediaPlaybackStateChanged> stateChangedList = toMyAtoms(data,
AtomsProto.Atom::getMediaPlaybackStateChanged);
@@ -533,13 +560,14 @@ public class MediaMetricsAtomTests extends DeviceTestCase implements IBuildRecei
public void testAttributionAllowlist() throws Exception {
ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG,
AtomsProto.Atom.MEDIAMETRICS_PLAYBACK_REPORTED_FIELD_NUMBER);
- DeviceUtils.runDeviceTests(getDevice(), TEST_PKG,
+ LogSessionIdListener listener = new LogSessionIdListener();
+ runDeviceTests(getDevice(), TEST_PKG,
"android.media.metrics.cts.MediaMetricsAtomHostSideTests",
- "testAttributionAllowlist");
+ "testAttributionAllowlist", listener);
+ String logSessionId = listener.getLogSessionId();
Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice());
- String logSessionId = getLogSessionId();
assertWithMessage("log session id").that(logSessionId).isNotEmpty();
List<AtomsProto.MediametricsPlaybackReported> playbackReportedList = toMyAtoms(data,
AtomsProto.Atom::getMediametricsPlaybackReported);
@@ -595,8 +623,9 @@ public class MediaMetricsAtomTests extends DeviceTestCase implements IBuildRecei
ConfigUtils.uploadConfigForPushedAtom(getDevice(), DeviceUtils.STATSD_ATOM_TEST_PKG,
AtomsProto.Atom.MEDIAMETRICS_AAUDIOSTREAM_REPORTED_FIELD_NUMBER);
- DeviceUtils.runDeviceTests(getDevice(), TEST_PKG,
- "android.media.metrics.cts.MediaMetricsAtomHostSideTests", testFunctionName);
+ runDeviceTests(getDevice(), TEST_PKG,
+ "android.media.metrics.cts.MediaMetricsAtomHostSideTests", testFunctionName,
+ new LogSessionIdListener());
Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
validateAAudioStreamAtom(direction);
@@ -650,17 +679,86 @@ public class MediaMetricsAtomTests extends DeviceTestCase implements IBuildRecei
"testAAudioLegacyOutputStream");
}
- private String getLogSessionId() throws DeviceNotAvailableException {
- // TODO(b/259258249): Name session id file after the test.
- String logSessionId = getDevice().pullFileContents(
- "/storage/emulated/0/Android/data/android.media.metrics"
- + ".cts/files/log_session_id" + ".txt");
- return logSessionId;
- }
-
private static <T> List<T> toMyAtoms(List<StatsLog.EventMetricData> data,
Function<AtomsProto.Atom, T> mapper) {
return data.stream().map(StatsLog.EventMetricData::getAtom).map(mapper).collect(
Collectors.toUnmodifiableList());
}
+
+ // TODO(b/265208340): update DeviceUtils to accept listeners.
+
+ /**
+ * Runs device side tests.
+ *
+ * @param device Can be retrieved by running getDevice() in a class that extends
+ * DeviceTestCase
+ * @param pkgName Test package name, such as "com.android.server.cts.statsdatom"
+ * @param testClassName Test class name which can either be a fully qualified name or "." + a
+ * class name; if null, all test in the package will be run
+ * @param testMethodName Test method name; if null, all tests in class or package will be run
+ * @return {@link TestRunResult} of this invocation
+ */
+ @Nonnull
+ private static TestRunResult runDeviceTests(ITestDevice device, String pkgName,
+ @Nullable String testClassName, @Nullable String testMethodName,
+ LogSessionIdListener listener)
+ throws DeviceNotAvailableException {
+ if (testClassName != null && testClassName.startsWith(".")) {
+ testClassName = pkgName + testClassName;
+ }
+
+ RemoteAndroidTestRunner testRunner = new RemoteAndroidTestRunner(
+ pkgName, TEST_RUNNER, device.getIDevice());
+ if (testClassName != null && testMethodName != null) {
+ testRunner.setMethodName(testClassName, testMethodName);
+ } else if (testClassName != null) {
+ testRunner.setClassName(testClassName);
+ }
+
+ assertThat(device.runInstrumentationTests(testRunner, listener)).isTrue();
+
+ final TestRunResult result = listener.getCurrentRunResults();
+ if (result.isRunFailure()) {
+ throw new Error("Failed to successfully run device tests for "
+ + result.getName() + ": " + result.getRunFailureMessage());
+ }
+ if (result.getNumTests() == 0) {
+ throw new Error("No tests were run on the device");
+ }
+ if (result.hasFailedTests()) {
+ StringBuilder errorBuilder = new StringBuilder("On-device tests failed:\n");
+ for (Map.Entry<TestDescription, TestResult> resultEntry :
+ result.getTestResults().entrySet()) {
+ if (!resultEntry.getValue().getStatus().equals(
+ com.android.ddmlib.testrunner.TestResult.TestStatus.PASSED)) {
+ errorBuilder.append(resultEntry.getKey().toString());
+ errorBuilder.append(":\n");
+ errorBuilder.append(resultEntry.getValue().getStackTrace());
+ }
+ }
+ throw new AssertionError(errorBuilder.toString());
+ }
+
+ return result;
+ }
+
+ private static final class LogSessionIdListener extends CollectingTestListener {
+
+ @Nullable
+ private String mLogSessionId;
+
+ @Nullable
+ public String getLogSessionId() {
+ return mLogSessionId;
+ }
+
+ @Override
+ public void testEnded(TestDescription test, long endTime,
+ HashMap<String, MetricMeasurement.Metric> testMetrics) {
+ super.testEnded(test, endTime, testMetrics);
+ LogUtil.CLog.i("testEnded MetricMeasurement.Metric " + testMetrics);
+ // TODO(b/265311058): use a common constant for metrics keys.
+ mLogSessionId = testMetrics.get("log_session_id").getMeasurements().getSingleString();
+ }
+ }
}
diff --git a/tests/JobScheduler/src/android/jobscheduler/cts/ConnectivityConstraintTest.java b/tests/JobScheduler/src/android/jobscheduler/cts/ConnectivityConstraintTest.java
index 00d7517d263..7b0d2616b4a 100644
--- a/tests/JobScheduler/src/android/jobscheduler/cts/ConnectivityConstraintTest.java
+++ b/tests/JobScheduler/src/android/jobscheduler/cts/ConnectivityConstraintTest.java
@@ -18,48 +18,25 @@ package android.jobscheduler.cts;
import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
-import static android.net.NetworkCapabilities.TRANSPORT_ETHERNET;
-import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
-import static com.android.compatibility.common.util.TestUtils.waitUntil;
-
-import android.Manifest;
import android.annotation.TargetApi;
import android.app.job.JobInfo;
import android.app.job.JobParameters;
import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
import android.content.pm.PackageManager;
-import android.location.LocationManager;
import android.net.ConnectivityManager;
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkRequest;
-import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiManager;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.Message;
import android.platform.test.annotations.RequiresDevice;
import android.provider.Settings;
import android.util.Log;
import com.android.compatibility.common.util.AppStandbyUtils;
import com.android.compatibility.common.util.BatteryUtils;
-import com.android.compatibility.common.util.CallbackAsserter;
-import com.android.compatibility.common.util.ShellIdentityUtils;
import com.android.compatibility.common.util.SystemUtil;
-import junit.framework.AssertionFailedError;
-
-import java.util.List;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicReference;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
/**
* Schedules jobs with the {@link android.app.job.JobScheduler} that have network connectivity
* constraints.
@@ -70,18 +47,13 @@ import java.util.regex.Pattern;
@RequiresDevice // Emulators don't always have access to wifi/network
public class ConnectivityConstraintTest extends BaseJobSchedulerTest {
private static final String TAG = "ConnectivityConstraintTest";
- private static final String RESTRICT_BACKGROUND_GET_CMD =
- "cmd netpolicy get restrict-background";
- private static final String RESTRICT_BACKGROUND_ON_CMD =
- "cmd netpolicy set restrict-background true";
- private static final String RESTRICT_BACKGROUND_OFF_CMD =
- "cmd netpolicy set restrict-background false";
/** Unique identifier for the job scheduled by this suite of tests. */
public static final int CONNECTIVITY_JOB_ID = ConnectivityConstraintTest.class.hashCode();
/** Wait this long before timing out the test. */
private static final long DEFAULT_TIMEOUT_MILLIS = 30000L; // 30 seconds.
+ private NetworkingHelper mNetworkingHelper;
private WifiManager mWifiManager;
private ConnectivityManager mCm;
@@ -89,21 +61,8 @@ public class ConnectivityConstraintTest extends BaseJobSchedulerTest {
private boolean mHasWifi;
/** Whether the device running these tests supports telephony. */
private boolean mHasTelephony;
- /** Whether the device running these tests supports ethernet. */
- private boolean mHasEthernet;
- /** Track whether WiFi was enabled in case we turn it off. */
- private boolean mInitialWiFiState;
- /** Track initial WiFi metered state. */
- private String mInitialWiFiMeteredState;
- private String mInitialWiFiSSID;
- /** Track whether restrict background policy was enabled in case we turn it off. */
- private boolean mInitialRestrictBackground;
- /** Track whether airplane mode was enabled in case we toggle it. */
- private boolean mInitialAirplaneMode;
/** Track whether the restricted bucket was enabled in case we toggle it. */
private String mInitialRestrictedBucketEnabled;
- /** Track the location mode in case we change it. */
- private String mInitialLocationMode;
private JobInfo.Builder mBuilder;
@@ -115,30 +74,20 @@ public class ConnectivityConstraintTest extends BaseJobSchedulerTest {
mWifiManager = (WifiManager) getContext().getSystemService(Context.WIFI_SERVICE);
mCm = (ConnectivityManager) getContext().getSystemService(Context.CONNECTIVITY_SERVICE);
+ mNetworkingHelper = new NetworkingHelper(getInstrumentation(), getContext());
PackageManager packageManager = mContext.getPackageManager();
mHasWifi = packageManager.hasSystemFeature(PackageManager.FEATURE_WIFI);
mHasTelephony = packageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY);
- mHasEthernet = packageManager.hasSystemFeature(PackageManager.FEATURE_ETHERNET);
mBuilder = new JobInfo.Builder(CONNECTIVITY_JOB_ID, kJobServiceComponent);
- mInitialLocationMode = Settings.Secure.getString(mContext.getContentResolver(),
- Settings.Secure.LOCATION_MODE);
if (mHasWifi) {
- mInitialWiFiState = mWifiManager.isWifiEnabled();
- ensureSavedWifiNetwork(mWifiManager);
- setWifiState(true, mCm, mWifiManager);
- mInitialWiFiSSID = getWifiSSID();
- mInitialWiFiMeteredState = getWifiMeteredStatus(mInitialWiFiSSID);
+ mNetworkingHelper.ensureSavedWifiNetwork();
}
- mInitialRestrictBackground = SystemUtil
- .runShellCommand(getInstrumentation(), RESTRICT_BACKGROUND_GET_CMD)
- .contains("enabled");
mInitialRestrictedBucketEnabled = Settings.Global.getString(mContext.getContentResolver(),
Settings.Global.ENABLE_RESTRICTED_BUCKET);
setDataSaverEnabled(false);
- mInitialAirplaneMode = isAirplaneModeOn();
- setAirplaneMode(false);
+ mNetworkingHelper.setAllNetworksEnabled(true);
// Force the test app out of the never bucket.
SystemUtil.runShellCommand("am set-standby-bucket "
+ TestAppInterface.TEST_APP_PACKAGE + " rare");
@@ -153,31 +102,12 @@ public class ConnectivityConstraintTest extends BaseJobSchedulerTest {
BatteryUtils.runDumpsysBatteryReset();
- // Restore initial restrict background data usage policy
- setDataSaverEnabled(mInitialRestrictBackground);
-
// Restore initial restricted bucket setting.
Settings.Global.putString(mContext.getContentResolver(),
Settings.Global.ENABLE_RESTRICTED_BUCKET, mInitialRestrictedBucketEnabled);
// Ensure that we leave WiFi in its previous state.
- if (mHasWifi) {
- setWifiMeteredState(mInitialWiFiSSID, mInitialWiFiMeteredState);
- if (mWifiManager.isWifiEnabled() != mInitialWiFiState) {
- try {
- setWifiState(mInitialWiFiState, mCm, mWifiManager);
- } catch (AssertionFailedError e) {
- // Don't fail the test just because wifi state wasn't set in tearDown.
- Log.e(TAG, "Failed to return wifi state to " + mInitialWiFiState, e);
- }
- }
- }
-
- // Restore initial airplane mode status. Do it after setting wifi in case wifi was
- // originally metered.
- setAirplaneMode(mInitialAirplaneMode);
-
- setLocationMode(mInitialLocationMode);
+ mNetworkingHelper.tearDown();
super.tearDown();
}
@@ -585,7 +515,7 @@ public class ConnectivityConstraintTest extends BaseJobSchedulerTest {
}
public void testJobParametersNetwork() throws Exception {
- setAirplaneMode(false);
+ mNetworkingHelper.setAllNetworksEnabled(true);
// Everything good.
final NetworkRequest nr = new NetworkRequest.Builder()
@@ -608,7 +538,7 @@ public class ConnectivityConstraintTest extends BaseJobSchedulerTest {
if (!hasEthernetConnection()) {
// Deadline passed with no network satisfied.
- setAirplaneMode(true);
+ mNetworkingHelper.setAllNetworksEnabled(false);
ji = mBuilder
.setRequiredNetwork(nr)
.setOverrideDeadline(0)
@@ -624,7 +554,7 @@ public class ConnectivityConstraintTest extends BaseJobSchedulerTest {
}
// No network requested
- setAirplaneMode(false);
+ mNetworkingHelper.setAllNetworksEnabled(true);
ji = mBuilder.setRequiredNetwork(null).build();
kTestEnvironment.setExpectedExecutions(1);
mJobScheduler.schedule(ji);
@@ -875,149 +805,25 @@ public class ConnectivityConstraintTest extends BaseJobSchedulerTest {
}
private boolean hasEthernetConnection() {
- if (!mHasEthernet) return false;
- Network[] networks = mCm.getAllNetworks();
- for (Network network : networks) {
- if (mCm.getNetworkCapabilities(network).hasTransport(TRANSPORT_ETHERNET)) {
- return true;
- }
- }
- return false;
- }
-
- private String unquoteSSID(String ssid) {
- // SSID is returned surrounded by quotes if it can be decoded as UTF-8.
- // Otherwise it's guaranteed not to start with a quote.
- if (ssid.charAt(0) == '"') {
- return ssid.substring(1, ssid.length() - 1);
- } else {
- return ssid;
- }
- }
-
- private String getWifiSSID() throws Exception {
- // Location needs to be enabled to get the WiFi information.
- setLocationMode(String.valueOf(Settings.Secure.LOCATION_MODE_ON));
- final AtomicReference<String> ssid = new AtomicReference<>();
- SystemUtil.runWithShellPermissionIdentity(() -> {
- ssid.set(mWifiManager.getConnectionInfo().getSSID());
- }, Manifest.permission.ACCESS_FINE_LOCATION);
- return unquoteSSID(ssid.get());
- }
-
- private void setLocationMode(String mode) throws Exception {
- Settings.Secure.putString(mContext.getContentResolver(),
- Settings.Secure.LOCATION_MODE, mode);
- final LocationManager locationManager = mContext.getSystemService(LocationManager.class);
- final boolean wantEnabled = !String.valueOf(Settings.Secure.LOCATION_MODE_OFF).equals(mode);
- waitUntil("Location " + (wantEnabled ? "not enabled" : "still enabled"),
- () -> wantEnabled == locationManager.isLocationEnabled());
- }
-
- // Returns "true", "false" or "none"
- private String getWifiMeteredStatus(String ssid) {
- // Interestingly giving the SSID as an argument to list wifi-networks
- // only works iff the network in question has the "false" policy.
- // Also unfortunately runShellCommand does not pass the command to the interpreter
- // so it's not possible to | grep the ssid.
- final String command = "cmd netpolicy list wifi-networks";
- final String policyString = SystemUtil.runShellCommand(command);
-
- final Matcher m = Pattern.compile("^" + ssid + ";(true|false|none)$",
- Pattern.MULTILINE | Pattern.UNIX_LINES).matcher(policyString);
- if (!m.find()) {
- fail("Unexpected format from cmd netpolicy (when looking for " + ssid + "): "
- + policyString);
- }
- return m.group(1);
+ return mNetworkingHelper.hasEthernetConnection();
}
private void setWifiMeteredState(boolean metered) throws Exception {
- if (metered) {
- // Make sure unmetered cellular networks don't interfere.
- setAirplaneMode(true);
- setWifiState(true, mCm, mWifiManager);
- }
- final String ssid = getWifiSSID();
- setWifiMeteredState(ssid, metered ? "true" : "false");
- }
-
- // metered should be "true", "false" or "none"
- private void setWifiMeteredState(String ssid, String metered) throws Exception {
- if (metered.equals(getWifiMeteredStatus(ssid))) {
- return;
- }
- SystemUtil.runShellCommand("cmd netpolicy set metered-network " + ssid + " " + metered);
- assertEquals(getWifiMeteredStatus(ssid), metered);
+ mNetworkingHelper.setWifiMeteredState(metered);
}
/**
* Ensure WiFi is enabled, and block until we've verified that we are in fact connected.
*/
private void connectToWifi() throws Exception {
- setWifiState(true, mCm, mWifiManager);
+ mNetworkingHelper.setWifiState(true);
}
/**
* Ensure WiFi is disabled, and block until we've verified that we are in fact disconnected.
*/
private void disconnectFromWifi() throws Exception {
- setWifiState(false, mCm, mWifiManager);
- }
-
- /** Ensures that the device has a wifi network saved. */
- static void ensureSavedWifiNetwork(WifiManager wifiManager) {
- final List<WifiConfiguration> savedNetworks =
- ShellIdentityUtils.invokeMethodWithShellPermissions(
- wifiManager, WifiManager::getConfiguredNetworks);
- assertFalse("Need at least one saved wifi network", savedNetworks.isEmpty());
- }
-
- /**
- * Set Wifi connection to specific state, and block until we've verified
- * that we are in the state.
- * Taken from {@link android.net.http.cts.ApacheHttpClientTest}.
- */
- static void setWifiState(final boolean enable,
- final ConnectivityManager cm, final WifiManager wm) throws Exception {
- if (enable != isWiFiConnected(cm, wm)) {
- NetworkRequest nr = new NetworkRequest.Builder().clearCapabilities().build();
- NetworkCapabilities nc = new NetworkCapabilities.Builder()
- .addTransportType(TRANSPORT_WIFI)
- .build();
- NetworkTracker tracker = new NetworkTracker(nc, enable, cm);
- cm.registerNetworkCallback(nr, tracker);
-
- if (enable) {
- SystemUtil.runShellCommand("svc wifi enable");
- waitUntil("Failed to enable Wifi", 30 /* seconds */, () -> wm.isWifiEnabled());
- //noinspection deprecation
- SystemUtil.runWithShellPermissionIdentity(wm::reconnect,
- android.Manifest.permission.NETWORK_SETTINGS);
- } else {
- SystemUtil.runShellCommand("svc wifi disable");
- }
-
- tracker.waitForStateChange();
-
- assertTrue("Wifi must be " + (enable ? "connected to" : "disconnected from")
- + " an access point for this test.",
- enable == isWiFiConnected(cm, wm));
-
- cm.unregisterNetworkCallback(tracker);
- }
- }
-
- static boolean isWiFiConnected(final ConnectivityManager cm, final WifiManager wm) {
- if (!wm.isWifiEnabled()) {
- return false;
- }
- final Network network = cm.getActiveNetwork();
- if (network == null) {
- return false;
- }
- final NetworkCapabilities networkCapabilities = cm.getNetworkCapabilities(network);
- return networkCapabilities != null && networkCapabilities.hasTransport(TRANSPORT_WIFI);
+ mNetworkingHelper.setWifiState(false);
}
/**
@@ -1029,13 +835,14 @@ public class ConnectivityConstraintTest extends BaseJobSchedulerTest {
* @see #checkDeviceSupportsMobileData()
*/
private void disconnectWifiToConnectToMobile() throws Exception {
- setAirplaneMode(false);
+ mNetworkingHelper.setAllNetworksEnabled(true);
if (mHasWifi && mWifiManager.isWifiEnabled()) {
NetworkRequest nr = new NetworkRequest.Builder().clearCapabilities().build();
NetworkCapabilities nc = new NetworkCapabilities.Builder()
.addTransportType(TRANSPORT_CELLULAR)
.build();
- NetworkTracker tracker = new NetworkTracker(nc, true, mCm);
+ NetworkingHelper.NetworkTracker tracker =
+ new NetworkingHelper.NetworkTracker(nc, true, mCm);
mCm.registerNetworkCallback(nr, tracker);
disconnectFromWifi();
@@ -1052,107 +859,6 @@ public class ConnectivityConstraintTest extends BaseJobSchedulerTest {
* If the policy is on, it interferes with tests that relies on metered connection.
*/
private void setDataSaverEnabled(boolean enabled) throws Exception {
- SystemUtil.runShellCommand(getInstrumentation(),
- enabled ? RESTRICT_BACKGROUND_ON_CMD : RESTRICT_BACKGROUND_OFF_CMD);
- }
-
- private boolean isAirplaneModeOn() throws Exception {
- final String output = SystemUtil.runShellCommand(getInstrumentation(),
- "cmd connectivity airplane-mode").trim();
- return "enabled".equals(output);
- }
-
- private void setAirplaneMode(boolean on) throws Exception {
- if (isAirplaneModeOn() == on) {
- return;
- }
- final CallbackAsserter airplaneModeBroadcastAsserter = CallbackAsserter.forBroadcast(
- new IntentFilter(Intent.ACTION_AIRPLANE_MODE_CHANGED));
- SystemUtil.runShellCommand(getInstrumentation(),
- "cmd connectivity airplane-mode " + (on ? "enable" : "disable"));
- airplaneModeBroadcastAsserter.assertCalled("Didn't get airplane mode changed broadcast",
- 15 /* 15 seconds */);
- waitUntil("Networks didn't change to " + (!on ? " on" : " off"), 60 /* seconds */,
- () -> {
- if (on) {
- return mCm.getActiveNetwork() == null
- && (!mHasWifi || !isWiFiConnected(mCm, mWifiManager));
- } else {
- return mCm.getActiveNetwork() != null;
- }
- });
- // Wait some time for the network changes to propagate. Can't use
- // waitUntil(isAirplaneModeOn() == on) because the response quickly gives the new
- // airplane mode status even though the network changes haven't propagated all the way to
- // JobScheduler.
- Thread.sleep(5000);
- }
-
- private static class NetworkTracker extends ConnectivityManager.NetworkCallback {
- private static final int MSG_CHECK_ACTIVE_NETWORK = 1;
- private final ConnectivityManager mCm;
-
- private final CountDownLatch mReceiveLatch = new CountDownLatch(1);
-
- private final NetworkCapabilities mExpectedCapabilities;
-
- private final boolean mExpectedConnected;
-
- private final Handler mHandler = new Handler(Looper.getMainLooper()) {
- @Override
- public void handleMessage(Message msg) {
- if (msg.what == MSG_CHECK_ACTIVE_NETWORK) {
- checkActiveNetwork();
- }
- }
- };
-
- private NetworkTracker(NetworkCapabilities expectedCapabilities, boolean expectedConnected,
- ConnectivityManager cm) {
- mExpectedCapabilities = expectedCapabilities;
- mExpectedConnected = expectedConnected;
- mCm = cm;
- }
-
- @Override
- public void onAvailable(Network network) {
- // Available doesn't mean it's the active network. We need to check that separately.
- checkActiveNetwork();
- }
-
- @Override
- public void onLost(Network network) {
- checkActiveNetwork();
- }
-
- boolean waitForStateChange() throws InterruptedException {
- checkActiveNetwork();
- return mReceiveLatch.await(60, TimeUnit.SECONDS);
- }
-
- private void checkActiveNetwork() {
- mHandler.removeMessages(MSG_CHECK_ACTIVE_NETWORK);
- if (mReceiveLatch.getCount() == 0) {
- return;
- }
-
- Network activeNetwork = mCm.getActiveNetwork();
- if (mExpectedConnected) {
- if (activeNetwork != null && mExpectedCapabilities.satisfiedByNetworkCapabilities(
- mCm.getNetworkCapabilities(activeNetwork))) {
- mReceiveLatch.countDown();
- } else {
- mHandler.sendEmptyMessageDelayed(MSG_CHECK_ACTIVE_NETWORK, 5000);
- }
- } else {
- if (activeNetwork == null
- || !mExpectedCapabilities.satisfiedByNetworkCapabilities(
- mCm.getNetworkCapabilities(activeNetwork))) {
- mReceiveLatch.countDown();
- } else {
- mHandler.sendEmptyMessageDelayed(MSG_CHECK_ACTIVE_NETWORK, 5000);
- }
- }
- }
+ mNetworkingHelper.setDataSaverEnabled(enabled);
}
}
diff --git a/tests/JobScheduler/src/android/jobscheduler/cts/JobThrottlingTest.java b/tests/JobScheduler/src/android/jobscheduler/cts/JobThrottlingTest.java
index ddbb4aa64ae..7cc15765747 100644
--- a/tests/JobScheduler/src/android/jobscheduler/cts/JobThrottlingTest.java
+++ b/tests/JobScheduler/src/android/jobscheduler/cts/JobThrottlingTest.java
@@ -18,23 +18,17 @@ package android.jobscheduler.cts;
import static android.app.job.JobInfo.NETWORK_TYPE_ANY;
import static android.app.job.JobInfo.NETWORK_TYPE_NONE;
-import static android.jobscheduler.cts.ConnectivityConstraintTest.ensureSavedWifiNetwork;
-import static android.jobscheduler.cts.ConnectivityConstraintTest.isWiFiConnected;
-import static android.jobscheduler.cts.ConnectivityConstraintTest.setWifiState;
import static android.jobscheduler.cts.TestAppInterface.TEST_APP_PACKAGE;
import static android.os.PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED;
import static com.android.compatibility.common.util.TestUtils.waitUntil;
-import static junit.framework.Assert.fail;
-
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeFalse;
import static org.junit.Assume.assumeTrue;
-import android.Manifest;
import android.app.AppOpsManager;
import android.app.job.JobInfo;
import android.app.job.JobParameters;
@@ -44,9 +38,6 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.jobscheduler.cts.jobtestapp.TestJobSchedulerReceiver;
-import android.location.LocationManager;
-import android.net.ConnectivityManager;
-import android.net.wifi.WifiManager;
import android.os.PowerManager;
import android.os.SystemClock;
import android.os.Temperature;
@@ -64,23 +55,14 @@ import androidx.test.runner.AndroidJUnit4;
import com.android.compatibility.common.util.AppOpsUtils;
import com.android.compatibility.common.util.AppStandbyUtils;
import com.android.compatibility.common.util.BatteryUtils;
-import com.android.compatibility.common.util.CallbackAsserter;
import com.android.compatibility.common.util.DeviceConfigStateHelper;
-import com.android.compatibility.common.util.SystemUtil;
import com.android.compatibility.common.util.ThermalUtils;
-import junit.framework.AssertionFailedError;
-
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
-import java.io.IOException;
-import java.util.concurrent.atomic.AtomicReference;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
/**
* Tests related to job throttling -- device idle, app standby and battery saver.
*/
@@ -106,22 +88,15 @@ public class JobThrottlingTest {
private Context mContext;
private UiDevice mUiDevice;
+ private NetworkingHelper mNetworkingHelper;
private PowerManager mPowerManager;
private int mTestJobId;
private int mTestPackageUid;
private boolean mDeviceInDoze;
private boolean mDeviceIdleEnabled;
private boolean mAppStandbyEnabled;
- private WifiManager mWifiManager;
- private ConnectivityManager mCm;
- /** Whether the device running these tests supports WiFi. */
- private boolean mHasWifi;
- /** Track whether WiFi was enabled in case we turn it off. */
- private boolean mInitialWiFiState;
- private boolean mInitialAirplaneModeState;
private String mInitialDisplayTimeout;
private String mInitialRestrictedBucketEnabled;
- private String mInitialLocationMode;
private String mInitialBatteryStatsConstants;
private boolean mAutomotiveDevice;
private boolean mLeanbackOnly;
@@ -154,6 +129,8 @@ public class JobThrottlingTest {
public void setUp() throws Exception {
mContext = InstrumentationRegistry.getTargetContext();
mUiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
+ mNetworkingHelper =
+ new NetworkingHelper(InstrumentationRegistry.getInstrumentation(), mContext);
mPowerManager = mContext.getSystemService(PowerManager.class);
mDeviceInDoze = mPowerManager.isDeviceIdleMode();
mTestPackageUid = mContext.getPackageManager().getPackageUid(TEST_APP_PACKAGE, 0);
@@ -171,11 +148,6 @@ public class JobThrottlingTest {
} else {
Log.w(TAG, "App standby not enabled on test device");
}
- mWifiManager = mContext.getSystemService(WifiManager.class);
- mCm = mContext.getSystemService(ConnectivityManager.class);
- mHasWifi = mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI);
- mInitialWiFiState = mWifiManager.isWifiEnabled();
- mInitialAirplaneModeState = isAirplaneModeOn();
mInitialRestrictedBucketEnabled = Settings.Global.getString(mContext.getContentResolver(),
Settings.Global.ENABLE_RESTRICTED_BUCKET);
mInitialBatteryStatsConstants = Settings.Global.getString(mContext.getContentResolver(),
@@ -183,8 +155,6 @@ public class JobThrottlingTest {
// Make sure ACTION_CHARGING is sent immediately.
Settings.Global.putString(mContext.getContentResolver(),
Settings.Global.BATTERY_STATS_CONSTANTS, "battery_charged_delay_ms=0");
- mInitialLocationMode = Settings.Secure.getString(mContext.getContentResolver(),
- Settings.Secure.LOCATION_MODE);
// Make sure test jobs can run regardless of bucket.
mDeviceConfigStateHelper =
new DeviceConfigStateHelper(DeviceConfig.NAMESPACE_JOB_SCHEDULER);
@@ -603,7 +573,7 @@ public class JobThrottlingTest {
mDeviceConfigStateHelper.set("qc_timing_session_coalescing_duration_ms", "0");
mDeviceConfigStateHelper.set("qc_max_session_count_restricted", "0");
- setAirplaneMode(true);
+ mNetworkingHelper.setAllNetworksEnabled(false);
setScreenState(true);
setChargingState(false);
@@ -634,9 +604,9 @@ public class JobThrottlingTest {
assumeTrue("app standby not enabled", mAppStandbyEnabled);
assumeFalse("not testable in automotive device", mAutomotiveDevice);
assumeFalse("not testable in leanback device", mLeanbackOnly);
-
- assumeTrue(mHasWifi);
- ensureSavedWifiNetwork(mWifiManager);
+ assumeFalse("not testable, since ethernet is connected", hasEthernetConnection());
+ assumeTrue(mNetworkingHelper.hasWifiFeature());
+ mNetworkingHelper.ensureSavedWifiNetwork();
setRestrictedBucketEnabled(true);
@@ -644,7 +614,7 @@ public class JobThrottlingTest {
mDeviceConfigStateHelper.set("qc_timing_session_coalescing_duration_ms", "0");
mDeviceConfigStateHelper.set("qc_max_session_count_restricted", "0");
- setAirplaneMode(true);
+ mNetworkingHelper.setAllNetworksEnabled(false);
setScreenState(true);
setChargingState(false);
@@ -673,9 +643,8 @@ public class JobThrottlingTest {
assertFalse("New job started in RESTRICTED bucket", mTestAppInterface.awaitJobStart(3_000));
// Add network
- setAirplaneMode(false);
- setWifiState(true, mCm, mWifiManager);
- setWifiMeteredState(false);
+ mNetworkingHelper.setAllNetworksEnabled(true);
+ mNetworkingHelper.setWifiMeteredState(false);
runJob();
assertTrue("New job didn't start in RESTRICTED bucket",
mTestAppInterface.awaitJobStart(5_000));
@@ -978,8 +947,8 @@ public class JobThrottlingTest {
assumeFalse("not testable in automotive device", mAutomotiveDevice);
assumeFalse("not testable in leanback device", mLeanbackOnly);
- assumeTrue(mHasWifi);
- ensureSavedWifiNetwork(mWifiManager);
+ assumeTrue(mNetworkingHelper.hasWifiFeature());
+ mNetworkingHelper.ensureSavedWifiNetwork();
setRestrictedBucketEnabled(true);
setTestPackageStandbyBucket(Bucket.RESTRICTED);
@@ -989,9 +958,8 @@ public class JobThrottlingTest {
mDeviceConfigStateHelper.set("qc_max_session_count_restricted", "0");
// Satisfy all additional constraints.
- setAirplaneMode(false);
- setWifiState(true, mCm, mWifiManager);
- setWifiMeteredState(false);
+ mNetworkingHelper.setAllNetworksEnabled(true);
+ mNetworkingHelper.setWifiMeteredState(false);
setChargingState(true);
BatteryUtils.runDumpsysBatterySetLevel(100);
setScreenState(false);
@@ -1004,13 +972,12 @@ public class JobThrottlingTest {
runJob();
assertTrue("New job didn't start in RESTRICTED bucket",
mTestAppInterface.awaitJobStart(DEFAULT_WAIT_TIMEOUT));
- setAirplaneMode(true);
+ mNetworkingHelper.setAllNetworksEnabled(false);
assertTrue("New job didn't stop when connectivity dropped",
mTestAppInterface.awaitJobStop(DEFAULT_WAIT_TIMEOUT));
assertEquals(JobParameters.STOP_REASON_CONSTRAINT_CONNECTIVITY,
mTestAppInterface.getLastParams().getStopReason());
- setAirplaneMode(false);
- setWifiState(true, mCm, mWifiManager);
+ mNetworkingHelper.setAllNetworksEnabled(true);
// Idle
mTestAppInterface.scheduleJob(false, NETWORK_TYPE_ANY, false);
@@ -1195,23 +1162,12 @@ public class JobThrottlingTest {
Settings.Global.BATTERY_STATS_CONSTANTS, mInitialBatteryStatsConstants);
removeTestAppFromTempWhitelist();
- // Ensure that we leave WiFi in its previous state.
- if (mHasWifi && mWifiManager.isWifiEnabled() != mInitialWiFiState) {
- try {
- setWifiState(mInitialWiFiState, mCm, mWifiManager);
- } catch (AssertionFailedError e) {
- // Don't fail the test just because wifi state wasn't set in tearDown.
- Log.e(TAG, "Failed to return wifi state to " + mInitialWiFiState, e);
- }
- }
+ mNetworkingHelper.tearDown();
mDeviceConfigStateHelper.restoreOriginalValues();
mActivityManagerDeviceConfigStateHelper.restoreOriginalValues();
Settings.Global.putString(mContext.getContentResolver(),
Settings.Global.ENABLE_RESTRICTED_BUCKET, mInitialRestrictedBucketEnabled);
- if (isAirplaneModeOn() != mInitialAirplaneModeState) {
- setAirplaneMode(mInitialAirplaneModeState);
- }
- setLocationMode(mInitialLocationMode);
+
mUiDevice.executeShellCommand(
"cmd jobscheduler reset-execution-quota -u " + UserHandle.myUserId()
+ " " + TEST_APP_PACKAGE);
@@ -1367,110 +1323,8 @@ public class JobThrottlingTest {
+ " -u " + UserHandle.myUserId() + " " + TEST_APP_PACKAGE + " " + mTestJobId);
}
- private boolean isAirplaneModeOn() throws IOException {
- final String output =
- mUiDevice.executeShellCommand("cmd connectivity airplane-mode").trim();
- return "enabled".equals(output);
- }
-
- private void setAirplaneMode(boolean on) throws Exception {
- final CallbackAsserter airplaneModeBroadcastAsserter = CallbackAsserter.forBroadcast(
- new IntentFilter(Intent.ACTION_AIRPLANE_MODE_CHANGED));
- mUiDevice.executeShellCommand(
- "cmd connectivity airplane-mode " + (on ? "enable" : "disable"));
- airplaneModeBroadcastAsserter.assertCalled("Didn't get airplane mode changed broadcast",
- 15 /* 15 seconds */);
- if (!on && mHasWifi) {
- // Force wifi to connect ASAP.
- mUiDevice.executeShellCommand("svc wifi enable");
- waitUntil("Failed to enable Wifi", 30 /* seconds */,
- () -> {
- return mWifiManager.isWifiEnabled();
- });
- //noinspection deprecation
- SystemUtil.runWithShellPermissionIdentity(mWifiManager::reconnect,
- android.Manifest.permission.NETWORK_SETTINGS);
- }
- waitUntil("Networks didn't change to " + (!on ? "on" : "off"), 60 /* seconds */,
- () -> {
- if (on) {
- return mCm.getActiveNetwork() == null
- && (!mHasWifi || !isWiFiConnected(mCm, mWifiManager));
- } else {
- return mCm.getActiveNetwork() != null;
- }
- });
- // Wait some time for the network changes to propagate. Can't use
- // waitUntil(isAirplaneModeOn() == on) because the response quickly gives the new
- // airplane mode status even though the network changes haven't propagated all the way to
- // JobScheduler.
- Thread.sleep(5000);
- }
-
- private static String unquoteSSID(String ssid) {
- // SSID is returned surrounded by quotes if it can be decoded as UTF-8.
- // Otherwise it's guaranteed not to start with a quote.
- if (ssid.charAt(0) == '"') {
- return ssid.substring(1, ssid.length() - 1);
- } else {
- return ssid;
- }
- }
-
- private String getWifiSSID() throws Exception {
- // Location needs to be enabled to get the WiFi information.
- setLocationMode(String.valueOf(Settings.Secure.LOCATION_MODE_ON));
- final AtomicReference<String> ssid = new AtomicReference<>();
- SystemUtil.runWithShellPermissionIdentity(() -> {
- ssid.set(mWifiManager.getConnectionInfo().getSSID());
- }, Manifest.permission.ACCESS_FINE_LOCATION);
- return unquoteSSID(ssid.get());
- }
-
- private void setLocationMode(String mode) throws Exception {
- Settings.Secure.putString(mContext.getContentResolver(),
- Settings.Secure.LOCATION_MODE, mode);
- final LocationManager locationManager = mContext.getSystemService(LocationManager.class);
- final boolean wantEnabled = !String.valueOf(Settings.Secure.LOCATION_MODE_OFF).equals(mode);
- waitUntil("Location " + (wantEnabled ? "not enabled" : "still enabled"),
- () -> wantEnabled == locationManager.isLocationEnabled());
- }
-
- // Returns "true", "false" or "none"
- private String getWifiMeteredStatus(String ssid) {
- // Interestingly giving the SSID as an argument to list wifi-networks
- // only works iff the network in question has the "false" policy.
- // Also unfortunately runShellCommand does not pass the command to the interpreter
- // so it's not possible to | grep the ssid.
- final String command = "cmd netpolicy list wifi-networks";
- final String policyString = SystemUtil.runShellCommand(command);
-
- final Matcher m = Pattern.compile("^" + ssid + ";(true|false|none)$",
- Pattern.MULTILINE | Pattern.UNIX_LINES).matcher(policyString);
- if (!m.find()) {
- fail("Unexpected format from cmd netpolicy (when looking for " + ssid + "): "
- + policyString);
- }
- return m.group(1);
- }
-
- private void setWifiMeteredState(boolean metered) throws Exception {
- if (metered) {
- // Make sure unmetered cellular networks don't interfere.
- setAirplaneMode(true);
- setWifiState(true, mCm, mWifiManager);
- }
- final String ssid = getWifiSSID();
- setWifiMeteredState(ssid, metered ? "true" : "false");
- }
-
- // metered should be "true", "false" or "none"
- private void setWifiMeteredState(String ssid, String metered) {
- if (metered.equals(getWifiMeteredStatus(ssid))) {
- return;
- }
- SystemUtil.runShellCommand("cmd netpolicy set metered-network " + ssid + " " + metered);
- assertEquals(getWifiMeteredStatus(ssid), metered);
+ private boolean hasEthernetConnection() {
+ return mNetworkingHelper.hasEthernetConnection();
}
private String getJobState() throws Exception {
diff --git a/tests/JobScheduler/src/android/jobscheduler/cts/NetworkingHelper.java b/tests/JobScheduler/src/android/jobscheduler/cts/NetworkingHelper.java
new file mode 100644
index 00000000000..1402975cfe6
--- /dev/null
+++ b/tests/JobScheduler/src/android/jobscheduler/cts/NetworkingHelper.java
@@ -0,0 +1,432 @@
+/*
+ * Copyright (C) 2022 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.jobscheduler.cts;
+
+import static android.net.NetworkCapabilities.TRANSPORT_ETHERNET;
+import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
+
+import static com.android.compatibility.common.util.TestUtils.waitUntil;
+
+import static junit.framework.Assert.fail;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+
+import android.Manifest;
+import android.annotation.NonNull;
+import android.app.Instrumentation;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.PackageManager;
+import android.location.LocationManager;
+import android.net.ConnectivityManager;
+import android.net.Network;
+import android.net.NetworkCapabilities;
+import android.net.NetworkRequest;
+import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiManager;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.provider.Settings;
+import android.util.Log;
+
+import com.android.compatibility.common.util.CallbackAsserter;
+import com.android.compatibility.common.util.ShellIdentityUtils;
+import com.android.compatibility.common.util.SystemUtil;
+
+import junit.framework.AssertionFailedError;
+
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class NetworkingHelper {
+ private static final String TAG = "JsNetworkingUtils";
+
+ private static final String RESTRICT_BACKGROUND_GET_CMD =
+ "cmd netpolicy get restrict-background";
+ private static final String RESTRICT_BACKGROUND_ON_CMD =
+ "cmd netpolicy set restrict-background true";
+ private static final String RESTRICT_BACKGROUND_OFF_CMD =
+ "cmd netpolicy set restrict-background false";
+
+ private final Context mContext;
+ private final Instrumentation mInstrumentation;
+
+ private final ConnectivityManager mConnectivityManager;
+ private final WifiManager mWifiManager;
+
+ /** Whether the device running these tests supports WiFi. */
+ private final boolean mHasWifi;
+ /** Whether the device running these tests supports ethernet. */
+ private final boolean mHasEthernet;
+ /** Whether the device running these tests supports telephony. */
+ private final boolean mHasTelephony;
+
+ private final boolean mInitialAirplaneModeState;
+ private final boolean mInitialDataSaverState;
+ private final String mInitialLocationMode;
+ private final boolean mInitialWiFiState;
+ private String mInitialWiFiMeteredState;
+ private String mInitialWiFiSSID;
+
+ NetworkingHelper(@NonNull Instrumentation instrumentation, @NonNull Context context)
+ throws Exception {
+ mContext = context;
+ mInstrumentation = instrumentation;
+
+ mConnectivityManager = context.getSystemService(ConnectivityManager.class);
+ mWifiManager = context.getSystemService(WifiManager.class);
+
+ PackageManager packageManager = mContext.getPackageManager();
+ mHasWifi = packageManager.hasSystemFeature(PackageManager.FEATURE_WIFI);
+ mHasEthernet = packageManager.hasSystemFeature(PackageManager.FEATURE_ETHERNET);
+ mHasTelephony = packageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY);
+
+ mInitialAirplaneModeState = isAirplaneModeOn();
+ mInitialDataSaverState = isDataSaverEnabled();
+ mInitialLocationMode = Settings.Secure.getString(
+ mContext.getContentResolver(), Settings.Secure.LOCATION_MODE);
+ mInitialWiFiState = mHasWifi && isWifiEnabled();
+ }
+
+ /** Ensures that the device has a wifi network saved. */
+ void ensureSavedWifiNetwork() throws Exception {
+ if (!mHasWifi) {
+ return;
+ }
+ final List<WifiConfiguration> savedNetworks =
+ ShellIdentityUtils.invokeMethodWithShellPermissions(
+ mWifiManager, WifiManager::getConfiguredNetworks);
+ assertFalse("Need at least one saved wifi network", savedNetworks.isEmpty());
+
+ setWifiState(true);
+ if (mInitialWiFiSSID == null) {
+ mInitialWiFiSSID = getWifiSSID();
+ mInitialWiFiMeteredState = getWifiMeteredStatus(mInitialWiFiSSID);
+ }
+ }
+
+ // Returns "true", "false", or "none".
+ private String getWifiMeteredStatus(String ssid) {
+ // Interestingly giving the SSID as an argument to list wifi-networks
+ // only works iff the network in question has the "false" policy.
+ // Also unfortunately runShellCommand does not pass the command to the interpreter
+ // so it's not possible to | grep the ssid.
+ final String command = "cmd netpolicy list wifi-networks";
+ final String policyString = SystemUtil.runShellCommand(command);
+
+ final Matcher m = Pattern.compile(ssid + ";(true|false|none)",
+ Pattern.MULTILINE | Pattern.UNIX_LINES).matcher(policyString);
+ if (!m.find()) {
+ fail("Unexpected format from cmd netpolicy (when looking for " + ssid + "): "
+ + policyString);
+ }
+ return m.group(1);
+ }
+
+ @NonNull
+ private String getWifiSSID() throws Exception {
+ // Location needs to be enabled to get the WiFi information.
+ setLocationMode(String.valueOf(Settings.Secure.LOCATION_MODE_ON));
+ final AtomicReference<String> ssid = new AtomicReference<>();
+ SystemUtil.runWithShellPermissionIdentity(
+ () -> ssid.set(mWifiManager.getConnectionInfo().getSSID()),
+ Manifest.permission.ACCESS_FINE_LOCATION);
+ return unquoteSSID(ssid.get());
+ }
+
+ boolean hasEthernetConnection() {
+ if (!mHasEthernet) return false;
+ Network[] networks = mConnectivityManager.getAllNetworks();
+ for (Network network : networks) {
+ if (mConnectivityManager.getNetworkCapabilities(network)
+ .hasTransport(TRANSPORT_ETHERNET)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ boolean hasWifiFeature() {
+ return mHasWifi;
+ }
+
+ boolean isAirplaneModeOn() throws Exception {
+ final String output = SystemUtil.runShellCommand(mInstrumentation,
+ "cmd connectivity airplane-mode").trim();
+ return "enabled".equals(output);
+ }
+
+ boolean isDataSaverEnabled() throws Exception {
+ return SystemUtil
+ .runShellCommand(mInstrumentation, RESTRICT_BACKGROUND_GET_CMD)
+ .contains("enabled");
+ }
+
+ boolean isWiFiConnected() {
+ if (!mWifiManager.isWifiEnabled()) {
+ return false;
+ }
+ final Network network = mConnectivityManager.getActiveNetwork();
+ if (network == null) {
+ return false;
+ }
+ final NetworkCapabilities networkCapabilities =
+ mConnectivityManager.getNetworkCapabilities(network);
+ return networkCapabilities != null && networkCapabilities.hasTransport(TRANSPORT_WIFI);
+ }
+
+ boolean isWifiEnabled() {
+ return mWifiManager.isWifiEnabled();
+ }
+
+ /**
+ * Tries to set all network statuses to {@code enabled}.
+ * However, this does not support ethernet connections.
+ * Confirm that {@link #hasEthernetConnection()} returns false before relying on this.
+ */
+ void setAllNetworksEnabled(boolean enabled) throws Exception {
+ if (mHasWifi) {
+ setWifiState(enabled);
+ }
+ setAirplaneMode(!enabled);
+ }
+
+ void setAirplaneMode(boolean on) throws Exception {
+ if (isAirplaneModeOn() == on) {
+ return;
+ }
+ final CallbackAsserter airplaneModeBroadcastAsserter = CallbackAsserter.forBroadcast(
+ new IntentFilter(Intent.ACTION_AIRPLANE_MODE_CHANGED));
+ SystemUtil.runShellCommand(mInstrumentation,
+ "cmd connectivity airplane-mode " + (on ? "enable" : "disable"));
+ airplaneModeBroadcastAsserter.assertCalled("Didn't get airplane mode changed broadcast",
+ 15 /* 15 seconds */);
+ if (!on && mHasWifi) {
+ // Try to trigger some network connection.
+ setWifiState(true);
+ }
+ waitUntil("Airplane mode didn't change to " + (on ? " on" : " off"), 60 /* seconds */,
+ () -> {
+ // Airplane mode only affects the cellular network. If the device doesn't
+ // support cellular, then we can only check that the airplane mode toggle is on.
+ if (!mHasTelephony) {
+ return on == isAirplaneModeOn();
+ }
+ if (on) {
+ Network[] networks = mConnectivityManager.getAllNetworks();
+ for (Network network : networks) {
+ if (mConnectivityManager.getNetworkCapabilities(network)
+ .hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) {
+ return false;
+ }
+ }
+ return true;
+ } else {
+ return mConnectivityManager.getActiveNetwork() != null;
+ }
+ });
+ // Wait some time for the network changes to propagate. Can't use
+ // waitUntil(isAirplaneModeOn() == on) because the response quickly gives the new
+ // airplane mode status even though the network changes haven't propagated all the way to
+ // JobScheduler.
+ Thread.sleep(5000);
+ }
+
+ /**
+ * Ensures that restrict background data usage policy is turned off.
+ * If the policy is on, it interferes with tests that relies on metered connection.
+ */
+ void setDataSaverEnabled(boolean enabled) throws Exception {
+ SystemUtil.runShellCommand(mInstrumentation,
+ enabled ? RESTRICT_BACKGROUND_ON_CMD : RESTRICT_BACKGROUND_OFF_CMD);
+ }
+
+ private void setLocationMode(String mode) throws Exception {
+ Settings.Secure.putString(mContext.getContentResolver(),
+ Settings.Secure.LOCATION_MODE, mode);
+ final LocationManager locationManager = mContext.getSystemService(LocationManager.class);
+ final boolean wantEnabled = !String.valueOf(Settings.Secure.LOCATION_MODE_OFF).equals(mode);
+ waitUntil("Location " + (wantEnabled ? "not enabled" : "still enabled"),
+ () -> wantEnabled == locationManager.isLocationEnabled());
+ }
+
+ void setWifiMeteredState(boolean metered) throws Exception {
+ if (metered) {
+ // Make sure unmetered cellular networks don't interfere.
+ setAirplaneMode(true);
+ setWifiState(true);
+ }
+ final String ssid = getWifiSSID();
+ setWifiMeteredState(ssid, metered ? "true" : "false");
+ }
+
+ // metered should be "true", "false" or "none"
+ private void setWifiMeteredState(String ssid, String metered) {
+ if (metered.equals(getWifiMeteredStatus(ssid))) {
+ return;
+ }
+ SystemUtil.runShellCommand("cmd netpolicy set metered-network " + ssid + " " + metered);
+ assertEquals(getWifiMeteredStatus(ssid), metered);
+ }
+
+ /**
+ * Set Wifi connection to specific state, and block until we've verified
+ * that we are in the state.
+ * Taken from {@link android.net.http.cts.ApacheHttpClientTest}.
+ */
+ void setWifiState(final boolean enable) throws Exception {
+ if (enable != isWiFiConnected()) {
+ NetworkRequest nr = new NetworkRequest.Builder().clearCapabilities().build();
+ NetworkCapabilities nc = new NetworkCapabilities.Builder()
+ .addTransportType(TRANSPORT_WIFI)
+ .build();
+ NetworkTracker tracker = new NetworkTracker(nc, enable, mConnectivityManager);
+ mConnectivityManager.registerNetworkCallback(nr, tracker);
+
+ if (enable) {
+ SystemUtil.runShellCommand("svc wifi enable");
+ waitUntil("Failed to enable Wifi", 30 /* seconds */,
+ this::isWifiEnabled);
+ //noinspection deprecation
+ SystemUtil.runWithShellPermissionIdentity(mWifiManager::reconnect,
+ android.Manifest.permission.NETWORK_SETTINGS);
+ } else {
+ SystemUtil.runShellCommand("svc wifi disable");
+ }
+
+ tracker.waitForStateChange();
+
+ assertEquals("Wifi must be " + (enable ? "connected to" : "disconnected from")
+ + " an access point for this test.", enable, isWiFiConnected());
+
+ mConnectivityManager.unregisterNetworkCallback(tracker);
+ }
+ }
+
+ void tearDown() throws Exception {
+ // Restore initial restrict background data usage policy
+ setDataSaverEnabled(mInitialDataSaverState);
+
+ // Ensure that we leave WiFi in its previous state.
+ if (mHasWifi) {
+ if (mInitialWiFiSSID != null) {
+ setWifiMeteredState(mInitialWiFiSSID, mInitialWiFiMeteredState);
+ }
+ if (mWifiManager.isWifiEnabled() != mInitialWiFiState) {
+ try {
+ setWifiState(mInitialWiFiState);
+ } catch (AssertionFailedError e) {
+ // Don't fail the test just because wifi state wasn't set in tearDown.
+ Log.e(TAG, "Failed to return wifi state to " + mInitialWiFiState, e);
+ }
+ }
+ }
+
+ // Restore initial airplane mode status. Do it after setting wifi in case wifi was
+ // originally metered.
+ if (isAirplaneModeOn() != mInitialAirplaneModeState) {
+ setAirplaneMode(mInitialAirplaneModeState);
+ }
+
+ setLocationMode(mInitialLocationMode);
+ }
+
+ private String unquoteSSID(String ssid) {
+ // SSID is returned surrounded by quotes if it can be decoded as UTF-8.
+ // Otherwise it's guaranteed not to start with a quote.
+ if (ssid.charAt(0) == '"') {
+ return ssid.substring(1, ssid.length() - 1);
+ } else {
+ return ssid;
+ }
+ }
+
+ static class NetworkTracker extends ConnectivityManager.NetworkCallback {
+ private static final int MSG_CHECK_ACTIVE_NETWORK = 1;
+ private final ConnectivityManager mConnectivityManager;
+
+ private final CountDownLatch mReceiveLatch = new CountDownLatch(1);
+
+ private final NetworkCapabilities mExpectedCapabilities;
+
+ private final boolean mExpectedConnected;
+
+ private final Handler mHandler = new Handler(Looper.getMainLooper()) {
+ @Override
+ public void handleMessage(Message msg) {
+ if (msg.what == MSG_CHECK_ACTIVE_NETWORK) {
+ checkActiveNetwork();
+ }
+ }
+ };
+
+ NetworkTracker(NetworkCapabilities expectedCapabilities, boolean expectedConnected,
+ ConnectivityManager cm) {
+ mExpectedCapabilities = expectedCapabilities;
+ mExpectedConnected = expectedConnected;
+ mConnectivityManager = cm;
+ }
+
+ @Override
+ public void onAvailable(Network network) {
+ // Available doesn't mean it's the active network. We need to check that separately.
+ checkActiveNetwork();
+ }
+
+ @Override
+ public void onLost(Network network) {
+ checkActiveNetwork();
+ }
+
+ boolean waitForStateChange() throws InterruptedException {
+ checkActiveNetwork();
+ return mReceiveLatch.await(60, TimeUnit.SECONDS);
+ }
+
+ private void checkActiveNetwork() {
+ mHandler.removeMessages(MSG_CHECK_ACTIVE_NETWORK);
+ if (mReceiveLatch.getCount() == 0) {
+ return;
+ }
+
+ Network activeNetwork = mConnectivityManager.getActiveNetwork();
+ if (mExpectedConnected) {
+ if (activeNetwork != null && mExpectedCapabilities.satisfiedByNetworkCapabilities(
+ mConnectivityManager.getNetworkCapabilities(activeNetwork))) {
+ mReceiveLatch.countDown();
+ } else {
+ mHandler.sendEmptyMessageDelayed(MSG_CHECK_ACTIVE_NETWORK, 5000);
+ }
+ } else {
+ if (activeNetwork == null
+ || !mExpectedCapabilities.satisfiedByNetworkCapabilities(
+ mConnectivityManager.getNetworkCapabilities(activeNetwork))) {
+ mReceiveLatch.countDown();
+ } else {
+ mHandler.sendEmptyMessageDelayed(MSG_CHECK_ACTIVE_NETWORK, 5000);
+ }
+ }
+ }
+ }
+}
diff --git a/tests/mediapc/common/Android.bp b/tests/mediapc/common/Android.bp
index 663dabc9c01..02fd7143513 100644
--- a/tests/mediapc/common/Android.bp
+++ b/tests/mediapc/common/Android.bp
@@ -25,7 +25,8 @@ java_library {
"compatibility-device-util-axt",
"android.test.base",
"auto_value_annotations",
- "guava"
+ "guava",
+ "cts-verifier-framework",
],
plugins: ["auto_value_plugin"],
}
@@ -35,7 +36,7 @@ android_test {
compile_multilib: "both",
static_libs: [
"compatibility-device-util-axt",
- "MediaPerformanceClassCommon"
+ "MediaPerformanceClassCommon",
],
platform_apis: true,
srcs: ["tests/src/**/*.java"],
diff --git a/tests/mediapc/common/src/android/mediapc/cts/common/PerformanceClassEvaluator.java b/tests/mediapc/common/src/android/mediapc/cts/common/PerformanceClassEvaluator.java
index 5f8ef128fd1..1e803c20bde 100644
--- a/tests/mediapc/common/src/android/mediapc/cts/common/PerformanceClassEvaluator.java
+++ b/tests/mediapc/common/src/android/mediapc/cts/common/PerformanceClassEvaluator.java
@@ -25,6 +25,11 @@ import android.media.MediaFormat;
import android.os.Build;
import android.util.Log;
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import com.android.compatibility.common.util.DeviceReportLog;
+import com.android.cts.verifier.CtsVerifierReportLog;
+
import com.google.common.base.Preconditions;
import org.junit.rules.TestName;
@@ -676,6 +681,42 @@ public class PerformanceClassEvaluator {
}
/**
+ * Helper method used to create ConcurrentCodecRequirements, builds and fills out the
+ * a requirement for tests ran with a resolution of 720p
+ */
+ private static ConcurrentCodecRequirement create720p(String requirementId,
+ RequiredMeasurement<?> measure) {
+ RequiredMeasurement<Integer> testResolution = RequiredMeasurement.<Integer>builder()
+ .setId(RequirementConstants.TEST_RESOLUTION)
+ .setPredicate(RequirementConstants.INTEGER_EQ)
+ .addRequiredValue(Build.VERSION_CODES.R, 720)
+ .build();
+
+ ConcurrentCodecRequirement req = new ConcurrentCodecRequirement(requirementId, measure,
+ testResolution);
+ req.setMeasuredValue(RequirementConstants.TEST_RESOLUTION, 720);
+ return req;
+ }
+
+ /**
+ * Helper method used to create ConcurrentCodecRequirements, builds and fills out the
+ * a requirement for tests ran with a resolution of 1080p
+ */
+ private static ConcurrentCodecRequirement create1080p(String requirementId,
+ RequiredMeasurement<?> measure) {
+ RequiredMeasurement<Integer> testResolution = RequiredMeasurement.<Integer>builder()
+ .setId(RequirementConstants.TEST_RESOLUTION)
+ .setPredicate(RequirementConstants.INTEGER_EQ)
+ .addRequiredValue(Build.VERSION_CODES.TIRAMISU, 1080)
+ .build();
+
+ ConcurrentCodecRequirement req = new ConcurrentCodecRequirement(requirementId, measure,
+ testResolution);
+ req.setMeasuredValue(RequirementConstants.TEST_RESOLUTION, 1080);
+ return req;
+ }
+
+ /**
* [2.2.7.1/5.1/H-1-1] MUST advertise the maximum number of hardware video decoder
* sessions that can be run concurrently in any codec combination via the
* CodecCapabilities.getMaxSupportedInstances() and VideoCapabilities
@@ -694,7 +735,7 @@ public class PerformanceClassEvaluator {
resolution))
.build();
- return new ConcurrentCodecRequirement(RequirementConstants.R5_1__H_1_1, maxInstances);
+ return create720p(RequirementConstants.R5_1__H_1_1, maxInstances);
}
/**
@@ -710,7 +751,7 @@ public class PerformanceClassEvaluator {
.addRequiredValue(Build.VERSION_CODES.TIRAMISU, 6)
.build();
- return new ConcurrentCodecRequirement(RequirementConstants.R5_1__H_1_1, maxInstances);
+ return create1080p(RequirementConstants.R5_1__H_1_1, maxInstances);
}
/**
@@ -729,8 +770,7 @@ public class PerformanceClassEvaluator {
getReqMinConcurrentFps(Build.VERSION_CODES.S, mimeType1, mimeType2, resolution))
.build();
- return new ConcurrentCodecRequirement(RequirementConstants.R5_1__H_1_2,
- reqConcurrentFps);
+ return create720p(RequirementConstants.R5_1__H_1_2, reqConcurrentFps);
}
/**
@@ -745,8 +785,7 @@ public class PerformanceClassEvaluator {
.addRequiredValue(Build.VERSION_CODES.TIRAMISU, 6 * FPS_30_TOLERANCE)
.build();
- return new ConcurrentCodecRequirement(RequirementConstants.R5_1__H_1_2,
- reqConcurrentFps);
+ return create1080p(RequirementConstants.R5_1__H_1_2, reqConcurrentFps);
}
/**
@@ -768,7 +807,7 @@ public class PerformanceClassEvaluator {
resolution))
.build();
- return new ConcurrentCodecRequirement(RequirementConstants.R5_1__H_1_3, maxInstances);
+ return create720p(RequirementConstants.R5_1__H_1_3, maxInstances);
}
/**
@@ -784,7 +823,7 @@ public class PerformanceClassEvaluator {
.addRequiredValue(Build.VERSION_CODES.TIRAMISU, 6)
.build();
- return new ConcurrentCodecRequirement(RequirementConstants.R5_1__H_1_3, maxInstances);
+ return create1080p(RequirementConstants.R5_1__H_1_3, maxInstances);
}
/**
@@ -801,8 +840,7 @@ public class PerformanceClassEvaluator {
.addRequiredValue(Build.VERSION_CODES.S, 0.0)
.build();
- return new ConcurrentCodecRequirement(RequirementConstants.R5_1__H_1_4,
- reqConcurrentFps);
+ return create720p(RequirementConstants.R5_1__H_1_4, reqConcurrentFps);
}
/**
@@ -818,8 +856,7 @@ public class PerformanceClassEvaluator {
.addRequiredValue(Build.VERSION_CODES.TIRAMISU, 0.0)
.build();
- return new ConcurrentCodecRequirement(RequirementConstants.R5_1__H_1_4,
- reqConcurrentFps);
+ return create1080p(RequirementConstants.R5_1__H_1_4, reqConcurrentFps);
}
/**
@@ -841,7 +878,7 @@ public class PerformanceClassEvaluator {
resolution))
.build();
- return new ConcurrentCodecRequirement(RequirementConstants.R5_1__H_1_5, maxInstances);
+ return create720p(RequirementConstants.R5_1__H_1_5, maxInstances);
}
/**
@@ -857,7 +894,7 @@ public class PerformanceClassEvaluator {
.addRequiredValue(Build.VERSION_CODES.TIRAMISU, 6)
.build();
- return new ConcurrentCodecRequirement(RequirementConstants.R5_1__H_1_5, maxInstances);
+ return create1080p(RequirementConstants.R5_1__H_1_5, maxInstances);
}
/**
@@ -879,8 +916,7 @@ public class PerformanceClassEvaluator {
/ 2)
.build();
- return new ConcurrentCodecRequirement(RequirementConstants.R5_1__H_1_6,
- reqConcurrentFps);
+ return create720p(RequirementConstants.R5_1__H_1_6, reqConcurrentFps);
}
/**
@@ -896,8 +932,7 @@ public class PerformanceClassEvaluator {
.addRequiredValue(Build.VERSION_CODES.TIRAMISU, 6 * FPS_30_TOLERANCE / 2)
.build();
- return new ConcurrentCodecRequirement(RequirementConstants.R5_1__H_1_6,
- reqConcurrentFps);
+ return create1080p(RequirementConstants.R5_1__H_1_6, reqConcurrentFps);
}
/**
@@ -912,8 +947,7 @@ public class PerformanceClassEvaluator {
.addRequiredValue(Build.VERSION_CODES.TIRAMISU, 2 * FPS_30_TOLERANCE)
.build();
- return new ConcurrentCodecRequirement(RequirementConstants.R5_1__H_1_9,
- reqConcurrentFps);
+ return create1080p(RequirementConstants.R5_1__H_1_9, reqConcurrentFps);
}
/**
@@ -929,8 +963,7 @@ public class PerformanceClassEvaluator {
.addRequiredValue(Build.VERSION_CODES.TIRAMISU, 4 * FPS_30_TOLERANCE)
.build();
- return new ConcurrentCodecRequirement(RequirementConstants.R5_1__H_1_10,
- reqConcurrentFps);
+ return create1080p(RequirementConstants.R5_1__H_1_10, reqConcurrentFps);
}
}
@@ -1742,8 +1775,12 @@ public class PerformanceClassEvaluator {
return this.addRequirement(AudioTap2ToneLatencyRequirement.createR5_6__H_1_1());
}
+ private enum SubmitType {
+ TRADEFED, VERIFIER
+ }
+
public void submitAndCheck() {
- boolean perfClassMet = submit();
+ boolean perfClassMet = submit(SubmitType.TRADEFED);
// check performance class
assumeTrue("Build.VERSION.MEDIA_PERFORMANCE_CLASS is not declared", Utils.isPerfClass());
@@ -1751,20 +1788,34 @@ public class PerformanceClassEvaluator {
}
public void submitAndVerify() {
- boolean perfClassMet = submit();
+ boolean perfClassMet = submit(SubmitType.VERIFIER);
if (!perfClassMet && Utils.isPerfClass()) {
Log.w(TAG, "Device did not meet specified performance class: " + Utils.getPerfClass());
}
}
- public boolean submit() {
+ private boolean submit(SubmitType type) {
boolean perfClassMet = true;
for (Requirement req: this.mRequirements) {
- perfClassMet &= req.writeLogAndCheck(this.mTestName);
+ switch (type) {
+ case VERIFIER:
+ CtsVerifierReportLog verifierLog = new CtsVerifierReportLog(
+ RequirementConstants.REPORT_LOG_NAME, req.id());
+ perfClassMet &= req.writeLogAndCheck(verifierLog, this.mTestName);
+ verifierLog.submit();
+ break;
+
+ case TRADEFED:
+ default:
+ DeviceReportLog tradefedLog = new DeviceReportLog(
+ RequirementConstants.REPORT_LOG_NAME, req.id());
+ perfClassMet &= req.writeLogAndCheck(tradefedLog, this.mTestName);
+ tradefedLog.submit(InstrumentationRegistry.getInstrumentation());
+ break;
+ }
}
this.mRequirements.clear(); // makes sure report isn't submitted twice
return perfClassMet;
}
-
}
diff --git a/tests/mediapc/common/src/android/mediapc/cts/common/RequiredMeasurement.java b/tests/mediapc/common/src/android/mediapc/cts/common/RequiredMeasurement.java
index f89cb286a95..777a8f24598 100644
--- a/tests/mediapc/common/src/android/mediapc/cts/common/RequiredMeasurement.java
+++ b/tests/mediapc/common/src/android/mediapc/cts/common/RequiredMeasurement.java
@@ -16,9 +16,10 @@
package android.mediapc.cts.common;
-import com.android.compatibility.common.util.DeviceReportLog;
+import com.android.compatibility.common.util.ReportLog;
import com.android.compatibility.common.util.ResultType;
import com.android.compatibility.common.util.ResultUnit;
+
import com.google.auto.value.AutoValue;
import com.google.common.collect.ImmutableMap;
@@ -113,7 +114,7 @@ public abstract class RequiredMeasurement<T> {
+ "\n\tExpected Values: " + this.expectedValues();
}
- public void writeValue(DeviceReportLog log) throws IllegalStateException {
+ public void writeValue(ReportLog log) throws IllegalStateException {
if (!this.measuredValueSet) {
throw new IllegalStateException("measured value not set for required measurement "
diff --git a/tests/mediapc/common/src/android/mediapc/cts/common/Requirement.java b/tests/mediapc/common/src/android/mediapc/cts/common/Requirement.java
index 445c5c60c69..2160b10ebaf 100644
--- a/tests/mediapc/common/src/android/mediapc/cts/common/Requirement.java
+++ b/tests/mediapc/common/src/android/mediapc/cts/common/Requirement.java
@@ -18,15 +18,13 @@ package android.mediapc.cts.common;
import android.util.Log;
-import androidx.test.platform.app.InstrumentationRegistry;
-
-import com.android.compatibility.common.util.DeviceReportLog;
+import com.android.compatibility.common.util.ReportLog;
import com.android.compatibility.common.util.ResultType;
import com.android.compatibility.common.util.ResultUnit;
+
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableMap;
-import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
@@ -113,7 +111,7 @@ public abstract class Requirement {
/**
* @return whether or not the requirement meets the device's specified performance class
*/
- public boolean writeLogAndCheck(String testName) {
+ public boolean writeLogAndCheck(ReportLog log, String testName) {
if (this.id == RequirementConstants.RTBD) {
// skip upload on any requirement without a specified id
Log.i(this.TAG, testName + "has requirement without set requirement id and test " +
@@ -123,7 +121,6 @@ public abstract class Requirement {
int perfClass = this.computePerformanceClass();
- DeviceReportLog log = new DeviceReportLog(RequirementConstants.REPORT_LOG_NAME, this.id);
log.addValue(RequirementConstants.TN_FIELD_NAME, testName, ResultType.NEUTRAL,
ResultUnit.NONE);
for (RequiredMeasurement rm: this.mRequiredMeasurements.values()) {
@@ -131,7 +128,6 @@ public abstract class Requirement {
}
log.addValue(RequirementConstants.PC_FIELD_NAME, perfClass, ResultType.NEUTRAL,
ResultUnit.NONE);
- log.submit(InstrumentationRegistry.getInstrumentation());
return this.checkPerformanceClass(Utils.getPerfClass());
}
diff --git a/tests/mediapc/common/src/android/mediapc/cts/common/RequirementConstants.java b/tests/mediapc/common/src/android/mediapc/cts/common/RequirementConstants.java
index 6f055954297..6893e620d93 100644
--- a/tests/mediapc/common/src/android/mediapc/cts/common/RequirementConstants.java
+++ b/tests/mediapc/common/src/android/mediapc/cts/common/RequirementConstants.java
@@ -80,6 +80,7 @@ public class RequirementConstants {
public static final String RTBD = "tbd"; // placeholder for requirements without a set id
public static final String CONCURRENT_SESSIONS = "concurrent_sessions";
+ public static final String TEST_RESOLUTION = "resolution";
public static final String CONCURRENT_FPS = "concurrent_fps";
public static final String SUPPORTED_PERFORMANCE_POINTS = "supported_performance_points";
public static final String FRAMES_DROPPED = "frame_drops_per_30sec";
diff --git a/tests/mediapc/common/tests/src/android/mediapc/cts/common/RequirementTest.java b/tests/mediapc/common/tests/src/android/mediapc/cts/common/RequirementTest.java
index daa9d274df7..1c5035b4d26 100644
--- a/tests/mediapc/common/tests/src/android/mediapc/cts/common/RequirementTest.java
+++ b/tests/mediapc/common/tests/src/android/mediapc/cts/common/RequirementTest.java
@@ -22,6 +22,8 @@ import static org.junit.Assert.assertThrows;
import android.os.Build;
+import com.android.compatibility.common.util.DeviceReportLog;
+
import org.junit.Test;
public class RequirementTest {
@@ -197,9 +199,10 @@ public class RequirementTest {
@Test
public void writeLogAndCheck_UnsetMeasurement() {
TestReq testReq = TestReq.create();
+ DeviceReportLog testLog = new DeviceReportLog("test", "test");
assertThrows(
IllegalStateException.class,
- () -> testReq.writeLogAndCheck("writeLogAndCheck_UnsetMeasurement"));
+ () -> testReq.writeLogAndCheck(testLog, "writeLogAndCheck_UnsetMeasurement"));
}
}
diff --git a/tests/tests/permission3/src/android/permission3/cts/BaseUsePermissionTest.kt b/tests/tests/permission3/src/android/permission3/cts/BaseUsePermissionTest.kt
index dfefabca4d0..f2e6affd515 100755
--- a/tests/tests/permission3/src/android/permission3/cts/BaseUsePermissionTest.kt
+++ b/tests/tests/permission3/src/android/permission3/cts/BaseUsePermissionTest.kt
@@ -597,8 +597,8 @@ abstract class BaseUsePermissionTest : BasePermissionTest() {
button.click()
}
- val shouldShowStorageWarning = !isWatch &&
- SdkLevel.isAtLeastT() && targetSdk <= Build.VERSION_CODES.S_V2 &&
+ val shouldShowStorageWarning = SdkLevel.isAtLeastT() &&
+ targetSdk <= Build.VERSION_CODES.S_V2 &&
permission in MEDIA_PERMISSIONS
if (shouldShowStorageWarning) {
click(By.res(ALERT_DIALOG_OK_BUTTON))