پیکربندی سرویس ART

قبل از شروع ، یک نمای کلی سطح بالا از سرویس هنری را ببینید.

با شروع Android 14 ، مجموعه AOT در دستگاه برای برنامه ها (AKA DEXOPT) توسط سرویس هنری اداره می شود. سرویس هنری بخشی از ماژول هنر است و می توانید آن را از طریق ویژگی های سیستم و API ها سفارشی کنید.

خصوصیات سیستم

سرویس هنری از تمام گزینه های مربوط به Dex2oat پشتیبانی می کند.

علاوه بر این ، سرویس هنری از خصوصیات سیستم زیر پشتیبانی می کند:

pm.dexopt. <دلیل>

این مجموعه ای از خصوصیات سیستم است که فیلترهای کامپایلر پیش فرض را برای کلیه دلایل تدوین از پیش تعریف شده شرح داده شده در سناریوهای DexOPT تعیین می کند.

برای اطلاعات بیشتر ، به فیلترهای کامپایلر مراجعه کنید.

مقادیر پیش فرض استاندارد عبارتند از:

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 (پیش فرض: سرعت)

این فیلتر کامپایلر Fallback برای برنامه های استفاده شده توسط برنامه های دیگر است.

در اصل ، سرویس ART در صورت امکان ، به طور معمول در طول Dexopt پس زمینه ، مجموعه ای از speed-profile را هدایت می کند. با این حال ، برخی از برنامه ها وجود دارد که توسط برنامه های دیگر استفاده می شود (یا از طریق <uses-library> یا به صورت پویا با استفاده از Context#createPackageContext با CONTEXT_INCLUDE_CODE ). چنین برنامه هایی به دلایل حریم خصوصی نمی توانند از پروفایل های محلی استفاده کنند.

برای چنین برنامه ای ، در صورت درخواست تدوین با هدایت مشخصات ، سرویس هنری ابتدا سعی می کند از پروفایل ابری استفاده کند. اگر یک پروفایل ابر وجود نداشته باشد ، سرویس هنری برای استفاده از فیلتر کامپایلر مشخص شده توسط pm.dexopt.shared باز می گردد.

اگر تدوین درخواست شده با هدایت مشخص شود ، این خاصیت هیچ تاثیری ندارد.

pm.dexopt. <Eln> .concurrency (پیش فرض: 1)

این تعداد دعوت های Dex2oat برای دلایل خاص تدوین از پیش تعریف شده ( first-boot ، boot-after-ota ، boot-after-mainline-update و bg-dexopt ) است.

توجه داشته باشید که تأثیر این گزینه با گزینه های استفاده از منابع Dex2oat ( dalvik.vm.*dex2oat-threads ، dalvik.vm.*dex2oat-cpu-set و پروفایل های کار) ترکیب شده است:

  • dalvik.vm.*dex2oat-threads تعداد موضوعات مربوط به هر دعوت Dex2oat را کنترل می کند ، در حالی که pm.dexopt.<reason>.concurrency . یعنی حداکثر تعداد موضوعات همزمان محصول دو ویژگی سیستم است.
  • dalvik.vm.*dex2oat-cpu-set و پروفایل های کار همیشه استفاده از هسته CPU را بدون در نظر گرفتن حداکثر تعداد موضوعات همزمان (که در بالا مورد بحث قرار گرفت) محدود می کند.

یک دعوت Dex2oat ممکن است به طور کامل از تمام هسته های CPU استفاده نکند ، صرف نظر از dalvik.vm.*dex2oat-threads . بنابراین ، افزایش تعداد دعوت های dex2oat ( pm.dexopt.<reason>.concurrency ) می تواند از هسته های CPU بهتر استفاده کند ، تا پیشرفت کلی DexOPT را سرعت بخشد. این به ویژه در طول بوت مفید است.

با این وجود ، داشتن تعداد زیادی از دعوت های Dex2oat ممکن است باعث شود دستگاه از حافظه خارج شود ، حتی اگر این امر با تنظیم dalvik.vm.dex2oat-swap به true کاهش یابد تا اجازه استفاده از یک فایل مبادله شود. بسیاری از دعوت ها نیز ممکن است باعث تغییر زمینه غیر ضروری شود. بنابراین، این عدد باید بر اساس محصول به محصول به دقت تنظیم شود.

pm.dexopt.downgrade_after_inactive_days (پیش‌فرض: تنظیم نشده)

اگر این گزینه تنظیم شده باشد، سرویس ART فقط برنامه‌های مورد استفاده در آخرین تعداد روز معین را حذف می‌کند.

علاوه بر این، اگر فضای ذخیره‌سازی تقریباً کم باشد، در طول Dexopt پس‌زمینه، ART Service فیلتر کامپایلر برنامه‌هایی را که در چند روز گذشته استفاده نشده‌اند، کاهش می‌دهد تا فضا آزاد شود. دلیل کامپایلر برای این inactive است و فیلتر کامپایلر توسط pm.dexopt.inactive تعیین می شود. آستانه فضایی برای فعال کردن این ویژگی، آستانه فضای کم Storage Manager (قابل تنظیم از طریق تنظیمات جهانی sys_storage_threshold_percentage و sys_storage_threshold_max_bytes ، پیش‌فرض: 500 مگابایت) به اضافه 500 مگابایت است.

اگر لیست بسته ها را از طریق ArtManagerLocal#setBatchDexoptStartCallback سفارشی کنید، بسته های موجود در لیست ارائه شده توسط BatchDexoptStartCallback برای bg-dexopt هرگز تنزل داده نمی شوند.

pm.dexopt.disable_bg_dexopt (پیش‌فرض: نادرست)

این فقط برای آزمایش است. از برنامه ریزی ART Service برای Dexopt پس زمینه جلوگیری می کند.

اگر کار dexopt پس‌زمینه قبلاً برنامه‌ریزی شده است اما هنوز اجرا نشده است، این گزینه تأثیری ندارد. یعنی کار همچنان ادامه خواهد داشت.

دنباله ای از دستورات توصیه شده برای جلوگیری از اجرای کار پس زمینه dexopt عبارتند از:

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

خط اول از برنامه ریزی کار پس زمینه dexopt جلوگیری می کند، اگر هنوز برنامه ریزی نشده باشد. خط دوم کار dexopt پس‌زمینه را از زمان‌بندی خارج می‌کند، اگر از قبل برنامه‌ریزی شده باشد، و بلافاصله کار dexopt پس‌زمینه را لغو می‌کند، اگر در حال اجرا باشد.

API های سرویس ART

سرویس ART API های جاوا را برای سفارشی سازی در معرض نمایش می گذارد. API ها در ArtManagerLocal تعریف شده اند. برای موارد استفاده، Javadoc را در art/libartservice/service/java/com/android/server/art/ArtManagerLocal.java ببینید ( منبع Android 14 ، منبع توسعه منتشر نشده ).

ArtManagerLocal یک تکی است که توسط LocalManagerRegistry نگهداری می شود. یک تابع کمکی com.android.server.pm.DexOptHelper#getArtManagerLocal به شما کمک می کند آن را بدست آورید.

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

بیشتر APIها به نمونه‌ای از PackageManagerLocal.FilteredSnapshot نیاز دارند که اطلاعات همه برنامه‌ها را در خود نگه می‌دارد. می‌توانید آن را با تماس با PackageManagerLocal#withFilteredSnapshot دریافت کنید، جایی که PackageManagerLocal نیز تک‌تنه‌ای است که توسط LocalManagerRegistry نگهداری می‌شود و می‌توانید آن را از com.android.server.pm.PackageManagerServiceUtils#getPackageManagerLocal دریافت کنید.

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

موارد زیر برخی از موارد استفاده معمولی از APIها هستند.

dexopt را برای یک برنامه فعال کنید

می‌توانید در هر زمانی با تماس با ArtManagerLocal#dexoptPackage dexopt را برای هر برنامه فعال کنید.

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

شما همچنین می توانید دلیل dexopt خود را بیان کنید. اگر این کار را انجام دهید، کلاس اولویت و فیلتر کامپایلر باید به صراحت تنظیم شوند.

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

دکسوپت را لغو کنید

اگر عملیاتی با یک تماس dexoptPackage آغاز شود، می‌توانید یک سیگنال لغو را ارسال کنید، که به شما امکان می‌دهد عملیات را در نقطه‌ای لغو کنید. این می تواند زمانی مفید باشد که dexopt را به صورت ناهمزمان اجرا می کنید.

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

همچنین می‌توانید dexopt پس‌زمینه را که توسط ART Service آغاز شده است، لغو کنید.

getArtManagerLocal().cancelBackgroundDexoptJob();

نتایج dexopt را دریافت کنید

اگر عملیاتی با فراخوانی dexoptPackage آغاز شود، می‌توانید نتیجه را از مقدار بازگشتی دریافت کنید.

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

// Process the result here.
...

سرویس ART همچنین در بسیاری از سناریوها، مانند پس‌زمینه، عملیات dexopt را آغاز می‌کند. برای گوش دادن به همه نتایج dexopt، خواه این عملیات با یک تماس dexoptPackage یا با سرویس ART آغاز شود، از ArtManagerLocal#addDexoptDoneCallback استفاده کنید.

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

اولین آرگومان تعیین می‌کند که آیا فقط به‌روزرسانی‌ها در نتیجه گنجانده شود یا خیر. اگر می خواهید فقط به بسته هایی گوش دهید که توسط dexopt به روز می شوند، آن را روی true تنظیم کنید.

آرگومان دوم مجری callback است. برای اجرای callback در همان رشته ای که dexopt را انجام می دهد، از Runnable::run استفاده کنید. اگر نمی‌خواهید پاسخ به تماس، دکسوپت را مسدود کند، از یک اجراکننده ناهمزمان استفاده کنید.

می توانید چندین تماس را اضافه کنید و ART Service همه آنها را به صورت متوالی اجرا می کند. همه تماس‌های برگشتی برای همه تماس‌های آینده فعال می‌مانند مگر اینکه آنها را حذف کنید.

اگر می‌خواهید پاسخ تماسی را حذف کنید، هنگام افزودن آن، مرجع آن را نگه دارید و از 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);

