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

Commit b9f76e10 authored by Zimuzo Ezeozue's avatar Zimuzo Ezeozue Committed by Android (Google) Code Review
Browse files

Merge "Extend AnrController to improve ANR dialog controls" into sc-dev

parents daeb58b5 465e3b71
Loading
Loading
Loading
Loading
+23 −1
Original line number Diff line number Diff line
@@ -23,7 +23,29 @@ package android.app;
public interface AnrController {
    /**
     * Returns the delay in milliseconds for an ANR dialog that is about to be shown for
     * {@code packageName}.
     * {@code packageName} with {@code uid}.
     *
     * Implementations should only return a positive value if they actually expect the
     * {@code packageName} to be delayed due to them.

     * If there are multiple controllers registered, the controller with the max delay will
     * be selected and will receive an {@link #onAnrDelayStarted} callback at the start of the
     * delay and an {@link #onAnrDelayCompleted} at the end of the delay.
     */
    long getAnrDelayMillis(String packageName, int uid);

    /**
     * Notifies the controller at the start of the ANR dialog delay for {@code packageName} with
     * {@code uid}. The controller can decide to show a progress UI after this notification.
     */
    void onAnrDelayStarted(String packageName, int uid);

    /**
     * Notifies the controller at the end of the ANR dialog delay for {@code packageName} with
     * {@code uid}.
     *
     * @return whether the ANR dialog should be shown or cancelled. {@code true} if the
     * ANR dialog should be shown, {@code false} if it should be cancelled.
     */
    boolean onAnrDelayCompleted(String packageName, int uid);
}
+24 −8
Original line number Diff line number Diff line
@@ -51,6 +51,7 @@ import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.app.ActivityManager;
import android.app.ActivityManagerInternal;
import android.app.AnrController;
import android.app.AppOpsManager;
import android.app.IActivityManager;
import android.app.KeyguardManager;
@@ -938,14 +939,29 @@ class StorageManagerService extends IStorageManager.Stub

        if (transcodeEnabled) {
            LocalServices.getService(ActivityManagerInternal.class)
                    .registerAnrController((packageName, uid) -> {
                        try {
                            return mStorageSessionController.getAnrDelayMillis(packageName, uid);
                        } catch (ExternalStorageServiceException e) {
                            Log.e(TAG, "Failed to get ANR delay for " + packageName, e);
                            return 0;
                .registerAnrController(new ExternalStorageServiceAnrController());
        }
                    });
    }

    // 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");
            return delay;
        }

        @Override
        public void onAnrDelayStarted(String packageName, int uid) {
            Log.d(TAG, "onAnrDelayStarted: " + packageName);
        }

        @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;
        }
    }

+21 −1
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@ import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_N

import android.app.ActivityManager;
import android.app.ActivityOptions;
import android.app.AnrController;
import android.app.ApplicationErrorReport;
import android.app.ApplicationExitInfo;
import android.content.ActivityNotFoundException;
@@ -1058,7 +1059,26 @@ class AppErrors {
                    Settings.Secure.ANR_SHOW_BACKGROUND, 0,
                    mService.mUserController.getCurrentUserId()) != 0;
            if (mService.mAtmInternal.canShowErrorDialogs() || showBackground) {
                AnrController anrController = errState.getDialogController().getAnrController();
                if (anrController == null) {
                    errState.getDialogController().showAnrDialogs(data);
                } else {
                    String packageName = proc.info.packageName;
                    int uid = proc.info.uid;
                    boolean showDialog = anrController.onAnrDelayCompleted(packageName, uid);

                    if (showDialog) {
                        Slog.d(TAG, "ANR delay completed. Showing ANR dialog for package: "
                                + packageName);
                        errState.getDialogController().showAnrDialogs(data);
                    } else {
                        Slog.d(TAG, "ANR delay completed. Cancelling ANR dialog for package: "
                                + packageName);
                        errState.setNotResponding(false);
                        errState.setNotRespondingReport(null);
                        errState.getDialogController().clearAnrDialogs();
                    }
                }
            } else {
                MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_APP_ANR,
                        AppNotRespondingDialog.CANT_SHOW);
+21 −0
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@

package com.android.server.am;

import android.annotation.Nullable;
import android.app.AnrController;
import android.app.Dialog;
import android.content.Context;

@@ -57,6 +59,13 @@ final class ErrorDialogController {
    @GuardedBy("mProcLock")
    private AppWaitingForDebuggerDialog mWaitDialog;

    /**
     * ANR dialog controller
     */
    @GuardedBy("mProcLock")
    @Nullable
    private AnrController mAnrController;

    @GuardedBy("mProcLock")
    boolean hasCrashDialogs() {
        return mCrashDialogs != null;
@@ -118,6 +127,7 @@ final class ErrorDialogController {
        }
        forAllDialogs(mAnrDialogs, Dialog::dismiss);
        mAnrDialogs = null;
        mAnrController = null;
    }

    @GuardedBy("mProcLock")
@@ -220,6 +230,17 @@ final class ErrorDialogController {
        });
    }

    @GuardedBy("mProcLock")
    @Nullable
    AnrController getAnrController() {
        return mAnrController;
    }

    @GuardedBy("mProcLock")
    void setAnrController(AnrController controller) {
        mAnrController = controller;
    }

    /**
     * Helper function to collect contexts from crashed app located displays.
     *
+12 −4
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ import static com.android.server.am.ActivityManagerService.MY_PID;
import static com.android.server.am.ProcessRecord.TAG;

import android.app.ActivityManager;
import android.app.AnrController;
import android.app.ApplicationErrorReport;
import android.app.ApplicationExitInfo;
import android.content.ComponentName;
@@ -418,10 +419,16 @@ class ProcessErrorStateRecord {

        // Retrieve max ANR delay from AnrControllers without the mService lock since the
        // controllers might in turn call into apps
        long anrDialogDelayMs = mService.mActivityTaskManager.getMaxAnrDelayMillis(aInfo);
        if (aInfo != null && aInfo.packageName != null && anrDialogDelayMs > 0) {
            Slog.i(TAG, "Delaying ANR dialog for " + aInfo.packageName + " for " + anrDialogDelayMs
                    + "ms");
        AnrController anrController = mService.mActivityTaskManager.getAnrController(aInfo);
        long anrDialogDelayMs = 0;
        if (anrController != null) {
            String packageName = aInfo.packageName;
            int uid = aInfo.uid;
            anrDialogDelayMs = anrController.getAnrDelayMillis(packageName, uid);
            // Might execute an async binder call to a system app to show an interim
            // ANR progress UI
            anrController.onAnrDelayStarted(packageName, uid);
            Slog.i(TAG, "ANR delay of " + anrDialogDelayMs + "ms started for " + packageName);
        }

        synchronized (mService) {
@@ -440,6 +447,7 @@ class ProcessErrorStateRecord {
                // Set the app's notResponding state, and look up the errorReportReceiver
                makeAppNotRespondingLSP(activityShortComponentName,
                        annotation != null ? "ANR " + annotation : "ANR", info.toString());
                mDialogController.setAnrController(anrController);
            }

            // Notify package manager service to possibly update package state
Loading