Merge "WifiManager: add iface name and mode labels"
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index 46b981e..2736ba6e 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -467,21 +467,12 @@
     void notifyDexLoad(String loadingPackageName, in List<String> dexPaths, String loaderIsa);
 
     /**
-     * Ask the package manager to perform dex-opt (if needed) on the given
-     * package if it already hasn't done so.
-     *
-     * In most cases, apps are dexopted in advance and this function will
-     * be a no-op.
-     */
-    boolean performDexOptIfNeeded(String packageName);
-
-    /**
      * Ask the package manager to perform a dex-opt for the given reason. The package
      * manager will map the reason to a compiler filter according to the current system
      * configuration.
      */
     boolean performDexOpt(String packageName, boolean checkProfiles,
-            int compileReason, boolean force);
+            int compileReason, boolean force, boolean bootComplete);
 
     /**
      * Ask the package manager to perform a dex-opt with the given compiler filter.
@@ -490,7 +481,7 @@
      *       definite state.
      */
     boolean performDexOptMode(String packageName, boolean checkProfiles,
-            String targetCompilerFilter, boolean force);
+            String targetCompilerFilter, boolean force, boolean bootComplete);
 
     /**
      * Ask the package manager to perform a dex-opt with the given compiler filter on the
diff --git a/services/core/java/com/android/server/connectivity/Tethering.java b/services/core/java/com/android/server/connectivity/Tethering.java
index ee89d57..f212c80 100644
--- a/services/core/java/com/android/server/connectivity/Tethering.java
+++ b/services/core/java/com/android/server/connectivity/Tethering.java
@@ -52,6 +52,7 @@
 import android.net.wifi.WifiManager;
 import android.os.Binder;
 import android.os.Bundle;
+import android.os.Handler;
 import android.os.INetworkManagementService;
 import android.os.Looper;
 import android.os.Message;
@@ -195,8 +196,10 @@
         mTetherMasterSM = new TetherMasterSM("TetherMaster", mLooper);
         mTetherMasterSM.start();
 
-        mOffloadController = new OffloadController(mTetherMasterSM.getHandler(),
-                deps.getOffloadHardwareInterface(), mLog);
+        final Handler smHandler = mTetherMasterSM.getHandler();
+        mOffloadController = new OffloadController(smHandler,
+                deps.getOffloadHardwareInterface(smHandler, mLog),
+                mLog);
         mUpstreamNetworkMonitor = new UpstreamNetworkMonitor(
                 mContext, mTetherMasterSM, TetherMasterSM.EVENT_UPSTREAM_CALLBACK, mLog);
         mForwardedDownstreams = new HashSet<>();
@@ -1083,7 +1086,6 @@
         TetherMasterSM(String name, Looper looper) {
             super(name, looper);
 
-            //Add states
             mInitialState = new InitialState();
             mTetherModeAliveState = new TetherModeAliveState();
             mSetIpForwardingEnabledErrorState = new SetIpForwardingEnabledErrorState();
@@ -1397,10 +1399,11 @@
 
                 mSimChange.startListening();
                 mUpstreamNetworkMonitor.start();
-                mOffloadController.start();
 
+                // TODO: De-duplicate with updateUpstreamWanted() below.
                 if (upstreamWanted()) {
                     mUpstreamWanted = true;
+                    mOffloadController.start();
                     chooseUpstreamType(true);
                     mTryCell = false;
                 }
@@ -1419,6 +1422,13 @@
             private boolean updateUpstreamWanted() {
                 final boolean previousUpstreamWanted = mUpstreamWanted;
                 mUpstreamWanted = upstreamWanted();
+                if (mUpstreamWanted != previousUpstreamWanted) {
+                    if (mUpstreamWanted) {
+                        mOffloadController.start();
+                    } else {
+                        mOffloadController.stop();
+                    }
+                }
                 return previousUpstreamWanted;
             }
 
diff --git a/services/core/java/com/android/server/connectivity/tethering/OffloadController.java b/services/core/java/com/android/server/connectivity/tethering/OffloadController.java
index ec7ab5b..12899d8 100644
--- a/services/core/java/com/android/server/connectivity/tethering/OffloadController.java
+++ b/services/core/java/com/android/server/connectivity/tethering/OffloadController.java
@@ -49,12 +49,30 @@
             mConfigInitialized = mHwInterface.initOffloadConfig();
             if (!mConfigInitialized) {
                 mLog.i("tethering offload config not supported");
+                stop();
                 return;
             }
         }
 
-        // TODO: Create and register ITetheringOffloadCallback.
-        mControlInitialized = mHwInterface.initOffloadControl();
+        mControlInitialized = mHwInterface.initOffloadControl(
+                new OffloadHardwareInterface.ControlCallback() {
+                    @Override
+                    public void onOffloadEvent(int event) {
+                        mLog.log("got offload event: " + event);
+                    }
+
+                    @Override
+                    public void onNatTimeoutUpdate(int proto,
+                                                   String srcAddr, int srcPort,
+                                                   String dstAddr, int dstPort) {
+                        mLog.log(String.format("NAT timeout update: %s (%s,%s) -> (%s,%s)",
+                                proto, srcAddr, srcPort, dstAddr, dstPort));
+                    }
+                });
+        if (!mControlInitialized) {
+            mLog.i("tethering offload control not supported");
+            stop();
+        }
     }
 
     public void stop() {
diff --git a/services/core/java/com/android/server/connectivity/tethering/OffloadHardwareInterface.java b/services/core/java/com/android/server/connectivity/tethering/OffloadHardwareInterface.java
index 87fc491..0429ab3 100644
--- a/services/core/java/com/android/server/connectivity/tethering/OffloadHardwareInterface.java
+++ b/services/core/java/com/android/server/connectivity/tethering/OffloadHardwareInterface.java
@@ -17,9 +17,11 @@
 package com.android.server.connectivity.tethering;
 
 import android.hardware.tetheroffload.control.V1_0.IOffloadControl;
-import android.hardware.tetheroffload.control.V1_0.IOffloadControl.stopOffloadCallback;
+import android.hardware.tetheroffload.control.V1_0.ITetheringOffloadCallback;
+import android.hardware.tetheroffload.control.V1_0.NatTimeoutUpdate;
+import android.os.Handler;
 import android.os.RemoteException;
-import android.util.Log;
+import android.net.util.SharedLog;
 
 
 /**
@@ -32,46 +34,102 @@
 
     private static native boolean configOffload();
 
+    private final Handler mHandler;
+    private final SharedLog mLog;
     private IOffloadControl mOffloadControl;
+    private TetheringOffloadCallback mTetheringOffloadCallback;
+    private ControlCallback mControlCallback;
 
-    public OffloadHardwareInterface() {}
+    public static class ControlCallback {
+        public void onOffloadEvent(int event) {}
+
+        public void onNatTimeoutUpdate(int proto,
+                                       String srcAddr, int srcPort,
+                                       String dstAddr, int dstPort) {}
+    }
+
+    public OffloadHardwareInterface(Handler h, SharedLog log) {
+        mHandler = h;
+        mLog = log.forSubComponent(TAG);
+    }
 
     public boolean initOffloadConfig() {
         return configOffload();
     }
 
-    // TODO: Extend this to take a TetheringControlCallback for registration.
-    public boolean initOffloadControl() {
+    public boolean initOffloadControl(ControlCallback controlCb) {
+        mControlCallback = controlCb;
+
         if (mOffloadControl == null) {
             try {
                 mOffloadControl = IOffloadControl.getService();
             } catch (RemoteException e) {
-                Log.d(TAG, "tethering offload control not supported: " + e);
+                mLog.e("tethering offload control not supported: " + e);
                 return false;
             }
         }
 
-        // TODO: call mOffloadControl.initOffload(...callback...);
+        mTetheringOffloadCallback = new TetheringOffloadCallback(mHandler, mControlCallback);
+        final CbResults results = new CbResults();
+        try {
+            mOffloadControl.initOffload(
+                    mTetheringOffloadCallback,
+                    (boolean success, String errMsg) -> {
+                        results.success = success;
+                        results.errMsg = errMsg;
+                    });
+        } catch (RemoteException e) {
+            mLog.e("failed to initOffload: " + e);
+            return false;
+        }
 
-        return true;
+        if (!results.success) mLog.e("initOffload failed: " + results.errMsg);
+        return results.success;
     }
 
     public void stopOffloadControl() {
-        if (mOffloadControl == null) return;
-
-        try {
-            final stopOffloadCallback cb = new stopOffloadCallback() {
-                @Override
-                public void onValues(boolean success, String errMsg) {
-                    if (success) return;
-
-                    Log.e(TAG, "stopOffload failed: " + errMsg);
-                }
-            };
-            mOffloadControl.stopOffload(cb);
-        } catch (RemoteException e) {
-            Log.d(TAG, "failed to stopOffload: " + e);
+        if (mOffloadControl != null) {
+            try {
+                mOffloadControl.stopOffload(
+                        (boolean success, String errMsg) -> {
+                            if (!success) mLog.e("stopOffload failed: " + errMsg);
+                        });
+            } catch (RemoteException e) {
+                mLog.e("failed to stopOffload: " + e);
+            }
         }
         mOffloadControl = null;
+        mTetheringOffloadCallback = null;
+        mControlCallback = null;
+    }
+
+    private static class TetheringOffloadCallback extends ITetheringOffloadCallback.Stub {
+        public final Handler handler;
+        public final ControlCallback controlCb;
+
+        public TetheringOffloadCallback(Handler h, ControlCallback cb) {
+            handler = h;
+            controlCb = cb;
+        }
+
+        @Override
+        public void onEvent(int event) {
+            handler.post(() -> { controlCb.onOffloadEvent(event); });
+        }
+
+        @Override
+        public void updateTimeout(NatTimeoutUpdate params) {
+            handler.post(() -> {
+                    controlCb.onNatTimeoutUpdate(
+                        params.proto,
+                        params.src.addr, params.src.port,
+                        params.dst.addr, params.dst.port);
+            });
+        }
+    }
+
+    private static class CbResults {
+        boolean success;
+        String errMsg;
     }
 }
diff --git a/services/core/java/com/android/server/connectivity/tethering/TetheringDependencies.java b/services/core/java/com/android/server/connectivity/tethering/TetheringDependencies.java
index be2cf08..b8174b6 100644
--- a/services/core/java/com/android/server/connectivity/tethering/TetheringDependencies.java
+++ b/services/core/java/com/android/server/connectivity/tethering/TetheringDependencies.java
@@ -16,6 +16,9 @@
 
 package com.android.server.connectivity.tethering;
 
+import android.os.Handler;
+import android.net.util.SharedLog;
+
 
 /**
  * Capture tethering dependencies, for injection.
@@ -23,7 +26,7 @@
  * @hide
  */
 public class TetheringDependencies {
-    public OffloadHardwareInterface getOffloadHardwareInterface() {
-        return new OffloadHardwareInterface();
+    public OffloadHardwareInterface getOffloadHardwareInterface(Handler h, SharedLog log) {
+        return new OffloadHardwareInterface(h, log);
     }
 }
diff --git a/services/core/java/com/android/server/pm/BackgroundDexOptService.java b/services/core/java/com/android/server/pm/BackgroundDexOptService.java
index d364d17..adfd7b3 100644
--- a/services/core/java/com/android/server/pm/BackgroundDexOptService.java
+++ b/services/core/java/com/android/server/pm/BackgroundDexOptService.java
@@ -211,7 +211,8 @@
             pm.performDexOpt(pkg,
                     /* checkProfiles */ false,
                     PackageManagerService.REASON_BOOT,
-                    /* force */ false);
+                    /* force */ false,
+                    /* bootComplete */ true);
         }
         // Ran to completion, so we abandon our timeslice and do not reschedule.
         jobFinished(jobParams, /* reschedule */ false);
