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

Commit 1985e314 authored by Zim's avatar Zim
Browse files

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
parent 055878b4
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -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<String> getPrimaryVolumeIds();
}
+53 −7
Original line number Diff line number Diff line
@@ -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<String> getPrimaryVolumeIds() {
            final List<String> 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;
        }
    }
}
+9 −3
Original line number Diff line number Diff line
@@ -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<String, Session> mSessions = new HashMap<>();
    @GuardedBy("mLock") private final Set<Integer> 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<String> primarySessionIds = mSmInternal.getPrimaryVolumeIds();
        synchronized (mSessionsLock) {
            for (String sessionId : mSessions.keySet()) {
                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);
    }

    /**