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:
- "ANR official documents."
- "TraceView Android performance analysis of the use (application of time-consuming analysis)"
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.