From 5d72ab379c9f280ee114bccb096f0ba69b61dd41 Mon Sep 17 00:00:00 2001 From: Jiakai Zhang Date: Mon, 5 Feb 2024 23:41:48 +0800 Subject: [PATCH] Add PreRebootDexoptJob. Refactoring and boilerplate changes. Bug: 311377497 Test: m Change-Id: Ibe9870bc60918c572ce75aa46bd885d2bc71fe00 --- .../android/server/art/ArtManagerLocal.java | 21 +++++ .../server/art/BackgroundDexoptJob.java | 11 ++- .../art/BackgroundDexoptJobService.java | 14 ++- .../server/art/PreRebootDexoptJob.java | 87 +++++++++++++++++++ .../art/model/ArtServiceJobInterface.java | 30 +++++++ .../server/art/BackgroundDexoptJobTest.java | 3 +- 6 files changed, 157 insertions(+), 9 deletions(-) create mode 100644 libartservice/service/java/com/android/server/art/PreRebootDexoptJob.java create mode 100644 libartservice/service/java/com/android/server/art/model/ArtServiceJobInterface.java diff --git a/libartservice/service/java/com/android/server/art/ArtManagerLocal.java b/libartservice/service/java/com/android/server/art/ArtManagerLocal.java index 69cba7d860..d4e3c59f45 100644 --- a/libartservice/service/java/com/android/server/art/ArtManagerLocal.java +++ b/libartservice/service/java/com/android/server/art/ArtManagerLocal.java @@ -1024,6 +1024,17 @@ BackgroundDexoptJob getBackgroundDexoptJob() { return mInjector.getBackgroundDexoptJob(); } + /** + * Should be used by {@link BackgroundDexoptJobService} ONLY. + * + * @hide + */ + @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) + @NonNull + PreRebootDexoptJob getPreRebootDexoptJob() { + return mInjector.getPreRebootDexoptJob(); + } + @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) @Nullable private DexoptResult maybeDowngradePackages( @@ -1354,6 +1365,7 @@ public static class Injector { @Nullable private final PackageManagerLocal mPackageManagerLocal; @Nullable private final Config mConfig; @Nullable private BackgroundDexoptJob mBgDexoptJob = null; + @Nullable private PreRebootDexoptJob mPrDexoptJob = null; /** For compatibility with S and T. New code should not use this. */ @Deprecated @@ -1441,6 +1453,15 @@ public synchronized BackgroundDexoptJob getBackgroundDexoptJob() { return mBgDexoptJob; } + @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) + @NonNull + public synchronized PreRebootDexoptJob getPreRebootDexoptJob() { + if (mPrDexoptJob == null) { + mPrDexoptJob = new PreRebootDexoptJob(mContext); + } + return mPrDexoptJob; + } + @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) @NonNull public UserManager getUserManager() { diff --git a/libartservice/service/java/com/android/server/art/BackgroundDexoptJob.java b/libartservice/service/java/com/android/server/art/BackgroundDexoptJob.java index 9aeb2828fb..289c7cd235 100644 --- a/libartservice/service/java/com/android/server/art/BackgroundDexoptJob.java +++ b/libartservice/service/java/com/android/server/art/BackgroundDexoptJob.java @@ -41,6 +41,7 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.server.LocalManagerRegistry; import com.android.server.art.model.ArtFlags; +import com.android.server.art.model.ArtServiceJobInterface; import com.android.server.art.model.Config; import com.android.server.art.model.DexoptResult; import com.android.server.art.model.OperationProgress; @@ -59,7 +60,7 @@ /** @hide */ @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) -public class BackgroundDexoptJob { +public class BackgroundDexoptJob implements ArtServiceJobInterface { private static final String TAG = ArtManagerLocal.TAG; /** @@ -68,7 +69,7 @@ public class BackgroundDexoptJob { */ private static final String JOB_PKG_NAME = Utils.PLATFORM_PACKAGE_NAME; /** An arbitrary number. Must be unique among all jobs owned by the system uid. */ - private static final int JOB_ID = 27873780; + public static final int JOB_ID = 27873780; @VisibleForTesting public static final long JOB_INTERVAL_MS = TimeUnit.DAYS.toMillis(1); @@ -89,6 +90,7 @@ public BackgroundDexoptJob(@NonNull Injector injector) { } /** Handles {@link BackgroundDexoptJobService#onStartJob(JobParameters)}. */ + @Override public boolean onStartJob( @NonNull BackgroundDexoptJobService jobService, @NonNull JobParameters params) { start().thenAcceptAsync(result -> { @@ -113,6 +115,7 @@ public boolean onStartJob( } /** Handles {@link BackgroundDexoptJobService#onStopJob(JobParameters)}. */ + @Override public boolean onStopJob(@NonNull JobParameters params) { synchronized (this) { mLastStopReason = Optional.of(params.getStopReason()); @@ -124,7 +127,7 @@ public boolean onStopJob(@NonNull JobParameters params) { /** Handles {@link ArtManagerLocal#scheduleBackgroundDexoptJob()}. */ public @ScheduleStatus int schedule() { - if (this != BackgroundDexoptJobService.getJob()) { + if (this != BackgroundDexoptJobService.getJob(JOB_ID)) { throw new IllegalStateException("This job cannot be scheduled"); } @@ -164,7 +167,7 @@ public boolean onStopJob(@NonNull JobParameters params) { /** Handles {@link ArtManagerLocal#unscheduleBackgroundDexoptJob()}. */ public void unschedule() { - if (this != BackgroundDexoptJobService.getJob()) { + if (this != BackgroundDexoptJobService.getJob(JOB_ID)) { throw new IllegalStateException("This job cannot be unscheduled"); } diff --git a/libartservice/service/java/com/android/server/art/BackgroundDexoptJobService.java b/libartservice/service/java/com/android/server/art/BackgroundDexoptJobService.java index 41425ee5cc..8bcc4b98be 100644 --- a/libartservice/service/java/com/android/server/art/BackgroundDexoptJobService.java +++ b/libartservice/service/java/com/android/server/art/BackgroundDexoptJobService.java @@ -24,6 +24,7 @@ import androidx.annotation.RequiresApi; import com.android.server.LocalManagerRegistry; +import com.android.server.art.model.ArtServiceJobInterface; /** * Entry point for the callback from the job scheduler. This class is instantiated by the system @@ -35,16 +36,21 @@ public class BackgroundDexoptJobService extends JobService { @Override public boolean onStartJob(@NonNull JobParameters params) { - return getJob().onStartJob(this, params); + return getJob(params.getJobId()).onStartJob(this, params); } @Override public boolean onStopJob(@NonNull JobParameters params) { - return getJob().onStopJob(params); + return getJob(params.getJobId()).onStopJob(params); } @NonNull - static BackgroundDexoptJob getJob() { - return LocalManagerRegistry.getManager(ArtManagerLocal.class).getBackgroundDexoptJob(); + static ArtServiceJobInterface getJob(int jobId) { + if (jobId == BackgroundDexoptJob.JOB_ID) { + return LocalManagerRegistry.getManager(ArtManagerLocal.class).getBackgroundDexoptJob(); + } else if (jobId == PreRebootDexoptJob.JOB_ID) { + return LocalManagerRegistry.getManager(ArtManagerLocal.class).getPreRebootDexoptJob(); + } + throw new IllegalArgumentException("Unknown job ID " + jobId); } } diff --git a/libartservice/service/java/com/android/server/art/PreRebootDexoptJob.java b/libartservice/service/java/com/android/server/art/PreRebootDexoptJob.java new file mode 100644 index 0000000000..74bf913e62 --- /dev/null +++ b/libartservice/service/java/com/android/server/art/PreRebootDexoptJob.java @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.art; + +import static com.android.server.art.model.ArtFlags.ScheduleStatus; + +import android.annotation.NonNull; +import android.app.job.JobParameters; +import android.content.Context; +import android.os.Build; + +import androidx.annotation.RequiresApi; + +import com.android.internal.annotations.VisibleForTesting; +import com.android.server.art.model.ArtFlags; +import com.android.server.art.model.ArtServiceJobInterface; + +/** @hide */ +@RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) +public class PreRebootDexoptJob implements ArtServiceJobInterface { + private static final String TAG = ArtManagerLocal.TAG; + + /** + * "android" is the package name for a declared in + * frameworks/base/core/res/AndroidManifest.xml + */ + private static final String JOB_PKG_NAME = Utils.PLATFORM_PACKAGE_NAME; + /** An arbitrary number. Must be unique among all jobs owned by the system uid. */ + public static final int JOB_ID = 27873781; + + @NonNull private final Injector mInjector; + + public PreRebootDexoptJob(@NonNull Context context) { + this(new Injector(context)); + } + + @VisibleForTesting + public PreRebootDexoptJob(@NonNull Injector injector) { + mInjector = injector; + } + + @Override + public boolean onStartJob( + @NonNull BackgroundDexoptJobService jobService, @NonNull JobParameters params) { + // "true" means the job will continue running until `jobFinished` is called. + return false; + } + + @Override + public boolean onStopJob(@NonNull JobParameters params) { + // "true" means to execute again in the same interval with the default retry policy. + return true; + } + + public @ScheduleStatus int schedule() { + // TODO(b/311377497): Schedule the job. + return ArtFlags.SCHEDULE_SUCCESS; + } + + /** + * Injector pattern for testing purpose. + * + * @hide + */ + @VisibleForTesting + public static class Injector { + @NonNull private final Context mContext; + + Injector(@NonNull Context context) { + mContext = context; + } + } +} diff --git a/libartservice/service/java/com/android/server/art/model/ArtServiceJobInterface.java b/libartservice/service/java/com/android/server/art/model/ArtServiceJobInterface.java new file mode 100644 index 0000000000..569996c566 --- /dev/null +++ b/libartservice/service/java/com/android/server/art/model/ArtServiceJobInterface.java @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.art.model; + +import android.annotation.NonNull; +import android.app.job.JobParameters; + +import com.android.server.art.BackgroundDexoptJobService; + +/** @hide */ +public interface ArtServiceJobInterface { + boolean onStartJob( + @NonNull BackgroundDexoptJobService jobService, @NonNull JobParameters params); + + boolean onStopJob(@NonNull JobParameters params); +} diff --git a/libartservice/service/javatests/com/android/server/art/BackgroundDexoptJobTest.java b/libartservice/service/javatests/com/android/server/art/BackgroundDexoptJobTest.java index c61461d0c9..85ae079c77 100644 --- a/libartservice/service/javatests/com/android/server/art/BackgroundDexoptJobTest.java +++ b/libartservice/service/javatests/com/android/server/art/BackgroundDexoptJobTest.java @@ -16,6 +16,7 @@ package com.android.server.art; +import static com.android.server.art.BackgroundDexoptJob.JOB_ID; import static com.android.server.art.model.Config.Callback; import static com.android.server.art.model.DexoptResult.DexoptResultStatus; import static com.android.server.art.model.DexoptResult.PackageDexoptResult; @@ -103,7 +104,7 @@ public void setUp() throws Exception { lenient().when(mInjector.getJobScheduler()).thenReturn(mJobScheduler); mBackgroundDexoptJob = new BackgroundDexoptJob(mInjector); - lenient().when(BackgroundDexoptJobService.getJob()).thenReturn(mBackgroundDexoptJob); + lenient().when(BackgroundDexoptJobService.getJob(JOB_ID)).thenReturn(mBackgroundDexoptJob); lenient() .doAnswer(invocation -> {