diff options
author | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2023-01-07 22:05:37 +0000 |
---|---|---|
committer | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2023-01-07 22:05:37 +0000 |
commit | 81025012dc7a102176449d269186de91e984c594 (patch) | |
tree | 922e8108e83e90657b3070c66407827ca9e731dc | |
parent | 99cb88b1c7be7c1b12da45316656546ced4cde26 (diff) | |
parent | fea58811da97306a4364a83088bf10ae877100a3 (diff) | |
download | cts-android13-qpr2-s3-release.tar.gz |
Snap for 9465878 from fea58811da97306a4364a83088bf10ae877100a3 to tm-qpr2-releaseandroid-13.0.0_r49android-13.0.0_r45android-13.0.0_r44android-13.0.0_r43android-13.0.0_r42android-13.0.0_r41android-13.0.0_r40android-13.0.0_r39android-13.0.0_r38android-13.0.0_r37android-13.0.0_r36android-13.0.0_r35android-13.0.0_r34android-13.0.0_r33android-13.0.0_r32android13-qpr2-s9-releaseandroid13-qpr2-s8-releaseandroid13-qpr2-s7-releaseandroid13-qpr2-s6-releaseandroid13-qpr2-s5-releaseandroid13-qpr2-s3-releaseandroid13-qpr2-s2-releaseandroid13-qpr2-s12-releaseandroid13-qpr2-s11-releaseandroid13-qpr2-s10-releaseandroid13-qpr2-s1-releaseandroid13-qpr2-releaseandroid13-qpr2-b-s1-release
Change-Id: Ia74ad141050c67928486cd10de198eada7ff9db1
4 files changed, 470 insertions, 477 deletions
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 b885a57ec25..3f386fac7c4 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/tests/telephony/current/src/android/telephony/cts/VisualVoicemailServiceTest.java b/tests/tests/telephony/current/src/android/telephony/cts/VisualVoicemailServiceTest.java index f77b879effe..f9691828646 100644 --- a/tests/tests/telephony/current/src/android/telephony/cts/VisualVoicemailServiceTest.java +++ b/tests/tests/telephony/current/src/android/telephony/cts/VisualVoicemailServiceTest.java @@ -532,7 +532,8 @@ public class VisualVoicemailServiceTest { for (SmsMessage message : messages) { String body = message.getMessageBody(); - if ((body == null || message.getReceivedEncodingType() == ENCODING_8BIT) + if ((body == null || (message.is3gpp() + && message.getReceivedEncodingType() == ENCODING_8BIT)) && message.getUserData() != null) { Log.d(TAG, "onReceive decode using UTF-8"); // Attempt to interpret the user data as UTF-8. UTF-8 string over data SMS using |