diff options
-rw-r--r-- | core/java/android/os/ArtModuleServiceManager.java | 32 |
1 files changed, 27 insertions, 5 deletions
diff --git a/core/java/android/os/ArtModuleServiceManager.java b/core/java/android/os/ArtModuleServiceManager.java index e0b631d69ca8..995094bb1318 100644 --- a/core/java/android/os/ArtModuleServiceManager.java +++ b/core/java/android/os/ArtModuleServiceManager.java @@ -37,10 +37,12 @@ public class ArtModuleServiceManager { /** A class that exposes the method to obtain each system service. */ public static final class ServiceRegisterer { @NonNull private final String mServiceName; + private final boolean mRetry; /** @hide */ - public ServiceRegisterer(@NonNull String serviceName) { + public ServiceRegisterer(@NonNull String serviceName, boolean retry) { mServiceName = serviceName; + mRetry = retry; } /** @@ -53,27 +55,47 @@ public class ArtModuleServiceManager { */ @Nullable public IBinder waitForService() { - return ServiceManager.waitForService(mServiceName); + if (mRetry) { + return ServiceManager.waitForService(mServiceName); + } + IBinder binder = ServiceManager.getService(mServiceName); + for (int remainingTimeMs = 5000; binder == null && remainingTimeMs > 0; + remainingTimeMs -= 100) { + // There can be a race: + // 1. Client A invokes "ctl.start", which starts the service. + // 2. Client A gets a service handle from `ServiceManager.getService`. + // 3. Client B invokes "ctl.start", which does nothing because the service is + // already running. + // 4. Client A drops the service handle. The service is notified that there is no + // more client at that point, so it shuts down itself. + // 5. Client B cannot get a service handle from `ServiceManager.getService` because + // the service is shut down. + // To address this problem, we invoke "ctl.start" repeatedly. + SystemProperties.set("ctl.start", mServiceName); + SystemClock.sleep(100); + binder = ServiceManager.getService(mServiceName); + } + return binder; } } /** Returns {@link ServiceRegisterer} for the "artd" service. */ @NonNull public ServiceRegisterer getArtdServiceRegisterer() { - return new ServiceRegisterer("artd"); + return new ServiceRegisterer("artd", true /* retry */); } /** Returns {@link ServiceRegisterer} for the "artd_pre_reboot" service. */ @NonNull @FlaggedApi(Flags.FLAG_USE_ART_SERVICE_V2) public ServiceRegisterer getArtdPreRebootServiceRegisterer() { - return new ServiceRegisterer("artd_pre_reboot"); + return new ServiceRegisterer("artd_pre_reboot", false /* retry */); } /** Returns {@link ServiceRegisterer} for the "dexopt_chroot_setup" service. */ @NonNull @FlaggedApi(Flags.FLAG_USE_ART_SERVICE_V2) public ServiceRegisterer getDexoptChrootSetupServiceRegisterer() { - return new ServiceRegisterer("dexopt_chroot_setup"); + return new ServiceRegisterer("dexopt_chroot_setup", true /* retry */); } } |