-
Notifications
You must be signed in to change notification settings - Fork 627
Host activity interrupted error & dialog dismissal #3341
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Host activity interrupted error & dialog dismissal #3341
Conversation
|
||
@GuardedBy("cachedNewReleaseLock") | ||
private AppDistributionReleaseInternal cachedNewRelease; | ||
AtomicReference<AppDistributionReleaseInternal> cachedNewRelease = new AtomicReference(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since this had a separate lock from the cached task, I thought we could reduce the number of blocks by adding an atomic reference
Coverage Report 1Affected Products
Test Logs
Notes |
The public api surface has changed for the subproject firebase-appdistribution: Please update the api.txt files for the subprojects being affected by this change by running ./gradlew ${subproject}:generateApiTxtFile. Also perform a major/minor bump accordingly. |
Size Report 1Affected Products
Test Logs
Notes |
Wanted to get this up before EOD still needs some cleaning before review |
The public api surface has changed for the subproject firebase-appdistribution: Please update the api.txt files for the subprojects being affected by this change by running ./gradlew ${subproject}:generateApiTxtFile. Also perform a major/minor bump accordingly. |
if (dialogHostActivityHasChanged(activity)) { | ||
setUpdateIfNewReleaseWithHostError(); | ||
} else { | ||
signInConfirmationDialog.show(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@lfkellogg Would like to discuss this with you. If we kept the past implementation of calling the method the task hangs on failure. If we set the task to fail then if the user has some failure listener that will be called. I believe we ran into this before not sure if there was a resolution.
|
||
return showUpdateDialogTask.getTask(); | ||
} | ||
|
||
private void setRemakeDialogsToFalse() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since we're just using this in one place, and it's already being called from a synchronized block, we might as well just inline it.
private boolean remakeUpdateDialog = false; | ||
@Nullable private Activity dialogHostActivity = null; | ||
|
||
@GuardedBy("updateIfNewReleaseTaskLock") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think either of these booleans need to be protected by this lock, or any other lock. They're almost always read or written from the main thread (in lifecycle callbacks), and in the case where they're being set to false in updateIfNewReleaseAvailable, it won't practically affect anything because there's no task in progress at that point.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That is true I agree calling the updateIfNewRelease would not be an issue. I don't see a problem with onPause being called multiple times from different places but if those are all on the main thread there shouldn't be a deadlock issue so as long as we are sure of that we can change it.
...pdistribution/src/main/java/com/google/firebase/appdistribution/FirebaseAppDistribution.java
Show resolved
Hide resolved
|
||
private void updateConfirmationDialogClosedCallback(TaskCompletionSource showUpdateDialogTask) { | ||
synchronized (updateIfNewReleaseTaskLock) { | ||
remakeUpdateConfirmationDialog = false; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don't need this anymore, right? I'd just drop it and inline this method.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will remove for now. We don't have this on signIn but it might be nice to have since it does set the remake variable to false when the dialog is cancelled. That may be unnecessary but it makes sense to set it after that since it does not need to be remade at that point. Curious on your thoughts about that.
…d-error' into fad-add-host-activity-interrupted-error
/test smoke-tests |
@VisibleForTesting | ||
void onActivityDestroyed(@NonNull Activity activity) { | ||
// If the dialogHostActivity is being destroyed it is set to null. This is to ensure that | ||
// onResume shows the dialog on a configuration change and not check the activity reference |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"and does not check" ? And please put a .
on the end of the comment.
} | ||
|
||
private boolean awaitingSignInDialogConfirmation() { | ||
return (updateIfNewReleaseAvailableIsTaskInProgress() && remakeSignInConfirmationDialog); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Even though it wouldn't make a practical difference, wouldn't it make more sense if this checked if showSignInDialogTask
was in progress, instead of cachedUpdateIfNewReleaseTask
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That does make more sense and it shouldn't change anything will change
} | ||
|
||
private boolean awaitingUpdateDialogConfirmation() { | ||
return (updateIfNewReleaseAvailableIsTaskInProgress() && remakeUpdateConfirmationDialog); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here, but showUpdateDialogTask
|
||
assertAlertDialogShown(); | ||
assertFalse(updateTask.isComplete()); | ||
} | ||
|
||
@Test | ||
public void taskCancelledOnDestroy_whenSignInDialogShowing() { | ||
public void | ||
updateIfNewReleaseAvailable_signInTaskCancelled_whenSignInDialogShowingAndNewActivityStarts() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: for this and the next test, could you change the name of the test to put the "when" clause in the middle of the name, and the expected behavior at the end? E.g. updateIfNewReleaseAvailable_whenSignInDialogShowingAndNewActivityStarts_signInTaskCancelled
...ution/test-app/src/main/java/com/googletest/firebase/appdistribution/testapp/MainActivity.kt
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some nits, but this looks great!
@rachaprince: The following test failed, say
Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. I understand the commands that are listed here. |
This PR makes it so that if the host activity is interrupted and put on pause then we want for it to resume to show a dialog. If there is a new activity that resumes then we cancel the task.