Pass ART module version and app version to dex2oat.

Those values are passed through the "--comments" flag. It doesn't take
any effect, but it will be surfaced in crash reports on crashes.

Bug: 249016777
Test: m test-art-host-gtest-art_artd_tests
Test: atest ArtServiceTests
Test: -
  1. adb shell pm compile -m verify -f --full com.google.android.youtube
  2. See "--comments" in the logs.
Ignore-AOSP-First: ART Services
Change-Id: Ib3816d879320af433fa787e680acc21ae00d31aa
diff --git a/artd/artd.cc b/artd/artd.cc
index fd2da31..34d9782 100644
--- a/artd/artd.cc
+++ b/artd/artd.cc
@@ -932,6 +932,9 @@
       in_instructionSet, in_compilerFilter, in_priorityClass, in_dexoptOptions, args);
   AddPerfConfigFlags(in_priorityClass, art_exec_args, args);
 
+  // For being surfaced in crash reports on crashes.
+  args.Add("--comments=%s", in_dexoptOptions.comments);
+
   art_exec_args.Add("--keep-fds=%s", fd_logger.GetFds()).Add("--").Concat(std::move(args));
 
   LOG(INFO) << "Running dex2oat: " << Join(art_exec_args.Get(), /*separator=*/" ")
diff --git a/artd/artd_test.cc b/artd/artd_test.cc
index 3fd7b24..1fca5a7 100644
--- a/artd/artd_test.cc
+++ b/artd/artd_test.cc
@@ -761,6 +761,7 @@
       .debuggable = false,
       .generateAppImage = false,
       .hiddenApiPolicyEnabled = false,
+      .comments = "my-comments",
   };
 
   EXPECT_CALL(
@@ -771,7 +772,8 @@
                                             Contains(Flag("-Xtarget-sdk-version:", "123")),
                                             Not(Contains("--debuggable")),
                                             Not(Contains(Flag("--app-image-fd=", _))),
-                                            Not(Contains(Flag("-Xhidden-api-policy:", _))))),
+                                            Not(Contains(Flag("-Xhidden-api-policy:", _))),
+                                            Contains(Flag("--comments=", "my-comments")))),
                           _,
                           _))
       .WillOnce(Return(0));
diff --git a/artd/binder/com/android/server/art/DexoptOptions.aidl b/artd/binder/com/android/server/art/DexoptOptions.aidl
index 351c079..305445e 100644
--- a/artd/binder/com/android/server/art/DexoptOptions.aidl
+++ b/artd/binder/com/android/server/art/DexoptOptions.aidl
@@ -39,4 +39,6 @@
     boolean generateAppImage;
     /** -Xhidden-api-policy:enabled */
     boolean hiddenApiPolicyEnabled;
+    /** --comments */
+    @utf8InCpp String comments;
 }
diff --git a/libartservice/service/java/com/android/server/art/Dexopter.java b/libartservice/service/java/com/android/server/art/Dexopter.java
index 24ba783..aec852d 100644
--- a/libartservice/service/java/com/android/server/art/Dexopter.java
+++ b/libartservice/service/java/com/android/server/art/Dexopter.java
@@ -45,6 +45,7 @@
 import com.android.server.art.model.DetailedDexInfo;
 import com.android.server.art.model.DexoptParams;
 import com.android.server.art.model.DexoptResult;
+import com.android.server.pm.PackageManagerLocal;
 import com.android.server.pm.pkg.AndroidPackage;
 import com.android.server.pm.pkg.PackageState;
 
@@ -55,11 +56,14 @@
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Map;
 import java.util.Objects;
 
 /** @hide */
 public abstract class Dexopter<DexInfoType extends DetailedDexInfo> {
     private static final String TAG = "Dexopter";
+    private static final List<String> ART_PACKAGE_NAMES =
+            List.of("com.google.android.art", "com.android.art", "com.google.android.go.art");
 
     @NonNull protected final Injector mInjector;
     @NonNull protected final PackageState mPkgState;
@@ -365,6 +369,9 @@
         dexoptOptions.generateAppImage =
                 isProfileGuidedFilter && isAppImageAllowed(dexInfo) && isAppImageEnabled();
         dexoptOptions.hiddenApiPolicyEnabled = isHiddenApiPolicyEnabled();
+        dexoptOptions.comments = String.format(
+                "app-version-name:%s,app-version-code:%d,art-version:%d", mPkg.getVersionName(),
+                mPkg.getLongVersionCode(), mInjector.getArtVersion());
         return dexoptOptions;
     }
 
