Skip to content
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

Scoped Storage: Handle storage being revoked #13396

Merged
merged 5 commits into from
Mar 26, 2023

Conversation

david-allison
Copy link
Member

@david-allison david-allison commented Mar 4, 2023

Pull Request template

Purpose / Description

If a user uninstalls and selects 'keep data', the user retains access to their preferences, so we retain deckPath and can use it to determine if their collection is no longer accessible

If a user uninstalls AnkiDroid, preserveLegacyExternalStorage no longer works.

This means they have a deckPath of /storage/emulated/0/AnkiDroid which can no longer be accessed.

Their data exists, but cannot be accessed unless:

  • They restore from AnkiWeb
  • They have a colpkg
  • They manually copy the folder over
  • They install a non-Google-Play copy

Provide a dialog with options:

Fixes

Related: #5304

Approach

Screenshot 2023-03-04 at 03 07 40
Screenshot 2023-03-04 at 03 09 18

How Has This Been Tested?

API 31 emulator, manually with the provided shell script

Checklist

  • You have a descriptive commit message with a short title (first line, max 50 chars).
  • You have commented your code, particularly in hard-to-understand areas
  • You have performed a self-review of your own code
  • UI changes: include screenshots of all affected screens (in particular showing any new or changed strings)
  • UI Changes: You have tested your change using the Google Accessibility Scanner

@david-allison david-allison added Review High Priority Request for high priority review Blocked by dependency Currently blocked by some other dependent / related change labels Mar 4, 2023
@github-actions
Copy link
Contributor

github-actions bot commented Mar 4, 2023

Message to maintainers, this PR contains strings changes.

  1. Before merging this PR, it is best to run the "Sync Translations" GitHub action, then make and merge a PR from the i18n_sync branch to get translations cleaned out.
  2. Then merge this PR, and immediately do another translation PR so the huge change made by this PR's key changes are all by themselves.

Read more about updating strings on the wiki,

@david-allison david-allison changed the title Scoped Storage: Handle when storage revoked Scoped Storage: Handle storage being revoked Mar 4, 2023
@mikehardy mikehardy force-pushed the scoped-storage-permissions-2 branch from ab9474f to 271ee7a Compare March 24, 2023 02:53
@mikehardy mikehardy removed the Blocked by dependency Currently blocked by some other dependent / related change label Mar 24, 2023
@mikehardy

This comment was marked as outdated.

@mikehardy

This comment was marked as outdated.

@mikehardy

This comment was marked as outdated.

@mikehardy mikehardy force-pushed the scoped-storage-permissions-2 branch from 271ee7a to 4eadafe Compare March 24, 2023 16:34
@@ -452,7 +452,9 @@ open class AnkiActivity : AppCompatActivity, SimpleMessageDialogListener, Collec
* @param newFragment the DialogFragment you want to show
*/
open fun showDialogFragment(newFragment: DialogFragment) {
showDialogFragment(this, newFragment)
runOnUiThread {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you explain the rationale behind this change?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this is not called on the UI thread we get the exception:

Exception: java.lang.IllegalStateException: Must be called from main thread of fragment host

I don't recall the situation which caused this. I strongly suspect it's the line(s):

                deckPicker.launchCatchingTask {
                    CollectionHelper.ankiDroidDirectoryOverride = newAnkiDroidDirectory

                    CollectionManager.withCol {
                        deckPicker.showImportDialog(
                            ImportOptions(
                                importTextFile = false,
                                importColpkg = true,
                                importApkg = false
                            )
                        )
                    }
                }

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMHO, you might want to revisit that code instead. withCol is intended to operate on the collection and optionally return a value - doing UI work inside it is generally a code smell. In this case it doesn't even appear to be using the provided collection scope, so as far as I can see, if this code has any effect, it would just be to serialize concurrent access if it's not already serialized. If the importing dialog needs to access the collection, it should be calling withCol itself, or the collection object should be passed in to it (but the former is probably a better option in most cases, since that minimizes the time the collection is held locked from other UI).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@david-allison not sure what you want to do with this one - this does indeed seem like a valid suggestion (move where the withCol happens / remove UI thread thing here) but it seems like it will be halt merge here. If we merge as is we are open to ANRs / UI non-responsiveness which is certainly a performance concern / could be considered a correctness concern.

I'm leaning towards merging this PR with this as a known defect peeled into a different issue. What do you think?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Concrete suggestion that would work for me then, and stop a back-and-forth: if you agree a new issue works, create the issue, link here, and then I think this is merge-able.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay - having napped on this (insert old man joke here...) I'm going to peel it to an issue and go with this.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#13499 is the peel out issue - I napped on this and I want to keep it moving on the main track, smaller issues should not derail progress

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unless I'm getting this wrong, this is trivial to solve, because if the withCol collection isn't used, it can be simply removed.

                deckPicker.launchCatchingTask {
                    CollectionHelper.ankiDroidDirectoryOverride = newAnkiDroidDirectory
                    deckPicker.showImportDialog(
                        ImportOptions(
                            importTextFile = false,
                            importColpkg = true,
                            importApkg = false
                        )
                    )
                }

And being on the "likely to bug, but trivial to fix" side of things" makes it better to fix on this PR.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P.s.: perhaps the launchCatchingTask can be dropped as well

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry @BrayanDSO - I hit the merge button before I saw this 🙈

@mikehardy
Copy link
Member

@ShridharGoel - David responded I think to your comments and re-pushed but with one trivial refactor element missing. I just fixed that and rebased upstream/main back into the PR then pushed that. I think it is ready for review again 🤞 . Thank you!

Copy link
Member

@BrayanDSO BrayanDSO left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall, LGTM. Soft approval because I haven't tested it yet

AnkiDroid/src/main/res/values/01-core.xml Outdated Show resolved Hide resolved
If a user uninstalls AnkiDroid, `preserveLegacyStorage` no longer
works

This means they have a deckPath of `/storage/emulated/0/AnkiDroid`
which can no longer be accessed.

Their data exists, but cannot be accessed unless:
* They restore from AnkiWeb
* They have a colpkg
* They manually copy the folder over
* They install a non-Google-Play copy

Options:
* Restore from AnkiWeb
* Restore folder access
   (https://github.com/ankidroid/Anki-Android/wiki/Full-Storage-Access)
* Restore backup (Hidden - Not Implemented)
* Get Help (Link to: Google Group)
* Delete collection and create a new one

Issue 5304
`getCollectionPath` should be used when the collection is closed
Exception: java.lang.IllegalStateException: Must be called from main thread of fragment host
If a user has uninstalled the app, one of the options should
be to restore from a .colpkg

Use `ankiDroidDirectoryOverride` as code uses the location in
 CollectionHelper rather than `col.path`. Defining a temporary
 collection in `CollectionManager` was deemed to be too challenging

Tested with 'Don't keep activities' and failures in the import copy

Issue 5304
@mikehardy mikehardy merged commit 56e0a24 into ankidroid:main Mar 26, 2023
@github-actions github-actions bot added this to the 2.16 release milestone Mar 26, 2023
@github-actions github-actions bot removed the Review High Priority Request for high priority review label Mar 26, 2023
@david-allison david-allison deleted the scoped-storage-permissions-2 branch October 25, 2023 10:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
No open projects
Development

Successfully merging this pull request may close these issues.

5 participants