لیست بسته و پارامترهای dexopt را سفارشی کنید

سرویس ART خود عملیات dexopt را در هنگام بوت و پس‌زمینه dexopt آغاز می‌کند. برای سفارشی کردن لیست بسته یا پارامترهای dexopt برای آن عملیات، از 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.
      }
    });

می توانید مواردی را به لیست بسته اضافه کنید، موارد را از آن حذف کنید، آن را مرتب کنید یا حتی از یک لیست کاملاً متفاوت استفاده کنید.

تماس پاسخ شما باید دلایل ناشناخته را نادیده بگیرد زیرا ممکن است در آینده دلایل بیشتری اضافه شود.

می توانید حداکثر یک BatchDexoptStartCallback تنظیم کنید. پاسخ تماس برای همه تماس‌های آینده فعال باقی می‌ماند مگر اینکه آن را پاک کنید.

اگر می خواهید پاسخ به تماس را پاک کنید ، از ArtManagerLocal#clearBatchDexoptStartCallback استفاده کنید.

getArtManagerLocal().clearBatchDexoptStartCallback();

پارامترهای کار پس زمینه dexopt را سفارشی کنید

به طور پیش‌فرض، زمانی که دستگاه بی‌حرکت است و در حال شارژ است، کار dexopt پس‌زمینه یک بار در روز اجرا می‌شود. این می تواند با استفاده از ArtManagerLocal#setScheduleBackgroundDexoptJobCallback تغییر یابد.

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

