Sebelum memulai, lihat ringkasan tingkat tinggi ART Service.
Mulai Android 14, kompilasi AOT di perangkat untuk aplikasi (juga dikenal sebagai dexopt) ditangani oleh ART Service. ART Service adalah bagian dari modul ART, dan Anda dapat menyesuaikannya melalui properti sistem dan API.
Properti sistem
ART Service mendukung semua opsi dex2oat yang relevan.
Selain itu, ART Service mendukung properti sistem berikut:
pm.dexopt.<reason>
Ini adalah kumpulan properti sistem yang menentukan filter compiler default untuk semua alasan kompilasi yang telah ditentukan sebelumnya dan dijelaskan dalam skenario Dexopt.
Untuk mengetahui informasi selengkapnya, lihat Filter compiler.
Nilai default standar adalah:
pm.dexopt.first-boot=verify
pm.dexopt.boot-after-ota=verify
pm.dexopt.boot-after-mainline-update=verify
pm.dexopt.bg-dexopt=speed-profile
pm.dexopt.inactive=verify
pm.dexopt.cmdline=verify
pm.dexopt.shared (default: speed)
Ini adalah filter compiler pengganti untuk aplikasi yang digunakan oleh aplikasi lain.
Pada prinsipnya, ART Service melakukan kompilasi yang dipandu profil (speed-profile) untuk semua aplikasi jika memungkinkan, biasanya selama dexopt latar belakang. Namun, ada
beberapa aplikasi yang digunakan oleh aplikasi lain (baik melalui <uses-library> atau dimuat
secara dinamis menggunakan Context#createPackageContext dengan
CONTEXT_INCLUDE_CODE). Aplikasi tersebut tidak dapat menggunakan profil lokal karena alasan privasi.
Untuk aplikasi semacam itu, jika kompilasi yang dipandu profil diminta, ART Service akan mencoba menggunakan profil cloud terlebih dahulu. Jika profil cloud tidak ada, ART Service akan kembali menggunakan filter compiler yang ditentukan oleh pm.dexopt.shared.
Jika kompilasi yang diminta tidak dipandu profil, properti ini tidak akan berpengaruh.
pm.dexopt.<reason>.concurrency (default: 1)
Ini adalah jumlah pemanggilan dex2oat untuk alasan kompilasi tertentu yang telah ditentukan sebelumnya (first-boot, boot-after-ota, boot-after-mainline-update, dan bg-dexopt).
Perhatikan bahwa efek opsi ini digabungkan dengan
opsi penggunaan resource dex2oat (dalvik.vm.*dex2oat-threads,
dalvik.vm.*dex2oat-cpu-set, dan profil tugas):
dalvik.vm.*dex2oat-threadsmengontrol jumlah thread untuk setiap pemanggilan dex2oat, sedangkanpm.dexopt.<reason>.concurrencymengontrol jumlah pemanggilan dex2oat. Artinya, jumlah maksimum thread serentak adalah hasil perkalian dari dua properti sistem.dalvik.vm.*dex2oat-cpu-setdan profil tugas selalu membatasi penggunaan core CPU, terlepas dari jumlah maksimum thread serentak (dibahas di atas).
Satu pemanggilan dex2oat mungkin tidak sepenuhnya menggunakan semua core CPU, terlepas dari dalvik.vm.*dex2oat-threads. Oleh karena itu, meningkatkan jumlah pemanggilan dex2oat (pm.dexopt.<reason>.concurrency) dapat menggunakan core CPU dengan lebih baik, untuk
mempercepat progres dexopt secara keseluruhan. Hal ini sangat berguna selama booting.
Namun, terlalu banyak pemanggilan dex2oat dapat menyebabkan perangkat kehabisan memori, meskipun hal ini dapat dikurangi dengan menetapkan dalvik.vm.dex2oat-swap ke true untuk mengizinkan penggunaan file swap. Terlalu banyak pemanggilan juga dapat menyebabkan pengalihan konteks yang tidak perlu. Oleh karena itu, angka ini harus disesuaikan dengan cermat berdasarkan produk.
pm.dexopt.downgrade_after_inactive_days (default: not set)
Jika opsi ini ditetapkan, ART Service hanya akan melakukan dexopt pada aplikasi yang digunakan dalam jumlah hari terakhir yang diberikan.
Selain itu, jika penyimpanan hampir penuh, selama dexopt latar belakang, ART Service akan menurunkan filter compiler aplikasi yang tidak digunakan dalam jumlah hari terakhir yang diberikan, untuk mengosongkan ruang. Alasan compiler untuk hal ini adalah inactive,
dan filter compiler ditentukan oleh pm.dexopt.inactive. Batas ruang untuk memicu fitur ini adalah batas ruang rendah Storage Manager (dapat dikonfigurasi melalui setelan global sys_storage_threshold_percentage dan sys_storage_threshold_max_bytes, default: 500 MB) ditambah 500 MB.
Jika Anda menyesuaikan daftar paket melalui
ArtManagerLocal#setBatchDexoptStartCallback, paket dalam daftar yang disediakan
oleh BatchDexoptStartCallback untuk bg-dexopt tidak akan pernah diturunkan.
pm.dexopt.disable_bg_dexopt (default: false)
Ini hanya untuk pengujian. Tindakan ini mencegah ART Service menjadwalkan tugas dexopt latar belakang.
Jika tugas dexopt latar belakang sudah dijadwalkan tetapi belum berjalan, opsi ini tidak akan berpengaruh. Artinya, tugas akan tetap berjalan.
Urutan perintah yang direkomendasikan untuk mencegah tugas dexopt latar belakang berjalan adalah:
setprop pm.dexopt.disable_bg_dexopt true
pm bg-dexopt-job --disable
Baris pertama mencegah tugas dexopt latar belakang dijadwalkan, jika belum dijadwalkan. Baris kedua membatalkan jadwal tugas dexopt latar belakang, jika sudah dijadwalkan, dan membatalkan tugas dexopt latar belakang segera, jika sedang berjalan.
ART Service API
ART Service mengekspos Java API untuk penyesuaian. API ditentukan dalam ArtManagerLocal. Lihat Javadoc di
art/libartservice/service/java/com/android/server/art/ArtManagerLocal.java untuk
penggunaan (sumber Android 14, sumber pengembangan yang belum dirilis).
ArtManagerLocal adalah singleton yang disimpan oleh LocalManagerRegistry. Fungsi helper com.android.server.pm.DexOptHelper#getArtManagerLocal membantu Anda mendapatkannya.
import static com.android.server.pm.DexOptHelper.getArtManagerLocal;
Sebagian besar API memerlukan instance PackageManagerLocal.FilteredSnapshot, yang menyimpan informasi semua aplikasi. Anda bisa mendapatkannya dengan memanggil
PackageManagerLocal#withFilteredSnapshot, yang mana PackageManagerLocal juga
merupakan singleton yang disimpan oleh LocalManagerRegistry dan dapat diperoleh dari
com.android.server.pm.PackageManagerServiceUtils#getPackageManagerLocal.
import static com.android.server.pm.PackageManagerServiceUtils.getPackageManagerLocal;
Berikut adalah beberapa kasus penggunaan API yang umum.
Memicu dexopt untuk aplikasi
Anda dapat memicu dexopt untuk aplikasi kapan saja dengan memanggil ArtManagerLocal#dexoptPackage.
try (var snapshot = getPackageManagerLocal().withFilteredSnapshot()) {
getArtManagerLocal().dexoptPackage(
snapshot,
"com.google.android.calculator",
new DexoptParams.Builder(ReasonMapping.REASON_INSTALL).build());
}
Anda juga dapat meneruskan alasan dexopt Anda sendiri. Jika melakukannya, class prioritas dan filter compiler harus ditetapkan secara eksplisit.
try (var snapshot = getPackageManagerLocal().withFilteredSnapshot()) {
getArtManagerLocal().dexoptPackage(
snapshot,
"com.google.android.calculator",
new DexoptParams.Builder("my-reason")
.setCompilerFilter("speed-profile")
.setPriorityClass(ArtFlags.PRIORITY_BACKGROUND)
.build());
}
Membatalkan dexopt
Jika operasi dimulai dengan panggilan dexoptPackage, Anda dapat meneruskan sinyal pembatalan, yang memungkinkan Anda membatalkan operasi pada suatu titik. Hal ini dapat berguna saat Anda menjalankan dexopt secara asinkron.
Executor executor = ...; // Your asynchronous executor here.
var cancellationSignal = new CancellationSignal();
executor.execute(() -> {
try (var snapshot = getPackageManagerLocal().withFilteredSnapshot()) {
getArtManagerLocal().dexoptPackage(
snapshot,
"com.google.android.calculator",
new DexoptParams.Builder(ReasonMapping.REASON_INSTALL).build(),
cancellationSignal);
}
});
// When you want to cancel the operation.
cancellationSignal.cancel();
Anda juga dapat membatalkan dexopt latar belakang, yang dimulai oleh ART Service.
getArtManagerLocal().cancelBackgroundDexoptJob();
Mendapatkan hasil dexopt
Jika operasi dimulai dengan panggilan dexoptPackage, Anda bisa mendapatkan hasilnya dari nilai yang ditampilkan.
DexoptResult result;
try (var snapshot = getPackageManagerLocal().withFilteredSnapshot()) {
result = getArtManagerLocal().dexoptPackage(...);
}
// Process the result here.
...
ART Service juga memulai operasi dexopt sendiri dalam banyak skenario, seperti dexopt latar belakang. Untuk memproses semua hasil dexopt, baik operasi dimulai dengan panggilan dexoptPackage atau oleh ART Service, gunakan ArtManagerLocal#addDexoptDoneCallback.
getArtManagerLocal().addDexoptDoneCallback(
false /* onlyIncludeUpdates */,
Runnable::run,
(result) -> {
// Process the result here.
...
});
Argumen pertama menentukan apakah hanya menyertakan pembaruan dalam hasil. Jika Anda hanya ingin memproses paket yang diperbarui oleh dexopt, tetapkan ke benar (true).
Argumen kedua adalah eksekutor callback. Untuk menjalankan callback pada thread yang sama yang melakukan dexopt, gunakan Runnable::run. Jika Anda tidak ingin callback memblokir dexopt, gunakan eksekutor asinkron.
Anda dapat menambahkan beberapa callback, dan ART Service akan menjalankan semuanya secara berurutan. Semua callback akan tetap aktif untuk semua panggilan mendatang kecuali jika Anda menghapusnya.
Jika Anda ingin menghapus callback, simpan referensi callback saat Anda menambahkannya, dan gunakan ArtManagerLocal#removeDexoptDoneCallback.
DexoptDoneCallback callback = (result) -> {
// Process the result here.
...
};
getArtManagerLocal().addDexoptDoneCallback(
false /* onlyIncludeUpdates */, Runnable::run, callback);
// When you want to remove it.
getArtManagerLocal().removeDexoptDoneCallback(callback);
Menyesuaikan daftar paket dan parameter dexopt
ART Service memulai operasi dexopt sendiri selama booting dan dexopt latar belakang. Untuk menyesuaikan daftar paket atau parameter dexopt untuk operasi tersebut, gunakan ArtManagerLocal#setBatchDexoptStartCallback.
getArtManagerLocal().setBatchDexoptStartCallback(
Runnable::run,
(snapshot, reason, defaultPackages, builder, cancellationSignal) -> {
switch (reason) {
case ReasonMapping.REASON_BG_DEXOPT:
var myPackages = new ArrayList<String>(defaultPackages);
myPackages.add(...);
myPackages.remove(...);
myPackages.sort(...);
builder.setPackages(myPackages);
break;
default:
// Ignore unknown reasons.
}
});
Anda dapat menambahkan item ke daftar paket, menghapus item dari daftar, mengurutkannya, atau bahkan menggunakan daftar yang sama sekali berbeda.
Callback Anda harus mengabaikan alasan yang tidak diketahui karena alasan lainnya dapat ditambahkan di masa mendatang.
Anda dapat menetapkan maksimal satu BatchDexoptStartCallback. Callback akan tetap aktif untuk semua panggilan mendatang kecuali jika Anda menghapusnya.
Jika Anda ingin menghapus callback, gunakan ArtManagerLocal#clearBatchDexoptStartCallback.
getArtManagerLocal().clearBatchDexoptStartCallback();
Menyesuaikan parameter tugas dexopt latar belakang
Secara default, tugas dexopt latar belakang berjalan sekali sehari saat perangkat tidak ada aktivitas dan sedang diisi daya. Hal ini dapat diubah menggunakan ArtManagerLocal#setScheduleBackgroundDexoptJobCallback.
getArtManagerLocal().setScheduleBackgroundDexoptJobCallback(
Runnable::run,
builder -> {
builder.setPeriodic(TimeUnit.DAYS.toMillis(2));
});
setBackoffCriteria dokumentasi. Tugas yang dibatalkan akan dicoba lagi dengan kebijakan percobaan ulang default (30 detik, eksponensial, dibatasi hingga 5 jam). Sayangnya, karena batasan Job Scheduler API, kebijakan percobaan ulang ini tidak dapat diubah.
Anda dapat menetapkan maksimal satu ScheduleBackgroundDexoptJobCallback. Callback akan tetap aktif untuk semua panggilan mendatang kecuali jika Anda menghapusnya.
Jika Anda ingin menghapus callback, gunakan ArtManagerLocal#clearScheduleBackgroundDexoptJobCallback.
getArtManagerLocal().clearScheduleBackgroundDexoptJobCallback();
Menonaktifkan dexopt untuk sementara
Setiap operasi dexopt yang dimulai oleh ART Service akan memicu BatchDexoptStartCallback. Anda dapat terus membatalkan operasi untuk menonaktifkan dexopt secara efektif.
Jika operasi yang Anda batalkan adalah dexopt latar belakang, operasi tersebut akan mengikuti kebijakan percobaan ulang default (30 detik, eksponensial, dibatasi hingga 5 jam).
// Good example.
var shouldDisableDexopt = new AtomicBoolean(false);
getArtManagerLocal().setBatchDexoptStartCallback(
Runnable::run,
(snapshot, reason, defaultPackages, builder, cancellationSignal) -> {
if (shouldDisableDexopt.get()) {
cancellationSignal.cancel();
}
});
// Disable dexopt.
shouldDisableDexopt.set(true);
getArtManagerLocal().cancelBackgroundDexoptJob();
// Re-enable dexopt.
shouldDisableDexopt.set(false);
Anda dapat memiliki maksimal satu BatchDexoptStartCallback. Jika Anda juga ingin menggunakan BatchDexoptStartCallback untuk menyesuaikan daftar paket atau parameter dexopt, Anda harus menggabungkan kode ke dalam satu callback.
// Bad example.
// Disable dexopt.
getArtManagerLocal().unscheduleBackgroundDexoptJob();
// Re-enable dexopt.
getArtManagerLocal().scheduleBackgroundDexoptJob();
Operasi dexopt yang dilakukan saat penginstalan aplikasi tidak dimulai oleh ART Service. Sebagai gantinya, operasi ini dimulai oleh pengelola paket melalui panggilan dexoptPackage. Oleh karena itu, operasi ini tidak memicu BatchDexoptStartCallback. Untuk menonaktifkan dexopt saat penginstalan aplikasi, cegah pengelola paket memanggil dexoptPackage.
Mengganti filter compiler untuk paket tertentu (Android 15+)
Anda dapat mengganti filter compiler untuk paket tertentu dengan mendaftarkan callback melalui setAdjustCompilerFilterCallback. Callback dipanggil setiap kali paket akan di-dexopt, terlepas dari apakah dexopt dimulai oleh ART Service selama booting dan dexopt latar belakang atau oleh panggilan API dexoptPackage.
Jika paket tidak memerlukan penyesuaian, callback harus menampilkan originalCompilerFilter.
getArtManagerLocal().setAdjustCompilerFilterCallback(
Runnable::run,
(packageName, originalCompilerFilter, reason) -> {
if (isVeryImportantPackage(packageName)) {
return "speed-profile";
}
return originalCompilerFilter;
});
Anda hanya dapat menetapkan satu AdjustCompilerFilterCallback. Jika Anda ingin menggunakan AdjustCompilerFilterCallback untuk mengganti filter compiler untuk beberapa paket, Anda harus menggabungkan kode ke dalam satu callback. Callback akan tetap aktif untuk semua panggilan mendatang kecuali jika Anda menghapusnya.
Jika Anda ingin menghapus callback, gunakan ArtManagerLocal#clearAdjustCompilerFilterCallback.
getArtManagerLocal().clearAdjustCompilerFilterCallback();
Penyesuaian lainnya
ART Service juga mendukung beberapa penyesuaian lainnya.
Menetapkan batas suhu untuk dexopt latar belakang
Kontrol suhu tugas dexopt latar belakang dilakukan oleh Job Scheduler.
Tugas akan segera dibatalkan saat suhu mencapai
THERMAL_STATUS_MODERATE. Batas THERMAL_STATUS_MODERATE dapat disesuaikan.
Menentukan apakah dexopt latar belakang sedang berjalan
Tugas dexopt latar belakang dikelola oleh Job Scheduler, dan ID tugasnya adalah 27873780. Untuk menentukan apakah tugas sedang berjalan, gunakan Job Scheduler API.
// Good example.
var jobScheduler =
Objects.requireNonNull(mContext.getSystemService(JobScheduler.class));
int reason = jobScheduler.getPendingJobReason(27873780);
if (reason == PENDING_JOB_REASON_EXECUTING) {
// Do something when the job is running.
...
}
pm.dexopt.downgrade_after_inactive_days ditetapkan, dan penyimpanan hampir penuh, ART Service akan memanggil BatchDexoptStartCallback sekali, tetapi memanggil DexoptDoneCallback dua kali (sekali untuk menurunkan dan sekali untuk dexopt).// Bad example.
var backgroundDexoptRunning = new AtomicBoolean(false);
getArtManagerLocal().setBatchDexoptStartCallback(
Runnable::run,
(snapshot, reason, defaultPackages, builder, cancellationSignal) -> {
if (reason.equals(ReasonMapping.REASON_BG_DEXOPT)) {
backgroundDexoptRunning.set(true);
}
});
getArtManagerLocal().addDexoptDoneCallback(
false /* onlyIncludeUpdates */,
Runnable::run,
(result) -> {
if (result.getReason().equals(ReasonMapping.REASON_BG_DEXOPT)) {
backgroundDexoptRunning.set(false);
}
});
if (backgroundDexoptRunning.get()) {
// Do something when the job is running.
...
}
Menyediakan profil untuk dexopt
Untuk menggunakan profil untuk memandu dexopt, letakkan file .prof atau file .dm di samping APK.
File .prof harus berupa file profil format biner, dan nama file harus berupa nama file APK + .prof. Misalnya,
base.apk.prof
Nama file .dm harus berupa nama file APK dengan ekstensi yang diganti dengan .dm. Misalnya,
base.dm
Untuk memverifikasi bahwa profil digunakan untuk dexopt, jalankan dexopt dengan speed-profile dan periksa hasilnya.
pm art clear-app-profiles <package-name>
pm compile -m speed-profile -f -v <package-name>
Baris pertama menghapus semua profil yang dihasilkan oleh runtime (yaitu, profil di /data/misc/profiles), jika ada, untuk memastikan bahwa profil di samping APK adalah satu-satunya profil yang mungkin digunakan oleh ART Service. Baris kedua menjalankan dexopt dengan speed-profile, dan meneruskan -v untuk mencetak hasil verbose.
Jika profil sedang digunakan, Anda akan melihat actualCompilerFilter=speed-profile di hasilnya. Jika tidak, Anda akan melihat actualCompilerFilter=verify. Misalnya,
DexContainerFileDexoptResult{dexContainerFile=/data/app/~~QR0fTV0UbDbIP1Su7XzyPg==/com.google.android.gms-LvusF2uARKOtBbcaPHdUtQ==/base.apk, primaryAbi=true, abi=x86_64, actualCompilerFilter=speed-profile, status=PERFORMED, dex2oatWallTimeMillis=4549, dex2oatCpuTimeMillis=14550, sizeBytes=3715344, sizeBeforeBytes=3715344}
Alasan umum mengapa ART Service tidak menggunakan profil mencakup hal berikut:
- Profil memiliki nama file yang salah atau tidak berada di samping APK.
- Profil berada dalam format yang salah.
- Profil tidak cocok dengan APK. (Checksum dalam profil tidak cocok dengan checksum file
.dexdi APK.)