Don't assume that the profile exists.

Before this change, the profile of a primary dex is created by
Package Manager on app installation, the profile of a secondary dex is
created by DexLoadReporter on dex load, and the runtime assumes that the
profile always exists. After this change, the runtime can create the
profile if it doesn't exist. This has the following benefits:
- When ART Services wants to clear a profile, it can simply delete it,
  as opposed to the installd's approach: acquiring a flock and trucating
  the file. This reduces the risk of artd encountering a dead lock.
- We can eventually make PM and DexLoadReporter simpler by removing the
  code that creates profiles.

Bug: 248318911
Test: art/test.py -b -r --host -t 595
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:03379d9b00d068e2a9d9ab0e34cfe630343f22ce)
Merged-In: I929e3856f02f498ed203d1af0e7859337a82669a
Change-Id: I929e3856f02f498ed203d1af0e7859337a82669a
diff --git a/runtime/jit/profile_saver.cc b/runtime/jit/profile_saver.cc
index ae05851..e1a10b8 100644
--- a/runtime/jit/profile_saver.cc
+++ b/runtime/jit/profile_saver.cc
@@ -23,7 +23,6 @@
 #include <unistd.h>
 
 #include "android-base/strings.h"
-
 #include "art_method-inl.h"
 #include "base/compiler_filter.h"
 #include "base/enums.h"
@@ -32,6 +31,7 @@
 #include "base/stl_util.h"
 #include "base/systrace.h"
 #include "base/time_utils.h"
+#include "base/unix_file/fd_file.h"
 #include "class_table-inl.h"
 #include "dex/dex_file_loader.h"
 #include "dex_reference_collection.h"
@@ -869,10 +869,23 @@
     {
       ProfileCompilationInfo info(Runtime::Current()->GetArenaPool(),
                                   /*for_boot_image=*/ options_.GetProfileBootClassPath());
-      if (!info.Load(filename, /*clear_if_invalid=*/ true)) {
-        LOG(WARNING) << "Could not forcefully load profile " << filename;
-        continue;
+      if (OS::FileExists(filename.c_str())) {
+        if (!info.Load(filename, /*clear_if_invalid=*/true)) {
+          LOG(WARNING) << "Could not forcefully load profile " << filename;
+          continue;
+        }
+      } else {
+        // Create a file if it doesn't exist.
+        unix_file::FdFile file(filename.c_str(),
+                               O_WRONLY | O_TRUNC | O_CREAT,
+                               S_IRUSR | S_IWUSR,
+                               /*check_usage=*/false);
+        if (!file.IsValid()) {
+          LOG(WARNING) << "Could not create profile " << filename;
+          continue;
+        }
       }
+
       uint64_t last_save_number_of_methods = info.GetNumberOfMethods();
       uint64_t last_save_number_of_classes = info.GetNumberOfResolvedClasses();
       VLOG(profiler) << "last_save_number_of_methods=" << last_save_number_of_methods
diff --git a/test/595-profile-saving/src/Main.java b/test/595-profile-saving/src/Main.java
index 5b1a448..37a8e6c 100644
--- a/test/595-profile-saving/src/Main.java
+++ b/test/595-profile-saving/src/Main.java
@@ -39,8 +39,12 @@
           File.class, Method.class);
       testAddMethodToProfile(file, appMethod);
 
+      // Delete the file to check that the runtime can save the profile even if the file doesn't
+      // exist.
+      file.delete();
+
       // Test that the profile saves a boot class path method with a profiling info.
-      Method bootMethod = File.class.getDeclaredMethod("delete");
+      Method bootMethod = File.class.getDeclaredMethod("exists");
       if (bootMethod.getDeclaringClass().getClassLoader() != Object.class.getClassLoader()) {
         System.out.println("Class loader does not match boot class");
       }