From 1985e314e27987d8adb4a70f8895442aa34a96c5 Mon Sep 17 00:00:00 2001 From: Zim Date: Tue, 2 Mar 2021 09:30:41 +0000 Subject: [PATCH] Implement ANR delay with app IO blocked reason The ExternalStorageService now notifies the system_server of app IO blocked reasons, specifically transcoding. If an ANR occurs, we query these reasons for the uid to modify the ANR dialog behavior Bug: 170486601 Test: Manual Change-Id: I86f800c4a6c565a7bced0f2a5c5da7ba6c048168 --- .../os/storage/StorageManagerInternal.java | 7 +++ .../android/server/StorageManagerService.java | 60 ++++++++++++++++--- .../server/storage/StorageUserConnection.java | 12 +++- 3 files changed, 69 insertions(+), 10 deletions(-) diff --git a/core/java/android/os/storage/StorageManagerInternal.java b/core/java/android/os/storage/StorageManagerInternal.java index b12bb2ece4c2f..396ba2d3cea51 100644 --- a/core/java/android/os/storage/StorageManagerInternal.java +++ b/core/java/android/os/storage/StorageManagerInternal.java @@ -20,6 +20,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.os.IVold; +import java.util.List; import java.util.Set; /** @@ -112,4 +113,10 @@ public abstract class StorageManagerInternal { * @param bytes number of bytes which need to be freed */ public abstract void freeCache(@Nullable String volumeUuid, long bytes); + + /** + * Returns the {@link VolumeInfo#getId()} values for the volumes matching + * {@link VolumeInfo#isPrimary()} + */ + public abstract List getPrimaryVolumeIds(); } diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java index 233a50d417ad1..5486ca67dd97f 100644 --- a/services/core/java/com/android/server/StorageManagerService.java +++ b/services/core/java/com/android/server/StorageManagerService.java @@ -573,6 +573,12 @@ class StorageManagerService extends IStorageManager.Stub */ private static final int PBKDF2_HASH_ROUNDS = 1024; + private static final String ANR_DELAY_MILLIS_DEVICE_CONFIG_KEY = + "anr_delay_millis"; + + private static final String ANR_DELAY_NOTIFY_EXTERNAL_STORAGE_SERVICE_DEVICE_CONFIG_KEY = + "anr_delay_notify_external_storage_service"; + /** * Mounted OBB tracking information. Used to track the current state of all * OBBs. @@ -943,25 +949,51 @@ class StorageManagerService extends IStorageManager.Stub } } - // TODO(b/170486601): Check transcoding status based on events pushed from the MediaProvider private class ExternalStorageServiceAnrController implements AnrController { @Override public long getAnrDelayMillis(String packageName, int uid) { - int delay = SystemProperties.getInt("sys.fuse.transcode_anr_delay", 0); - Log.d(TAG, "getAnrDelayMillis: " + packageName + ". Delaying for " + delay + "ms"); + if (!isAppIoBlocked(uid)) { + return 0; + } + + int delay = DeviceConfig.getInt(DeviceConfig.NAMESPACE_STORAGE_NATIVE_BOOT, + ANR_DELAY_MILLIS_DEVICE_CONFIG_KEY, 0); + Slog.v(TAG, "getAnrDelayMillis for " + packageName + ". " + delay + "ms"); return delay; } @Override public void onAnrDelayStarted(String packageName, int uid) { - Log.d(TAG, "onAnrDelayStarted: " + packageName); + if (!isAppIoBlocked(uid)) { + return; + } + + boolean notifyExternalStorageService = DeviceConfig.getBoolean( + DeviceConfig.NAMESPACE_STORAGE_NATIVE_BOOT, + ANR_DELAY_NOTIFY_EXTERNAL_STORAGE_SERVICE_DEVICE_CONFIG_KEY, true); + if (notifyExternalStorageService) { + Slog.d(TAG, "onAnrDelayStarted for " + packageName + + ". Notifying external storage service"); + try { + mStorageSessionController.notifyAnrDelayStarted(packageName, uid, 0 /* tid */, + StorageManager.APP_IO_BLOCKED_REASON_TRANSCODING); + } catch (ExternalStorageServiceException e) { + Slog.e(TAG, "Failed to notify ANR delay started for " + packageName, e); + } + } else { + // TODO(b/170973510): Implement framework spinning dialog for ANR delay + } } @Override public boolean onAnrDelayCompleted(String packageName, int uid) { - boolean show = SystemProperties.getBoolean("sys.fuse.transcode_anr_dialog_show", true); - Log.d(TAG, "onAnrDelayCompleted: " + packageName + ". Show: " + show); - return show; + if (isAppIoBlocked(uid)) { + Slog.d(TAG, "onAnrDelayCompleted for " + packageName + ". Showing ANR dialog..."); + return true; + } else { + Slog.d(TAG, "onAnrDelayCompleted for " + packageName + ". Skipping ANR dialog..."); + return false; + } } } @@ -4637,5 +4669,19 @@ class StorageManagerService extends IStorageManager.Stub Binder.restoreCallingIdentity(token); } } + + @Override + public List getPrimaryVolumeIds() { + final List primaryVolumeIds = new ArrayList<>(); + synchronized (mLock) { + for (int i = 0; i < mVolumes.size(); i++) { + final VolumeInfo vol = mVolumes.valueAt(i); + if (vol.isPrimary()) { + primaryVolumeIds.add(vol.getId()); + } + } + } + return primaryVolumeIds; + } } } diff --git a/services/core/java/com/android/server/storage/StorageUserConnection.java b/services/core/java/com/android/server/storage/StorageUserConnection.java index d2b05c0914d7e..797f0f2e677be 100644 --- a/services/core/java/com/android/server/storage/StorageUserConnection.java +++ b/services/core/java/com/android/server/storage/StorageUserConnection.java @@ -53,6 +53,7 @@ import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; +import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Set; @@ -72,6 +73,7 @@ public final class StorageUserConnection { private final Context mContext; private final int mUserId; private final StorageSessionController mSessionController; + private final StorageManagerInternal mSmInternal; private final ActiveConnection mActiveConnection = new ActiveConnection(); @GuardedBy("mLock") private final Map mSessions = new HashMap<>(); @GuardedBy("mLock") private final Set mUidsBlockedOnIo = new ArraySet<>(); @@ -81,6 +83,7 @@ public final class StorageUserConnection { mContext = Objects.requireNonNull(context); mUserId = Preconditions.checkArgumentNonnegative(userId); mSessionController = controller; + mSmInternal = LocalServices.getService(StorageManagerInternal.class); mHandlerThread = new HandlerThread("StorageUserConnectionThread-" + mUserId); mHandlerThread.start(); } @@ -152,9 +155,13 @@ public final class StorageUserConnection { */ public void notifyAnrDelayStarted(String packageName, int uid, int tid, int reason) throws ExternalStorageServiceException { + List primarySessionIds = mSmInternal.getPrimaryVolumeIds(); synchronized (mSessionsLock) { for (String sessionId : mSessions.keySet()) { - mActiveConnection.notifyAnrDelayStarted(packageName, uid, tid, reason); + if (primarySessionIds.contains(sessionId)) { + mActiveConnection.notifyAnrDelayStarted(packageName, uid, tid, reason); + return; + } } } } @@ -201,8 +208,7 @@ public final class StorageUserConnection { return; } } - StorageManagerInternal sm = LocalServices.getService(StorageManagerInternal.class); - sm.resetUser(mUserId); + mSmInternal.resetUser(mUserId); } /**