می توانید حداکثر یک ScheduleBackgroundDexoptJobCallback تنظیم کنید. پاسخ تماس برای همه تماس‌های آینده فعال باقی می‌ماند مگر اینکه آن را پاک کنید.

اگر می‌خواهید پاسخ تماس را پاک کنید، از ArtManagerLocal#clearScheduleBackgroundDexoptJobCallback استفاده کنید.

getArtManagerLocal().clearScheduleBackgroundDexoptJobCallback();

Dexopt را به طور موقت غیرفعال کنید

هر عملیات dexopt که توسط ART Service آغاز می شود، BatchDexoptStartCallback را راه اندازی می کند. برای غیرفعال کردن موثر dexopt، می توانید به لغو عملیات ادامه دهید.

اگر عملیاتی که لغو می‌کنید dexopt پس‌زمینه باشد، از خط‌مشی تکرار پیش‌فرض پیروی می‌کند (30 ثانیه، نمایی، محدود به 5 ساعت).

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

شما می توانید حداکثر یک BatchDexoptStartCallback داشته باشید. اگر همچنین می‌خواهید از BatchDexoptStartCallback برای سفارشی‌سازی لیست بسته یا پارامترهای dexopt استفاده کنید، باید کد را در یک پاسخ به تماس ترکیب کنید.

