[automerger skipped] Replace the usage of UidRange am: 2257ecc830 -s ours am: 5e8d1596b6 -s ours
am skip reason: skip tag Change-Id I4bc0daf5ad9e4b4043f4a897ddab16aec8f8a536 with SHA-1 41918d6cd1 is already in history
Original change: https://googleplex-android-review.googlesource.com/c/platform/packages/modules/Connectivity/+/13958466
Change-Id: I056312ed3ec9c22854a09fa2f75cacca19c07e03
diff --git a/TEST_MAPPING b/TEST_MAPPING
index ef96d88..389453a 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -15,7 +15,8 @@
],
"mainline-presubmit": [
{
- "name": "CtsNetTestCasesLatestSdk[CaptivePortalLoginGoogle.apk+NetworkStackGoogle.apk+com.google.android.resolv.apex+com.google.android.tethering.apex]",
+ // TODO: add back the tethering modules when updatable in this branch
+ "name": "CtsNetTestCasesLatestSdk[CaptivePortalLoginGoogle.apk+NetworkStackGoogle.apk+com.google.android.resolv.apex]",
"options": [
{
"exclude-annotation": "com.android.testutils.SkipPresubmit"
@@ -26,7 +27,8 @@
// Tests on physical devices with SIM cards: postsubmit only for capacity constraints
"mainline-postsubmit": [
{
- "name": "CtsNetTestCasesLatestSdk[CaptivePortalLoginGoogle.apk+NetworkStackGoogle.apk+com.google.android.resolv.apex+com.google.android.tethering.apex]",
+ // TODO: add back the tethering module when updatable in this branch
+ "name": "CtsNetTestCasesLatestSdk[CaptivePortalLoginGoogle.apk+NetworkStackGoogle.apk+com.google.android.resolv.apex]",
"keywords": ["sim"]
}
]
diff --git a/Tethering/Android.bp b/Tethering/Android.bp
index 742fd02..4eafc2a 100644
--- a/Tethering/Android.bp
+++ b/Tethering/Android.bp
@@ -25,7 +25,7 @@
srcs: [
"apishim/**/*.java",
"src/**/*.java",
- ":framework-tethering-shared-srcs",
+ ":framework-connectivity-shared-srcs",
":tethering-module-utils-srcs",
":services-tethering-shared-srcs",
],
@@ -41,6 +41,7 @@
"netd-client",
],
libs: [
+ "framework-connectivity",
"framework-statsd.stubs.module_lib",
"framework-tethering.impl",
"framework-wifi",
diff --git a/Tethering/apex/Android.bp b/Tethering/apex/Android.bp
index 6703e46..164bda4 100644
--- a/Tethering/apex/Android.bp
+++ b/Tethering/apex/Android.bp
@@ -20,14 +20,25 @@
apex {
name: "com.android.tethering",
- updatable: true,
- min_sdk_version: "30",
- java_libs: ["framework-tethering"],
+ // TODO: make updatable again once this contains only updatable artifacts (in particular, this
+ // cannot build as updatable unless service-connectivity builds against stable API).
+ updatable: false,
+ // min_sdk_version: "30",
+ java_libs: [
+ "framework-tethering",
+ "service-connectivity",
+ ],
+ jni_libs: [
+ "libservice-connectivity",
+ ],
bpfs: [
"offload.o",
"test.o",
],
- apps: ["Tethering"],
+ apps: [
+ "ServiceConnectivityResources",
+ "Tethering",
+ ],
manifest: "manifest.json",
key: "com.android.tethering.key",
@@ -50,6 +61,7 @@
base: "com.android.tethering",
package_name: "com.android.tethering.inprocess",
apps: [
+ "ServiceConnectivityResources",
"InProcessTethering",
],
}
diff --git a/Tethering/common/TetheringLib/Android.bp b/Tethering/common/TetheringLib/Android.bp
index 2631d08..b141eae 100644
--- a/Tethering/common/TetheringLib/Android.bp
+++ b/Tethering/common/TetheringLib/Android.bp
@@ -26,6 +26,13 @@
],
srcs: [":framework-tethering-srcs"],
+ libs: ["framework-connectivity"],
+ stub_only_libs: ["framework-connectivity"],
+ aidl: {
+ include_dirs: [
+ "frameworks/base/packages/Connectivity/framework/aidl-export",
+ ],
+ },
jarjar_rules: "jarjar-rules.txt",
installable: true,
diff --git a/Tethering/jarjar-rules.txt b/Tethering/jarjar-rules.txt
index d1ad569..5de4b97 100644
--- a/Tethering/jarjar-rules.txt
+++ b/Tethering/jarjar-rules.txt
@@ -1,5 +1,5 @@
-# These must be kept in sync with the framework-tethering-shared-srcs filegroup.
-# Classes from the framework-tethering-shared-srcs filegroup.
+# These must be kept in sync with the framework-connectivity-shared-srcs filegroup.
+# Classes from the framework-connectivity-shared-srcs filegroup.
# If there are files in that filegroup that are not covered below, the classes in the
# module will be overwritten by the ones in the framework.
rule com.android.internal.util.** com.android.networkstack.tethering.util.@1
diff --git a/Tethering/src/android/net/ip/RouterAdvertisementDaemon.java b/Tethering/src/android/net/ip/RouterAdvertisementDaemon.java
index 7c0b7cc..afccd0a 100644
--- a/Tethering/src/android/net/ip/RouterAdvertisementDaemon.java
+++ b/Tethering/src/android/net/ip/RouterAdvertisementDaemon.java
@@ -37,7 +37,7 @@
import android.util.Log;
import com.android.internal.annotations.GuardedBy;
-import com.android.internal.util.TrafficStatsConstants;
+import com.android.net.module.util.NetworkStackConstants;
import java.io.FileDescriptor;
import java.io.IOException;
@@ -589,7 +589,7 @@
final int send_timout_ms = 300;
final int oldTag = TrafficStats.getAndSetThreadStatsTag(
- TrafficStatsConstants.TAG_SYSTEM_NEIGHBOR);
+ NetworkStackConstants.TAG_SYSTEM_NEIGHBOR);
try {
mSocket = Os.socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
// Setting SNDTIMEO is purely for defensive purposes.
diff --git a/Tethering/src/com/android/networkstack/tethering/TetheringService.java b/Tethering/src/com/android/networkstack/tethering/TetheringService.java
index 1622175..f3cd549 100644
--- a/Tethering/src/com/android/networkstack/tethering/TetheringService.java
+++ b/Tethering/src/com/android/networkstack/tethering/TetheringService.java
@@ -302,10 +302,8 @@
boolean checkAndNoteWriteSettingsOperation(@NonNull Context context, int uid,
@NonNull String callingPackage, @Nullable String callingAttributionTag,
boolean throwException) {
- // TODO: on S and above, pass the attribution tag to Settings instead of throwing it away.
- // This will likely require a SettingsShim class.
return Settings.checkAndNoteWriteSettingsOperation(context, uid, callingPackage,
- throwException);
+ callingAttributionTag, throwException);
}
/**
diff --git a/Tethering/tests/unit/Android.bp b/Tethering/tests/unit/Android.bp
index d469b37..41135f2 100644
--- a/Tethering/tests/unit/Android.bp
+++ b/Tethering/tests/unit/Android.bp
@@ -33,6 +33,7 @@
sdk_version: "core_platform",
libs: [
"framework-minus-apex",
+ "framework-connectivity.stubs.module_lib",
"framework-tethering.impl",
],
visibility: [
@@ -66,6 +67,7 @@
"ext",
"framework-minus-apex",
"framework-res",
+ "framework-connectivity.impl",
"framework-tethering.impl",
"framework-wifi.stubs.module_lib",
],
diff --git a/tests/cts/hostside/AndroidTest.xml b/tests/cts/hostside/AndroidTest.xml
index b7fefaf..7a73313 100644
--- a/tests/cts/hostside/AndroidTest.xml
+++ b/tests/cts/hostside/AndroidTest.xml
@@ -23,7 +23,10 @@
<target_preparer class="com.android.compatibility.common.tradefed.targetprep.LocationCheck" />
<target_preparer class="com.android.cts.net.NetworkPolicyTestsPreparer" />
+ <!-- Enabling change id ALLOW_TEST_API_ACCESS allows that package to access @TestApi methods -->
<target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
+ <option name="run-command" value="am compat enable ALLOW_TEST_API_ACCESS com.android.cts.net.hostside.app2" />
+ <option name="teardown-command" value="am compat reset ALLOW_TEST_API_ACCESS com.android.cts.net.hostside.app2" />
<option name="teardown-command" value="cmd power set-mode 0" />
<option name="teardown-command" value="cmd battery reset" />
<option name="teardown-command" value="cmd netpolicy stop-watching" />
diff --git a/tests/cts/hostside/aidl/com/android/cts/net/hostside/IMyService.aidl b/tests/cts/hostside/aidl/com/android/cts/net/hostside/IMyService.aidl
index 5aafdf0..fbbb68b 100644
--- a/tests/cts/hostside/aidl/com/android/cts/net/hostside/IMyService.aidl
+++ b/tests/cts/hostside/aidl/com/android/cts/net/hostside/IMyService.aidl
@@ -16,6 +16,8 @@
package com.android.cts.net.hostside;
+import android.app.job.JobInfo;
+
import com.android.cts.net.hostside.INetworkCallback;
interface IMyService {
@@ -26,4 +28,5 @@
void sendNotification(int notificationId, String notificationType);
void registerNetworkCallback(in INetworkCallback cb);
void unregisterNetworkCallback();
+ void scheduleJob(in JobInfo jobInfo);
}
diff --git a/tests/cts/hostside/aidl/com/android/cts/net/hostside/INetworkStateObserver.aidl b/tests/cts/hostside/aidl/com/android/cts/net/hostside/INetworkStateObserver.aidl
index 165f530..19198c5 100644
--- a/tests/cts/hostside/aidl/com/android/cts/net/hostside/INetworkStateObserver.aidl
+++ b/tests/cts/hostside/aidl/com/android/cts/net/hostside/INetworkStateObserver.aidl
@@ -17,6 +17,10 @@
package com.android.cts.net.hostside;
interface INetworkStateObserver {
- boolean isForeground();
- void onNetworkStateChecked(String resultData);
+ void onNetworkStateChecked(int resultCode, String resultData);
+
+ const int RESULT_SUCCESS_NETWORK_STATE_CHECKED = 0;
+ const int RESULT_ERROR_UNEXPECTED_PROC_STATE = 1;
+ const int RESULT_ERROR_UNEXPECTED_CAPABILITIES = 2;
+ const int RESULT_ERROR_OTHER = 3;
}
\ No newline at end of file
diff --git a/tests/cts/hostside/app/Android.bp b/tests/cts/hostside/app/Android.bp
index 50fda6d..f351b47 100644
--- a/tests/cts/hostside/app/Android.bp
+++ b/tests/cts/hostside/app/Android.bp
@@ -37,10 +37,6 @@
"android.test.base",
],
srcs: ["src/**/*.java"],
- // STOPSHIP: remove this before releasing any networking modules.
- exclude_srcs: [
- "src/com/android/cts/net/hostside/VpnTest.java",
- ],
// Tag this module as a cts test artifact
test_suites: [
"cts",
diff --git a/tests/cts/hostside/app/src/com/android/cts/net/hostside/AbstractAppIdleTestCase.java b/tests/cts/hostside/app/src/com/android/cts/net/hostside/AbstractAppIdleTestCase.java
index f9e30b6..d9ff539 100644
--- a/tests/cts/hostside/app/src/com/android/cts/net/hostside/AbstractAppIdleTestCase.java
+++ b/tests/cts/hostside/app/src/com/android/cts/net/hostside/AbstractAppIdleTestCase.java
@@ -50,7 +50,7 @@
public final void tearDown() throws Exception {
super.tearDown();
- executeSilentShellCommand("cmd battery reset");
+ resetBatteryState();
setAppIdle(false);
}
diff --git a/tests/cts/hostside/app/src/com/android/cts/net/hostside/AbstractDozeModeTestCase.java b/tests/cts/hostside/app/src/com/android/cts/net/hostside/AbstractDozeModeTestCase.java
index 6f32c56..e0ce4ea 100644
--- a/tests/cts/hostside/app/src/com/android/cts/net/hostside/AbstractDozeModeTestCase.java
+++ b/tests/cts/hostside/app/src/com/android/cts/net/hostside/AbstractDozeModeTestCase.java
@@ -101,7 +101,7 @@
@Test
public void testBackgroundNetworkAccess_enabledButWhitelistedOnNotificationAction()
throws Exception {
- setPendingIntentWhitelistDuration(NETWORK_TIMEOUT_MS);
+ setPendingIntentAllowlistDuration(NETWORK_TIMEOUT_MS);
try {
registerNotificationListenerService();
setDozeMode(true);
diff --git a/tests/cts/hostside/app/src/com/android/cts/net/hostside/AbstractExpeditedJobTest.java b/tests/cts/hostside/app/src/com/android/cts/net/hostside/AbstractExpeditedJobTest.java
new file mode 100644
index 0000000..a850e3b
--- /dev/null
+++ b/tests/cts/hostside/app/src/com/android/cts/net/hostside/AbstractExpeditedJobTest.java
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.net.hostside;
+
+import static com.android.cts.net.hostside.NetworkPolicyTestUtils.setRestrictBackground;
+import static com.android.cts.net.hostside.Property.APP_STANDBY_MODE;
+import static com.android.cts.net.hostside.Property.BATTERY_SAVER_MODE;
+import static com.android.cts.net.hostside.Property.DATA_SAVER_MODE;
+import static com.android.cts.net.hostside.Property.DOZE_MODE;
+import static com.android.cts.net.hostside.Property.METERED_NETWORK;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+public class AbstractExpeditedJobTest extends AbstractRestrictBackgroundNetworkTestCase {
+ @Before
+ public final void setUp() throws Exception {
+ super.setUp();
+ resetDeviceState();
+ }
+
+ @After
+ public final void tearDown() throws Exception {
+ super.tearDown();
+ resetDeviceState();
+ }
+
+ private void resetDeviceState() throws Exception {
+ resetBatteryState();
+ setBatterySaverMode(false);
+ setRestrictBackground(false);
+ setAppIdle(false);
+ setDozeMode(false);
+ }
+
+ @Test
+ @RequiredProperties({BATTERY_SAVER_MODE})
+ public void testNetworkAccess_batterySaverMode() throws Exception {
+ assertBackgroundNetworkAccess(true);
+ assertExpeditedJobHasNetworkAccess();
+
+ setBatterySaverMode(true);
+ assertBackgroundNetworkAccess(false);
+ assertExpeditedJobHasNetworkAccess();
+ }
+
+ @Test
+ @RequiredProperties({DATA_SAVER_MODE, METERED_NETWORK})
+ public void testNetworkAccess_dataSaverMode() throws Exception {
+ assertBackgroundNetworkAccess(true);
+ assertExpeditedJobHasNetworkAccess();
+
+ setRestrictBackground(true);
+ assertBackgroundNetworkAccess(false);
+ assertExpeditedJobHasNoNetworkAccess();
+ }
+
+ @Test
+ @RequiredProperties({APP_STANDBY_MODE})
+ public void testNetworkAccess_appIdleState() throws Exception {
+ turnBatteryOn();
+ assertBackgroundNetworkAccess(true);
+ assertExpeditedJobHasNetworkAccess();
+
+ setAppIdle(true);
+ assertBackgroundNetworkAccess(false);
+ assertExpeditedJobHasNetworkAccess();
+ }
+
+ @Test
+ @RequiredProperties({DOZE_MODE})
+ public void testNetworkAccess_dozeMode() throws Exception {
+ assertBackgroundNetworkAccess(true);
+ assertExpeditedJobHasNetworkAccess();
+
+ setDozeMode(true);
+ assertBackgroundNetworkAccess(false);
+ assertExpeditedJobHasNetworkAccess();
+ }
+
+ @Test
+ @RequiredProperties({DATA_SAVER_MODE, BATTERY_SAVER_MODE, METERED_NETWORK})
+ public void testNetworkAccess_dataAndBatterySaverMode() throws Exception {
+ assertBackgroundNetworkAccess(true);
+ assertExpeditedJobHasNetworkAccess();
+
+ setRestrictBackground(true);
+ setBatterySaverMode(true);
+ assertBackgroundNetworkAccess(false);
+ assertExpeditedJobHasNoNetworkAccess();
+ }
+
+ @Test
+ @RequiredProperties({DOZE_MODE, DATA_SAVER_MODE, METERED_NETWORK})
+ public void testNetworkAccess_dozeAndDataSaverMode() throws Exception {
+ assertBackgroundNetworkAccess(true);
+ assertExpeditedJobHasNetworkAccess();
+
+ setRestrictBackground(true);
+ setDozeMode(true);
+ assertBackgroundNetworkAccess(false);
+ assertExpeditedJobHasNoNetworkAccess();
+ }
+
+ @Test
+ @RequiredProperties({DATA_SAVER_MODE, BATTERY_SAVER_MODE, METERED_NETWORK, DOZE_MODE,
+ APP_STANDBY_MODE})
+ public void testNetworkAccess_allRestrictionsEnabled() throws Exception {
+ assertBackgroundNetworkAccess(true);
+ assertExpeditedJobHasNetworkAccess();
+
+ setRestrictBackground(true);
+ setBatterySaverMode(true);
+ setAppIdle(true);
+ setDozeMode(true);
+ assertBackgroundNetworkAccess(false);
+ assertExpeditedJobHasNoNetworkAccess();
+ }
+}
diff --git a/tests/cts/hostside/app/src/com/android/cts/net/hostside/AbstractRestrictBackgroundNetworkTestCase.java b/tests/cts/hostside/app/src/com/android/cts/net/hostside/AbstractRestrictBackgroundNetworkTestCase.java
index f423503..ac649b2 100644
--- a/tests/cts/hostside/app/src/com/android/cts/net/hostside/AbstractRestrictBackgroundNetworkTestCase.java
+++ b/tests/cts/hostside/app/src/com/android/cts/net/hostside/AbstractRestrictBackgroundNetworkTestCase.java
@@ -22,10 +22,12 @@
import static android.os.BatteryManager.BATTERY_PLUGGED_WIRELESS;
import static com.android.cts.net.hostside.NetworkPolicyTestUtils.executeShellCommand;
+import static com.android.cts.net.hostside.NetworkPolicyTestUtils.forceRunJob;
import static com.android.cts.net.hostside.NetworkPolicyTestUtils.getConnectivityManager;
import static com.android.cts.net.hostside.NetworkPolicyTestUtils.getContext;
import static com.android.cts.net.hostside.NetworkPolicyTestUtils.getInstrumentation;
-import static com.android.cts.net.hostside.NetworkPolicyTestUtils.getWifiManager;
+import static com.android.cts.net.hostside.NetworkPolicyTestUtils.isAppStandbySupported;
+import static com.android.cts.net.hostside.NetworkPolicyTestUtils.isBatterySaverSupported;
import static com.android.cts.net.hostside.NetworkPolicyTestUtils.isDozeModeSupported;
import static com.android.cts.net.hostside.NetworkPolicyTestUtils.restrictBackgroundValueToString;
@@ -38,6 +40,7 @@
import android.app.ActivityManager;
import android.app.Instrumentation;
import android.app.NotificationManager;
+import android.app.job.JobInfo;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
@@ -46,19 +49,23 @@
import android.net.ConnectivityManager;
import android.net.NetworkInfo.DetailedState;
import android.net.NetworkInfo.State;
-import android.net.wifi.WifiManager;
import android.os.BatteryManager;
import android.os.Binder;
import android.os.Bundle;
import android.os.SystemClock;
-import android.provider.Settings;
+import android.provider.DeviceConfig;
import android.service.notification.NotificationListenerService;
import android.util.Log;
+import android.util.Pair;
+
+import com.android.compatibility.common.util.BatteryUtils;
+import com.android.compatibility.common.util.DeviceConfigStateHelper;
import org.junit.Rule;
import org.junit.rules.RuleChain;
import org.junit.runner.RunWith;
+import java.util.ArrayList;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
@@ -75,12 +82,22 @@
private static final String TEST_APP2_ACTIVITY_CLASS = TEST_APP2_PKG + ".MyActivity";
private static final String TEST_APP2_SERVICE_CLASS = TEST_APP2_PKG + ".MyForegroundService";
+ private static final String TEST_APP2_JOB_SERVICE_CLASS = TEST_APP2_PKG + ".MyJobService";
+
+ private static final ComponentName TEST_JOB_COMPONENT = new ComponentName(
+ TEST_APP2_PKG, TEST_APP2_JOB_SERVICE_CLASS);
+
+ private static final int TEST_JOB_ID = 7357437;
private static final int SLEEP_TIME_SEC = 1;
// Constants below must match values defined on app2's Common.java
private static final String MANIFEST_RECEIVER = "ManifestReceiver";
private static final String DYNAMIC_RECEIVER = "DynamicReceiver";
+ private static final String ACTION_FINISH_ACTIVITY =
+ "com.android.cts.net.hostside.app2.action.FINISH_ACTIVITY";
+ private static final String ACTION_FINISH_JOB =
+ "com.android.cts.net.hostside.app2.action.FINISH_JOB";
private static final String ACTION_RECEIVER_READY =
"com.android.cts.net.hostside.app2.action.RECEIVER_READY";
@@ -102,17 +119,22 @@
private static final String NETWORK_STATUS_SEPARATOR = "\\|";
private static final int SECOND_IN_MS = 1000;
static final int NETWORK_TIMEOUT_MS = 15 * SECOND_IN_MS;
+
private static int PROCESS_STATE_FOREGROUND_SERVICE;
+ private static int PROCESS_STATE_IMPORTANT_FOREGROUND;
private static final String KEY_NETWORK_STATE_OBSERVER = TEST_PKG + ".observer";
+ private static final String KEY_SKIP_VALIDATION_CHECKS = TEST_PKG + ".skip_validation_checks";
protected static final int TYPE_COMPONENT_ACTIVTIY = 0;
protected static final int TYPE_COMPONENT_FOREGROUND_SERVICE = 1;
+ protected static final int TYPE_EXPEDITED_JOB = 2;
private static final int BATTERY_STATE_TIMEOUT_MS = 5000;
private static final int BATTERY_STATE_CHECK_INTERVAL_MS = 500;
- private static final int FOREGROUND_PROC_NETWORK_TIMEOUT_MS = 6000;
+ private static final int ACTIVITY_NETWORK_STATE_TIMEOUT_MS = 6_000;
+ private static final int JOB_NETWORK_STATE_TIMEOUT_MS = 10_000;
// Must be higher than NETWORK_TIMEOUT_MS
private static final int ORDERED_BROADCAST_TIMEOUT_MS = NETWORK_TIMEOUT_MS * 4;
@@ -130,24 +152,27 @@
protected int mUid;
private int mMyUid;
private MyServiceClient mServiceClient;
- private String mDeviceIdleConstantsSetting;
+ private DeviceConfigStateHelper mDeviceIdleDeviceConfigStateHelper;
@Rule
public final RuleChain mRuleChain = RuleChain.outerRule(new RequiredPropertiesRule())
.around(new MeterednessConfigurationRule());
protected void setUp() throws Exception {
-
+ // TODO: Annotate these constants with @TestApi instead of obtaining them using reflection
PROCESS_STATE_FOREGROUND_SERVICE = (Integer) ActivityManager.class
.getDeclaredField("PROCESS_STATE_FOREGROUND_SERVICE").get(null);
+ PROCESS_STATE_IMPORTANT_FOREGROUND = (Integer) ActivityManager.class
+ .getDeclaredField("PROCESS_STATE_IMPORTANT_FOREGROUND").get(null);
mInstrumentation = getInstrumentation();
mContext = getContext();
mCm = getConnectivityManager();
+ mDeviceIdleDeviceConfigStateHelper =
+ new DeviceConfigStateHelper(DeviceConfig.NAMESPACE_DEVICE_IDLE);
mUid = getUid(TEST_APP2_PKG);
mMyUid = getUid(mContext.getPackageName());
mServiceClient = new MyServiceClient(mContext);
mServiceClient.bind();
- mDeviceIdleConstantsSetting = "device_idle_constants";
executeShellCommand("cmd netpolicy start-watching " + mUid);
setAppIdle(false);
@@ -254,8 +279,8 @@
/**
* Asserts that an app always have access while on foreground or running a foreground service.
*
- * <p>This method will launch an activity and a foreground service to make the assertion, but
- * will finish the activity / stop the service afterwards.
+ * <p>This method will launch an activity, a foreground service to make
+ * the assertion, but will finish the activity / stop the service afterwards.
*/
protected void assertsForegroundAlwaysHasNetworkAccess() throws Exception{
// Checks foreground first.
@@ -267,6 +292,16 @@
stopForegroundService();
}
+ protected void assertExpeditedJobHasNetworkAccess() throws Exception {
+ launchComponentAndAssertNetworkAccess(TYPE_EXPEDITED_JOB);
+ finishExpeditedJob();
+ }
+
+ protected void assertExpeditedJobHasNoNetworkAccess() throws Exception {
+ launchComponentAndAssertNetworkAccess(TYPE_EXPEDITED_JOB, false);
+ finishExpeditedJob();
+ }
+
protected final void assertBackgroundState() throws Exception {
final int maxTries = 30;
ProcessState state = null;
@@ -323,7 +358,7 @@
* Returns whether an app state should be considered "background" for restriction purposes.
*/
protected boolean isBackground(int state) {
- return state > PROCESS_STATE_FOREGROUND_SERVICE;
+ return state > PROCESS_STATE_IMPORTANT_FOREGROUND;
}
/**
@@ -338,7 +373,7 @@
for (int i = 1; i <= maxTries; i++) {
error = checkNetworkAccess(expectAvailable);
- if (error.isEmpty()) return;
+ if (error == null) return;
// TODO: ideally, it should retry only when it cannot connect to an external site,
// or no retry at all! But, currently, the initial change fails almost always on
@@ -410,7 +445,7 @@
errors.append("\tnetworkInfo: " + networkInfo + "\n");
errors.append("\tconnectionCheckDetails: " + connectionCheckDetails + "\n");
}
- return errors.toString();
+ return errors.length() == 0 ? null : errors.toString();
}
/**
@@ -602,6 +637,10 @@
assertBatteryState(true);
}
+ protected void resetBatteryState() {
+ BatteryUtils.runDumpsysBatteryReset();
+ }
+
private void assertBatteryState(boolean pluggedIn) throws Exception {
final long endTime = SystemClock.elapsedRealtime() + BATTERY_STATE_TIMEOUT_MS;
while (isDevicePluggedIn() != pluggedIn && SystemClock.elapsedRealtime() <= endTime) {
@@ -628,6 +667,9 @@
}
protected void setBatterySaverMode(boolean enabled) throws Exception {
+ if (!isBatterySaverSupported()) {
+ return;
+ }
Log.i(TAG, "Setting Battery Saver Mode to " + enabled);
if (enabled) {
turnBatteryOn();
@@ -639,8 +681,9 @@
}
protected void setDozeMode(boolean enabled) throws Exception {
- // Check doze mode is supported.
- assertTrue("Device does not support Doze Mode", isDozeModeSupported());
+ if (!isDozeModeSupported()) {
+ return;
+ }
Log.i(TAG, "Setting Doze Mode to " + enabled);
if (enabled) {
@@ -660,12 +703,18 @@
}
protected void setAppIdle(boolean enabled) throws Exception {
+ if (!isAppStandbySupported()) {
+ return;
+ }
Log.i(TAG, "Setting app idle to " + enabled);
executeSilentShellCommand("am set-inactive " + TEST_APP2_PKG + " " + enabled );
assertAppIdle(enabled);
}
protected void setAppIdleNoAssert(boolean enabled) throws Exception {
+ if (!isAppStandbySupported()) {
+ return;
+ }
Log.i(TAG, "Setting app idle to " + enabled);
executeSilentShellCommand("am set-inactive " + TEST_APP2_PKG + " " + enabled );
}
@@ -725,18 +774,21 @@
nm.isNotificationListenerAccessGranted(listenerComponent));
}
- protected void setPendingIntentWhitelistDuration(int durationMs) throws Exception {
- executeSilentShellCommand(String.format(
- "settings put global %s %s=%d", mDeviceIdleConstantsSetting,
- "notification_whitelist_duration", durationMs));
+ protected void setPendingIntentAllowlistDuration(long durationMs) {
+ mDeviceIdleDeviceConfigStateHelper.set("notification_allowlist_duration_ms",
+ String.valueOf(durationMs));
}
- protected void resetDeviceIdleSettings() throws Exception {
- executeShellCommand(String.format("settings delete global %s",
- mDeviceIdleConstantsSetting));
+ protected void resetDeviceIdleSettings() {
+ mDeviceIdleDeviceConfigStateHelper.restoreOriginalValues();
}
protected void launchComponentAndAssertNetworkAccess(int type) throws Exception {
+ launchComponentAndAssertNetworkAccess(type, true);
+ }
+
+ protected void launchComponentAndAssertNetworkAccess(int type, boolean expectAvailable)
+ throws Exception {
if (type == TYPE_COMPONENT_FOREGROUND_SERVICE) {
startForegroundService();
assertForegroundServiceNetworkAccess();
@@ -748,21 +800,61 @@
final CountDownLatch latch = new CountDownLatch(1);
final Intent launchIntent = getIntentForComponent(type);
final Bundle extras = new Bundle();
- final String[] errors = new String[]{null};
- extras.putBinder(KEY_NETWORK_STATE_OBSERVER, getNewNetworkStateObserver(latch, errors));
+ final ArrayList<Pair<Integer, String>> result = new ArrayList<>(1);
+ extras.putBinder(KEY_NETWORK_STATE_OBSERVER, getNewNetworkStateObserver(latch, result));
+ extras.putBoolean(KEY_SKIP_VALIDATION_CHECKS, !expectAvailable);
launchIntent.putExtras(extras);
mContext.startActivity(launchIntent);
- if (latch.await(FOREGROUND_PROC_NETWORK_TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
- if (!errors[0].isEmpty()) {
- if (errors[0] == APP_NOT_FOREGROUND_ERROR) {
- // App didn't come to foreground when the activity is started, so try again.
- assertForegroundNetworkAccess();
- } else {
- fail("Network is not available for app2 (" + mUid + "): " + errors[0]);
+ if (latch.await(ACTIVITY_NETWORK_STATE_TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
+ final int resultCode = result.get(0).first;
+ final String resultData = result.get(0).second;
+ if (resultCode == INetworkStateObserver.RESULT_SUCCESS_NETWORK_STATE_CHECKED) {
+ final String error = checkForAvailabilityInResultData(
+ resultData, expectAvailable);
+ if (error != null) {
+ fail("Network is not available for activity in app2 (" + mUid + "): "
+ + error);
}
+ } else if (resultCode == INetworkStateObserver.RESULT_ERROR_UNEXPECTED_PROC_STATE) {
+ Log.d(TAG, resultData);
+ // App didn't come to foreground when the activity is started, so try again.
+ assertForegroundNetworkAccess();
+ } else {
+ fail("Unexpected resultCode=" + resultCode + "; received=[" + resultData + "]");
}
} else {
- fail("Timed out waiting for network availability status from app2 (" + mUid + ")");
+ fail("Timed out waiting for network availability status from app2's activity ("
+ + mUid + ")");
+ }
+ } else if (type == TYPE_EXPEDITED_JOB) {
+ final Bundle extras = new Bundle();
+ final ArrayList<Pair<Integer, String>> result = new ArrayList<>(1);
+ final CountDownLatch latch = new CountDownLatch(1);
+ extras.putBinder(KEY_NETWORK_STATE_OBSERVER, getNewNetworkStateObserver(latch, result));
+ extras.putBoolean(KEY_SKIP_VALIDATION_CHECKS, !expectAvailable);
+ final JobInfo jobInfo = new JobInfo.Builder(TEST_JOB_ID, TEST_JOB_COMPONENT)
+ .setExpedited(true)
+ .setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY)
+ .setTransientExtras(extras)
+ .build();
+ mServiceClient.scheduleJob(jobInfo);
+ forceRunJob(TEST_APP2_PKG, TEST_JOB_ID);
+ if (latch.await(JOB_NETWORK_STATE_TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
+ final int resultCode = result.get(0).first;
+ final String resultData = result.get(0).second;
+ if (resultCode == INetworkStateObserver.RESULT_SUCCESS_NETWORK_STATE_CHECKED) {
+ final String error = checkForAvailabilityInResultData(
+ resultData, expectAvailable);
+ if (error != null) {
+ fail("Network is not available for expedited job in app2 (" + mUid + "): "
+ + error);
+ }
+ } else {
+ fail("Unexpected resultCode=" + resultCode + "; received=[" + resultData + "]");
+ }
+ } else {
+ fail("Timed out waiting for network availability status from app2's expedited job ("
+ + mUid + ")");
}
} else {
throw new IllegalArgumentException("Unknown type: " + type);
@@ -796,36 +888,34 @@
}
private Binder getNewNetworkStateObserver(final CountDownLatch latch,
- final String[] errors) {
+ final ArrayList<Pair<Integer, String>> result) {
return new INetworkStateObserver.Stub() {
@Override
- public boolean isForeground() {
- try {
- final ProcessState state = getProcessStateByUid(mUid);
- return !isBackground(state.state);
- } catch (Exception e) {
- Log.d(TAG, "Error while reading the proc state for " + mUid + ": " + e);
- return false;
- }
- }
-
- @Override
- public void onNetworkStateChecked(String resultData) {
- errors[0] = resultData == null
- ? APP_NOT_FOREGROUND_ERROR
- : checkForAvailabilityInResultData(resultData, true);
+ public void onNetworkStateChecked(int resultCode, String resultData) {
+ result.add(Pair.create(resultCode, resultData));
latch.countDown();
}
};
}
/**
- * Finishes an activity on app2 so its process is demoted fromforeground status.
+ * Finishes an activity on app2 so its process is demoted from foreground status.
*/
protected void finishActivity() throws Exception {
- executeShellCommand("am broadcast -a "
- + " com.android.cts.net.hostside.app2.action.FINISH_ACTIVITY "
- + "--receiver-foreground --receiver-registered-only");
+ final Intent intent = new Intent(ACTION_FINISH_ACTIVITY)
+ .setPackage(TEST_APP2_PKG)
+ .setFlags(Intent.FLAG_RECEIVER_FOREGROUND | Intent.FLAG_RECEIVER_REGISTERED_ONLY);
+ sendOrderedBroadcast(intent);
+ }
+
+ /**
+ * Finishes the expedited job on app2 so its process is demoted from foreground status.
+ */
+ private void finishExpeditedJob() throws Exception {
+ final Intent intent = new Intent(ACTION_FINISH_JOB)
+ .setPackage(TEST_APP2_PKG)
+ .setFlags(Intent.FLAG_RECEIVER_FOREGROUND | Intent.FLAG_RECEIVER_REGISTERED_ONLY);
+ sendOrderedBroadcast(intent);
}
protected void sendNotification(int notificationId, String notificationType) throws Exception {
diff --git a/tests/cts/hostside/app/src/com/android/cts/net/hostside/ExpeditedJobMeteredTest.java b/tests/cts/hostside/app/src/com/android/cts/net/hostside/ExpeditedJobMeteredTest.java
new file mode 100644
index 0000000..3809534
--- /dev/null
+++ b/tests/cts/hostside/app/src/com/android/cts/net/hostside/ExpeditedJobMeteredTest.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.net.hostside;
+
+import static com.android.cts.net.hostside.Property.METERED_NETWORK;
+
+@RequiredProperties({METERED_NETWORK})
+public class ExpeditedJobMeteredTest extends AbstractExpeditedJobTest {
+}
diff --git a/tests/cts/hostside/app/src/com/android/cts/net/hostside/ExpeditedJobNonMeteredTest.java b/tests/cts/hostside/app/src/com/android/cts/net/hostside/ExpeditedJobNonMeteredTest.java
new file mode 100644
index 0000000..6596269
--- /dev/null
+++ b/tests/cts/hostside/app/src/com/android/cts/net/hostside/ExpeditedJobNonMeteredTest.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.net.hostside;
+
+import static com.android.cts.net.hostside.Property.NON_METERED_NETWORK;
+
+@RequiredProperties({NON_METERED_NETWORK})
+public class ExpeditedJobNonMeteredTest extends AbstractExpeditedJobTest {
+}
diff --git a/tests/cts/hostside/app/src/com/android/cts/net/hostside/MyServiceClient.java b/tests/cts/hostside/app/src/com/android/cts/net/hostside/MyServiceClient.java
index 6546e26..1339be6 100644
--- a/tests/cts/hostside/app/src/com/android/cts/net/hostside/MyServiceClient.java
+++ b/tests/cts/hostside/app/src/com/android/cts/net/hostside/MyServiceClient.java
@@ -16,6 +16,7 @@
package com.android.cts.net.hostside;
+import android.app.job.JobInfo;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -104,4 +105,8 @@
public void unregisterNetworkCallback() throws RemoteException {
mService.unregisterNetworkCallback();
}
+
+ public void scheduleJob(JobInfo jobInfo) throws RemoteException {
+ mService.scheduleJob(jobInfo);
+ }
}
diff --git a/tests/cts/hostside/app/src/com/android/cts/net/hostside/NetworkPolicyTestUtils.java b/tests/cts/hostside/app/src/com/android/cts/net/hostside/NetworkPolicyTestUtils.java
index 05f86f7..9d1d418 100644
--- a/tests/cts/hostside/app/src/com/android/cts/net/hostside/NetworkPolicyTestUtils.java
+++ b/tests/cts/hostside/app/src/com/android/cts/net/hostside/NetworkPolicyTestUtils.java
@@ -48,6 +48,7 @@
import android.net.wifi.WifiManager.ActionListener;
import android.os.PersistableBundle;
import android.os.Process;
+import android.os.UserHandle;
import android.telephony.CarrierConfigManager;
import android.telephony.SubscriptionManager;
import android.telephony.data.ApnSetting;
@@ -106,11 +107,11 @@
if (mDataSaverSupported == null) {
assertMyRestrictBackgroundStatus(RESTRICT_BACKGROUND_STATUS_DISABLED);
try {
- setRestrictBackground(true);
+ setRestrictBackgroundInternal(true);
mDataSaverSupported = !isMyRestrictBackgroundStatus(
RESTRICT_BACKGROUND_STATUS_DISABLED);
} finally {
- setRestrictBackground(false);
+ setRestrictBackgroundInternal(false);
}
}
return mDataSaverSupported;
@@ -137,6 +138,12 @@
return am.isLowRamDevice();
}
+ /** Forces JobScheduler to run the job if constraints are met. */
+ public static void forceRunJob(String pkg, int jobId) {
+ executeShellCommand("cmd jobscheduler run -f -u " + UserHandle.myUserId()
+ + " " + pkg + " " + jobId);
+ }
+
public static boolean isLocationEnabled() {
final LocationManager lm = (LocationManager) getContext().getSystemService(
Context.LOCATION_SERVICE);
@@ -318,6 +325,13 @@
}
public static void setRestrictBackground(boolean enabled) {
+ if (!isDataSaverSupported()) {
+ return;
+ }
+ setRestrictBackgroundInternal(enabled);
+ }
+
+ private static void setRestrictBackgroundInternal(boolean enabled) {
executeShellCommand("cmd netpolicy set restrict-background " + enabled);
final String output = executeShellCommand("cmd netpolicy get restrict-background");
final String expectedSuffix = enabled ? "enabled" : "disabled";
diff --git a/tests/cts/hostside/app2/Android.bp b/tests/cts/hostside/app2/Android.bp
index b448459..dd33eed 100644
--- a/tests/cts/hostside/app2/Android.bp
+++ b/tests/cts/hostside/app2/Android.bp
@@ -21,7 +21,7 @@
android_test_helper_app {
name: "CtsHostsideNetworkTestsApp2",
defaults: ["cts_support_defaults"],
- sdk_version: "current",
+ sdk_version: "test_current",
static_libs: ["CtsHostsideNetworkTestsAidl"],
srcs: ["src/**/*.java"],
// Tag this module as a cts test artifact
diff --git a/tests/cts/hostside/app2/AndroidManifest.xml b/tests/cts/hostside/app2/AndroidManifest.xml
index eb777f2..4ac4bcb 100644
--- a/tests/cts/hostside/app2/AndroidManifest.xml
+++ b/tests/cts/hostside/app2/AndroidManifest.xml
@@ -21,20 +21,24 @@
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
<uses-permission android:name="android.permission.INTERNET"/>
+ <uses-permission android:name="android.permission.PACKAGE_USAGE_STATS" />
<!--
- This application is used to listen to RESTRICT_BACKGROUND_CHANGED intents and store
- them in a shared preferences which is then read by the test app. These broadcasts are
- handled by 2 listeners, one defined the manifest and another dynamically registered by
- a service.
+ This application is used to listen to RESTRICT_BACKGROUND_CHANGED intents and store
+ them in a shared preferences which is then read by the test app. These broadcasts are
+ handled by 2 listeners, one defined the manifest and another dynamically registered by
+ a service.
- The manifest-defined listener also handles ordered broadcasts used to share data with the
- test app.
+ The manifest-defined listener also handles ordered broadcasts used to share data with the
+ test app.
- This application also provides a service, RemoteSocketFactoryService, that the test app can
- use to open sockets to remote hosts as a different user ID.
- -->
- <application android:usesCleartextTraffic="true">
+ This application also provides a service, RemoteSocketFactoryService, that the test app can
+ use to open sockets to remote hosts as a different user ID.
+ -->
+ <application android:usesCleartextTraffic="true"
+ android:testOnly="true"
+ android:debuggable="true">
+
<activity android:name=".MyActivity"
android:exported="true"/>
<service android:name=".MyService"
@@ -55,6 +59,8 @@
<action android:name="com.android.cts.net.hostside.app2.action.SHOW_TOAST"/>
</intent-filter>
</receiver>
+ <service android:name=".MyJobService"
+ android:permission="android.permission.BIND_JOB_SERVICE" />
</application>
</manifest>
diff --git a/tests/cts/hostside/app2/src/com/android/cts/net/hostside/app2/Common.java b/tests/cts/hostside/app2/src/com/android/cts/net/hostside/app2/Common.java
index 351733e..62b508c 100644
--- a/tests/cts/hostside/app2/src/com/android/cts/net/hostside/app2/Common.java
+++ b/tests/cts/hostside/app2/src/com/android/cts/net/hostside/app2/Common.java
@@ -15,11 +15,13 @@
*/
package com.android.cts.net.hostside.app2;
+import android.app.ActivityManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.AsyncTask;
import android.os.Bundle;
+import android.os.Process;
import android.os.RemoteException;
import android.util.Log;
@@ -38,6 +40,8 @@
"com.android.cts.net.hostside.app2.action.RECEIVER_READY";
static final String ACTION_FINISH_ACTIVITY =
"com.android.cts.net.hostside.app2.action.FINISH_ACTIVITY";
+ static final String ACTION_FINISH_JOB =
+ "com.android.cts.net.hostside.app2.action.FINISH_JOB";
static final String ACTION_SHOW_TOAST =
"com.android.cts.net.hostside.app2.action.SHOW_TOAST";
@@ -51,6 +55,11 @@
static final String TEST_PKG = "com.android.cts.net.hostside";
static final String KEY_NETWORK_STATE_OBSERVER = TEST_PKG + ".observer";
+ static final String KEY_SKIP_VALIDATION_CHECKS = TEST_PKG + ".skip_validation_checks";
+
+ static final int TYPE_COMPONENT_ACTIVTY = 0;
+ static final int TYPE_COMPONENT_FOREGROUND_SERVICE = 1;
+ static final int TYPE_COMPONENT_EXPEDITED_JOB = 2;
static int getUid(Context context) {
final String packageName = context.getPackageName();
@@ -61,11 +70,57 @@
}
}
- static void notifyNetworkStateObserver(Context context, Intent intent) {
+ private static boolean validateComponentState(Context context, int componentType,
+ INetworkStateObserver observer) throws RemoteException {
+ final ActivityManager activityManager = context.getSystemService(ActivityManager.class);
+ switch (componentType) {
+ case TYPE_COMPONENT_ACTIVTY: {
+ final int procState = activityManager.getUidProcessState(Process.myUid());
+ if (procState != ActivityManager.PROCESS_STATE_TOP) {
+ observer.onNetworkStateChecked(
+ INetworkStateObserver.RESULT_ERROR_UNEXPECTED_PROC_STATE,
+ "Unexpected procstate: " + procState);
+ return false;
+ }
+ return true;
+ }
+ case TYPE_COMPONENT_FOREGROUND_SERVICE: {
+ final int procState = activityManager.getUidProcessState(Process.myUid());
+ if (procState != ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE) {
+ observer.onNetworkStateChecked(
+ INetworkStateObserver.RESULT_ERROR_UNEXPECTED_PROC_STATE,
+ "Unexpected procstate: " + procState);
+ return false;
+ }
+ return true;
+ }
+ case TYPE_COMPONENT_EXPEDITED_JOB: {
+ final int capabilities = activityManager.getUidProcessCapabilities(Process.myUid());
+ if ((capabilities & ActivityManager.PROCESS_CAPABILITY_NETWORK) == 0) {
+ observer.onNetworkStateChecked(
+ INetworkStateObserver.RESULT_ERROR_UNEXPECTED_CAPABILITIES,
+ "Unexpected capabilities: " + capabilities);
+ return false;
+ }
+ return true;
+ }
+ default: {
+ observer.onNetworkStateChecked(INetworkStateObserver.RESULT_ERROR_OTHER,
+ "Unknown component type: " + componentType);
+ return false;
+ }
+ }
+ }
+
+ static void notifyNetworkStateObserver(Context context, Intent intent, int componentType) {
if (intent == null) {
return;
}
final Bundle extras = intent.getExtras();
+ notifyNetworkStateObserver(context, extras, componentType);
+ }
+
+ static void notifyNetworkStateObserver(Context context, Bundle extras, int componentType) {
if (extras == null) {
return;
}
@@ -73,17 +128,17 @@
extras.getBinder(KEY_NETWORK_STATE_OBSERVER));
if (observer != null) {
try {
- if (!observer.isForeground()) {
- Log.e(TAG, "App didn't come to foreground");
- observer.onNetworkStateChecked(null);
+ final boolean skipValidation = extras.getBoolean(KEY_SKIP_VALIDATION_CHECKS);
+ if (!skipValidation && !validateComponentState(context, componentType, observer)) {
return;
}
} catch (RemoteException e) {
- Log.e(TAG, "Error occurred while reading the proc state: " + e);
+ Log.e(TAG, "Error occurred while informing the validation result: " + e);
}
AsyncTask.execute(() -> {
try {
observer.onNetworkStateChecked(
+ INetworkStateObserver.RESULT_SUCCESS_NETWORK_STATE_CHECKED,
MyBroadcastReceiver.checkNetworkStatus(context));
} catch (RemoteException e) {
Log.e(TAG, "Error occurred while notifying the observer: " + e);
diff --git a/tests/cts/hostside/app2/src/com/android/cts/net/hostside/app2/MyActivity.java b/tests/cts/hostside/app2/src/com/android/cts/net/hostside/app2/MyActivity.java
index 286cc2f..9fdb9c9 100644
--- a/tests/cts/hostside/app2/src/com/android/cts/net/hostside/app2/MyActivity.java
+++ b/tests/cts/hostside/app2/src/com/android/cts/net/hostside/app2/MyActivity.java
@@ -18,6 +18,7 @@
import static com.android.cts.net.hostside.app2.Common.ACTION_FINISH_ACTIVITY;
import static com.android.cts.net.hostside.app2.Common.TAG;
import static com.android.cts.net.hostside.app2.Common.TEST_PKG;
+import static com.android.cts.net.hostside.app2.Common.TYPE_COMPONENT_ACTIVTY;
import android.app.Activity;
import android.content.BroadcastReceiver;
@@ -42,7 +43,7 @@
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(TAG, "MyActivity.onCreate()");
- Common.notifyNetworkStateObserver(this, getIntent());
+ Common.notifyNetworkStateObserver(this, getIntent(), TYPE_COMPONENT_ACTIVTY);
finishCommandReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
diff --git a/tests/cts/hostside/app2/src/com/android/cts/net/hostside/app2/MyBroadcastReceiver.java b/tests/cts/hostside/app2/src/com/android/cts/net/hostside/app2/MyBroadcastReceiver.java
index aa54075..c9ae16f 100644
--- a/tests/cts/hostside/app2/src/com/android/cts/net/hostside/app2/MyBroadcastReceiver.java
+++ b/tests/cts/hostside/app2/src/com/android/cts/net/hostside/app2/MyBroadcastReceiver.java
@@ -201,7 +201,7 @@
Log.d(TAG, "sendNotification: id=" + notificationId + ", type=" + notificationType);
final Intent serviceIntent = new Intent(context, MyService.class);
final PendingIntent pendingIntent = PendingIntent.getService(context, 0, serviceIntent,
- notificationId);
+ PendingIntent.FLAG_MUTABLE);
final Bundle bundle = new Bundle();
bundle.putCharSequence("parcelable", "I am not");
diff --git a/tests/cts/hostside/app2/src/com/android/cts/net/hostside/app2/MyForegroundService.java b/tests/cts/hostside/app2/src/com/android/cts/net/hostside/app2/MyForegroundService.java
index ff4ba65..b55761c 100644
--- a/tests/cts/hostside/app2/src/com/android/cts/net/hostside/app2/MyForegroundService.java
+++ b/tests/cts/hostside/app2/src/com/android/cts/net/hostside/app2/MyForegroundService.java
@@ -17,6 +17,7 @@
import static com.android.cts.net.hostside.app2.Common.TAG;
import static com.android.cts.net.hostside.app2.Common.TEST_PKG;
+import static com.android.cts.net.hostside.app2.Common.TYPE_COMPONENT_FOREGROUND_SERVICE;
import android.R;
import android.app.Notification;
@@ -58,7 +59,7 @@
startForeground(42, new Notification.Builder(this, NOTIFICATION_CHANNEL_ID)
.setSmallIcon(R.drawable.ic_dialog_alert) // any icon is fine
.build());
- Common.notifyNetworkStateObserver(this, intent);
+ Common.notifyNetworkStateObserver(this, intent, TYPE_COMPONENT_FOREGROUND_SERVICE);
break;
case FLAG_STOP_FOREGROUND:
Log.d(TAG, "Stopping foreground");
diff --git a/tests/cts/hostside/app2/src/com/android/cts/net/hostside/app2/MyJobService.java b/tests/cts/hostside/app2/src/com/android/cts/net/hostside/app2/MyJobService.java
new file mode 100644
index 0000000..51c3157
--- /dev/null
+++ b/tests/cts/hostside/app2/src/com/android/cts/net/hostside/app2/MyJobService.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.cts.net.hostside.app2;
+
+import static com.android.cts.net.hostside.app2.Common.ACTION_FINISH_JOB;
+import static com.android.cts.net.hostside.app2.Common.TAG;
+import static com.android.cts.net.hostside.app2.Common.TYPE_COMPONENT_EXPEDITED_JOB;
+
+import android.app.job.JobParameters;
+import android.app.job.JobService;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.util.Log;
+
+public class MyJobService extends JobService {
+
+ private BroadcastReceiver mFinishCommandReceiver = null;
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ Log.v(TAG, "MyJobService.onCreate()");
+ }
+
+ @Override
+ public boolean onStartJob(JobParameters params) {
+ Log.v(TAG, "MyJobService.onStartJob()");
+ Common.notifyNetworkStateObserver(this, params.getTransientExtras(),
+ TYPE_COMPONENT_EXPEDITED_JOB);
+ mFinishCommandReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ Log.v(TAG, "Finishing MyJobService");
+ try {
+ jobFinished(params, /*wantsReschedule=*/ false);
+ } finally {
+ if (mFinishCommandReceiver != null) {
+ unregisterReceiver(mFinishCommandReceiver);
+ mFinishCommandReceiver = null;
+ }
+ }
+ }
+ };
+ registerReceiver(mFinishCommandReceiver, new IntentFilter(ACTION_FINISH_JOB));
+ return true;
+ }
+
+ @Override
+ public boolean onStopJob(JobParameters params) {
+ // If this job is stopped before it had a chance to send network status via
+ // INetworkStateObserver, the test will fail. It could happen either due to test timing out
+ // or this app moving to a lower proc_state and losing network access.
+ Log.v(TAG, "MyJobService.onStopJob()");
+ if (mFinishCommandReceiver != null) {
+ unregisterReceiver(mFinishCommandReceiver);
+ mFinishCommandReceiver = null;
+ }
+ return false;
+ }
+
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ Log.v(TAG, "MyJobService.onDestroy()");
+ }
+}
diff --git a/tests/cts/hostside/app2/src/com/android/cts/net/hostside/app2/MyService.java b/tests/cts/hostside/app2/src/com/android/cts/net/hostside/app2/MyService.java
index 1c9ff05..9e10d41 100644
--- a/tests/cts/hostside/app2/src/com/android/cts/net/hostside/app2/MyService.java
+++ b/tests/cts/hostside/app2/src/com/android/cts/net/hostside/app2/MyService.java
@@ -24,6 +24,8 @@
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.Service;
+import android.app.job.JobInfo;
+import android.app.job.JobScheduler;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
@@ -154,6 +156,13 @@
mNetworkCallback = null;
}
}
+
+ @Override
+ public void scheduleJob(JobInfo jobInfo) {
+ final JobScheduler jobScheduler = getApplicationContext()
+ .getSystemService(JobScheduler.class);
+ jobScheduler.schedule(jobInfo);
+ }
};
private NetworkRequest makeNetworkRequest() {
diff --git a/tests/cts/hostside/src/com/android/cts/net/HostsideNetworkTestCase.java b/tests/cts/hostside/src/com/android/cts/net/HostsideNetworkTestCase.java
index 37420bf..89c79d3 100644
--- a/tests/cts/hostside/src/com/android/cts/net/HostsideNetworkTestCase.java
+++ b/tests/cts/hostside/src/com/android/cts/net/HostsideNetworkTestCase.java
@@ -80,7 +80,7 @@
DeviceNotAvailableException {
CompatibilityBuildHelper buildHelper = new CompatibilityBuildHelper(mCtsBuild);
assertNull(getDevice().installPackage(buildHelper.getTestFile(apk),
- false /* reinstall */, true /* grantPermissions */));
+ false /* reinstall */, true /* grantPermissions */, "-t"));
}
protected void uninstallPackage(String packageName, boolean shouldSucceed)
diff --git a/tests/cts/hostside/src/com/android/cts/net/HostsideRestrictBackgroundNetworkTests.java b/tests/cts/hostside/src/com/android/cts/net/HostsideRestrictBackgroundNetworkTests.java
index 0e25d5e..d026fe0 100644
--- a/tests/cts/hostside/src/com/android/cts/net/HostsideRestrictBackgroundNetworkTests.java
+++ b/tests/cts/hostside/src/com/android/cts/net/HostsideRestrictBackgroundNetworkTests.java
@@ -318,11 +318,23 @@
/**************************
* Restricted mode tests. *
**************************/
- public void testRestrictedMode_networkAccess() throws Exception {
+ public void testNetworkAccess_restrictedMode() throws Exception {
runDeviceTests(TEST_PKG, TEST_PKG + ".RestrictedModeTest",
"testNetworkAccess");
}
+ /************************
+ * Expedited job tests. *
+ ************************/
+
+ public void testMeteredNetworkAccess_expeditedJob() throws Exception {
+ runDeviceTests(TEST_PKG, TEST_PKG + ".ExpeditedJobMeteredTest");
+ }
+
+ public void testNonMeteredNetworkAccess_expeditedJob() throws Exception {
+ runDeviceTests(TEST_PKG, TEST_PKG + ".ExpeditedJobNonMeteredTest");
+ }
+
/*******************
* Helper methods. *
*******************/
diff --git a/tests/cts/net/Android.bp b/tests/cts/net/Android.bp
index 4a1020d..cd69b13 100644
--- a/tests/cts/net/Android.bp
+++ b/tests/cts/net/Android.bp
@@ -39,10 +39,6 @@
"src/**/*.java",
"src/**/*.kt",
],
- exclude_srcs: [
- // TODO: delete this after mainline-prod snaps to sc-dev.
- "src/android/net/cts/NetworkAgentTest.kt",
- ],
jarjar_rules: "jarjar-rules-shared.txt",
static_libs: [
"bouncycastle-unbundled",
@@ -68,7 +64,6 @@
// devices.
android_test {
name: "CtsNetTestCases",
- enabled: false, // Disabled in mainline-prod
defaults: ["CtsNetTestCasesDefaults"],
// TODO: CTS should not depend on the entirety of the networkstack code.
static_libs: [
diff --git a/tests/cts/net/AndroidTestTemplate.xml b/tests/cts/net/AndroidTestTemplate.xml
index 78a01e2..474eefe 100644
--- a/tests/cts/net/AndroidTestTemplate.xml
+++ b/tests/cts/net/AndroidTestTemplate.xml
@@ -21,6 +21,7 @@
<option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
<option name="config-descriptor:metadata" key="mainline-param" value="CaptivePortalLoginGoogle.apk+NetworkStackGoogle.apk+com.google.android.resolv.apex+com.google.android.tethering.apex" />
+ <option name="config-descriptor:metadata" key="mainline-param" value="CaptivePortalLoginGoogle.apk+NetworkStackGoogle.apk+com.google.android.resolv.apex" />
<option name="not-shardable" value="true" />
<target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
<option name="cleanup-apks" value="true" />
diff --git a/tests/cts/net/src/android/net/cts/NetworkRequestTest.java b/tests/cts/net/src/android/net/cts/NetworkRequestTest.java
index 30c4e72..9906c30 100644
--- a/tests/cts/net/src/android/net/cts/NetworkRequestTest.java
+++ b/tests/cts/net/src/android/net/cts/NetworkRequestTest.java
@@ -39,17 +39,20 @@
import android.net.NetworkCapabilities;
import android.net.NetworkRequest;
import android.net.NetworkSpecifier;
-import android.net.UidRange;
import android.net.wifi.WifiNetworkSpecifier;
import android.os.Build;
import android.os.PatternMatcher;
import android.os.Process;
import android.util.ArraySet;
+import android.util.Range;
import androidx.test.runner.AndroidJUnit4;
import com.android.modules.utils.build.SdkLevel;
import com.android.networkstack.apishim.ConstantsShim;
+import com.android.networkstack.apishim.NetworkRequestShimImpl;
+import com.android.networkstack.apishim.common.NetworkRequestShim;
+import com.android.networkstack.apishim.common.UnsupportedApiLevelException;
import com.android.testutils.DevSdkIgnoreRule;
import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo;
@@ -57,6 +60,8 @@
import org.junit.Test;
import org.junit.runner.RunWith;
+import java.util.Set;
+
@RunWith(AndroidJUnit4.class)
public class NetworkRequestTest {
@Rule
@@ -225,6 +230,14 @@
assertTrue(requestCellularInternet.canBeSatisfiedBy(capCellularVpnMmsInternet));
}
+ private void setUids(NetworkRequest.Builder builder, Set<Range<Integer>> ranges)
+ throws UnsupportedApiLevelException {
+ if (SdkLevel.isAtLeastS()) {
+ final NetworkRequestShim networkRequestShim = NetworkRequestShimImpl.newInstance();
+ networkRequestShim.setUids(builder, ranges);
+ }
+ }
+
@Test
@IgnoreUpTo(Build.VERSION_CODES.Q)
public void testInvariantInCanBeSatisfiedBy() {
@@ -232,15 +245,26 @@
// NetworkCapabilities.satisfiedByNetworkCapabilities().
final LocalNetworkSpecifier specifier1 = new LocalNetworkSpecifier(1234 /* id */);
final int uid = Process.myUid();
- final ArraySet<UidRange> ranges = new ArraySet<>();
- ranges.add(new UidRange(uid, uid));
- final NetworkRequest requestCombination = new NetworkRequest.Builder()
+ final NetworkRequest.Builder nrBuilder = new NetworkRequest.Builder()
.addTransportType(TRANSPORT_CELLULAR)
.addCapability(NET_CAPABILITY_INTERNET)
.setLinkUpstreamBandwidthKbps(1000)
.setNetworkSpecifier(specifier1)
- .setSignalStrength(-123)
- .setUids(ranges).build();
+ .setSignalStrength(-123);
+
+ // The uid ranges should be set into the request, but setUids() takes a set of UidRange
+ // that is hidden and inaccessible from shims. Before, S setUids will be a no-op. But
+ // because NetworkRequest.Builder sets the UID of the request to the current UID, the
+ // request contains the current UID both on S and before S.
+ final Set<Range<Integer>> ranges = new ArraySet<>();
+ ranges.add(new Range<Integer>(uid, uid));
+ try {
+ setUids(nrBuilder, ranges);
+ } catch (UnsupportedApiLevelException e) {
+ // Not supported before API31.
+ }
+ final NetworkRequest requestCombination = nrBuilder.build();
+
final NetworkCapabilities capCell = new NetworkCapabilities.Builder()
.addTransportType(TRANSPORT_CELLULAR).build();
assertCorrectlySatisfies(false, requestCombination, capCell);