@@ -688,5 +695,25 @@
         public StorageManager getStorageManager() {
             return Objects.requireNonNull(mContext.getSystemService(StorageManager.class));
         }
+
+        @NonNull
+        private PackageManagerLocal getPackageManagerLocal() {
+            return Objects.requireNonNull(
+                    LocalManagerRegistry.getManager(PackageManagerLocal.class));
+        }
+
+        public long getArtVersion() {
+            try (var snapshot = getPackageManagerLocal().withUnfilteredSnapshot()) {
+                Map<String, PackageState> packageStates = snapshot.getPackageStates();
+                for (String artPackageName : ART_PACKAGE_NAMES) {
+                    PackageState pkgState = packageStates.get(artPackageName);
+                    if (pkgState != null) {
+                        AndroidPackage pkg = Utils.getPackageOrThrow(pkgState);
+                        return pkg.getLongVersionCode();
+                    }
+                }
+            }
+            return -1;
+        }
     }
 }
diff --git a/libartservice/service/javatests/com/android/server/art/PrimaryDexopterParameterizedTest.java b/libartservice/service/javatests/com/android/server/art/PrimaryDexopterParameterizedTest.java
index f0ef8f5..162f28c 100644
--- a/libartservice/service/javatests/com/android/server/art/PrimaryDexopterParameterizedTest.java
+++ b/libartservice/service/javatests/com/android/server/art/PrimaryDexopterParameterizedTest.java
@@ -230,7 +230,10 @@
         ArgumentMatcher<DexoptOptions> dexoptOptionsMatcher = options
                 -> options.compilationReason.equals("install") && options.targetSdkVersion == 123
                 && options.debuggable == mParams.mExpectedIsDebuggable
-                && options.hiddenApiPolicyEnabled == mParams.mExpectedIsHiddenApiPolicyEnabled;
+                && options.hiddenApiPolicyEnabled == mParams.mExpectedIsHiddenApiPolicyEnabled
+                && options.comments.equals(
+                        String.format("app-version-name:%s,app-version-code:%d,art-version:%d",
+                                APP_VERSION_NAME, APP_VERSION_CODE, ART_VERSION));
 
         when(mArtd.createCancellationSignal()).thenReturn(mock(IArtdCancellationSignal.class));
         when(mArtd.getDmFileVisibility(any())).thenReturn(FileVisibility.NOT_FOUND);
diff --git a/libartservice/service/javatests/com/android/server/art/PrimaryDexopterTestBase.java b/libartservice/service/javatests/com/android/server/art/PrimaryDexopterTestBase.java
index 3b94961..94e0b48 100644
--- a/libartservice/service/javatests/com/android/server/art/PrimaryDexopterTestBase.java
+++ b/libartservice/service/javatests/com/android/server/art/PrimaryDexopterTestBase.java
@@ -52,6 +52,9 @@
     protected static final String PKG_NAME = "com.example.foo";
     protected static final int UID = 12345;
     protected static final int SHARED_GID = UserHandle.getSharedAppGid(UID);
+    protected static final long ART_VERSION = 331413030l;
+    protected static final String APP_VERSION_NAME = "12.34.56";
+    protected static final long APP_VERSION_CODE = 1536036288l;
 
     @Rule
     public StaticMockitoRule mockitoRule = new StaticMockitoRule(
@@ -76,6 +79,7 @@
         lenient().when(mInjector.getUserManager()).thenReturn(mUserManager);
         lenient().when(mInjector.getDexUseManager()).thenReturn(mDexUseManager);
         lenient().when(mInjector.getStorageManager()).thenReturn(mStorageManager);
+        lenient().when(mInjector.getArtVersion()).thenReturn(ART_VERSION);
 
         lenient()
                 .when(SystemProperties.get("dalvik.vm.systemuicompilerfilter"))
@@ -136,6 +140,8 @@
         lenient().when(pkg.getTargetSdkVersion()).thenReturn(123);
         lenient().when(pkg.isSignedWithPlatformKey()).thenReturn(false);
         lenient().when(pkg.isNonSdkApiRequested()).thenReturn(false);
+        lenient().when(pkg.getVersionName()).thenReturn(APP_VERSION_NAME);
+        lenient().when(pkg.getLongVersionCode()).thenReturn(APP_VERSION_CODE);
         return pkg;
     }