// Bad example.

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

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

عملیات dexopt انجام شده در نصب برنامه توسط ART Service آغاز نشده است. در عوض، توسط مدیر بسته از طریق یک تماس dexoptPackage آغاز می شود. بنابراین، BatchDexoptStartCallback را راه‌اندازی نمی‌کند . برای غیرفعال کردن dexopt در نصب برنامه، از تماس مدیر بسته با dexoptPackage جلوگیری کنید.

نادیده گرفتن فیلتر کامپایلر برای بسته‌های خاص (Android 15 (AOSP آزمایشی)+)

می‌توانید فیلتر کامپایلر را برای بسته‌های خاصی با ثبت یک تماس از طریق setAdjustCompilerFilterCallback لغو کنید. هر زمان که بسته‌ای قرار است حذف شود، تماس برگشتی فراخوانی می‌شود، مهم نیست که دکسوپت توسط سرویس ART در هنگام بوت و پس‌زمینه دکسوپت یا با تماس API dexoptPackage آغاز شود.

اگر بسته ای نیاز به تنظیم نداشته باشد، پاسخ تماس باید originalCompilerFilter برگرداند.

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

شما می توانید تنها یک AdjustCompilerFilterCallback تنظیم کنید. اگر می خواهید از AdjustCompilerFilterCallback برای نادیده گرفتن فیلتر کامپایلر برای چندین بسته استفاده کنید ، باید کد را در یک پاسخ به یک پاسخ ترکیب کنید. پاسخ تماس برای همه تماس‌های آینده فعال باقی می‌ماند مگر اینکه آن را پاک کنید.

اگر می‌خواهید پاسخ تماس را پاک کنید، از ArtManagerLocal#clearAdjustCompilerFilterCallback استفاده کنید.

getArtManagerLocal().clearAdjustCompilerFilterCallback();

سایر سفارشی سازی ها

سرویس ART از برخی سفارشی سازی های دیگر نیز پشتیبانی می کند.

آستانه حرارتی را برای پس‌زمینه دکسوپت تنظیم کنید

کنترل حرارتی کار پس زمینه Dexopt توسط برنامه ریزی شغلی انجام می شود. هنگامی که دما به THERMAL_STATUS_MODERATE رسید، کار بلافاصله لغو می شود. آستانه THERMAL_STATUS_MODERATE قابل تنظیم است.

تعیین کنید که آیا پس زمینه Dexopt در حال اجرا است

کار پس زمینه dexopt توسط Job Scheduler مدیریت می شود و شناسه شغلی آن 27873780 است. برای تعیین اینکه آیا کار در حال اجرا است ، از 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.
  ...
}
// 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 ارائه دهید

برای استفاده از نمایه برای هدایت dexopt، یک فایل .prof یا یک فایل .dm در کنار APK قرار دهید.

پرونده .prof باید یک فایل پروفایل با دودویی باشد و نام پرونده باید نام پرونده APK + باشد .prof . مثلا،

base.apk.prof

نام فایل فایل .dm باید نام فایل APK با پسوند جایگزین با .dm باشد. مثلا،

base.dm

برای اطمینان از اینکه پروفایل برای dexopt استفاده می شود، dexopt را با speed-profile اجرا کنید و نتیجه را بررسی کنید.

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

خط اول تمام پروفایل های تولید شده توسط زمان اجرا را پاک می کند (به عنوان مثال ، آنهایی که در /data/misc/profiles ) وجود دارد ، در صورت وجود ، اطمینان حاصل کنید که نمایه در کنار APK تنها مشخصاتی است که احتمالاً سرویس هنری می تواند از آن استفاده کند. خط دوم Dexopt را با speed-profile اجرا می کند و برای چاپ نتیجه کلامی -v می گذرد.

اگر از نمایه استفاده می شود ، در نتیجه actualCompilerFilter=speed-profile را می بینید. در غیر این صورت، actualCompilerFilter=verify مشاهده می کنید. مثلا،

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 Service شامل موارد زیر است:

  • نمایه نام پرونده اشتباه دارد یا در کنار APK نیست.
  • نمایه در قالب اشتباه است.
  • نمایه با APK مطابقت ندارد. (چک های موجود در نمایه با چک های پرونده های .dex در APK مطابقت ندارند.)