Здесь код, в котором происходит ошибка 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);
}
}
}
}
Поскольку вы не можете повлиять на рассматриваемые устройства , вам нужно будет решить эту проблему. Сообщение о фиксации указывает нам четкое направление: убедитесь, что вы не удаляете представления в обратных вызовах, которые здесь происходят.