Update AMS to use NetworkManagementInternal.isNetworkRestrictedForUid.

And add global setting WAIT_FOR_NETWORK_TIMEOUT_MS.

Bug: 27803922
Test: runtest -c com.android.server.am.ActivityManagerServiceTest frameworks-services
      cts-tradefed run singleCommand cts-dev --module CtsHostsideNetworkTests -t com.android.cts.net.HostsideRestrictBackgroundNetworkTests
      runtest -c android.provider.SettingsBackupTest frameworks-core
      and manual

Change-Id: I6949cd517255670e2ce21ab2de24271082461b11
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 146d2d3..3864706 100755
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -9731,6 +9731,15 @@
         public static final String RETAIL_DEMO_MODE_CONSTANTS = "retail_demo_mode_constants";
 
         /**
+         * Indicates the maximum time that an app is blocked for the network rules to get updated.
+         *
+         * Type: long
+         *
+         * @hide
+         */
+        public static final String NETWORK_ACCESS_TIMEOUT_MS = "network_access_timeout_ms";
+
+        /**
          * The reason for the settings database being downgraded. This is only for
          * troubleshooting purposes and its value should not be interpreted in any way.
          *
diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
index 0cfdaf5..15fb7fa 100644
--- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
@@ -327,6 +327,7 @@
                     Settings.Global.USE_GOOGLE_MAIL,
                     Settings.Global.VT_IMS_ENABLED,
                     Settings.Global.WAIT_FOR_DEBUGGER,
+                    Settings.Global.NETWORK_ACCESS_TIMEOUT_MS,
                     Settings.Global.WARNING_TEMPERATURE,
                     Settings.Global.WEBVIEW_DATA_REDUCTION_PROXY_KEY,
                     Settings.Global.WEBVIEW_FALLBACK_LOGIC_ENABLED,
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 5956923..98274c4 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -54,6 +54,7 @@
 import static android.provider.Settings.Global.DEVELOPMENT_ENABLE_FREEFORM_WINDOWS_SUPPORT;
 import static android.provider.Settings.Global.DEVELOPMENT_FORCE_RESIZABLE_ACTIVITIES;
 import static android.provider.Settings.Global.DEVELOPMENT_FORCE_RTL;
+import static android.provider.Settings.Global.NETWORK_ACCESS_TIMEOUT_MS;
 import static android.provider.Settings.Global.WAIT_FOR_DEBUGGER;
 import static android.provider.Settings.System.FONT_SCALE;
 import static android.service.voice.VoiceInteractionSession.SHOW_SOURCE_APPLICATION;
@@ -359,6 +360,7 @@
 import com.android.server.IntentResolver;
 import com.android.server.LocalServices;
 import com.android.server.LockGuard;
+import com.android.server.NetworkManagementInternal;
 import com.android.server.RescueParty;
 import com.android.server.ServiceThread;
 import com.android.server.SystemConfig;
@@ -574,9 +576,9 @@
     static final boolean TAKE_FULLSCREEN_SCREENSHOTS = true;
 
     /**
-     * Indicates the maximum time spent waiting for the network rules to get updated.
+     * Default value for {@link Settings.Global#NETWORK_ACCESS_TIMEOUT_MS}.
      */
-    private static final long WAIT_FOR_NETWORK_TIMEOUT_MS = 2000; // 2 sec
+    private static final long NETWORK_ACCESS_TIMEOUT_DEFAULT_MS = 0; // 0 sec
 
     /**
      * State indicating that there is no need for any blocking for network.
@@ -751,6 +753,12 @@
 
     final AppErrors mAppErrors;
 
+    /**
+     * Indicates the maximum time spent waiting for the network rules to get updated.
+     */
+    @VisibleForTesting
+    long mWaitForNetworkTimeoutMs;
+
     public boolean canShowErrorDialogs() {
         return mShowDialogs && !mSleeping && !mShuttingDown
                 && !mKeyguardController.isKeyguardShowing();
@@ -13737,6 +13745,8 @@
         final boolean forceRtl = Settings.Global.getInt(resolver, DEVELOPMENT_FORCE_RTL, 0) != 0;
         final boolean forceResizable = Settings.Global.getInt(
                 resolver, DEVELOPMENT_FORCE_RESIZABLE_ACTIVITIES, 0) != 0;
+        final long waitForNetworkTimeoutMs = Settings.Global.getLong(resolver,
+                NETWORK_ACCESS_TIMEOUT_MS, NETWORK_ACCESS_TIMEOUT_DEFAULT_MS);
         final boolean supportsLeanbackOnly =
                 mContext.getPackageManager().hasSystemFeature(FEATURE_LEANBACK_ONLY);
 
@@ -13792,6 +13802,7 @@
                 mFullscreenThumbnailScale = res.getFraction(
                     com.android.internal.R.fraction.thumbnail_fullscreen_scale, 1, 1);
             }
