ART Services: Implement cancellation.

Bug: 244412198
Test: atest ArtServiceTests
Test: manual -
  1. adb shell pm art optimize-package -m speed -f \
        com.google.android.youtube
  2. adb shell pm art cancel <job-id>
Ignore-AOSP-First: ART Services.
Change-Id: I3ae3e5e65d1f2bfc7961d2df541e98a3c2e8a2d6
diff --git a/libartservice/service/java/com/android/server/art/DexOptHelper.java b/libartservice/service/java/com/android/server/art/DexOptHelper.java
index 89bd8f4..de15dd4 100644
--- a/libartservice/service/java/com/android/server/art/DexOptHelper.java
+++ b/libartservice/service/java/com/android/server/art/DexOptHelper.java
@@ -24,6 +24,7 @@
 import android.apphibernation.AppHibernationManager;
 import android.content.Context;
 import android.os.Binder;
+import android.os.CancellationSignal;
 import android.os.PowerManager;
 import android.os.RemoteException;
 import android.os.WorkSource;
@@ -74,11 +75,15 @@
     @NonNull
     public OptimizeResult dexopt(@NonNull PackageDataSnapshot snapshot,
             @NonNull PackageState pkgState, @NonNull AndroidPackageApi pkg,
-            @NonNull OptimizeParams params) throws RemoteException {
+            @NonNull OptimizeParams params, @NonNull CancellationSignal cancellationSignal)
+            throws RemoteException {
         List<DexFileOptimizeResult> results = new ArrayList<>();
         Supplier<OptimizeResult> createResult = ()
                 -> new OptimizeResult(params.getCompilerFilter(), params.getReason(),
                         List.of(new PackageOptimizeResult(pkgState.getPackageName(), results)));
+        Supplier<Boolean> hasCancelledResult = ()
+                -> results.stream().anyMatch(
+                        result -> result.getStatus() == OptimizeResult.OPTIMIZE_CANCELLED);
 
         if (!canOptimizePackage(pkgState, pkg)) {
             return createResult.get();
@@ -95,7 +100,11 @@
             wakeLock.acquire(WAKE_LOCK_TIMEOUT_MS);
 
             if ((params.getFlags() & ArtFlags.FLAG_FOR_PRIMARY_DEX) != 0) {
-                results.addAll(mInjector.getPrimaryDexOptimizer().dexopt(pkgState, pkg, params));
+                results.addAll(mInjector.getPrimaryDexOptimizer().dexopt(
+                        pkgState, pkg, params, cancellationSignal));
+                if (hasCancelledResult.get()) {
+                    return createResult.get();
+                }
             }
 
             if ((params.getFlags() & ArtFlags.FLAG_FOR_SECONDARY_DEX) != 0) {