OSDN Git Service

Use an in-process APK for in-process NetworkStack
authorRemi NGUYEN VAN <reminv@google.com>
Fri, 8 Mar 2019 08:20:49 +0000 (17:20 +0900)
committerRemi NGUYEN VAN <reminv@google.com>
Fri, 8 Mar 2019 10:18:40 +0000 (19:18 +0900)
Instead of having a library in the classpath where the NetworkStack is
created by reflection on devices using the network stack in-process,
just bind to a version of the network stack service that runs in the
system process.

If the in-process version is installed it will be used, otherwise the
module is used with its own process.

Bug: 127908503
Test: blueline boots and has functional WiFi
Test: atest FrameworksNetTests NetworkStackTests
Test: svelte build boots and has functional WiFi
Change-Id: I7722b173e5686e0dbb9cfddcfb34344b0f4135d9

packages/NetworkStack/Android.bp
packages/NetworkStack/AndroidManifest.xml
packages/NetworkStack/AndroidManifestBase.xml [new file with mode: 0644]
packages/NetworkStack/AndroidManifest_InProcess.xml [new file with mode: 0644]
packages/NetworkStack/tests/Android.bp
services/net/java/android/net/NetworkStackClient.java

index f210840..190247a 100644 (file)
 // limitations under the License.
 //
 
