ANR рдХреЗ рдХрд╛рд░рдг рдФрд░ рдЗрд╕рд╕реЗ рдХреИрд╕реЗ рдмрдЪреЗрдВ

ANR (рдПрдкреНрд▓рд┐рдХреЗрд╢рди рд░рд┐рд╕реНрдкреЙрдиреНрд╕рд┐рдВрдЧ рдирд╣реАрдВ) - рдПрдХ рддреНрд░реБрдЯрд┐ рдЬреЛ рддрдм рд╣реЛрддреА рд╣реИ рдЬрдм рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИред рдкрд░рд┐рдгрд╛рдорд╕реНрд╡рд░реВрдк, рдПрдХ рд╕рдВрд╡рд╛рдж рдмреЙрдХреНрд╕ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЛ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЛ рдкреНрд░рддреАрдХреНрд╖рд╛ рдХрд░рдиреЗ рдпрд╛ рдмрдВрдж рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдкреНрд░реЗрд░рд┐рдд рдХрд░рддрд╛ рд╣реИред
рдЫрд╡рд┐ рдКрдВрдЪрд╛рдИ

ANR рдХреА рд╕реНрдерд┐рддрд┐


  • рдЗрдирдкреБрдЯ рдЗрд╡реЗрдВрдЯ (рдмрдЯрди рдФрд░ рдЯрдЪ рдЗрд╡реЗрдВрдЯ) 5 рд╕реЗрдХрдВрдб рдХреЗ рд▓рд┐рдП рд╕рдВрд╕рд╛рдзрд┐рдд рдирд╣реАрдВ рд╣реЛрддреЗ рд╣реИрдВ;
  • рдмреНрд░реЙрдбрдХрд╛рд╕реНрдЯрд╕реАрд╡рд░ (onRecieve ()) рдирд┐рд░реНрджрд┐рд╖реНрдЯ рд╕рдордп рдХреЗ рднреАрддрд░ рд╕рдВрд╕рд╛рдзрд┐рдд рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ (рдЕрдЧреНрд░рднреВрдорд┐ - 10 рдПрд╕, рдкреГрд╖реНрдарднреВрдорд┐ - 60 рдПрд╕);
  • ContentProvider 10 рд╕реЗрдХрдВрдб рдХреЗ рднреАрддрд░ рдкреВрд░рд╛ рдирд╣реАрдВ рд╣реБрдЖред

рдЖрдорддреМрд░ рдкрд░ рдореБрдЦреНрдп рдзрд╛рдЧрд╛ рдЕрд╡рд░реБрджреНрдз рд╣реЛрддрд╛ рд╣реИред

рдпрджрд┐ рдЖрдк рдореЗрд░реЗ рд▓реЗрдЦ рдкрдврд╝рддреЗ рд╣реИрдВ, рддреЛ рдЖрдк рд╢рд╛рдпрдж рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдЗрд╕ рддрдереНрдп рдХреЗ рдЕрднреНрдпрд╕реНрдд рд╣реИрдВ рдХрд┐ рд╣рдо рд╕реНрд░реЛрдд рдХреЛрдб рдореЗрдВ рдХреНрд░реЙрд▓ рдХрд░рддреЗ рд╣реИрдВред рддреЛ рдЖрдЗрдП рджреЗрдЦреЗрдВ рдХрд┐ рд╣реБрдб рдХреЗ рдиреАрдЪреЗ рдПрдПрдирдЖрд░ рдХреИрд╕рд╛ рджрд┐рдЦрддрд╛ рд╣реИ ред

AppErrors рд╡рд░реНрдЧ рди рдХреЗрд╡рд▓ рдПрдПрдирдЖрд░, рдмрд▓реНрдХрд┐ рдЕрдиреНрдп рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреЛ рднреА рд╕рдВрднрд╛рд▓рддрд╛ рд╣реИ рдЬреЛ рджреБрд░реНрдШрдЯрдирд╛ рд╕рд╣рд┐рдд рдЖрд╡реЗрджрди рдореЗрдВ рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВред HandleShowAnrUi () рд╡рд┐рдзрд┐ рдХрдИ рдбреЗрд╡рд▓рдкрд░реНрд╕ рдФрд░ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛рдУрдВ рдХреЗ рд▓рд┐рдП рдпрд╣ рдбрд░рд╛рд╡рдирд╛ рд╡рд┐рдВрдбреЛ рдЦреЛрд▓рддрд╛ рд╣реИ рдЬреЛ ANR рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рддрд╛ рд╣реИред

class AppErrors { ... void handleShowAnrUi(Message msg) { Dialog dialogToShow = null; synchronized (mService) { AppNotRespondingDialog.Data data = (AppNotRespondingDialog.Data) msg.obj; final ProcessRecord proc = data.proc; if (proc == null) { Slog.e(TAG, "handleShowAnrUi: proc is null"); return; } if (proc.anrDialog != null) { Slog.e(TAG, "App already has anr dialog: " + proc); MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_APP_ANR, AppNotRespondingDialog.ALREADY_SHOWING); return; } 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(); } } ... 

