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

This commit is contained in:
Song Chun Fan
2023-05-18 17:24:08 +00:00
committed by Android (Google) Code Review
3 changed files with 83 additions and 0 deletions

View File

@@ -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);
}

View File

@@ -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 {

View File

@@ -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 {