summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Jiakai Zhang <jiakaiz@google.com> 2024-05-22 17:07:04 +0100
committer Jiakai Zhang <jiakaiz@google.com> 2024-05-23 18:07:55 +0000
commitcd27acf4832d51bc1243edd3bb391fcd3c29166c (patch)
tree764ea7c3e2c264d325199641bf1f29bead83fd1e
parent490e26f66c95b0d103c05573c46ff3322ba99e85 (diff)
Load the new service-art.jar into the memory.
Bug: 311377497 Test: Run Pre-reboot Dexopt. Change-Id: I49719d754175e5275460fea9af34f2dbc89dc14f
-rw-r--r--libartservice/service/java/com/android/server/art/prereboot/PreRebootDriver.java38
1 files changed, 29 insertions, 9 deletions
diff --git a/libartservice/service/java/com/android/server/art/prereboot/PreRebootDriver.java b/libartservice/service/java/com/android/server/art/prereboot/PreRebootDriver.java
index ef0b99ac34..c20a1ce8a8 100644
--- a/libartservice/service/java/com/android/server/art/prereboot/PreRebootDriver.java
+++ b/libartservice/service/java/com/android/server/art/prereboot/PreRebootDriver.java
@@ -27,6 +27,8 @@ import android.os.Build;
import android.os.CancellationSignal;
import android.os.RemoteException;
import android.os.ServiceSpecificException;
+import android.system.ErrnoException;
+import android.system.Os;
import androidx.annotation.RequiresApi;
@@ -41,6 +43,15 @@ import com.android.server.art.Utils;
import dalvik.system.DelegateLastClassLoader;
+import libcore.io.Streams;
+
+import java.io.FileDescriptor;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
/**
* Drives Pre-reboot Dexopt, through reflection.
*
@@ -80,7 +91,7 @@ public class PreRebootDriver {
Utils.logArtdException(e);
} catch (ServiceSpecificException e) {
AsLog.e("Failed to set up chroot", e);
- } catch (ReflectiveOperationException e) {
+ } catch (ReflectiveOperationException | IOException | ErrnoException e) {
AsLog.e("Failed to run pre-reboot dexopt", e);
} finally {
tearDown();
@@ -97,11 +108,10 @@ public class PreRebootDriver {
private void tearDown() {
// In general, the teardown unmounts apexes and partitions, and open files can keep the
- // mounts busy so that they cannot be unmounted. Therefore, two things can prevent the
- // teardown from succeeding: a running Pre-reboot artd process and the new `service-art.jar`
- // opened and mapped by system server. They are managed by the service manager and the
- // runtime respectively. There aren't reliable APIs to kill the former or close the latter,
- // so we have to do them by triggering GC and finalization, with sleep and retry mechanism.
+ // mounts busy so that they cannot be unmounted. Therefore, a running Pre-reboot artd
+ // process can prevent the teardown from succeeding. It's managed by the service manager,
+ // and there isn't a reliable API to kill it, so we have to kill it by triggering GC and
+ // finalization, with sleep and retry mechanism.
for (int numRetries = 3; numRetries > 0;) {
try {
Runtime.getRuntime().gc();
@@ -127,11 +137,21 @@ public class PreRebootDriver {
}
private void runFromChroot(@NonNull CancellationSignal cancellationSignal)
- throws ReflectiveOperationException {
+ throws ReflectiveOperationException, IOException, ErrnoException {
String chrootArtDir = CHROOT_DIR + "/apex/com.android.art";
String dexPath = chrootArtDir + "/javalib/service-art.jar";
- var classLoader =
- new DelegateLastClassLoader(dexPath, this.getClass().getClassLoader() /* parent */);
+
+ // We load the dex file into the memory and close it. In this way, the classloader won't
+ // prevent unmounting even if it fails to unload.
+ ClassLoader classLoader;
+ FileDescriptor memfd = Os.memfd_create("in memory from " + dexPath, 0 /* flags */);
+ try (FileOutputStream out = new FileOutputStream(memfd);
+ InputStream in = new FileInputStream(dexPath)) {
+ Streams.copy(in, out);
+ classLoader = new DelegateLastClassLoader("/proc/self/fd/" + memfd.getInt$(),
+ this.getClass().getClassLoader() /* parent */);
+ }
+
Class<?> preRebootManagerClass =
classLoader.loadClass("com.android.server.art.prereboot.PreRebootManager");
// Check if the dex file is loaded successfully. Note that the constructor of