Merge "Attempt at fixing broken tests and regressing performance."
diff --git a/core/java/android/os/INetworkManagementService.aidl b/core/java/android/os/INetworkManagementService.aidl
index 013e77f..0c211d6 100644
--- a/core/java/android/os/INetworkManagementService.aidl
+++ b/core/java/android/os/INetworkManagementService.aidl
@@ -437,6 +437,7 @@
 
     void addInterfaceToLocalNetwork(String iface, in List<RouteInfo> routes);
     void removeInterfaceFromLocalNetwork(String iface);
+    int removeRoutesFromLocalNetwork(in List<RouteInfo> routes);
 
     void setAllowOnlyVpnForUids(boolean enable, in UidRange[] uidRanges);
 }
diff --git a/packages/DocumentsUI/src/com/android/documentsui/services/CopyJob.java b/packages/DocumentsUI/src/com/android/documentsui/services/CopyJob.java
index c8f6a64..8eabbe4 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/services/CopyJob.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/services/CopyJob.java
@@ -273,6 +273,8 @@
         try {
             final ContentResolver resolver = appContext.getContentResolver();
             final Iterable<Uri> uris = srcs.getUris(appContext);
+
+            int docProcessed = 0;
             for (Uri uri : uris) {
                 DocumentInfo doc = DocumentInfo.fromUri(resolver, uri);
                 if (canCopy(doc, stack.root)) {
@@ -280,11 +282,16 @@
                 } else {
                     onFileFailed(doc);
                 }
+                ++docProcessed;
 
                 if (isCanceled()) {
                     return;
                 }
             }
+
+            // If docProcessed is different than the count claimed by UrisSupplier, add the number
+            // to failedFileCount.
+            failedFileCount += (srcs.getItemCount() - docProcessed);
         } catch(IOException e) {
             failedFileCount += srcs.getItemCount();
             throw new ResourceException("Failed to open the list of docs to copy.", e);
diff --git a/packages/DocumentsUI/src/com/android/documentsui/services/DeleteJob.java b/packages/DocumentsUI/src/com/android/documentsui/services/DeleteJob.java
index 64bc1a7..5a36818 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/services/DeleteJob.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/services/DeleteJob.java
@@ -120,6 +120,10 @@
 
                 ++mDocsProcessed;
             }
+
+            // If mDocProcessed is different than the count claimed by UrisSupplier, add the number
+            // to failedFileCount.
+            failedFileCount += (this.srcs.getItemCount() - mDocsProcessed);
             Metrics.logFileOperation(service, operationType, srcs, null);
         } catch(IOException e) {
             Log.e(TAG, "Failed to get list of docs or parent source.", e);
diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java
index be6364e..f2a2b3d 100644
--- a/services/core/java/com/android/server/NetworkManagementService.java
+++ b/services/core/java/com/android/server/NetworkManagementService.java
@@ -2751,4 +2751,19 @@
     public void removeInterfaceFromLocalNetwork(String iface) {
         modifyInterfaceInNetwork("remove", "local", iface);
     }
+
+    @Override
+    public int removeRoutesFromLocalNetwork(List<RouteInfo> routes) {
+        int failures = 0;
+
+        for (RouteInfo route : routes) {
+            try {
+                modifyRoute("remove", "local", route);
+            } catch (IllegalStateException e) {
+                failures++;
+            }
+        }
+
+        return failures;
+    }
 }
diff --git a/services/core/java/com/android/server/connectivity/tethering/IPv6TetheringInterfaceServices.java b/services/core/java/com/android/server/connectivity/tethering/IPv6TetheringInterfaceServices.java
index b742838..a58d243 100644
--- a/services/core/java/com/android/server/connectivity/tethering/IPv6TetheringInterfaceServices.java
+++ b/services/core/java/com/android/server/connectivity/tethering/IPv6TetheringInterfaceServices.java
@@ -157,8 +157,17 @@
             }
         } else {
             if (mLastLocalRoutes != null && !mLastLocalRoutes.isEmpty()) {
-                // TODO: Remove only locally added network routes.
-                // mNMSwervice.removeInterfaceFromLocalNetwork(mIfName);
+                try {
+                    final int removalFailures =
+                            mNMService.removeRoutesFromLocalNetwork(mLastLocalRoutes);
+                    if (removalFailures > 0) {
+                        Log.e(TAG,
+                                String.format("Failed to remove %d IPv6 routes from local table.",
+                                removalFailures));
+                    }
+                } catch (RemoteException e) {
+                    Log.e(TAG, "Failed to remove IPv6 routes from local table: ", e);
+                }
             }
         }