Get a copy of registered callbacks when invoking the callbacks so
that the callback can be removed safely after invocation

Bug: 291817331
Test: manual
Change-Id: I90814efc6253eefdadfdb83ed7b0fe6e98201ca7
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/activities/DevicePoliciesFragment.java b/DeviceLockController/src/com/android/devicelockcontroller/activities/DevicePoliciesFragment.java
index 04ecba6..7cf33ff 100644
--- a/DeviceLockController/src/com/android/devicelockcontroller/activities/DevicePoliciesFragment.java
+++ b/DeviceLockController/src/com/android/devicelockcontroller/activities/DevicePoliciesFragment.java
@@ -125,6 +125,7 @@
                 LogUtil.e(TAG, "Failed to finish setup flow!");
                 provisioningProgressViewModel.setProvisioningProgress(
                         ProvisioningProgress.PROVISIONING_FAILED);
+                setupController.removeListener(this);
             }
 
             @Override
@@ -132,6 +133,7 @@
                 LogUtil.i(TAG, "Successfully finished setup flow!");
                 provisioningProgressViewModel.setProvisioningProgress(
                         ProvisioningProgress.OPENING_KIOSK_APP);
+                setupController.removeListener(this);
             }
         });
     }
diff --git a/DeviceLockController/src/com/android/devicelockcontroller/policy/SetupControllerImpl.java b/DeviceLockController/src/com/android/devicelockcontroller/policy/SetupControllerImpl.java
index 1e00026..96950c6 100644
--- a/DeviceLockController/src/com/android/devicelockcontroller/policy/SetupControllerImpl.java
+++ b/DeviceLockController/src/com/android/devicelockcontroller/policy/SetupControllerImpl.java
@@ -53,6 +53,7 @@
 import com.android.devicelockcontroller.storage.SetupParametersClient;
 import com.android.devicelockcontroller.util.LogUtil;
 
+import com.google.common.collect.ImmutableList;
 import com.google.common.util.concurrent.FutureCallback;
 import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.ListenableFuture;
@@ -292,16 +293,20 @@
                                 LogUtil.i(TAG, "Handling successful setup");
                                 mCurrentSetupState = SetupStatus.SETUP_FINISHED;
                                 synchronized (mCallbacks) {
-                                    for (int i = 0, cbSize = mCallbacks.size(); i < cbSize; i++) {
-                                        mCallbacks.get(i).setupCompleted();
+                                    ImmutableList<SetupUpdatesCallbacks> callbacks =
+                                            ImmutableList.copyOf(mCallbacks);
+                                    for (int i = 0, cbSize = callbacks.size(); i < cbSize; i++) {
+                                        callbacks.get(i).setupCompleted();
                                     }
                                 }
                             } else {
                                 LogUtil.i(TAG, "Handling failed setup");
                                 mCurrentSetupState = SetupStatus.SETUP_FAILED;
                                 synchronized (mCallbacks) {
-                                    for (int i = 0, cbSize = mCallbacks.size(); i < cbSize; i++) {
-                                        mCallbacks.get(i).setupFailed(failReason);
+                                    ImmutableList<SetupUpdatesCallbacks> callbacks =
+                                            ImmutableList.copyOf(mCallbacks);
+                                    for (int i = 0, cbSize = callbacks.size(); i < cbSize; i++) {
+                                        callbacks.get(i).setupFailed(failReason);
                                     }
                                 }
                             }