2-phase initialization of NetworkPolicyManagerService

Split systemReady() into 2 callbacks:
1) networkScoreAndNetworkManagementServiceReady - called when required
    services are ready. NetworkPolicyManagerService starts its initialization
    on the worker thread
2) systemReady - wait for phase (1) to finish so that the service is fully
   initialized

NetworkPolicyManagerService is now prepared in parallel with
ConnectivityService and NetworkStatsService

Test: device boots without errors
Test: HostsideRestrictBackgroundNetworkTests and NetworkPolicyManagerServiceTest pass
Bug: 32315581
Change-Id: Ic9755ed096900247fa0bbb43f396d8bcb97ae6db
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index 533307e..ac3a025 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -139,6 +139,7 @@
 import android.os.MessageQueue.IdleHandler;
 import android.os.PowerManager;
 import android.os.PowerManagerInternal;
+import android.os.Process;
 import android.os.RemoteCallbackList;
 import android.os.RemoteException;
 import android.os.ResultReceiver;
@@ -197,6 +198,8 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
 
 /**
  * Service that maintains low-level network policy rules, using
@@ -565,9 +568,12 @@
         }
     }
 
-    public void systemReady() {
+    private void initService(CountDownLatch initCompleteSignal) {
         Trace.traceBegin(Trace.TRACE_TAG_NETWORK, "systemReady");
+        final int oldPriority = Process.getThreadPriority(Process.myTid());
         try {
+            // Boost thread's priority during system server init
+            Process.setThreadPriority(Process.THREAD_PRIORITY_FOREGROUND);
             if (!isBandwidthControlEnabled()) {
                 Slog.w(TAG, "bandwidth controls disabled, unable to enforce policy");
                 return;
@@ -672,11 +678,33 @@
             mContext.registerReceiver(mWifiStateReceiver, wifiStateFilter, null, mHandler);
 
             mUsageStats.addAppIdleStateChangeListener(new AppIdleStateChangeListener());
+            // tell systemReady() that the service has been initialized
+            initCompleteSignal.countDown();
         } finally {
+            // Restore the default priority after init is done
+            Process.setThreadPriority(oldPriority);
             Trace.traceEnd(Trace.TRACE_TAG_NETWORK);
         }
     }
 
+    public CountDownLatch networkScoreAndNetworkManagementServiceReady() {
+        final CountDownLatch initCompleteSignal = new CountDownLatch(1);
+        mHandler.post(() -> initService(initCompleteSignal));
+        return initCompleteSignal;
+    }
+
+    public void systemReady(CountDownLatch initCompleteSignal) {
+        // wait for initService to complete
+        try {
+            if (!initCompleteSignal.await(30, TimeUnit.SECONDS)) {
+                throw new IllegalStateException("Service " + TAG +" init timeout");
+            }
+        } catch (InterruptedException e) {
+            Thread.currentThread().interrupt();
+            throw new IllegalStateException("Service " + TAG + " init interrupted", e);
+        }
+    }
+
     final private IUidObserver mUidObserver = new IUidObserver.Stub() {
         @Override public void onUidStateChanged(int uid, int procState) throws RemoteException {
             Trace.traceBegin(Trace.TRACE_TAG_NETWORK, "onUidStateChanged");