@@ -288,7 +289,8 @@
                     ? pm.performDexOpt(pkg,
                             /* checkProfiles */ true,
                             PackageManagerService.REASON_BACKGROUND_DEXOPT,
-                            /* force */ false)
+                            /* force */ false,
+                            /* bootComplete */ true)
                     : pm.performDexOptSecondary(pkg,
                             PackageManagerService.REASON_BACKGROUND_DEXOPT,
                             /* force */ false);
diff --git a/services/core/java/com/android/server/pm/OtaDexoptService.java b/services/core/java/com/android/server/pm/OtaDexoptService.java
index d93d620..317250b 100644
--- a/services/core/java/com/android/server/pm/OtaDexoptService.java
+++ b/services/core/java/com/android/server/pm/OtaDexoptService.java
@@ -315,7 +315,8 @@
                 null /* ISAs */, false /* checkProfiles */,
                 getCompilerFilterForReason(compilationReason),
                 null /* CompilerStats.PackageStats */,
-                mPackageManagerService.getDexManager().isUsedByOtherApps(pkg.packageName));
+                mPackageManagerService.getDexManager().isUsedByOtherApps(pkg.packageName),
+                true /* bootComplete */);
 
         return commands;
     }
diff --git a/services/core/java/com/android/server/pm/PackageDexOptimizer.java b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
index 126ad26..49639b0 100644
--- a/services/core/java/com/android/server/pm/PackageDexOptimizer.java
+++ b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
@@ -104,7 +104,8 @@
      */
     int performDexOpt(PackageParser.Package pkg, String[] sharedLibraries,
             String[] instructionSets, boolean checkProfiles, String targetCompilationFilter,
-            CompilerStats.PackageStats packageStats, boolean isUsedByOtherApps) {
+            CompilerStats.PackageStats packageStats, boolean isUsedByOtherApps,
+            boolean bootComplete) {
         if (!canOptimizePackage(pkg)) {
             return DEX_OPT_SKIPPED;
         }
@@ -119,7 +120,7 @@
             }
             try {
                 return performDexOptLI(pkg, sharedLibraries, instructionSets, checkProfiles,
-                        targetCompilationFilter, packageStats, isUsedByOtherApps);
+                        targetCompilationFilter, packageStats, isUsedByOtherApps, bootComplete);
             } finally {
                 if (useLock) {
                     mDexoptWakeLock.release();
@@ -136,7 +137,7 @@
     private int performDexOptLI(PackageParser.Package pkg, String[] sharedLibraries,
             String[] targetInstructionSets, boolean checkForProfileUpdates,
             String targetCompilerFilter, CompilerStats.PackageStats packageStats,
-            boolean isUsedByOtherApps) {
+            boolean isUsedByOtherApps, boolean bootComplete) {
         final String[] instructionSets = targetInstructionSets != null ?
                 targetInstructionSets : getAppDexInstructionSets(pkg.applicationInfo);
         final String[] dexCodeInstructionSets = getDexCodeInstructionSets(instructionSets);
@@ -152,7 +153,7 @@
         // paths (b/34169257).
         String sharedLibrariesPath = getSharedLibrariesPath(sharedLibraries);
         // Get the dexopt flags after getRealCompilerFilter to make sure we get the correct flags.
-        final int dexoptFlags = getDexFlags(pkg, compilerFilter);
+        final int dexoptFlags = getDexFlags(pkg, compilerFilter, bootComplete);
 
         int result = DEX_OPT_SKIPPED;
         // TODO: Iterate based on dependency hierarchy (currently alphabetically by name)
@@ -274,7 +275,9 @@
     @GuardedBy("mInstallLock")
     private int dexOptSecondaryDexPathLI(ApplicationInfo info, String path, Set<String> isas,
             String compilerFilter, boolean isUsedByOtherApps) {
-        int dexoptFlags = getDexFlags(info, compilerFilter) | DEXOPT_SECONDARY_DEX;
+        // Secondary dex files are currently not compiled at boot.
+        int dexoptFlags = getDexFlags(info, compilerFilter, /* bootComplete */ true)
+                | DEXOPT_SECONDARY_DEX;
         // Check the app storage and add the appropriate flags.
         if (info.dataDir.equals(info.deviceProtectedDataDir)) {
             dexoptFlags |= DEXOPT_STORAGE_DE;
@@ -374,11 +377,12 @@
      * Computes the dex flags that needs to be pass to installd for the given package and compiler
      * filter.
      */
-    private int getDexFlags(PackageParser.Package pkg, String compilerFilter) {
-        return getDexFlags(pkg.applicationInfo, compilerFilter);
+    private int getDexFlags(PackageParser.Package pkg, String compilerFilter,
+            boolean bootComplete) {
+        return getDexFlags(pkg.applicationInfo, compilerFilter, bootComplete);
     }
 
-    private int getDexFlags(ApplicationInfo info, String compilerFilter) {
+    private int getDexFlags(ApplicationInfo info, String compilerFilter, boolean bootComplete) {
         int flags = info.flags;
         boolean debuggable = (flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
         // Profile guide compiled oat files should not be public.
@@ -389,7 +393,7 @@
                 (isPublic ? DEXOPT_PUBLIC : 0)
                 | (debuggable ? DEXOPT_DEBUGGABLE : 0)
                 | profileFlag
-                | DEXOPT_BOOTCOMPLETE;
+                | (bootComplete ? DEXOPT_BOOTCOMPLETE : 0);
         return adjustDexoptFlags(dexFlags);
     }
 
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 2391abd..4c732d7 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -2662,7 +2662,7 @@
                 }
 
                 int[] stats = performDexOptUpgrade(coreApps, false,
-                        getCompilerFilterForReason(REASON_CORE_APP));
+                        getCompilerFilterForReason(REASON_CORE_APP), /* bootComplete */ false);
 
                 final int elapsedTimeSeconds =
                         (int) TimeUnit.NANOSECONDS.toSeconds(System.nanoTime() - start);
@@ -7305,7 +7305,8 @@
 
         final long startTime = System.nanoTime();
         final int[] stats = performDexOptUpgrade(pkgs, mIsPreNUpgrade /* showDialog */,
-                    getCompilerFilterForReason(causeFirstBoot ? REASON_FIRST_BOOT : REASON_BOOT));
+                    getCompilerFilterForReason(causeFirstBoot ? REASON_FIRST_BOOT : REASON_BOOT),
+                    false /* bootComplete */);
 
         final int elapsedTimeSeconds =
                 (int) TimeUnit.NANOSECONDS.toSeconds(System.nanoTime() - startTime);
@@ -7324,7 +7325,7 @@
      * and {@code numberOfPackagesFailed}.
      */
     private int[] performDexOptUpgrade(List<PackageParser.Package> pkgs, boolean showDialog,
-            String compilerFilter) {
+            String compilerFilter, boolean bootComplete) {
 
         int numberOfPackagesVisited = 0;
         int numberOfPackagesOptimized = 0;
@@ -7381,7 +7382,8 @@
             int dexOptStatus = performDexOptTraced(pkg.packageName,
                     false /* checkProfiles */,
                     compilerFilter,
-                    false /* force */);
+                    false /* force */,
+                    bootComplete);
             switch (dexOptStatus) {
                 case PackageDexOptimizer.DEX_OPT_PERFORMED:
                     numberOfPackagesOptimized++;
@@ -7425,36 +7427,30 @@
         mDexManager.notifyDexLoad(ai, dexPaths, loaderIsa, userId);
     }
 
-    // TODO: this is not used nor needed. Delete it.
-    @Override
-    public boolean performDexOptIfNeeded(String packageName) {
-        int dexOptStatus = performDexOptTraced(packageName,
-                false /* checkProfiles */, getFullCompilerFilter(), false /* force */);
-        return dexOptStatus != PackageDexOptimizer.DEX_OPT_FAILED;
-    }
-
     @Override
     public boolean performDexOpt(String packageName,
-            boolean checkProfiles, int compileReason, boolean force) {
+            boolean checkProfiles, int compileReason, boolean force, boolean bootComplete) {
         int dexOptStatus = performDexOptTraced(packageName, checkProfiles,
-                getCompilerFilterForReason(compileReason), force);
+                getCompilerFilterForReason(compileReason), force, bootComplete);
         return dexOptStatus != PackageDexOptimizer.DEX_OPT_FAILED;
     }
 
     @Override
     public boolean performDexOptMode(String packageName,
-            boolean checkProfiles, String targetCompilerFilter, boolean force) {
+            boolean checkProfiles, String targetCompilerFilter, boolean force,
+            boolean bootComplete) {
         int dexOptStatus = performDexOptTraced(packageName, checkProfiles,
-                targetCompilerFilter, force);
+                targetCompilerFilter, force, bootComplete);
         return dexOptStatus != PackageDexOptimizer.DEX_OPT_FAILED;
     }
 
     private int performDexOptTraced(String packageName,
-                boolean checkProfiles, String targetCompilerFilter, boolean force) {
+                boolean checkProfiles, String targetCompilerFilter, boolean force,
+                boolean bootComplete) {
         Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "dexopt");
         try {
             return performDexOptInternal(packageName, checkProfiles,
-                    targetCompilerFilter, force);
+                    targetCompilerFilter, force, bootComplete);
         } finally {
             Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
         }
@@ -7463,7 +7459,8 @@
     // Run dexopt on a given package. Returns true if dexopt did not fail, i.e.
     // if the package can now be considered up to date for the given filter.
     private int performDexOptInternal(String packageName,
-                boolean checkProfiles, String targetCompilerFilter, boolean force) {
+                boolean checkProfiles, String targetCompilerFilter, boolean force,
+                boolean bootComplete) {
         PackageParser.Package p;
         synchronized (mPackages) {
             p = mPackages.get(packageName);
@@ -7478,7 +7475,7 @@
         try {
             synchronized (mInstallLock) {
                 return performDexOptInternalWithDependenciesLI(p, checkProfiles,
-                        targetCompilerFilter, force);
+                        targetCompilerFilter, force, bootComplete);
             }
         } finally {
             Binder.restoreCallingIdentity(callingId);
@@ -7499,7 +7496,7 @@
 
     private int performDexOptInternalWithDependenciesLI(PackageParser.Package p,
             boolean checkProfiles, String targetCompilerFilter,
-            boolean force) {
+            boolean force, boolean bootComplete) {
         // Select the dex optimizer based on the force parameter.
         // Note: The force option is rarely used (cmdline input for testing, mostly), so it's OK to
         //       allocate an object here.
@@ -7519,12 +7516,13 @@
                         false /* checkProfiles */,
                         getCompilerFilterForReason(REASON_NON_SYSTEM_LIBRARY),
                         getOrCreateCompilerPackageStats(depPackage),
-                        mDexManager.isUsedByOtherApps(p.packageName));
+                        mDexManager.isUsedByOtherApps(p.packageName),
+                        bootComplete);
             }
         }
         return pdo.performDexOpt(p, p.usesLibraryFiles, instructionSets, checkProfiles,
                 targetCompilerFilter, getOrCreateCompilerPackageStats(p),
-                mDexManager.isUsedByOtherApps(p.packageName));
+                mDexManager.isUsedByOtherApps(p.packageName), bootComplete);
     }
 
     // Performs dexopt on the used secondary dex files belonging to the given package.
