ART hizmeti yapılandırması

Başlamadan önce ART Hizmeti'ne genel bir bakış atın.

Android 14'ten itibaren uygulamalar için cihaz üzerinde AOT derlemesi (diğer adıyla dexopt) ART Hizmeti tarafından işlenir. ART Hizmeti, ART modülünün bir parçasıdır ve sistem özellikleri ile API'ler aracılığıyla özelleştirilebilir.

Sistem özellikleri

ART Hizmeti, ilgili tüm dex2oat seçeneklerini destekler.

Ayrıca, ART Hizmeti aşağıdaki sistem özelliklerini destekler:

pm.dexopt.<reason>

Bu, Dexopt senaryoları bölümünde açıklanan tüm önceden tanımlanmış derleme nedenleri için varsayılan derleyici filtrelerini belirleyen bir dizi sistem özelliğidir.

Daha fazla bilgi için Derleyici filtreleri başlıklı makaleyi inceleyin.

Standart varsayılan değerler şunlardır:

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 (varsayılan: speed)

Bu, diğer uygulamalar tarafından kullanılan uygulamalar için yedek derleyici filtresidir.

ART Hizmeti, mümkün olduğunda (genellikle arka planda dexopt sırasında) tüm uygulamalar için prensip olarak profile dayalı derleme (speed-profile) yapar. Ancak, diğer uygulamalar tarafından kullanılan (<uses-library> aracılığıyla veya Context#createPackageContext ile CONTEXT_INCLUDE_CODE kullanılarak dinamik olarak yüklenen) bazı uygulamalar vardır. Bu tür uygulamalar, gizlilik nedeniyle yerel profilleri kullanamaz.

Böyle bir uygulama için profile dayalı derleme istenirse ART Hizmeti önce bir bulut profili kullanmayı dener. Bulut profili yoksa ART Hizmeti, pm.dexopt.shared tarafından belirtilen derleyici filtresini kullanır.

İstenen derleme profile göre yönlendirilmiyorsa bu özelliğin etkisi olmaz.

pm.dexopt.<reason>.concurrency (varsayılan: 1)

Bu, belirli önceden tanımlanmış derleme nedenleri (first-boot, boot-after-ota, boot-after-mainline-update ve bg-dexopt) için dex2oat çağrılarının sayısıdır.

Bu seçeneğin etkisinin dex2oat kaynak kullanımı seçenekleriyle (dalvik.vm.*dex2oat-threads, dalvik.vm.*dex2oat-cpu-set ve görev profilleri) birleştirildiğini unutmayın:

  • dalvik.vm.*dex2oat-threads, her dex2oat çağırma işlemi için iş parçacığı sayısını kontrol ederken pm.dexopt.<reason>.concurrency, dex2oat çağırma işlemlerinin sayısını kontrol eder. Yani, eşzamanlı ileti dizilerinin maksimum sayısı, iki sistem özelliğinin çarpımıdır.
  • dalvik.vm.*dex2oat-cpu-set ve görev profilleri, eşzamanlı maksimum iş parçacığı sayısından (yukarıda bahsedilmiştir) bağımsız olarak her zaman CPU çekirdeği kullanımını sınırlar.

Tek bir dex2oat çağrısı, dalvik.vm.*dex2oat-threads'dan bağımsız olarak tüm CPU çekirdeklerini tam olarak kullanmayabilir. Bu nedenle, dex2oat çağrı sayısını artırmak (pm.dexopt.<reason>.concurrency), dexopt'un genel ilerleme hızını artırmak için CPU çekirdeklerinden daha iyi yararlanabilir. Bu, özellikle başlatma sırasında yararlıdır.

Ancak, çok fazla dex2oat çağrısı olması, takas dosyası kullanılmasına izin vermek için dalvik.vm.dex2oat-swap değerinin true olarak ayarlanmasıyla bu durum hafifletilebilse de cihazın belleğinin tükenmesine neden olabilir. Çok fazla çağırma işlemi de gereksiz bağlam geçişine neden olabilir. Bu nedenle, bu sayı ürün bazında dikkatli bir şekilde ayarlanmalıdır.

pm.dexopt.downgrade_after_inactive_days (varsayılan: ayarlanmadı)

Bu seçenek ayarlanırsa ART Hizmeti yalnızca son belirtilen gün sayısı içinde kullanılan uygulamaları dexopt eder.

Ayrıca, depolama alanı neredeyse dolmuşsa ART Hizmeti, arka planda dexopt sırasında yer açmak için son verilen gün sayısı içinde kullanılmayan uygulamaların derleyici filtresini düşürür. Bunun derleyici nedeni inactive, derleyici filtresi ise pm.dexopt.inactive tarafından belirlenir. Bu özelliği tetikleyecek alan eşiği, Depolama Yöneticisi'nin düşük alan eşiği (sys_storage_threshold_percentage ve sys_storage_threshold_max_bytes genel ayarları üzerinden yapılandırılabilir, varsayılan: 500 MB) artı 500 MB'tır.

ArtManagerLocal#setBatchDexoptStartCallback aracılığıyla paket listesini özelleştirirseniz BatchDexoptStartCallback tarafından bg-dexopt için sağlanan listedeki paketler hiçbir zaman eski sürüme düşürülmez.

pm.dexopt.disable_bg_dexopt (varsayılan: false)

Bu yalnızca test amaçlıdır. Bu, ART Hizmeti'nin arka planda dexopt işini planlamasını engeller.

Arka plandaki dexopt işi zaten planlanmış ancak henüz çalıştırılmamışsa bu seçeneğin etkisi olmaz. Yani iş yine de çalıştırılır.

Arka plandaki dexopt işinin çalışmasını önlemek için önerilen komut sırası şöyledir:

setprop pm.dexopt.disable_bg_dexopt true
pm bg-dexopt-job --disable

İlk satır, henüz planlanmamışsa arka plandaki dexopt işinin planlanmasını engeller. İkinci satır, arka planda dexopt işi zaten planlanmışsa planını kaldırır ve çalışıyorsa arka planda dexopt işini hemen iptal eder.

ART Service API'leri

ART Hizmeti, özelleştirme için Java API'leri sunar. API'ler ArtManagerLocal içinde tanımlanır. Kullanım alanları (Android 14 kaynağı, yayınlanmamış geliştirme kaynağı) için art/libartservice/service/java/com/android/server/art/ArtManagerLocal.java bölümündeki Javadoc'a bakın.

ArtManagerLocal, LocalManagerRegistry tarafından tutulan bir tekildir. com.android.server.pm.DexOptHelper#getArtManagerLocal yardımcı işlevi, bu bilgiyi almanıza yardımcı olur.

import static com.android.server.pm.DexOptHelper.getArtManagerLocal;

API'lerin çoğu, tüm uygulamaların bilgilerini içeren bir PackageManagerLocal.FilteredSnapshot örneği gerektirir. PackageManagerLocal#withFilteredSnapshot numaralı telefonu arayarak alabilirsiniz. Burada PackageManagerLocal, LocalManagerRegistry tarafından tutulan tekil bir öğedir ve com.android.server.pm.PackageManagerServiceUtils#getPackageManagerLocal adresinden alınabilir.

import static com.android.server.pm.PackageManagerServiceUtils.getPackageManagerLocal;

API'lerin tipik kullanım alanlarından bazıları aşağıda verilmiştir.

Bir uygulama için dexopt'u tetikleme

ArtManagerLocal#dexoptPackage işlevini çağırarak istediğiniz zaman herhangi bir uygulama için dexopt'u tetikleyebilirsiniz.

try (var snapshot = getPackageManagerLocal().withFilteredSnapshot()) {
  getArtManagerLocal().dexoptPackage(
      snapshot,
      "com.google.android.calculator",
      new DexoptParams.Builder(ReasonMapping.REASON_INSTALL).build());
}

Kendi dexopt nedeninizi de iletebilirsiniz. Bu durumda, öncelik sınıfı ve derleyici filtresi açıkça ayarlanmalıdır.

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());
}

