Support optimizing a single split.

Bug: 260078033
Test: atest ArtServiceTests
Test: adb shell pm art optimize-package -m speed-profile -f --split \"\" com.google.android.gms
Ignore-AOSP-First: ART Services.
Change-Id: I41a9eb0a1cca0f3bf0f62d6d761c25654bfe9787
diff --git a/libartservice/service/javatests/com/android/server/art/DexOptHelperTest.java b/libartservice/service/javatests/com/android/server/art/DexOptHelperTest.java
index 0653efb..ac79d26 100644
--- a/libartservice/service/javatests/com/android/server/art/DexOptHelperTest.java
+++ b/libartservice/service/javatests/com/android/server/art/DexOptHelperTest.java
@@ -22,6 +22,7 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import static org.junit.Assert.assertThrows;
 import static org.mockito.Mockito.any;
 import static org.mockito.Mockito.anyLong;
 import static org.mockito.Mockito.eq;
@@ -427,6 +428,34 @@
     }
 
     @Test
+    public void testDexoptSplit() throws Exception {
+        mRequestedPackages = List.of(PKG_NAME_FOO);
+        mParams = new OptimizeParams.Builder("install")
+                          .setCompilerFilter("speed-profile")
+                          .setFlags(ArtFlags.FLAG_FOR_PRIMARY_DEX | ArtFlags.FLAG_FOR_SINGLE_SPLIT)
+                          .setSplitName("split_0")
+                          .build();
+
+        mDexOptHelper.dexopt(
+                mSnapshot, mRequestedPackages, mParams, mCancellationSignal, mExecutor);
+    }
+
+    @Test
+    public void testDexoptSplitNotFound() throws Exception {
+        mRequestedPackages = List.of(PKG_NAME_FOO);
+        mParams = new OptimizeParams.Builder("install")
+                          .setCompilerFilter("speed-profile")
+                          .setFlags(ArtFlags.FLAG_FOR_PRIMARY_DEX | ArtFlags.FLAG_FOR_SINGLE_SPLIT)
+                          .setSplitName("split_bogus")
+                          .build();
+
+        assertThrows(IllegalArgumentException.class, () -> {
+            mDexOptHelper.dexopt(
+                    mSnapshot, mRequestedPackages, mParams, mCancellationSignal, mExecutor);
+        });
+    }
+
+    @Test
     public void testCallbacks() throws Exception {
         List<OptimizeResult> list1 = new ArrayList<>();
         mConfig.addOptimizePackageDoneCallback(Runnable::run, result -> list1.add(result));
@@ -467,20 +496,32 @@
         mConfig.addOptimizePackageDoneCallback(Runnable::run, callback);
     }
 
-    private AndroidPackage createPackage() {
+    private AndroidPackage createPackage(boolean multiSplit) {
         AndroidPackage pkg = mock(AndroidPackage.class);
+
         var baseSplit = mock(AndroidPackageSplit.class);
         lenient().when(baseSplit.isHasCode()).thenReturn(true);
-        lenient().when(pkg.getSplits()).thenReturn(List.of(baseSplit));
+
+        if (multiSplit) {
+            var split0 = mock(AndroidPackageSplit.class);
+            lenient().when(split0.getName()).thenReturn("split_0");
+            lenient().when(split0.isHasCode()).thenReturn(true);
+
+            lenient().when(pkg.getSplits()).thenReturn(List.of(baseSplit, split0));
+        } else {
+            lenient().when(pkg.getSplits()).thenReturn(List.of(baseSplit));
+        }
+
         return pkg;
     }
 
-    private PackageState createPackageState(String packageName, List<SharedLibrary> deps) {
+    private PackageState createPackageState(
+            String packageName, List<SharedLibrary> deps, boolean multiSplit) {
         PackageState pkgState = mock(PackageState.class);
         lenient().when(pkgState.getPackageName()).thenReturn(packageName);
         lenient().when(pkgState.getAppId()).thenReturn(12345);
         lenient().when(pkgState.getUsesLibraries()).thenReturn(deps);
-        AndroidPackage pkg = createPackage();
+        AndroidPackage pkg = createPackage(multiSplit);
         lenient().when(pkgState.getAndroidPackage()).thenReturn(pkg);
         return pkgState;
     }
@@ -515,32 +556,34 @@
         SharedLibrary lib1b = createLibrary("lib1b", PKG_NAME_LIB1, List.of(lib2, lib4));
         SharedLibrary lib1c = createLibrary("lib1c", PKG_NAME_LIB1, List.of(lib3));
 
-        mPkgStateFoo = createPackageState(PKG_NAME_FOO, List.of(lib1a));
+        mPkgStateFoo = createPackageState(PKG_NAME_FOO, List.of(lib1a), true /* multiSplit */);
         mPkgFoo = mPkgStateFoo.getAndroidPackage();
         lenient().when(mSnapshot.getPackageState(PKG_NAME_FOO)).thenReturn(mPkgStateFoo);
 
-        mPkgStateBar = createPackageState(PKG_NAME_BAR, List.of(lib1b));
+        mPkgStateBar = createPackageState(PKG_NAME_BAR, List.of(lib1b), false /* multiSplit */);
         mPkgBar = mPkgStateBar.getAndroidPackage();
         lenient().when(mSnapshot.getPackageState(PKG_NAME_BAR)).thenReturn(mPkgStateBar);
 
-        mPkgStateLib1 = createPackageState(PKG_NAME_LIB1, List.of(libbaz, lib2, lib3, lib4));
+        mPkgStateLib1 = createPackageState(
+                PKG_NAME_LIB1, List.of(libbaz, lib2, lib3, lib4), false /* multiSplit */);
         mPkgLib1 = mPkgStateLib1.getAndroidPackage();
         lenient().when(mSnapshot.getPackageState(PKG_NAME_LIB1)).thenReturn(mPkgStateLib1);
 
-        mPkgStateLib2 = createPackageState(PKG_NAME_LIB2, List.of());
+        mPkgStateLib2 = createPackageState(PKG_NAME_LIB2, List.of(), false /* multiSplit */);
         mPkgLib2 = mPkgStateLib2.getAndroidPackage();
         lenient().when(mSnapshot.getPackageState(PKG_NAME_LIB2)).thenReturn(mPkgStateLib2);
 
         // This should not be considered as a transitive dependency of any requested package, even
         // though it is a dependency of package "lib1".
-        PackageState pkgStateLib3 = createPackageState(PKG_NAME_LIB3, List.of());
+        PackageState pkgStateLib3 =
+                createPackageState(PKG_NAME_LIB3, List.of(), false /* multiSplit */);
         lenient().when(mSnapshot.getPackageState(PKG_NAME_LIB3)).thenReturn(pkgStateLib3);
 
-        mPkgStateLib4 = createPackageState(PKG_NAME_LIB4, List.of());
+        mPkgStateLib4 = createPackageState(PKG_NAME_LIB4, List.of(), false /* multiSplit */);
         mPkgLib4 = mPkgStateLib4.getAndroidPackage();
         lenient().when(mSnapshot.getPackageState(PKG_NAME_LIB4)).thenReturn(mPkgStateLib4);
 
-        mPkgStateLibbaz = createPackageState(PKG_NAME_LIBBAZ, List.of());
+        mPkgStateLibbaz = createPackageState(PKG_NAME_LIBBAZ, List.of(), false /* multiSplit */);
         mPkgLibbaz = mPkgStateLibbaz.getAndroidPackage();
         lenient().when(mSnapshot.getPackageState(PKG_NAME_LIBBAZ)).thenReturn(mPkgStateLibbaz);
     }