@@ -7670,7 +7668,8 @@
             // Don't use profiles since that may cause compilation to be skipped.
             final int res = performDexOptInternalWithDependenciesLI(pkg,
                     false /* checkProfiles */, getCompilerFilterForReason(REASON_FORCED_DEXOPT),
-                    true /* force */);
+                    true /* force */,
+                    true /* bootComplete */);
 
             Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
             if (res != PackageDexOptimizer.DEX_OPT_PERFORMED) {
@@ -15242,7 +15241,8 @@
                     null /* instructionSets */, false /* checkProfiles */,
                     getCompilerFilterForReason(REASON_INSTALL),
                     getOrCreateCompilerPackageStats(pkg),
-                    mDexManager.isUsedByOtherApps(pkg.packageName));
+                    mDexManager.isUsedByOtherApps(pkg.packageName),
+                    true /* bootComplete */);
             Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
 
             // Notify BackgroundDexOptService that the package has been changed.
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index 2f000c2..dd3af66 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -399,7 +399,8 @@
                     ? mInterface.performDexOptSecondary(packageName,
                             targetCompilerFilter, forceCompilation)
                     : mInterface.performDexOptMode(packageName,
-                            checkProfiles, targetCompilerFilter, forceCompilation);
+                            checkProfiles, targetCompilerFilter, forceCompilation,
+                            true /* bootComplete */);
             if (!result) {
                 failedPackages.add(packageName);
             }