Cancel dexopt

Bir işlem dexoptPackage çağrısıyla başlatılırsa işlemi bir noktada iptal etmenize olanak tanıyan bir iptal sinyali iletebilirsiniz. Bu, dexopt'u eşzamansız olarak çalıştırdığınızda yararlı olabilir.

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();

ART Hizmeti tarafından başlatılan arka planda dexopt işlemini de iptal edebilirsiniz.

getArtManagerLocal().cancelBackgroundDexoptJob();

dexopt sonuçlarını alma

Bir işlem dexoptPackage çağrısıyla başlatılırsa sonucu dönüş değerinden alabilirsiniz.

DexoptResult result;
try (var snapshot = getPackageManagerLocal().withFilteredSnapshot()) {
  result = getArtManagerLocal().dexoptPackage(...);
}

// Process the result here.
...

ART Hizmeti, arka planda dexopt gibi birçok senaryoda dexopt işlemlerini kendisi de başlatır. İşlem bir dexoptPackage çağrısıyla veya ART Hizmeti tarafından başlatılmış olsun, tüm dexopt sonuçlarını dinlemek için ArtManagerLocal#addDexoptDoneCallback kullanın.

getArtManagerLocal().addDexoptDoneCallback(
    false /* onlyIncludeUpdates */,
    Runnable::run,
    (result) -> {
      // Process the result here.
      ...
    });

