Android performance optimization -ANR causes and solutions

1, the emergence of the situation ANR

Satisfies the following case the system will prompt the pop ANR

Input events (key and touch events) has not been processed within the 5S;
BroadcastReceiver events (onRecieve () method) within the specified time not processed (foreground broadcast for the 10s, backstage broadcast for the 60s);
Service foreground 20s background 200s did not complete the boot ;
the ContentProvider the publish () not be completed within 10s.
Under normal circumstances that caused the main thread is blocked.

2. The principle of ANR

No response to input of an example process (based on 9.0 code):

ANR final pop-up dialog box position and handleShowAnrUi class AppErrors of AMS same directory () method. This class is used to handle a variety of error occurred in the program, not only the ANR, this class also forced Crash process.

 

    // base/core/java/com/android/server/am/AppErrors.java
    void handleShowAnrUi(Message msg) {
        Dialog dialogToShow = null;
        synchronized (mService) {
            AppNotRespondingDialog.Data data = (AppNotRespondingDialog.Data) msg.obj;
            // ...

            Intent intent = new Intent("android.intent.action.ANR");
            if (!mService.mProcessesReady) {
                intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
                        | Intent.FLAG_RECEIVER_FOREGROUND);
            }
            mService.broadcastIntentLocked(null, null, intent,
                    null, null, 0, null, null, null, AppOpsManager.OP_NONE,
                    null, false, false, MY_PID, Process.SYSTEM_UID, 0 /* TODO: Verify */);

            boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
                    Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
            if (mService.canShowErrorDialogs() || showBackground) {
                dialogToShow = new AppNotRespondingDialog(mService, mContext, data);
                proc.anrDialog = dialogToShow;
            } else {
                MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_APP_ANR,
                        AppNotRespondingDialog.CANT_SHOW);
                // Just kill the app if there is no dialog to be shown.
                mService.killAppAtUsersRequest(proc, null);
            }
        }
        // If we've created a crash dialog, show it without the lock held
        if (dialogToShow != null) {
            dialogToShow.show();
        }
    }

However, calls from the place of occurrence to ANR here to go through a lot of classes and methods. ANR is initially thrown in InputDispatcher.cpp in. We can define constants to find the location where the initial trigger:

 

// native/services/inputflinger/InputDispatcher.cpp
constexpr nsecs_t DEFAULT_INPUT_DISPATCHING_TIMEOUT = 5000 * 1000000LL; // 5 sec

From the position of this class will be triggered passed through layers of reach InputManagerService

 

// base/services/core/java/com/android/server/input/InputManagerService.java
private long notifyANR(InputApplicationHandle inputApplicationHandle,
        InputWindowHandle inputWindowHandle, String reason) {
    return mWindowManagerCallbacks.notifyANR(
            inputApplicationHandle, inputWindowHandle, reason);
}

mWindowManagerCallbacks here is InputMonitor:

 

// base/services/core/java/com/android/server/wm/InputMonitor.java
public long notifyANR(InputApplicationHandle inputApplicationHandle,
        InputWindowHandle inputWindowHandle, String reason) {
    // ... 略

    if (appWindowToken != null && appWindowToken.appToken != null) {
        final AppWindowContainerController controller = appWindowToken.getController();
        final boolean abort = controller != null
                && controller.keyDispatchingTimedOut(reason,
                        (windowState != null) ? windowState.mSession.mPid : -1);
        if (!abort) {
            return appWindowToken.mInputDispatchingTimeoutNanos;
        }
    } else if (windowState != null) {
        try {
            // 使用 AMS 的方法
            long timeout = ActivityManager.getService().inputDispatchingTimedOut(
                    windowState.mSession.mPid, aboveSystem, reason);
            if (timeout >= 0) {
                return timeout * 1000000L; // nanoseconds
            }
        } catch (RemoteException ex) {
        }
    }
    return 0; // abort dispatching
}

In the above method is called and then back to the AMS inputDispatchingTimedOut () method continues to process and eventually inputDispatchingTimedOut () method will be passed to the event AppErrors

 

// base/services/core/java/com/android/server/am/ActivityManagerService.java
public boolean inputDispatchingTimedOut(final ProcessRecord proc,
        final ActivityRecord activity, final ActivityRecord parent,
        final boolean aboveSystem, String reason) {
    // ...

    if (proc != null) {
        synchronized (this) {
            if (proc.debugging) {
                return false;
            }

            if (proc.instr != null) {
                Bundle info = new Bundle();
                info.putString("shortMsg", "keyDispatchingTimedOut");
                info.putString("longMsg", annotation);
                finishInstrumentationLocked(proc, Activity.RESULT_CANCELED, info);
                return true;
            }
        }
        mHandler.post(new Runnable() {
            @Override
            public void run() {
                // 使用 AppErrors 继续处理
                mAppErrors.appNotResponding(proc, activity, parent, aboveSystem, annotation);
            }
        });
    }

    return true;
}

When events are passed to the AppErrors, it will help Handler will process the message calls the original method and the pop-up dialog box.

Reference: "Android ANR principle of analysis"

3, ANR solution

Analysis of the causes and principles of ANR above, let's analyze at how to solve the ANR.

1. Use adb export ANR log and analyze

ANR system occurs when the information recording and ANR /data/anr/traces.txt file stored in the (relatively new in the system is stored in both / data / anr / anr_ * file). We can use the following ways to export it to your computer in order to reason ANR generated for analysis:

 

adb root
adb shell ls /data/anr
adb pull /data/anr/<filename>

When I ANR analysis when using the command ANR try to export logs have emerged Permission Denied. After this time, you can export the phone after Root, or try to modify the permissions to read and write files, or choose to export the logs to the sdcard in developer mode from sdcard and then send the logs to the computer terminal for viewing

2. Use traceview DDMS analysis

DDMS open in the AS, or to use the SDK installation directory monitor.bat open DDMS tools directory below.

Use TraceView tools can refer to the article: "Android performance TraceView analysis of the use (application time-consuming analysis)"

This positioning ANR idea is: use the location information to locate TraceView time-consuming method called time-consuming operation.

data:

3. Use open source project ANR-WatchDog detects ANR

Project address is  Github-ANR-WatchDog

The principle of the project: to create a detection thread that continue to UI thread post a task, then sleep a fixed time, such as before and again after the thread up the task of detecting whether or not to run the post, assuming that the task is not running, generating ANRError, and terminate the process.

4. Common ANR scene

I / O blocking
network congestion
multithreading deadlock
due to the method results in a reactive programming cycle to die
due to a business logic execution time is too long

5. The method of avoiding ANR


UI thread only as far as possible the work associated with the UI;
time-consuming work (such as database operations, I / O, network operations, etc.), using a separate worker thread processing;
with Handler to handle interactive UI thread and the worker threads;
use RxJava and other asynchronous messages to process.
In short, a principle is: not in the main thread to do time-consuming operation.

Published 56 original articles · won praise 1 · views 2913

Guess you like

Origin blog.csdn.net/chuhe1989/article/details/104564521