+            mWaitForNetworkTimeoutMs = waitForNetworkTimeoutMs;
         }
     }
 
@@ -22456,6 +22467,9 @@
     @VisibleForTesting
     @GuardedBy("this")
     void incrementProcStateSeqAndNotifyAppsLocked() {
+        if (mWaitForNetworkTimeoutMs <= 0) {
+            return;
+        }
         // Used for identifying which uids need to block for network.
         ArrayList<Integer> blockingUids = null;
         for (int i = mActiveUids.size() - 1; i >= 0; --i) {
@@ -23498,10 +23512,14 @@
                 }
                 final long startTime = SystemClock.uptimeMillis();
                 record.waitingForNetwork = true;
-                record.lock.wait(WAIT_FOR_NETWORK_TIMEOUT_MS);
+                record.lock.wait(mWaitForNetworkTimeoutMs);
                 record.waitingForNetwork = false;
                 final long totalTime = SystemClock.uptimeMillis() - startTime;
-                if (DEBUG_NETWORK ||  totalTime > WAIT_FOR_NETWORK_TIMEOUT_MS / 2) {
+                if (totalTime >= mWaitForNetworkTimeoutMs) {
+                    Slog.wtf(TAG_NETWORK, "Total time waited for network rules to get updated: "
+                            + totalTime + ". Uid: " + callingUid + " procStateSeq: "
+                            + procStateSeq);
+                } else if (DEBUG_NETWORK ||  totalTime >= mWaitForNetworkTimeoutMs / 2) {
                     Slog.d(TAG_NETWORK, "Total time waited for network rules to get updated: "
                             + totalTime + ". Uid: " + callingUid + " procStateSeq: "
                             + procStateSeq);
@@ -23796,6 +23814,8 @@
 
     @VisibleForTesting
     public static class Injector {
+        private NetworkManagementInternal mNmi;
+
         public AppOpsService getAppOpsService(File file, Handler handler) {
             return new AppOpsService(file, handler);
         }
@@ -23805,8 +23825,17 @@
         }
 
         public boolean isNetworkRestrictedForUid(int uid) {
-            // TODO: add implementation
+            if (ensureHasNetworkManagementInternal()) {
+                return mNmi.isNetworkRestrictedForUid(uid);
+            }
             return false;
         }
+
+        private boolean ensureHasNetworkManagementInternal() {
+            if (mNmi == null) {
+                mNmi = LocalServices.getService(NetworkManagementInternal.class);
+            }
+            return mNmi != null;
+        }
     }
 }
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/am/ActivityManagerServiceTest.java
index cc5764b..b12da34 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityManagerServiceTest.java
@@ -132,6 +132,7 @@
         mHandler = new TestHandler(mHandlerThread.getLooper());
         mInjector = new TestInjector();
         mAms = new ActivityManagerService(mInjector);
+        mAms.mWaitForNetworkTimeoutMs = 100;
     }
 
     @After
@@ -217,6 +218,17 @@
                 44, // exptectedCurProcStateSeq
                 -1, // expectedBlockState, -1 to verify there are no interactions with main thread.
                 false); // expectNotify
+
+        // Verify when waitForNetworkTimeout is 0, then procStateSeq is not incremented.
+        mAms.mWaitForNetworkTimeoutMs = 0;
+        mInjector.setNetworkRestrictedForUid(true);
+        verifySeqCounterAndInteractions(uidRec,
+                PROCESS_STATE_TOP, // prevState
+                PROCESS_STATE_IMPORTANT_BACKGROUND, // curState
+                44, // expectedGlobalCounter
+                44, // exptectedCurProcStateSeq
+                -1, // expectedBlockState, -1 to verify there are no interactions with main thread.
+                false); // expectNotify
     }
 
     private void verifySeqCounterAndInteractions(UidRecord uidRec, int prevState, int curState,