İlk bağımsız değişken, sonuçta yalnızca güncellemelerin yer alıp almayacağını belirler. Yalnızca dexopt tarafından güncellenen paketleri dinlemek istiyorsanız true olarak ayarlayın.

İkinci bağımsız değişken, geri çağırma işlevinin yürütücüsüdür. Geri çağırmayı dexopt'u gerçekleştiren aynı iş parçacığında yürütmek için Runnable::run kullanın. Geri aramanın dexopt'u engellemesini istemiyorsanız eşzamansız bir yürütücü kullanın.

Birden fazla geri çağırma ekleyebilirsiniz ve ART Hizmeti bunların tümünü sırayla yürütür. Kaldırmadığınız sürece tüm geri aramalar, gelecekteki tüm aramalar için etkin kalır.

Bir geri aramayı kaldırmak istiyorsanız geri aramayı eklerken referansını saklayın ve ArtManagerLocal#removeDexoptDoneCallback simgesini kullanın.

DexoptDoneCallback callback = (result) -> {
  // Process the result here.
  ...
};

getArtManagerLocal().addDexoptDoneCallback(
    false /* onlyIncludeUpdates */, Runnable::run, callback);

// When you want to remove it.
getArtManagerLocal().removeDexoptDoneCallback(callback);

Paket listesini ve dexopt parametrelerini özelleştirme

ART Hizmeti, açılış ve arka plan dexopt sırasında dexopt işlemlerini kendisi başlatır. Bu işlemler için paket listesini veya dexopt parametrelerini özelleştirmek istiyorsanız ArtManagerLocal#setBatchDexoptStartCallback kullanın.

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.
      }
    });

Paket listesine öğe ekleyebilir, listeden öğe kaldırabilir, listeyi sıralayabilir veya tamamen farklı bir liste kullanabilirsiniz.

Geri arama işleviniz, gelecekte daha fazla neden eklenebileceğinden bilinmeyen nedenleri yoksaymalıdır.

En fazla bir BatchDexoptStartCallback ayarlayabilirsiniz. Geri arama, temizlemediğiniz sürece gelecekteki tüm aramalar için etkin kalır.

Geri arama işlevini temizlemek istiyorsanız ArtManagerLocal#clearBatchDexoptStartCallback kullanın.

getArtManagerLocal().clearBatchDexoptStartCallback();

Arka plandaki dexopt işinin parametrelerini özelleştirme

Varsayılan olarak, arka plandaki dexopt işi cihaz boşta ve şarj olurken günde bir kez çalışır. Bu ayar, ArtManagerLocal#setScheduleBackgroundDexoptJobCallback kullanılarak değiştirilebilir.

getArtManagerLocal().setScheduleBackgroundDexoptJobCallback(
    Runnable::run,
    builder -> {
      builder.setPeriodic(TimeUnit.DAYS.toMillis(2));
    });

En fazla bir ScheduleBackgroundDexoptJobCallback ayarlayabilirsiniz. Geri arama, siz temizlemediğiniz sürece gelecekteki tüm aramalar için etkin kalır.

Geri arama işlevini temizlemek istiyorsanız ArtManagerLocal#clearScheduleBackgroundDexoptJobCallback kullanın.

getArtManagerLocal().clearScheduleBackgroundDexoptJobCallback();

dexopt'u geçici olarak devre dışı bırakma

ART Hizmeti tarafından başlatılan tüm dexopt işlemleri BatchDexoptStartCallback tetikler. dexopt'u etkili bir şekilde devre dışı bırakmak için işlemleri iptal etmeye devam edebilirsiniz.

İptal ettiğiniz işlem arka planda dexopt ise varsayılan yeniden deneme politikası (30 saniye, üstel, 5 saat ile sınırlı) uygulanır.

// 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);

En fazla bir BatchDexoptStartCallback olabilir. Paket listesini veya dexopt parametrelerini özelleştirmek için BatchDexoptStartCallback de kullanmak istiyorsanız kodu tek bir geri çağırma işleminde birleştirmeniz gerekir.

// Bad example.

// Disable dexopt.
getArtManagerLocal().unscheduleBackgroundDexoptJob();

// Re-enable dexopt.
getArtManagerLocal().scheduleBackgroundDexoptJob();

