Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 56ba9447 authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge changes I87740397,I0cc4538b,Iaceb2b7c

* changes:
  Wait for BOOT_COMPLETE event before scheduling the bootDexoptJob
  Use BatteryManagerInternal to determine low battery.
  BackgroundDexOptService: defer post-boot job further
parents 919e8c1b f0d01f45
Loading
Loading
Loading
Loading
+52 −64
Original line number Diff line number Diff line
@@ -16,7 +16,6 @@

package com.android.server.pm;

import static com.android.server.pm.PackageManagerService.DEBUG_DEXOPT;
import static com.android.server.pm.PackageManagerService.PLATFORM_PACKAGE_NAME;

import android.annotation.Nullable;
@@ -24,12 +23,13 @@ import android.app.job.JobInfo;
import android.app.job.JobParameters;
import android.app.job.JobScheduler;
import android.app.job.JobService;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageInfo;
import android.os.BatteryManager;
import android.os.BatteryManagerInternal;
import android.os.Environment;
import android.os.ServiceManager;
import android.os.SystemProperties;
@@ -37,6 +37,7 @@ import android.os.UserHandle;
import android.os.storage.StorageManager;
import android.util.ArraySet;
import android.util.Log;
import android.util.Slog;

import com.android.internal.util.ArrayUtils;
import com.android.internal.util.FrameworkStatsLog;
@@ -65,9 +66,7 @@ public class BackgroundDexOptService extends JobService {
    private static final int JOB_IDLE_OPTIMIZE = 800;
    private static final int JOB_POST_BOOT_UPDATE = 801;

    private static final long IDLE_OPTIMIZATION_PERIOD = DEBUG
            ? TimeUnit.MINUTES.toMillis(1)
            : TimeUnit.DAYS.toMillis(1);
    private static final long IDLE_OPTIMIZATION_PERIOD = TimeUnit.DAYS.toMillis(1);

    private static ComponentName sDexoptServiceName = new ComponentName(
            "android",
@@ -115,14 +114,24 @@ public class BackgroundDexOptService extends JobService {
            return;
        }

        JobScheduler js = (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE);
        final JobScheduler js = context.getSystemService(JobScheduler.class);

        // Schedule a one-off job which scans installed packages and updates
        // out-of-date oat files.
        // out-of-date oat files. Schedule it 10 minutes after the boot complete event,
        // so that we don't overload the boot with additional dex2oat compilations.
        context.registerReceiver(new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                js.schedule(new JobInfo.Builder(JOB_POST_BOOT_UPDATE, sDexoptServiceName)
                    .setMinimumLatency(TimeUnit.MINUTES.toMillis(1))
                    .setOverrideDeadline(TimeUnit.MINUTES.toMillis(1))
                        .setMinimumLatency(TimeUnit.MINUTES.toMillis(10))
                        .setOverrideDeadline(TimeUnit.MINUTES.toMillis(60))
                        .build());
                context.unregisterReceiver(this);
                if (DEBUG) {
                    Slog.i(TAG, "BootBgDexopt scheduled");
                }
            }
        }, new IntentFilter(Intent.ACTION_BOOT_COMPLETED));

        // Schedule a daily job which scans installed packages and compiles
        // those with fresh profiling data.
@@ -132,8 +141,8 @@ public class BackgroundDexOptService extends JobService {
                    .setPeriodic(IDLE_OPTIMIZATION_PERIOD)
                    .build());

        if (DEBUG_DEXOPT) {
            Log.i(TAG, "Jobs scheduled");
        if (DEBUG) {
            Slog.d(TAG, "BgDexopt scheduled");
        }
    }

