IndexOutOfBoundsException внутри setStoppedState WindowManagerGlobal - PullRequest
2 голосов
/ 30 мая 2020

Самый популярный sh в нашем приложении происходит только для Android 9 и только для нескольких устройств, таких как ZTE, TCL, Hisense, BLU, HYUNDAI.

Поскольку у нас нет доступа ни к одному из этих устройств, мы не смогли воспроизвести это, и поскольку это происходит внутри структуры Android, мы не уверены, что это ошибка в нашем коде ( хотя это должно быть, так как мы не смогли найти подобных сбоев в Stackoverflow).

Fatal Exception: java.lang.RuntimeException: Unable to stop activity {MyActivity}: java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
       at android.app.ActivityThread.callActivityOnStop(ActivityThread.java:4213)
       at android.app.ActivityThread.performStopActivityInner(ActivityThread.java:4183)
       at android.app.ActivityThread.handleStopActivity(ActivityThread.java:4263)
       at android.app.servertransaction.TransactionExecutor.performLifecycleSequence(TransactionExecutor.java:192)
       at android.app.servertransaction.TransactionExecutor.cycleToPath(TransactionExecutor.java:165)
       at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:142)
       at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:70)
       at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1816)
       at android.os.Handler.dispatchMessage(Handler.java:106)
       at android.os.Looper.loop(Looper.java:193)
       at android.app.ActivityThread.main(ActivityThread.java:6852)
       at java.lang.reflect.Method.invoke(Method.java)
       at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:504)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
Caused by java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
       at java.util.ArrayList.get(ArrayList.java:437)
       at android.view.WindowManagerGlobal.setStoppedState(WindowManagerGlobal.java:604)
       at android.app.Activity.performStop(Activity.java:8831)
       at android.app.ActivityThread.callActivityOnStop(ActivityThread.java:4205)
       at android.app.ActivityThread.performStopActivityInner(ActivityThread.java:4183)
       at android.app.ActivityThread.handleStopActivity(ActivityThread.java:4263)
       at android.app.servertransaction.TransactionExecutor.performLifecycleSequence(TransactionExecutor.java:192)
       at android.app.servertransaction.TransactionExecutor.cycleToPath(TransactionExecutor.java:165)
       at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:142)
       at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:70)
       at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1816)
       at android.os.Handler.dispatchMessage(Handler.java:106)
       at android.os.Looper.loop(Looper.java:193)
       at android.app.ActivityThread.main(ActivityThread.java:6852)
       at java.lang.reflect.Method.invoke(Method.java)
       at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:504)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)

Кто-нибудь сталкивался с подобным sh или имеет какое-либо представление о том, что вызывает root может быть?

1 Ответ

1 голос
/ 07 июня 2020

Здесь код, в котором происходит ошибка sh :

public void setStoppedState(IBinder token, boolean stopped) {
    synchronized (mLock) {
        int count = mViews.size();
        for (int i = 0; i < count; i++) {
            if (token == null || mParams.get(i).token == token) {
                ViewRootImpl root = mRoots.get(i);
                root.setWindowStopped(stopped);
            }
        }
    }
}

(номера строк не соответствуют точно вашей информации об исключении, потому что я не знал точного версия кода, используемого вашим устройством.)

Предполагая, что мы можем ожидать, что mViews, mParams и mRoots будут иметь одинаковую длину, этот код выглядит правильно.

Однако, если мы немного продвинемся вперед в истории git, мы обнаружим commit 978e7f87 :

From: tetsutoki.shiozawa@sony.com
Subject: Fix: WindowManagerGlobal#setStoppedState failed by IOOBE

Symptom:
An application crashed due to IndexOutOfBoundsException.
The exception was thrown at WindowManagerGlobal#setStoppedState.

Root cause:
setStoppedState invokes setWindowStopped for each ViewRoot by
ascending order. If an application removes its view within the
loop, loop index exceeds the number of items.

Solution:
Loop in descending order.

Я бы предположил, что устройства, на которых вы видите трещину sh не включают эту фиксацию, в то время как устройства без проблем c включают.

Новый код выглядит следующим образом:

public void setStoppedState(IBinder token, boolean stopped) {
    synchronized (mLock) {
        int count = mViews.size();
        for (int i = count - 1; i >= 0; i--) {
            if (token == null || mParams.get(i).token == token) {
                ViewRootImpl root = mRoots.get(i);
                // Client might remove the view by "stopped" event.
                root.setWindowStopped(stopped);
            }
        }
    }
}

Поскольку вы не можете повлиять на рассматриваемые устройства , вам нужно будет решить эту проблему. Сообщение о фиксации указывает нам четкое направление: убедитесь, что вы не удаляете представления в обратных вызовах, которые здесь происходят.

...