From 287d31f180e81aec77054699c457163bf3e9e8ad Mon Sep 17 00:00:00 2001 From: Jeff Sharkey Date: Mon, 6 Nov 2017 13:54:18 -0700 Subject: [PATCH] Abort long-running benchmarks, report progress. A typical storage device finishes the benchmark in under 10 seconds, but some extremely slow devices can take minutes, resulting in a confusing UX that looks like we've frozen. Even worse, we keep churning through all that I/O even though we know the device will blow past our user-warning threshold. So periodically check if we've timed out, and also use that to report progress up into the Settings UI. Test: manual Bug: 62201209, 65639764, 67055204 Exempt-From-Owner-Approval: I wrote the original code. Change-Id: Idd9d8c181651202d1434af879cff9355478a25c1 --- .../deviceinfo/StorageWizardBase.java | 28 ++++++++++++++---- .../StorageWizardFormatProgress.java | 29 +++++++++++++++---- 2 files changed, 46 insertions(+), 11 deletions(-) diff --git a/src/com/android/settings/deviceinfo/StorageWizardBase.java b/src/com/android/settings/deviceinfo/StorageWizardBase.java index c7bea30fe1f..c2ea2d23b19 100644 --- a/src/com/android/settings/deviceinfo/StorageWizardBase.java +++ b/src/com/android/settings/deviceinfo/StorageWizardBase.java @@ -16,15 +16,19 @@ package com.android.settings.deviceinfo; +import static com.android.settings.deviceinfo.StorageSettings.TAG; + import android.annotation.LayoutRes; import android.app.Activity; import android.graphics.Color; import android.os.Bundle; +import android.os.SystemClock; import android.os.storage.DiskInfo; import android.os.storage.StorageEventListener; import android.os.storage.StorageManager; import android.os.storage.VolumeInfo; import android.text.TextUtils; +import android.util.Log; import android.view.View; import android.view.ViewGroup; import android.view.Window; @@ -202,13 +206,27 @@ public abstract class StorageWizardBase extends Activity { } protected VolumeInfo findFirstVolume(int type) { - final List vols = mStorage.getVolumes(); - for (VolumeInfo vol : vols) { - if (Objects.equals(mDisk.getId(), vol.getDiskId()) && (vol.getType() == type)) { - return vol; + return findFirstVolume(type, 1); + } + + protected VolumeInfo findFirstVolume(int type, int attempts) { + while (true) { + final List vols = mStorage.getVolumes(); + for (VolumeInfo vol : vols) { + if (Objects.equals(mDisk.getId(), vol.getDiskId()) && (vol.getType() == type) + && (vol.getState() == VolumeInfo.STATE_MOUNTED)) { + return vol; + } + } + + if (--attempts > 0) { + Log.w(TAG, "Missing mounted volume of type " + type + " hosted by disk " + + mDisk.getId() + "; trying again"); + SystemClock.sleep(250); + } else { + return null; } } - return null; } private final StorageEventListener mStorageListener = new StorageEventListener() { diff --git a/src/com/android/settings/deviceinfo/StorageWizardFormatProgress.java b/src/com/android/settings/deviceinfo/StorageWizardFormatProgress.java index 59a18665836..3dfc74b6189 100644 --- a/src/com/android/settings/deviceinfo/StorageWizardFormatProgress.java +++ b/src/com/android/settings/deviceinfo/StorageWizardFormatProgress.java @@ -16,15 +16,20 @@ package com.android.settings.deviceinfo; +import static android.os.storage.VolumeInfo.TYPE_PRIVATE; + +import static com.android.settings.deviceinfo.StorageSettings.TAG; + import android.app.AlertDialog; import android.app.Dialog; -import android.app.DialogFragment; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.pm.IPackageMoveObserver; import android.os.AsyncTask; import android.os.Bundle; +import android.os.IVoldTaskListener; +import android.os.PersistableBundle; import android.os.storage.DiskInfo; import android.os.storage.StorageManager; import android.os.storage.VolumeInfo; @@ -38,8 +43,8 @@ import com.android.settings.R; import com.android.settings.core.instrumentation.InstrumentedDialogFragment; import java.util.Objects; - -import static com.android.settings.deviceinfo.StorageSettings.TAG; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.TimeUnit; public class StorageWizardFormatProgress extends StorageWizardBase { private static final String TAG_SLOW_WARNING = "slow_warning"; @@ -99,9 +104,21 @@ public class StorageWizardFormatProgress extends StorageWizardBase { storage.partitionPrivate(activity.mDisk.getId()); publishProgress(40); - final VolumeInfo privateVol = activity.findFirstVolume(VolumeInfo.TYPE_PRIVATE); - mPrivateBench = storage.benchmark(privateVol.getId()); - mPrivateBench /= 1000000; + final VolumeInfo privateVol = activity.findFirstVolume(TYPE_PRIVATE, 5); + final CompletableFuture result = new CompletableFuture<>(); + storage.benchmark(privateVol.getId(), new IVoldTaskListener.Stub() { + @Override + public void onStatus(int status, PersistableBundle extras) { + // Map benchmark 0-100% progress onto 40-80% + publishProgress(40 + ((status * 40) / 100)); + } + + @Override + public void onFinished(int status, PersistableBundle extras) { + result.complete(extras); + } + }); + mPrivateBench = result.get(60, TimeUnit.SECONDS).getLong("run", Long.MAX_VALUE); // If we just adopted the device that had been providing // physical storage, then automatically move storage to the