From 8735f07a698218d311826a140d08d611d3c23db1 Mon Sep 17 00:00:00 2001 From: Narayan Kamath Date: Tue, 16 Aug 2016 18:25:08 +0100 Subject: [PATCH] BackgroundDexOptService: Check for low storage conditions. Abort the service (without an early reschedule) if we find that we're running low on space. The low space check is performed (explicitly) after every dexopt. bug: 30865506 Change-Id: I8d31af8fe035701177f8b9a1eabb0b51f42027fe --- .../server/pm/BackgroundDexOptService.java | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/services/core/java/com/android/server/pm/BackgroundDexOptService.java b/services/core/java/com/android/server/pm/BackgroundDexOptService.java index 87f0581a78793..cec105816b36b 100644 --- a/services/core/java/com/android/server/pm/BackgroundDexOptService.java +++ b/services/core/java/com/android/server/pm/BackgroundDexOptService.java @@ -28,10 +28,13 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.os.BatteryManager; +import android.os.Environment; import android.os.ServiceManager; +import android.os.storage.StorageManager; import android.util.ArraySet; import android.util.Log; +import java.io.File; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.TimeUnit; @@ -66,6 +69,8 @@ public class BackgroundDexOptService extends JobService { */ final AtomicBoolean mExitPostBootUpdate = new AtomicBoolean(false); + private final File dataDir = Environment.getDataDirectory(); + public static void schedule(Context context) { JobScheduler js = (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE); @@ -113,6 +118,16 @@ public class BackgroundDexOptService extends JobService { return (100 * level / scale); } + private long getLowStorageThreshold() { + @SuppressWarnings("deprecation") + final long lowThreshold = StorageManager.from(this).getStorageLowBytes(dataDir); + if (lowThreshold == 0) { + Log.e(TAG, "Invalid low storage threshold"); + } + + return lowThreshold; + } + private boolean runPostBootUpdate(final JobParameters jobParams, final PackageManagerService pm, final ArraySet pkgs) { if (mExitPostBootUpdate.get()) { @@ -124,6 +139,8 @@ public class BackgroundDexOptService extends JobService { final int lowBatteryThreshold = getResources().getInteger( com.android.internal.R.integer.config_lowBatteryWarningLevel); + final long lowThreshold = getLowStorageThreshold(); + mAbortPostBootUpdate.set(false); new Thread("BackgroundDexOptService_PostBootUpdate") { @Override @@ -141,6 +158,14 @@ public class BackgroundDexOptService extends JobService { // Rather bail than completely drain the battery. break; } + long usableSpace = dataDir.getUsableSpace(); + if (usableSpace < lowThreshold) { + // Rather bail than completely fill up the disk. + Log.w(TAG, "Aborting background dex opt job due to low storage: " + + usableSpace); + break; + } + if (DEBUG_DEXOPT) { Log.i(TAG, "Updating package " + pkg); } @@ -171,6 +196,9 @@ public class BackgroundDexOptService extends JobService { mExitPostBootUpdate.set(true); mAbortIdleOptimization.set(false); + + final long lowThreshold = getLowStorageThreshold(); + new Thread("BackgroundDexOptService_IdleOptimization") { @Override public void run() { @@ -183,6 +211,15 @@ public class BackgroundDexOptService extends JobService { // Skip previously failing package continue; } + + long usableSpace = dataDir.getUsableSpace(); + if (usableSpace < lowThreshold) { + // Rather bail than completely fill up the disk. + Log.w(TAG, "Aborting background dex opt job due to low storage: " + + usableSpace); + break; + } + // Conservatively add package to the list of failing ones in case performDexOpt // never returns. synchronized (sFailedPackageNames) { @@ -213,6 +250,9 @@ public class BackgroundDexOptService extends JobService { Log.i(TAG, "onStartJob"); } + // NOTE: PackageManagerService.isStorageLow uses a different set of criteria from + // the checks above. This check is not "live" - the value is determined by a background + // restart with a period of ~1 minute. PackageManagerService pm = (PackageManagerService)ServiceManager.getService("package"); if (pm.isStorageLow()) { if (DEBUG_DEXOPT) {