diff options
author | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2023-01-15 21:44:56 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2023-01-15 21:44:56 +0000 |
commit | 8e11ea226c6d3e3a92da7e2cde11e33868ebf0b7 (patch) | |
tree | 1fba5a35f2903295820aba0acfc40f9bed358ca5 | |
parent | a86947bd57dde335601337b066de5b3942db5a30 (diff) | |
parent | 33375336400cc9d5262a8a9be512dc90f4ec9f7c (diff) | |
download | cts-sparse-9492874-L70600000958413829.tar.gz |
Merge "Snap for 9491998 from b02bdb209055b85ab3c85b0a485f683e9efc10f5 to android13-tests-release" into android13-tests-releasesparse-9492874-L70600000958413829
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)) |