Mainline wifi stack module

a) Moved wifi service to a separate APK
b) Use the IWifiStackConnector to load the wifi stack from
SystemServer (similar to network stack).
c) Create a new WifiStackClient interface for system server to interact
with the wifi stack (under new services/wifi folder). Note: This not planned
to be updated via wifi-sdk Apex.
d) Add priv-app permissions for the new wifi stack APK.

Bug: 113174748
Test: Device boots up & connects to wifi networks, hotspot toggle, etc.
Test: Will send for regression tests
Change-Id: I54b3a11ed30668bad5a387370484b2bb0eabca5f
Merged-In: I54b3a11ed30668bad5a387370484b2bb0eabca5f
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 73bc908..3adef3f 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -3735,6 +3735,14 @@
     public static final String NETWORK_STACK_SERVICE = "network_stack";
 
     /**
+     * Use with {@link android.os.ServiceManager.getService()} to retrieve a
+     * {@link android.net.WifiStackClient} IBinder for communicating with the network stack
+     * @hide
+     * @see android.net.WifiStackClient
+     */
+    public static final String WIFI_STACK_SERVICE = "wifi_stack";
+
+    /**
      * Use with {@link #getSystemService(String)} to retrieve a
      * {@link android.net.IpSecManager} for encrypting Sockets or Networks with
      * IPSec.
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index 89e26da..1b4867e 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -350,4 +350,19 @@
         <permission name="android.permission.MANAGE_DYNAMIC_SYSTEM"/>
     </privapp-permissions>
 
+    <privapp-permissions package="com.android.server.wifistack">
+        <permission name="android.permission.CHANGE_CONFIGURATION"/>
+        <permission name="android.permission.CONNECTIVITY_INTERNAL"/>
+        <permission name="android.permission.DUMP"/>
+        <permission name="android.permission.INTERACT_ACROSS_USERS"/>
+        <permission name="android.permission.LOCAL_MAC_ADDRESS"/>
+        <permission name="android.permission.MANAGE_USERS"/>
+        <permission name="android.permission.PACKAGE_USAGE_STATS"/>
+        <permission name="android.permission.READ_PRIVILEGED_PHONE_STATE"/>
+        <permission name="android.permission.REQUEST_NETWORK_SCORES"/>
+        <permission name="android.permission.WRITE_SECURE_SETTINGS"/>
+        <permission name="android.permission.UPDATE_DEVICE_STATS"/>
+        <permission name="android.permission.UPDATE_APP_OPS_STATS"/>
+        <permission name="android.permission.LOCATION_HARDWARE"/>
+    </privapp-permissions>
 </permissions>
diff --git a/services/Android.bp b/services/Android.bp
index b08d1a8..54157d0 100644
--- a/services/Android.bp
+++ b/services/Android.bp
@@ -35,6 +35,7 @@
         "services.usage",
         "services.usb",
         "services.voiceinteraction",
+        "services.wifi",
         "android.hidl.base-V1.0-java",
     ],
 
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index c6adf1b..4ba75a6 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -40,8 +40,8 @@
 import android.database.sqlite.SQLiteGlobal;
 import android.hardware.display.DisplayManagerInternal;
 import android.net.ConnectivityModuleConnector;
-import android.net.Network;
 import android.net.NetworkStackClient;
+import android.net.wifi.WifiStackClient;
 import android.os.BaseBundle;
 import android.os.Binder;
 import android.os.Build;
@@ -1346,40 +1346,6 @@
             t.traceEnd();
 
             if (context.getPackageManager().hasSystemFeature(
-                    PackageManager.FEATURE_WIFI)) {
-                // Wifi Service must be started first for wifi-related services.
-                t.traceBegin("StartWifi");
-                mSystemServiceManager.startService(WIFI_SERVICE_CLASS);
-                t.traceEnd();
-                t.traceBegin("StartWifiScanning");
-                mSystemServiceManager.startService(
-                        "com.android.server.wifi.scanner.WifiScanningService");
-                t.traceEnd();
-            }
-
-            if (context.getPackageManager().hasSystemFeature(
-                    PackageManager.FEATURE_WIFI_RTT)) {
-                t.traceBegin("StartRttService");
-                mSystemServiceManager.startService(
-                        "com.android.server.wifi.rtt.RttService");
-                t.traceEnd();
-            }
-
-            if (context.getPackageManager().hasSystemFeature(
-                    PackageManager.FEATURE_WIFI_AWARE)) {
-                t.traceBegin("StartWifiAware");
-                mSystemServiceManager.startService(WIFI_AWARE_SERVICE_CLASS);
-                t.traceEnd();
-            }
-
-            if (context.getPackageManager().hasSystemFeature(
-                    PackageManager.FEATURE_WIFI_DIRECT)) {
-                t.traceBegin("StartWifiP2P");
-                mSystemServiceManager.startService(WIFI_P2P_SERVICE_CLASS);
-                t.traceEnd();
-            }
-
-            if (context.getPackageManager().hasSystemFeature(
                     PackageManager.FEATURE_LOWPAN)) {
                 t.traceBegin("StartLowpan");
                 mSystemServiceManager.startService(LOWPAN_SERVICE_CLASS);
@@ -2184,6 +2150,15 @@
             }
             t.traceEnd();
 
+            t.traceBegin("StartWifiStack");
+            try {
+                WifiStackClient.getInstance().start();
+            } catch (Throwable e) {
+                reportWtf("starting Wifi Stack", e);
+            }
+            t.traceEnd();
+
+
             t.traceBegin("MakeLocationServiceReady");
             try {
                 if (locationF != null) {
diff --git a/services/wifi/Android.bp b/services/wifi/Android.bp
new file mode 100644
index 0000000..3c916a6
--- /dev/null
+++ b/services/wifi/Android.bp
@@ -0,0 +1,11 @@
+// Interfaces between the core system and the wifi mainline module.
+java_library_static {
+    name: "services.wifi",
+    srcs: [
+        "java/**/*.java",
+        "java/**/*.aidl",
+    ],
+    libs: [
+        "services.net",
+    ],
+}
diff --git a/services/wifi/java/android/net/wifi/IWifiStackConnector.aidl b/services/wifi/java/android/net/wifi/IWifiStackConnector.aidl
new file mode 100644
index 0000000..ad052b9
--- /dev/null
+++ b/services/wifi/java/android/net/wifi/IWifiStackConnector.aidl
@@ -0,0 +1,20 @@
+/**
+ * Copyright (c) 2019, 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 perNmissions and
+ * limitations under the License.
+ */
+package android.net.wifi;
+
+/** @hide */
+oneway interface IWifiStackConnector {
+}
diff --git a/services/wifi/java/android/net/wifi/WifiStackClient.java b/services/wifi/java/android/net/wifi/WifiStackClient.java
new file mode 100644
index 0000000..067d98b
--- /dev/null
+++ b/services/wifi/java/android/net/wifi/WifiStackClient.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2019 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.net.wifi;
+
+import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_HIGH;
+import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_NORMAL;
+
+import android.annotation.NonNull;
+import android.content.Context;
+import android.net.ConnectivityModuleConnector;
+import android.os.IBinder;
+import android.os.ServiceManager;
+import android.util.Log;
+
+/**
+ * Service used to communicate with the wifi stack, which could be running in a separate
+ * module.
+ * @hide
+ */
+public class WifiStackClient {
+    public static final String PERMISSION_MAINLINE_WIFI_STACK =
+            "android.permission.MAINLINE_WIFI_STACK";
+
+    private static final String TAG = WifiStackClient.class.getSimpleName();
+    private static WifiStackClient sInstance;
+
+    private WifiStackClient() { }
+
+    /**
+     * Get the WifiStackClient singleton instance.
+     */
+    public static synchronized WifiStackClient getInstance() {
+        if (sInstance == null) {
+            sInstance = new WifiStackClient();
+        }
+        return sInstance;
+    }
+
+    private class WifiStackConnection implements
+            ConnectivityModuleConnector.ModuleServiceCallback {
+        @Override
+        public void onModuleServiceConnected(IBinder service) {
+            Log.i(TAG, "Wifi stack connected");
+            registerWifiStackService(service);
+        }
+    }
+
+    private void registerWifiStackService(@NonNull IBinder service) {
+        ServiceManager.addService(Context.WIFI_STACK_SERVICE, service,
+                false /* allowIsolated */,
+                DUMP_FLAG_PRIORITY_HIGH | DUMP_FLAG_PRIORITY_NORMAL);
+        Log.i(TAG, "Wifi stack service registered");
+    }
+
+    /**
+     * Start the wifi stack. Should be called only once on device startup.
+     *
+     * <p>This method will start the wifi stack either in the wifi stack
+     * process, or inside the system server on devices that do not support the wifi stack
+     * module.
+     */
+    public void start() {
+        Log.i(TAG, "Starting wifi stack");
+        ConnectivityModuleConnector.getInstance().startModuleService(
+                IWifiStackConnector.class.getName(), PERMISSION_MAINLINE_WIFI_STACK,
+                new WifiStackConnection());
+    }
+}