Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5d67812f authored by Song Chun Fan's avatar Song Chun Fan Committed by Android (Google) Code Review
Browse files

Merge "[pm] shell command to wait for handler(s)" into udc-dev

parents a0fcec61 a2d63f09
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -791,4 +791,6 @@ interface IPackageManager {
    void setKeepUninstalledPackages(in List<String> packageList);

    boolean[] canPackageQuery(String sourcePackageName, in String[] targetPackageNames, int userId);

    boolean waitForHandler(long timeoutMillis, boolean forBackgroundHandler);
}
+31 −0
Original line number Diff line number Diff line
@@ -279,6 +279,7 @@ import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
@@ -6295,6 +6296,36 @@ public class PackageManagerService implements PackageSender, TestUtilityService
            }
        }

        /**
         * Wait for the handler to finish handling all pending messages.
         * @param timeoutMillis Maximum time in milliseconds to wait.
         * @param forBackgroundHandler Whether to wait for the background handler instead.
         * @return True if all the waiting messages in the handler has been handled.
         *         False if timeout.
         */
        @Override
        public boolean waitForHandler(long timeoutMillis, boolean forBackgroundHandler) {
            final CountDownLatch latch = new CountDownLatch(1);
            if (forBackgroundHandler) {
                mBackgroundHandler.post(latch::countDown);
            } else {
                mHandler.post(latch::countDown);
            }
            final long endTimeMillis = System.currentTimeMillis() + timeoutMillis;
            while (latch.getCount() > 0) {
                try {
                    final long remainingTimeMillis = endTimeMillis - System.currentTimeMillis();
                    if (remainingTimeMillis <= 0) {
                        return false;
                    }
                    return latch.await(remainingTimeMillis, TimeUnit.MILLISECONDS);
                } catch (InterruptedException e) {
                    // ignore and retry
                }
            }
            return true;
        }

        @Override
        public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
                throws RemoteException {
+50 −0
Original line number Diff line number Diff line
@@ -354,6 +354,10 @@ class PackageManagerShellCommand extends ShellCommand {
                    return runSetSilentUpdatesPolicy();
                case "get-app-metadata":
                    return runGetAppMetadata();
                case "wait-for-handler":
                    return runWaitForHandler(/* forBackgroundHandler= */ false);
                case "wait-for-background-handler":
                    return runWaitForHandler(/* forBackgroundHandler= */ true);
                default: {
                    if (ART_SERVICE_COMMANDS.contains(cmd)) {
                        if (DexOptHelper.useArtService()) {
@@ -3601,6 +3605,40 @@ class PackageManagerShellCommand extends ShellCommand {
        return 1;
    }

    private int runWaitForHandler(boolean forBackgroundHandler) {
        final PrintWriter pw = getOutPrintWriter();
        long timeoutMillis = 60000; // default timeout is 60 seconds
        String opt;
        while ((opt = getNextOption()) != null) {
            switch (opt) {
                case "--timeout":
                    timeoutMillis = Long.parseLong(getNextArgRequired());
                    break;
                default:
                    pw.println("Error: Unknown option: " + opt);
                    return -1;
            }
        }
        if (timeoutMillis <= 0) {
            pw.println("Error: --timeout value must be positive: " + timeoutMillis);
            return -1;
        }
        final boolean success;
        try {
            success = mInterface.waitForHandler(timeoutMillis, forBackgroundHandler);
        } catch (RemoteException e) {
            pw.println("Failure [" + e.getClass().getName() + " - " + e.getMessage() + "]");
            return -1;
        }
        if (success) {
            pw.println("Success");
            return 0;
        } else {
            pw.println("Timeout. PackageManager handlers are still busy.");
            return -1;
        }
    }

    private int runArtServiceCommand() {
        try (var in = ParcelFileDescriptor.dup(getInFileDescriptor());
                var out = ParcelFileDescriptor.dup(getOutFileDescriptor());
@@ -4427,6 +4465,18 @@ class PackageManagerShellCommand extends ShellCommand {
        pw.println("      --reset: restore the installer and throttle time to the default, and");
        pw.println("        clear tracks of silent updates in the system.");
        pw.println("");
        pw.println("  wait-for-handler --timeout <MILLIS>");
        pw.println("    Wait for a given amount of time till the package manager handler finishes");
        pw.println("    handling all pending messages.");
        pw.println("      --timeout: wait for a given number of milliseconds. If the handler(s)");
        pw.println("        fail to finish before the timeout, the command returns error.");
        pw.println("");
        pw.println("  wait-for-background-handler --timeout <MILLIS>");
        pw.println("    Wait for a given amount of time till the package manager's background");
        pw.println("    handler finishes handling all pending messages.");
        pw.println("      --timeout: wait for a given number of milliseconds. If the handler(s)");
        pw.println("        fail to finish before the timeout, the command returns error.");
        pw.println("");
        if (DexOptHelper.useArtService()) {
            printArtServiceHelp();
        } else {