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 yönetilir. ART Hizmeti, ART modülünün bir parçasıdır. Bu hizmeti, sistem özellikleri ve API'ler aracılığıyla özelleştirebilirsiniz.

Sistem özellikleri

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

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

pm.dexopt.<reason>

Bu, Dexopt senaryolarında açıklanan tüm önceden tanımlanmış derleme nedenleri için varsayılan derleyici filtrelerini belirleyen bir sistem özellikleri grubudur.

Daha fazla bilgi için Derleyici filtreleri bölümüne bakın.

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: hız)

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 profil yönlendirmeli derleme (speed-profile) yapar. Bununla birlikte, diğer uygulamalar tarafından kullanılan (<uses-library> aracılığıyla veya CONTEXT_INCLUDE_CODE ile Context#createPackageContext kullanılarak dinamik olarak yüklenen) bazı uygulamalar vardır. Bu tür uygulamalar, gizlilik nedeniyle yerel profilleri kullanamaz.

Bu tür bir uygulama için profil yönlendirmeli 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 profil odaklı değilse bu özelliğin hiçbir 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ğrısı için iş parçacığı sayısını, pm.dexopt.<reason>.concurrency ise dex2oat çağrılarının sayısını kontrol eder. Yani maksimum eşzamanlı iş parçacığı sayısı, iki sistem özelliğinin çarpımıdır.
  • dalvik.vm.*dex2oat-cpu-set ve görev profilleri, eşzamanlı maksimum ileti dizisi sayısından (yukarıda ele alınmıştır) bağımsız olarak her zaman CPU çekirdek kullanımını sınırlandırır.

Tek bir dex2oat çağrısı, dalvik.vm.*dex2oat-threads'ten bağımsız olarak tüm CPU çekirdeklerini tam olarak kullanamayabilir. Bu nedenle, dex2oat çağrılarının sayısını (pm.dexopt.<reason>.concurrency) artırmak, CPU çekirdeklerini daha iyi kullanabilir ve dexopt'in genel ilerleme hızını artırabilir. Bu, özellikle önyükleme sırasında yararlıdır.

Bununla birlikte, çok fazla dex2oat çağrısı olması, değişim dosyasının kullanılmasına izin vermek için dalvik.vm.dex2oat-swap politikasını true değerine ayarlamakla cihazın belleğin bitmesine neden olabilir. Çok fazla çağrı, gereksiz bağlam geçişine de neden olabilir. Bu nedenle, bu sayı ürüne göre dikkatlice 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'tan çıkarır.

Ayrıca, depolama alanı neredeyse doluysa ART Hizmeti, arka planda dexopt işlemi sırasında yer açmak için son belirtilen 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 tetikleyen 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'dır.

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

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

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

Arka planda dexopt işi zaten planlanmışsa ancak henüz çalıştırılmamışsa bu seçeneğin hiçbir etkisi olmaz. Yani iş çalışmaya devam eder.

Arka planda dexopt işinin çalışmasını önlemek için önerilen komut dizisi:

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

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

ART Hizmet API'leri

ART Hizmeti, özelleştirme için Java API'lerini gösterir. API'ler ArtManagerLocal adresinde tanımlanır. Kullanım alanları için art/libartservice/service/java/com/android/server/art/ArtManagerLocal.java içindeki Javadoc'a bakın (Android 14 kaynağı, yayınlanmamış geliştirme kaynağı).

ArtManagerLocal, LocalManagerRegistry tarafından tutulan tekil bir öğedir. com.android.server.pm.DexOptHelper#getArtManagerLocal yardımcı işlevi, bu değeri elde etmenize 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 çağrısı yaparak bu değeri alabilirsiniz. Burada PackageManagerLocal, LocalManagerRegistry tarafından tutulan ve com.android.server.pm.PackageManagerServiceUtils#getPackageManagerLocal'dan alınabilen tekil bir değerdir.

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

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

Bir uygulama için dexopt'i tetikleme

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

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

Ayrıca kendi dexopt nedeninizi de iletebilirsiniz. Bunu yaparsanız öncelik sınıfı ve derleyici filtresi açık bir şekilde 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());
}

Dexopt'yi iptal et

Bir işlem dexoptPackage çağrısıyla başlatılırsa iptal sinyali iletebilir ve böylece işlemi bir noktada iptal edebilirsiniz. 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();

Ayrıca, ART Hizmeti tarafından başlatılan arka plan devre dışı bırakma 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öndürülen değerden alabilirsiniz.

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

// Process the result here.
...