Uygulama yükleme sırasında gerçekleştirilen dexopt işlemi ART Service tarafından başlatılmaz. Bunun yerine, paket yöneticisi tarafından dexoptPackage çağrısı aracılığıyla başlatılır. Bu nedenle, tetiklenmez BatchDexoptStartCallback. Uygulama yüklenirken dexopt'u devre dışı bırakmak için paket yöneticisinin dexoptPackage işlevini çağırmasını engelleyin.

Belirli paketler için derleyici filtresini geçersiz kılma (Android 15 ve sonraki sürümler)

setAdjustCompilerFilterCallback üzerinden geri çağırma işlevi kaydederek belirli paketler için derleyici filtresini geçersiz kılabilirsiniz. Geri çağırma, dexopt işleminin ART Hizmeti tarafından başlatılıp başlatılmadığına bakılmaksızın, bir paket dexopt işlemine tabi tutulacağı her zaman çağrılır. Bu işlem, başlatma ve arka plan dexopt sırasında veya bir dexoptPackage API çağrısıyla başlatılabilir.

Bir paketin ayarlanması gerekmiyorsa geri çağırma işlevi originalCompilerFilter değerini döndürmelidir.

getArtManagerLocal().setAdjustCompilerFilterCallback(
    Runnable::run,
    (packageName, originalCompilerFilter, reason) -> {
      if (isVeryImportantPackage(packageName)) {
        return "speed-profile";
      }
      return originalCompilerFilter;
    });

Yalnızca bir AdjustCompilerFilterCallback ayarlayabilirsiniz. Birden fazla paket için derleyici filtresini geçersiz kılmak üzere AdjustCompilerFilterCallback kullanmak istiyorsanız kodu tek bir geri çağırma işleminde birleştirmeniz gerekir. Geri arama, siz temizlemediğiniz sürece gelecekteki tüm aramalar için etkin kalır.

Geri arama işlevini temizlemek istiyorsanız ArtManagerLocal#clearAdjustCompilerFilterCallback kullanın.

getArtManagerLocal().clearAdjustCompilerFilterCallback();

Diğer özelleştirmeler

ART Hizmeti, diğer bazı özelleştirmeleri de destekler.

Arka planda dexopt için termal eşiği ayarlama

Arka plandaki dexopt işinin termal kontrolü, İş Planlayıcı tarafından gerçekleştirilir. Sıcaklık THERMAL_STATUS_MODERATE'ye ulaştığında iş hemen iptal edilir. THERMAL_STATUS_MODERATE eşiği ayarlanabilir.

Arka planda dexopt'un çalışıp çalışmadığını belirleme

Arka plan dexopt işi, İş Zamanlayıcı tarafından yönetilir ve iş kimliği 27873780'dır. İşin çalışıp çalışmadığını belirlemek için Job Scheduler API'lerini kullanın.

// 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.
  ...
}
// 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.
  ...
}

dexopt için bir profil sağlama

dexopt'a yol göstermek için profil kullanmak istiyorsanız APK'nın yanına bir .prof dosyası veya .dm dosyası yerleştirin.

.prof dosyası, ikili biçimli bir profil dosyası olmalı ve dosya adı, APK'nın dosya adı + .prof olmalıdır. Örneğin,

base.apk.prof

.dm dosyasının adı, uzantısı .dm ile değiştirilmiş APK'nın dosya adı olmalıdır. Örneğin,

base.dm

Profilin dexopt için kullanıldığını doğrulamak üzere speed-profile ile dexopt'u çalıştırın ve sonucu kontrol edin.

pm art clear-app-profiles <package-name>
pm compile -m speed-profile -f -v <package-name>

İlk satır, APK'nın yanındaki profilin ART Hizmeti'nin kullanabileceği tek profil olmasını sağlamak için çalışma zamanı tarafından oluşturulan tüm profilleri (varsa /data/misc/profiles içindekiler) temizler. İkinci satır, speed-profile ile dexopt'u çalıştırır ve ayrıntılı sonucu yazdırmak için -v'yi iletir.

Profil kullanılıyorsa sonuçta actualCompilerFilter=speed-profile simgesi gösterilir. Aksi takdirde actualCompilerFilter=verify simgesini görürsünüz. Örneğin,

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}

ART Hizmeti'nin profili kullanmamasının tipik nedenleri şunlardır:

  • Profilin dosya adı yanlış veya profil, APK'nın yanında değil.
  • Profil yanlış biçimde.
  • Profil, APK ile eşleşmiyor. (Profildeki sağlama toplamları, APK'daki .dex dosyalarının sağlama toplamlarıyla eşleşmiyor.)