Merge "Fix java.lang.ArrayIndexOutOfBoundsException at ArraySet in GenericWindowPolicyController.onRunningAppsChanged()"

This commit is contained in:
Cliff Wu
2022-10-28 02:20:23 +00:00
committed by Android (Google) Code Review
2 changed files with 56 additions and 8 deletions

View File

@@ -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();
}
}
}

View File

@@ -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);
}
}