diff --git a/tests/net/java/com/android/server/connectivity/TetheringTest.java b/tests/net/java/com/android/server/connectivity/TetheringTest.java
index bc89c0f..d5a0b86 100644
--- a/tests/net/java/com/android/server/connectivity/TetheringTest.java
+++ b/tests/net/java/com/android/server/connectivity/TetheringTest.java
@@ -43,6 +43,7 @@
 import android.net.INetworkStatsService;
 import android.net.InterfaceConfiguration;
 import android.net.NetworkRequest;
+import android.net.util.SharedLog;
 import android.net.wifi.WifiConfiguration;
 import android.net.wifi.WifiManager;
 import android.os.Handler;
@@ -142,8 +143,8 @@
         };
         mServiceContext.registerReceiver(mBroadcastReceiver,
                 new IntentFilter(ConnectivityManager.ACTION_TETHER_STATE_CHANGED));
-        when(mTetheringDependencies.getOffloadHardwareInterface())
-                .thenReturn(mOffloadHardwareInterface);
+        when(mTetheringDependencies.getOffloadHardwareInterface(
+                any(Handler.class), any(SharedLog.class))).thenReturn(mOffloadHardwareInterface);
         mTethering = new Tethering(mServiceContext, mNMService, mStatsService, mPolicyManager,
                                    mLooper.getLooper(), mSystemProperties,
                                    mTetheringDependencies);