@@ -149,32 +158,11 @@ public class BackgroundDexOptService extends JobService {
        }
    }

    // Returns the current battery level as a 0-100 integer.
    private int getBatteryLevel() {
        IntentFilter filter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
        Intent intent = registerReceiver(null, filter);
        int level = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
        int scale = intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1);
        boolean present = intent.getBooleanExtra(BatteryManager.EXTRA_PRESENT, true);

        if (!present) {
            // No battery, treat as if 100%, no possibility of draining battery.
            return 100;
        }

        if (level < 0 || scale <= 0) {
            // Battery data unavailable. This should never happen, so assume the worst.
            return 0;
        }

        return (100 * level / scale);
    }

    private long getLowStorageThreshold(Context context) {
        @SuppressWarnings("deprecation")
        final long lowThreshold = StorageManager.from(context).getStorageLowBytes(mDataDir);
        if (lowThreshold == 0) {
            Log.e(TAG, "Invalid low storage threshold");
            Slog.e(TAG, "Invalid low storage threshold");
        }

        return lowThreshold;
@@ -198,9 +186,8 @@ public class BackgroundDexOptService extends JobService {

    private void postBootUpdate(JobParameters jobParams, PackageManagerService pm,
            ArraySet<String> pkgs) {
        // Load low battery threshold from the system config. This is a 0-100 integer.
        final int lowBatteryThreshold = getResources().getInteger(
                com.android.internal.R.integer.config_lowBatteryWarningLevel);
        final BatteryManagerInternal batteryManagerInternal =
                LocalServices.getService(BatteryManagerInternal.class);
        final long lowThreshold = getLowStorageThreshold(this);

        mAbortPostBootUpdate.set(false);
@@ -215,20 +202,19 @@ public class BackgroundDexOptService extends JobService {
                // Different job, which supersedes this one, is running.
                break;
            }
            if (getBatteryLevel() < lowBatteryThreshold) {
            if (batteryManagerInternal.getBatteryLevelLow()) {
                // Rather bail than completely drain the battery.
                break;
            }
            long usableSpace = mDataDir.getUsableSpace();
            if (usableSpace < lowThreshold) {
                // Rather bail than completely fill up the disk.
                Log.w(TAG, "Aborting background dex opt job due to low storage: " +
                Slog.w(TAG, "Aborting background dex opt job due to low storage: " +
                        usableSpace);
                break;
            }

            if (DEBUG_DEXOPT) {
                Log.i(TAG, "Updating package " + pkg);
            if (DEBUG) {
                Slog.i(TAG, "Updating package " + pkg);
            }

            // Update package if needed. Note that there can be no race between concurrent
@@ -260,13 +246,13 @@ public class BackgroundDexOptService extends JobService {
            public void run() {
                int result = idleOptimization(pm, pkgs, BackgroundDexOptService.this);
                if (result == OPTIMIZE_PROCESSED) {
                    Log.i(TAG, "Idle optimizations completed.");
                    Slog.i(TAG, "Idle optimizations completed.");
                } else if (result == OPTIMIZE_ABORT_NO_SPACE_LEFT) {
                    Log.w(TAG, "Idle optimizations aborted because of space constraints.");
                    Slog.w(TAG, "Idle optimizations aborted because of space constraints.");
                } else if (result == OPTIMIZE_ABORT_BY_JOB_SCHEDULER) {
                    Log.w(TAG, "Idle optimizations aborted by job scheduler.");
                    Slog.w(TAG, "Idle optimizations aborted by job scheduler.");
                } else {
                    Log.w(TAG, "Idle optimizations ended with unexpected code: " + result);
                    Slog.w(TAG, "Idle optimizations ended with unexpected code: " + result);
                }
                if (result != OPTIMIZE_ABORT_BY_JOB_SCHEDULER) {
                    // Abandon our timeslice and do not reschedule.
@@ -280,7 +266,7 @@ public class BackgroundDexOptService extends JobService {
    // Optimize the given packages and return the optimization result (one of the OPTIMIZE_* codes).
    private int idleOptimization(PackageManagerService pm, ArraySet<String> pkgs,
            Context context) {
        Log.i(TAG, "Performing idle optimizations");
        Slog.i(TAG, "Performing idle optimizations");
        // If post-boot update is still running, request that it exits early.
        mExitPostBootUpdate.set(true);
        mAbortIdleOptimization.set(false);
@@ -355,11 +341,15 @@ public class BackgroundDexOptService extends JobService {
            final long lowStorageThresholdForDowngrade = LOW_THRESHOLD_MULTIPLIER_FOR_DOWNGRADE
                    * lowStorageThreshold;
            boolean shouldDowngrade = shouldDowngrade(lowStorageThresholdForDowngrade);
            Log.d(TAG, "Should Downgrade " + shouldDowngrade);
            if (DEBUG) {
                Slog.d(TAG, "Should Downgrade " + shouldDowngrade);
            }
            if (shouldDowngrade) {
                Set<String> unusedPackages =
                        pm.getUnusedPackages(mDowngradeUnusedAppsThresholdInMillis);
                Log.d(TAG, "Unsused Packages " +  String.join(",", unusedPackages));
                if (DEBUG) {
                    Slog.d(TAG, "Unsused Packages " +  String.join(",", unusedPackages));
                }

                if (!unusedPackages.isEmpty()) {
                    for (String pkg : unusedPackages) {
@@ -431,7 +421,9 @@ public class BackgroundDexOptService extends JobService {
     */
    private boolean downgradePackage(PackageManagerService pm, String pkg,
            boolean isForPrimaryDex) {
        Log.d(TAG, "Downgrading " + pkg);
        if (DEBUG) {
            Slog.d(TAG, "Downgrading " + pkg);
        }
        boolean dex_opt_performed = false;
        int reason = PackageManagerService.REASON_INACTIVE_PACKAGE_DOWNGRADE;
        int dexoptFlags = DexoptOptions.DEXOPT_BOOT_COMPLETE
@@ -553,7 +545,7 @@ public class BackgroundDexOptService extends JobService {
        long usableSpace = mDataDir.getUsableSpace();
        if (usableSpace < lowStorageThreshold) {
            // Rather bail than completely fill up the disk.
            Log.w(TAG, "Aborting background dex opt job due to low storage: " + usableSpace);
            Slog.w(TAG, "Aborting background dex opt job due to low storage: " + usableSpace);
            return OPTIMIZE_ABORT_NO_SPACE_LEFT;
        }

@@ -592,8 +584,8 @@ public class BackgroundDexOptService extends JobService {

    @Override
    public boolean onStartJob(JobParameters params) {
        if (DEBUG_DEXOPT) {
            Log.i(TAG, "onStartJob");
        if (DEBUG) {
            Slog.i(TAG, "onStartJob");
        }

        // NOTE: PackageManagerService.isStorageLow uses a different set of criteria from
@@ -601,17 +593,13 @@ public class BackgroundDexOptService extends JobService {
        // restart with a period of ~1 minute.
        PackageManagerService pm = (PackageManagerService)ServiceManager.getService("package");
        if (pm.isStorageLow()) {
            if (DEBUG_DEXOPT) {
                Log.i(TAG, "Low storage, skipping this run");
            }
            Slog.i(TAG, "Low storage, skipping this run");
            return false;
        }

        final ArraySet<String> pkgs = pm.getOptimizablePackages();
        if (pkgs.isEmpty()) {
            if (DEBUG_DEXOPT) {
                Log.i(TAG, "No packages to optimize");
            }
            Slog.i(TAG, "No packages to optimize");
            return false;
        }

@@ -627,8 +615,8 @@ public class BackgroundDexOptService extends JobService {

    @Override
    public boolean onStopJob(JobParameters params) {
        if (DEBUG_DEXOPT) {
            Log.i(TAG, "onStopJob");
        if (DEBUG) {
            Slog.d(TAG, "onStopJob");
        }

        if (params.getJobId() == JOB_POST_BOOT_UPDATE) {
@@ -649,7 +637,7 @@ public class BackgroundDexOptService extends JobService {
    private void notifyPinService(ArraySet<String> updatedPackages) {
        PinnerService pinnerService = LocalServices.getService(PinnerService.class);
        if (pinnerService != null) {
            Log.i(TAG, "Pinning optimized code " + updatedPackages);
            Slog.i(TAG, "Pinning optimized code " + updatedPackages);
            pinnerService.update(updatedPackages, false /* force */);
        }
    }
@@ -684,7 +672,7 @@ public class BackgroundDexOptService extends JobService {
        final String sysPropKey = "pm.dexopt.downgrade_after_inactive_days";
        String sysPropValue = SystemProperties.get(sysPropKey);
        if (sysPropValue == null || sysPropValue.isEmpty()) {
            Log.w(TAG, "SysProp " + sysPropKey + " not set");
            Slog.w(TAG, "SysProp " + sysPropKey + " not set");
            return Long.MAX_VALUE;
        }
        return TimeUnit.DAYS.toMillis(Long.parseLong(sysPropValue));