Fix java.lang.ArrayIndexOutOfBoundsException at ArraySet in GenericWindowPolicyController.onRunningAppsChanged()
- Before iterating over mRunningAppsChangedListener, we need to confirm whether there is a listener in mRunningAppsChangedListener to avoid ArrayIndexOutOfBoundsException. - Use mGenericWindowPolicyControllerLock to protect mRunningAppsChangedListener access. Bug: 248192490 Test: Manual Change-Id: Iedd031f50659f027576086788392110a3432858a
This commit is contained in:
@@ -44,6 +44,7 @@ import android.view.Display;
|
||||
import android.window.DisplayWindowPolicyController;
|
||||
|
||||
import com.android.internal.annotations.GuardedBy;
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.app.BlockedAppStreamingActivity;
|
||||
|
||||
import java.util.List;
|
||||
@@ -112,7 +113,9 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController
|
||||
final ArraySet<Integer> mRunningUids = new ArraySet<>();
|
||||
@Nullable private final ActivityListener mActivityListener;
|
||||
private final Handler mHandler = new Handler(Looper.getMainLooper());
|
||||
private final ArraySet<RunningAppsChangedListener> mRunningAppsChangedListener =
|
||||
@NonNull
|
||||
@GuardedBy("mGenericWindowPolicyControllerLock")
|
||||
private final ArraySet<RunningAppsChangedListener> mRunningAppsChangedListeners =
|
||||
new ArraySet<>();
|
||||
@Nullable
|
||||
private final @AssociationRequest.DeviceProfile String mDeviceProfile;
|
||||
@@ -178,12 +181,16 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController
|
||||
|
||||
/** Register a listener for running applications changes. */
|
||||
public void registerRunningAppsChangedListener(@NonNull RunningAppsChangedListener listener) {
|
||||
mRunningAppsChangedListener.add(listener);
|
||||
synchronized (mGenericWindowPolicyControllerLock) {
|
||||
mRunningAppsChangedListeners.add(listener);
|
||||
}
|
||||
}
|
||||
|
||||
/** Unregister a listener for running applications changes. */
|
||||
public void unregisterRunningAppsChangedListener(@NonNull RunningAppsChangedListener listener) {
|
||||
mRunningAppsChangedListener.remove(listener);
|
||||
synchronized (mGenericWindowPolicyControllerLock) {
|
||||
mRunningAppsChangedListeners.remove(listener);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -283,12 +290,16 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController
|
||||
// Post callback on the main thread so it doesn't block activity launching
|
||||
mHandler.post(() -> mActivityListener.onDisplayEmpty(mDisplayId));
|
||||
}
|
||||
}
|
||||
mHandler.post(() -> {
|
||||
for (RunningAppsChangedListener listener : mRunningAppsChangedListener) {
|
||||
listener.onRunningAppsChanged(runningUids);
|
||||
if (!mRunningAppsChangedListeners.isEmpty()) {
|
||||
final ArraySet<RunningAppsChangedListener> listeners =
|
||||
new ArraySet<>(mRunningAppsChangedListeners);
|
||||
mHandler.post(() -> {
|
||||
for (RunningAppsChangedListener listener : listeners) {
|
||||
listener.onRunningAppsChanged(runningUids);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -354,4 +365,11 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
int getRunningAppsChangedListenersSizeForTesting() {
|
||||
synchronized (mGenericWindowPolicyControllerLock) {
|
||||
return mRunningAppsChangedListeners.size();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -891,4 +891,34 @@ public class VirtualDeviceManagerServiceTest {
|
||||
verify(mContext).startActivityAsUser(argThat(intent ->
|
||||
intent.filterEquals(blockedAppIntent)), any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void registerRunningAppsChangedListener_onRunningAppsChanged_listenersNotified() {
|
||||
ArraySet<Integer> uids = new ArraySet<>(Arrays.asList(UID_1, UID_2));
|
||||
mDeviceImpl.onVirtualDisplayCreatedLocked(
|
||||
mDeviceImpl.createWindowPolicyController(), DISPLAY_ID);
|
||||
GenericWindowPolicyController gwpc = mDeviceImpl.getWindowPolicyControllersForTesting().get(
|
||||
DISPLAY_ID);
|
||||
|
||||
gwpc.onRunningAppsChanged(uids);
|
||||
mDeviceImpl.onRunningAppsChanged(uids);
|
||||
|
||||
assertThat(gwpc.getRunningAppsChangedListenersSizeForTesting()).isEqualTo(1);
|
||||
verify(mRunningAppsChangedCallback).accept(new ArraySet<>(Arrays.asList(UID_1, UID_2)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void noRunningAppsChangedListener_onRunningAppsChanged_doesNotThrowException() {
|
||||
ArraySet<Integer> uids = new ArraySet<>(Arrays.asList(UID_1, UID_2));
|
||||
mDeviceImpl.onVirtualDisplayCreatedLocked(
|
||||
mDeviceImpl.createWindowPolicyController(), DISPLAY_ID);
|
||||
GenericWindowPolicyController gwpc = mDeviceImpl.getWindowPolicyControllersForTesting().get(
|
||||
DISPLAY_ID);
|
||||
mDeviceImpl.onVirtualDisplayRemovedLocked(DISPLAY_ID);
|
||||
|
||||
// This call should not throw any exceptions.
|
||||
gwpc.onRunningAppsChanged(uids);
|
||||
|
||||
assertThat(gwpc.getRunningAppsChangedListenersSizeForTesting()).isEqualTo(0);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user