рд╣рд╛рд▓рд╛рдВрдХрд┐, рдПрдПрдирдЖрд░ рдпрд╣рд╛рдВ рд╢реБрд░реВ рдирд╣реАрдВ рд╣реЛрддрд╛ рд╣реИред рдЬреИрд╕рд╛ рдХрд┐ рдореИрдВрдиреЗ рдКрдкрд░ рдХрд╣рд╛, рдЗрд╕ рддреНрд░реБрдЯрд┐ рдХреЗ рдкрд╣рд▓реЗ рдХрд╛рд░рдгреЛрдВ рдореЗрдВ рд╕реЗ рдПрдХ рдЗрдирдкреБрдЯ рдЗрд╡реЗрдВрдЯ рдХреА рджреЗрд░реА рд╣реИ, рдЬреЛ 5 рд╕реЗрдХрдВрдб рд╣реИред рдПрдХ рдЫреЛрдЯреА рдЦреЛрдЬ рд╕реЗ рд╣рдо рдпрд╣ рдкрддрд╛ рд▓рдЧрд╛ рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ рдпрд╣ рдорд╛рди рдХрд╣рд╛рдБ рд╕реЗрдЯ рд╣реИред

 namespace android { // Default input dispatching timeout if there is no focused application or paused window // from which to determine an appropriate dispatching timeout. const nsecs_t DEFAULT_INPUT_DISPATCHING_TIMEOUT = 5000 * 1000000LL; // 5 sec 

рдЕрдм рд╣рдо рдЙрд╕ рдХреЛрдб рдХреЛ рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ рдЬрд╣рд╛рдВ рдореВрд▓ рднрд╛рдЧ рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИред рдпрд╣ рд╡рд░реНрдЧ InputManagerService рдореЗрдВ рд╣реЛрддрд╛ рд╣реИред

  // Native callback. private long notifyANR(InputApplicationHandle inputApplicationHandle, InputWindowHandle inputWindowHandle, String reason) { return mWindowManagerCallbacks.notifyANR( inputApplicationHandle, inputWindowHandle, reason); } 

рдФрд░ рдпрд╣рд╛рдБ рдЗрдирдкреБрдЯрдореЙрдирд┐рдЯрд░ рдореЗрдВ mWindowManagerCallbacks рд╣реИ :

  if (appWindowToken != null && appWindowToken.appToken != null) { // Notify the activity manager about the timeout and let it decide whether // to abort dispatching or keep waiting. final AppWindowContainerController controller = appWindowToken.getController(); final boolean abort = controller != null && controller.keyDispatchingTimedOut(reason, (windowState != null) ? windowState.mSession.mPid : -1); if (!abort) { // The activity manager declined to abort dispatching. // Wait a bit longer and timeout again later. return appWindowToken.mInputDispatchingTimeoutNanos; } } else if (windowState != null) { try { // Notify the activity manager about the timeout and let it decide whether // to abort dispatching or keep waiting. long timeout = ActivityManager.getService().inputDispatchingTimedOut( windowState.mSession.mPid, aboveSystem, reason); if (timeout >= 0) { // The activity manager declined to abort dispatching. // Wait a bit longer and timeout again later. return timeout * 1000000L; // nanoseconds } } catch (RemoteException ex) { } } return 0; // abort dispatching } 

рдЪрд▓реЛ inputDispatchingTimedOut () рдкрд░ рдХрд░реАрдм рд╕реЗ рдирдЬрд╝рд░ рдбрд╛рд▓реЗрдВред рдпрд╣рд╛рдВ рд╣рдо рдХреЗрд╡рд▓ рдЯрд╛рдЗрдордЖрдЙрдЯ рдХреА рд╕рдорд╛рдкреНрддрд┐ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдПрдХреНрдЯрд┐рд╡рд┐рдЯреА рдореИрдиреЗрдЬрд░ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рд╕рдВрджреЗрд╢ рджрд┐рдЦрд╛рддреЗ рд╣реИрдВ рдФрд░ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЛ рдпрд╣ рдирд┐рд░реНрдгрдп рд▓реЗрдиреЗ рджреЗрддреЗ рд╣реИрдВ рдХрд┐ рдХреНрдпрд╛ рдХрд╛рд░реНрд░рд╡рд╛рдИ рдХреЛ рд░рджреНрдж рдХрд░рдирд╛ рд╣реИ рдпрд╛ рдкреНрд░рддреАрдХреНрд╖рд╛ рдХрд░рдирд╛ рдЬрд╛рд░реА рд░рдЦрдирд╛ рд╣реИред рдФрд░ рдпрд╣ ActivManagerService рдореЗрдВ рд╣реИ рдХрд┐ AppErrors рдХреЛ рдХреНрд░реИрд╢ рдпрд╛ ANR рдХреЗ рдорд╛рдорд▓реЗ рдореЗрдВ рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИред

  private boolean makeAppCrashingLocked(ProcessRecord app, String shortMsg, String longMsg, String stackTrace) { app.crashing = true; app.crashingReport = generateProcessError(app, ActivityManager.ProcessErrorStateInfo.CRASHED, null, shortMsg, longMsg, stackTrace); startAppProblemLocked(app); app.stopFreezingAllLocked(); return handleAppCrashLocked(app, shortMsg, longMsg, stackTrace); } private void makeAppNotRespondingLocked(ProcessRecord app, String activity, String shortMsg, String longMsg) { app.notResponding = true; app.notRespondingReport = generateProcessError(app, ActivityManager.ProcessErrorStateInfo.NOT_RESPONDING, activity, shortMsg, longMsg, null); startAppProblemLocked(app); app.stopFreezingAllLocked(); } 

ANR рдХреЗ рдореБрдЦреНрдп рдХрд╛рд░рдг


  • рдЗрдирдкреБрдЯ / рдЖрдЙрдЯрдкреБрдЯ рд▓реЙрдХ
  • рдиреЗрдЯрд╡рд░реНрдХ рдХреА рднреАрдбрд╝
  • рдзрд╛рдЧрд╛ рдЕрд╡рд░реБрджреНрдз
  • рдЕрдВрддрд╣реАрди рдкрд╛рд╢
  • рд╡реНрдпрд╛рдкрд╛рд░ рддрд░реНрдХ рдмрд╣реБрдд рд▓рдВрдмрд╛ рд▓рдЧрддрд╛ рд╣реИ

рдПрдПрдирдЖрд░ рд╕реЗ рдмрдЪрдирд╛


  • рдореБрдЦреНрдп рдпреВрдЬрд░ рдЗрдВрдЯрд░рдлреЗрд╕ рдереНрд░реЗрдб рдХреЗрд╡рд▓ рдпреВрдЬрд░ рдЗрдВрдЯрд░рдлреЗрд╕ рдХреЗ рд╕рд╛рде рдЬреБрдбрд╝реЗ рддрд░реНрдХ рдХреЛ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░рддрд╛ рд╣реИ;
  • рдЬрдЯрд┐рд▓ рдЧрдгрдирд╛ (рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдбреЗрдЯрд╛рдмреЗрд╕ рд╕рдВрдЪрд╛рд▓рди, рдЗрдирдкреБрдЯ-рдЖрдЙрдЯрдкреБрдЯ рд╕рдВрдЪрд╛рд▓рди, рдиреЗрдЯрд╡рд░реНрдХ рд╕рдВрдЪрд╛рд▓рди, рдЖрджрд┐) рдПрдХ рдЕрд▓рдЧ рд╕реНрдЯреНрд░реАрдо рдореЗрдВ рдХрд┐рдП рдЬрд╛рддреЗ рд╣реИрдВ;
  • рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдереНрд░реЗрдб рдФрд░ рд╡рд░реНрдХрдлрд╝реНрд▓реЛ рдХреЗ рдмреАрдЪ рдмрд╛рддрдЪреАрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╣реИрдВрдбрд▓рд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВ;
  • RxJava рдЖрджрд┐ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВред рдЕрддреБрд▓реНрдпрдХрд╛рд▓рд┐рдХ рд╕рдВрдЪрд╛рд▓рди рдХреЛ рд╕рдВрднрд╛рд▓рдиреЗ рдХреЗ рд▓рд┐рдПред

рдПрдПрдирдЖрд░ рдХреИрд╕реЗ рдкрдХрдбрд╝реЗрдВ


  • ANR рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЬрд╛рдирдХрд╛рд░реА рдлрд╝рд╛рдЗрд▓ /data/anr/traces.txt, рдпрд╛ рдПрдХ рдЕрд▓рдЧ рдкрде / рдбреЗрдЯрд╛ / anr / ar_ * рдореЗрдВ рд╕рдВрдЧреНрд░рд╣реАрдд рдХреА рдЬрд╛ рд╕рдХрддреА рд╣реИред рдЖрдк рдЗрд╕реЗ рдирд┐рдореНрди рдЖрджреЗрд╢реЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдкреНрд░рд╛рдкреНрдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:

     adb root adb shell ls /data/anr adb pull /data/anr/<filename> 
  • ANR рдХрд╛ рдкрддрд╛ рд▓рдЧрд╛рдиреЗ рдХреЗ рд▓рд┐рдП ANR-WatchDog рдУрдкрди рд╕реЛрд░реНрд╕ рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВ
  • рдПрдПрдирдЖрд░ рд╕реЗ рдмрдЪреЗрдВ рджреЗрдЦреЗрдВ :)

PS рдореИрдВ рдЯреЗрд▓реАрдЧреНрд░рд╛рдо рдЪреИрдирд▓ @paradisecurity рдореЗрдВ рд╕рднреА рдЪрдпрди рдкреНрд░рдХрд╛рд╢рд┐рдд рдХрд░рддрд╛ рд╣реВрдВред

Source: https://habr.com/ru/post/hi439086/


All Articles