-// Library including the network stack, used to compile the network stack app, or linked into the
-// system server on devices that run the stack there
-java_library {
-    name: "NetworkStackLib",
+// Library including the network stack, used to compile both variants of the network stack
+android_library {
+    name: "NetworkStackBase",
     sdk_version: "system_current",
-    installable: true,
+    min_sdk_version: "28",
     srcs: [
         "src/**/*.java",
         ":framework-networkstack-shared-srcs",
@@ -29,7 +28,24 @@ java_library {
         "netd_aidl_interface-java",
         "networkstack-aidl-interfaces-java",
         "datastallprotosnano",
-    ]
+    ],
+    manifest: "AndroidManifestBase.xml",
+}
+
+// Non-updatable in-process network stack for devices not using the module
+android_app {
+    name: "InProcessNetworkStack",
+    sdk_version: "system_current",
+    min_sdk_version: "28",
+    certificate: "platform",
+    privileged: true,
+    static_libs: [
+        "NetworkStackBase",
+    ],
+    jarjar_rules: "jarjar-rules-shared.txt",
+    // The permission configuration *must* be included to ensure security of the device
+    required: ["NetworkStackPermissionStub"],
+    manifest: "AndroidManifest_InProcess.xml",
 }
 
 // Updatable network stack packaged as an application
@@ -40,9 +56,10 @@ android_app {
     certificate: "networkstack",
     privileged: true,
     static_libs: [
-        "NetworkStackLib"
+        "NetworkStackBase"
     ],
     jarjar_rules: "jarjar-rules-shared.txt",
-    manifest: "AndroidManifest.xml",
+    // The permission configuration *must* be included to ensure security of the device
     required: ["NetworkStackPermissionStub"],
+    manifest: "AndroidManifest.xml",
 }
index 003f1e5..a90db11 100644 (file)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!--
 /*
- * Copyright (C) 2014 The Android Open Source Project
+ * 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.
 -->
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
           package="com.android.networkstack"
-          android:sharedUserId="android.uid.networkstack"
-          android:versionCode="11"
-          android:versionName="Q-initial">
-    <uses-sdk android:minSdkVersion="28" android:targetSdkVersion="28" />
-    <uses-permission android:name="android.permission.INTERNET" />
-    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
-    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
-    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
-    <uses-permission android:name="android.permission.CONNECTIVITY_INTERNAL" />
+          android:sharedUserId="android.uid.networkstack">
     <!-- Signature permission defined in NetworkStackStub -->
     <uses-permission android:name="android.permission.MAINLINE_NETWORK_STACK" />
-    <!-- Send latency broadcast as current user -->
-    <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS" />
-    <uses-permission android:name="android.permission.WAKE_LOCK" />
-    <uses-permission android:name="android.permission.READ_PRIVILEGED_PHONE_STATE" />
-    <application
-        android:label="NetworkStack"
-        android:defaultToDeviceProtectedStorage="true"
-        android:directBootAware="true"
-        android:usesCleartextTraffic="true">
+    <application>
         <service android:name="com.android.server.NetworkStackService">
             <intent-filter>
                 <action android:name="android.net.INetworkStackConnector"/>
             </intent-filter>
         </service>
     </application>
-</manifest>
+</manifest>
\ No newline at end of file
diff --git a/packages/NetworkStack/AndroidManifestBase.xml b/packages/NetworkStack/AndroidManifestBase.xml
new file mode 100644 (file)
index 0000000..621d30c
--- /dev/null
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * 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.
+ */
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="com.android.networkstack"
+          android:versionCode="11"
+          android:versionName="Q-initial">
+    <uses-sdk android:minSdkVersion="28" android:targetSdkVersion="28" />
+    <uses-permission android:name="android.permission.INTERNET" />
+    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
+    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
+    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
+    <uses-permission android:name="android.permission.CONNECTIVITY_INTERNAL" />
+    <!-- Send latency broadcast as current user -->
+    <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS" />
+    <uses-permission android:name="android.permission.WAKE_LOCK" />
+    <uses-permission android:name="android.permission.READ_PRIVILEGED_PHONE_STATE" />
+    <application
+        android:label="NetworkStack"
+        android:defaultToDeviceProtectedStorage="true"
+        android:directBootAware="true"
+        android:usesCleartextTraffic="true">
+    </application>
+</manifest>
diff --git a/packages/NetworkStack/AndroidManifest_InProcess.xml b/packages/NetworkStack/AndroidManifest_InProcess.xml
new file mode 100644 (file)
index 0000000..48fcecd
--- /dev/null
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * 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.
+ */
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="com.android.networkstack.inprocess"
+          android:sharedUserId="android.uid.system"
+          android:process="system">
+    <application>
+        <service android:name="com.android.server.NetworkStackService" android:process="system">
+            <intent-filter>
+                <action android:name="android.net.INetworkStackConnector.InProcess"/>
+            </intent-filter>
+        </service>
+    </application>
+</manifest>
\ No newline at end of file
index f22b647..690c2cf 100644 (file)
@@ -24,7 +24,7 @@ android_test {
         "androidx.test.rules",
         "frameworks-base-testutils",
         "mockito-target-extended-minus-junit4",
-        "NetworkStackLib",
+        "NetworkStackBase",
         "testables",
     ],
     libs: [
index 830dbbe..6bfc391 100644 (file)
@@ -42,7 +42,6 @@ import android.util.Slog;
 import com.android.internal.annotations.GuardedBy;
 
 import java.io.PrintWriter;
-import java.lang.reflect.InvocationTargetException;
 import java.util.ArrayList;
 
 /**
@@ -53,6 +52,7 @@ public class NetworkStackClient {
     private static final String TAG = NetworkStackClient.class.getSimpleName();
 
     private static final int NETWORKSTACK_TIMEOUT_MS = 10_000;
+    private static final String IN_PROCESS_SUFFIX = ".InProcess";
 
     private static NetworkStackClient sInstance;
 
@@ -175,42 +175,50 @@ public class NetworkStackClient {
     public void start(Context context) {
         log("Starting network stack");
         mNetworkStackStartRequested = true;
-        // Try to bind in-process if the library is available
-        IBinder connector = null;
-        try {
-            final Class service = Class.forName(
-                    "com.android.server.NetworkStackService",
-                    true /* initialize */,
-                    context.getClassLoader());
-            connector = (IBinder) service.getMethod("makeConnector", Context.class)
-                    .invoke(null, context);
-        } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
-            logWtf("Could not create network stack connector from NetworkStackService", e);
-            // TODO: crash/reboot system here ?
-            return;
-        } catch (ClassNotFoundException e) {
-            // Normal behavior if stack is provided by the app: fall through
+
+        final PackageManager pm = context.getPackageManager();
+
+        // Try to bind in-process if the device was shipped with an in-process version
+        Intent intent = getNetworkStackIntent(pm, true /* inSystemProcess */);
+
+        // Otherwise use the updatable module version
+        if (intent == null) {
+            intent = getNetworkStackIntent(pm, false /* inSystemProcess */);
+            log("Starting network stack process");
+        } else {
+            log("Starting network stack in-process");
         }
 
-        // In-process network stack. Add the service to the service manager here.
-        if (connector != null) {
-            log("Registering in-process network stack connector");
-            registerNetworkStackService(connector);
+        if (intent == null) {
+            logWtf("Could not resolve the network stack", null);
+            // TODO: crash/reboot system server ?
             return;
         }
-        // Start the network stack process. The service will be added to the service manager in
+
+        // Start the network stack. The service will be added to the service manager in
         // NetworkStackConnection.onServiceConnected().
-        log("Starting network stack process");
-        final Intent intent = new Intent(INetworkStackConnector.class.getName());
-        final ComponentName comp = intent.resolveSystemService(context.getPackageManager(), 0);
-        intent.setComponent(comp);
+        if (!context.bindServiceAsUser(intent, new NetworkStackConnection(),
+                Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT, UserHandle.SYSTEM)) {
+            logWtf("Could not bind to network stack with " + intent, null);
+            return;
+            // TODO: crash/reboot system server if no network stack after a timeout ?
+        }
+
+        log("Network stack service start requested");
+    }
+
+    @Nullable
+    private Intent getNetworkStackIntent(@NonNull PackageManager pm, boolean inSystemProcess) {
+        final String baseAction = INetworkStackConnector.class.getName();
+        final Intent intent =
+                new Intent(inSystemProcess ? baseAction + IN_PROCESS_SUFFIX : baseAction);
+        final ComponentName comp = intent.resolveSystemService(pm, 0);
 
         if (comp == null) {
-            logWtf("Could not resolve the network stack with " + intent, null);
-            // TODO: crash/reboot system server ?
-            return;
+            return null;
         }
-        final PackageManager pm = context.getPackageManager();
+        intent.setComponent(comp);
+
         int uid = -1;
         try {
             uid = pm.getPackageUidAsUser(comp.getPackageName(), UserHandle.USER_SYSTEM);
@@ -218,25 +226,27 @@ public class NetworkStackClient {
             logWtf("Network stack package not found", e);
             // Fall through
         }
-        if (uid != Process.NETWORK_STACK_UID) {
+
+        final int expectedUid = inSystemProcess ? Process.SYSTEM_UID : Process.NETWORK_STACK_UID;
+        if (uid != expectedUid) {
             throw new SecurityException("Invalid network stack UID: " + uid);
         }
 
+        if (!inSystemProcess) {
+            checkNetworkStackPermission(pm, comp);
+        }
+
+        return intent;
+    }
+
+    private void checkNetworkStackPermission(
+            @NonNull PackageManager pm, @NonNull ComponentName comp) {
         final int hasPermission =
                 pm.checkPermission(PERMISSION_MAINLINE_NETWORK_STACK, comp.getPackageName());
         if (hasPermission != PERMISSION_GRANTED) {
             throw new SecurityException(
                     "Network stack does not have permission " + PERMISSION_MAINLINE_NETWORK_STACK);
         }
-
-        if (!context.bindServiceAsUser(intent, new NetworkStackConnection(),
-                Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT, UserHandle.SYSTEM)) {
-            logWtf("Could not bind to network stack in-process, or in app with " + intent, null);
-            return;
-            // TODO: crash/reboot system server if no network stack after a timeout ?
-        }
-
-        log("Network stack service start requested");
     }
 
     private void log(@NonNull String message) {