ART Hizmeti, arka planda dexopt işlemi gibi birçok senaryoda dexopt işlemlerini kendisi de başlatır. İşlemin bir dexoptPackage çağrısı veya ART Hizmeti tarafından başlatılmış olması fark etmeksizin, tüm kaldırma sonuçlarını dinlemek için ArtManagerLocal#addDexoptDoneCallback işlevini kullanın.

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

İlk bağımsız değişken, sonuca yalnızca güncellemelerin dahil edilip edilmeyeceğini belirler. Yalnızca dexopt tarafından güncellenen paketleri dinlemek istiyorsanız bu değeri 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 işlemi gerçekleştiren aynı iş parçacığında yürütmek için Runnable::run işlevini kullanın. Geri çağırmanın dexopt'yi engellemesini istemiyorsanız eşzamansız bir yürütücü kullanın.

Birden fazla geri çağırma ekleyebilirsiniz. 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 çağırmayı kaldırmak isterseniz geri arama referansını eklerken ArtManagerLocal#removeDexoptDoneCallback 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, önyükleme ve arka planda dexopt sırasında dexopt işlemlerini kendisi başlatır. Bu işlemler için paket listesini veya dexopt parametrelerini özelleştirmek üzere ArtManagerLocal#setBatchDexoptStartCallback simgesini 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.

Gelecekte daha fazla neden eklenebilir. Bu nedenle, geri arama işleminizde bilinmeyen nedenler yoksayılmalıdır.

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

Geri aramayı silmek için ArtManagerLocal#clearBatchDexoptStartCallback simgesini kullanın.

getArtManagerLocal().clearBatchDexoptStartCallback();

Arka planda dexopt işinin parametrelerini özelleştirme

Varsayılan olarak, arka plan kaldırma 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 silmediğiniz sürece gelecekteki tüm aramalar için etkin kalır.

Geri çağırmayı temizlemek isterseniz ArtManagerLocal#clearScheduleBackgroundDexoptJobCallback işlevini 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 bir 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 saatle sınırlı) geçerli olur.

// 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'ünüz olabilir. Paket listesini veya dexopt parametrelerini özelleştirmek için BatchDexoptStartCallback'ü de kullanmak istiyorsanız kodu tek bir geri çağırma işlevinde birleştirmeniz gerekir.

// Bad example.

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

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

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

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

setAdjustCompilerFilterCallback aracılığıyla geri çağırma işlevi kaydederek belirli paketler için derleyici filtresini geçersiz kılabilirsiniz. Geri çağırma işlevi, bir paketin dexopt işlemine tabi tutulacağı her zaman çağrılır. Bu çağrı, dexopt işleminin ART Hizmeti tarafından önyükleme ve arka plan dexopt işlemi sırasında mı yoksa bir dexoptPackage API çağrısı tarafından mı başlatıldığına bakılmaksızın gerçekleşir.

Bir paketin ayarlanması gerekmiyorsa geri çağırma işlevi originalCompilerFilter 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şlevinde birleştirmeniz gerekir. Geri çağırma, silmediğiniz sürece gelecekteki tüm çağrılar için etkin kalır.

Geri aramayı silmek için ArtManagerLocal#clearAdjustCompilerFilterCallback simgesini 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 plan dexopt işinin termal kontrolü, İş Planlayıcı tarafından gerçekleştirilir. Sıcaklık THERMAL_STATUS_MODERATE'e 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 planda dexopt işi İş Planlayıcı tarafından yönetilir ve iş kimliği 27873780'tü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ğlayın

Dexopt'a rehberlik etmek için bir profil kullanmak istiyorsanız APK'nın yanına bir .prof dosyası veya .dm dosyası ekleyin.

.prof dosyası ikili biçimli bir profil dosyası olmalı ve dosya adı, APK dosya adının .prof ile birlikte yazılmış halidir. Örneğin,

base.apk.prof

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

base.dm

Profilin dexopt için kullanıldığını doğrulamak üzere dexopt'u speed-profile ile ç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 Service'in kullanabileceği tek profil olduğundan emin olmak için çalışma zamanı tarafından oluşturulan tüm profilleri (/data/misc/profiles içinde olanlar) temizler. İkinci satır, dexopt'u speed-profile ile çalıştırır ve ayrıntılı sonucu yazdırmak için -v parametresini iletir.

Profil kullanılıyorsa sonuçta actualCompilerFilter=speed-profile simgesi gösterilir. Aksi durumda actualCompilerFilter=verify gösterilir. Ö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 hizmetinin profili kullanmamasının yaygın nedenleri şunlardır:

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