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

App backup format v2 with compression and deduplication #750

Open
wants to merge 56 commits into
base: android15
Choose a base branch
from

Conversation

grote
Copy link
Collaborator

@grote grote commented Sep 24, 2024

Lot's of improvements in this new format which was inspired by restic and borg2. I expect overall more reliable and faster backups. See the added design document for more details.

Compatibility with old formats (v0 and v1) should be retained. So with this new version, you can restore those old backups, but you can't use an old version to restore a backup from this new version.

Fixes #267, #299, #476, #566, #559, #649, #701, #737, #745, #753, #754, #755, #759

This also moves key derivation via HKDF into the core.
We still support downloading in v1 format for some time.
We still support restoring in v1 format for some time.
while maintaining support for v0 and v1
while maintaining support for v0 and v1
We'll probably keep metadata around for internal information about backup state
as it isn't needed anymore with v2 since we don't do duplicate restore sets anymore
The token used to be very important, because it was our restore set folder name. Now it is just a number in a snapshot, so things get a bit simpler.
This class is responsible for caching blobs during a backup run,
so we can know that a blob for the given chunk ID already exists
and does not need to be uploaded again.

It builds up its cache from snapshots available on the backend
and from the persistent cache that includes blobs that could not be added to a snapshot,
because the backup was aborted.
which manages interactions with snapshots, such as loading, saving and removing them.
It also keeps a reference to the latestSnapshot that holds important re-usable data.
Historically, metadata was uploaded to the backend after each app update and contained all essential data that is now in snapshots. We still support reading metadata for legacy backups and use the metadata classes as a common wrapper for snapshots. However, there is no need anymore to write out complete historic metadata and maintain duplicated unused information there. This got removed. THe information we do still save and write out is only for UI representation of backup state.

The time of last backup is now managed by SettingsManager.
as they all relate to interacting with the backup repository
We don't get notified about the start nor the end of such a backup run, so we need hacks to do initialization and finalization.
Instead of showing 'Waiting to be backed up...'
otherwise all LoggingFactory ClassLoader lookups that cause disk reads are logged when koin initializes classes
Even though we use d2d, backup is only forced for user apps.
We need to account for IME insets when applying padding to the window.
Now, we don't do partial backups anymore. A snapshot is only done at the end and no information can make it to the backup before. Hence the old error notification with number of apps backed up didn't make sense anymore.
when user is asked to choose a backup to restore
@t-m-w
Copy link
Collaborator

t-m-w commented Oct 1, 2024

v2 contains a scenario that should be addressed to avoid unexpected data loss, stemming from the fact that snapshots only reference user data emerging from that snapshot's backup run, not referencing any user data from prior runs:

  1. A user has an app with user data they find valuable.
  2. The user force-stops the app, or the system stops it - or otherwise, for whatever reason, it does not get included in a backup run; there are multiple reasons this could happen.
  3. As stated, the resulting snapshot does not reference the app's user data, by design, because the system did not provide it; snapshots only reference data provided at the time the backup was taken.
  4. So, restoring this snapshot does not restore the user data for the app, even though the user data was present on the device at the time. Prior to the advent of v2's snapshots, the app's latest-backed-up user data would remain within the backup set, so it would be restored.
  5. The user can still restore the app's data from an older snapshot, if it occurs to them to do so. They would need to keep an eye on Backup Status to know to do this.
  6. v2 keeps a snapshot from the prior week, but beyond that, if the app continued to be skipped in the backup (remained force-stopped, etc), its user data would no longer be referenced by any snapshots and could not be restored. Prior to v2, the app's user data would still be restorable at this time.

How could this be resolved? I only have a couple of ideas for now, and neither is perfect.

  1. Preserve a similar behavior to pre-v2 by referencing data from older snapshots when the backup of an app's user data fails. This has the downside that we are deliberately referencing stale data, but the upside that it won't be purged from the backup data and will result in a restore state that is closer to what the user expects. If this is done, there should be a way to demonstrate that the data is stale/older, just as there was pre-v2, with the ability to see app backup status and dates.
  2. Find a portable way to force apps to be backed up even if they're stopped or whatever. This could be quite hack-ish and might not even be doable without framework changes.

@grote
Copy link
Collaborator Author

grote commented Oct 1, 2024

A user has an app with user data they find valuable.
The user force-stops the app

Why would the user force stop that app, if it is so valuable?

or the system stops it

have we seen this already in practice? So far I haven't seen confirmed reports of this happening.

Prior to the advent of v2's snapshots, the app's latest-backed-up user data would remain within the backup set, so it would be restored.

If not repeated writing of backup.metadata to Nextcloud corrupted the entire file and made the entire backup unusable.

v2 keeps a snapshot from the prior week, but beyond that, if the app continued to be skipped in the backup (remained force-stopped, etc), its user data would no longer be referenced by any snapshots and could not be restored.

Any usage of the app, even just a recurring worker task or something like that would remove the app from its force stopped state. On your personal phone is there any force stopped app you care about?

Then as soon as the app is being used again, it would enter into backups.

Preserve a similar behavior to pre-v2 by referencing data from older snapshots when the backup of an app's user data fails.

It doesn't fail, the app is just no longer considered eligible for backup by the system. We do however have a place where we record apps that don't get backed up. There we could look up the last snapshot at least and see if the app had data there. Still, I am not convinced that this is a good solution, because the scenario seems pretty artificial to me.

Find a portable way to force apps to be backed up even if they're stopped or whatever.

I don't think there's a way to do this without modifying the system itself.

@t-m-w
Copy link
Collaborator

t-m-w commented Oct 1, 2024

Why would the user force stop that app, if it is so valuable?

Maybe the last time you used it, it stopped responding, and you force-stopped it. Maybe when it runs, it's buggy and uses a lot of resources, so you only run it sometimes. Maybe you were trying to improve your battery life, so you force-stopped some things. I don't know, but I don't think we should be opinionated against the practice. Also, does the Foreground Services Task Manager (Active Apps) stop apps in a way that would affect this? I don't know.

or the system stops it

have we seen this already in practice? So far I haven't seen confirmed reports of this happening.

On your personal phone is there any force stopped app you care about?

Yes. Not many, but some. Here's a selection of my own apps which say "Not backed up as it wasn't used recently" and, for most of them, I have no idea why (or, I could rephrase as, I probably don't open them often, but I don't recall force-stopping them):

  1. Catima. I have shoppers cards in here. I haven't opened it in a while, maybe not even since it was restored, but I really don't want to lose them or have to hunt them down later.
  2. Chiaki. It's paired to my game console. Minor loss I guess, but still a loss I'd rather not have.
  3. Organic Maps. I don't use it that often, but I have Saved Places I would like to keep.
  4. Progress Bars. I am tracking progress on something here. That progress is very slow - so slow that I barely open the app - but it would be annoying to lose it.
  5. Terminal Emulator. Although I may not use it often, I have scripts in there that I don't want to lose.

Those are just some apps where I think it would matter. There are others that I'm sure I've started before and don't recall force-stopping that are marked this way. It's a known issue on either or both the CalyxOS / Seedvault side. Why make it even worse?

Another question would be, if the user restores from a backup, then takes another snapshots, will that snapshot not contain any apps they've yet to open?

In my opinion, the user shouldn't need to think about these things at all. I know that AOSP makes that hard for us though.

@gdt
Copy link

gdt commented Oct 1, 2024

I'm with @t-m-w in that apps that are not running should not be excluded. (I get it that it's complicated and hard.)

@t-m-w
Copy link
Collaborator

t-m-w commented Oct 1, 2024

I'm with @t-m-w in that apps that are not running should not be excluded. (I get it that it's complicated and hard.)

Just to make sure it's clear, it's not that apps which aren't running are excluded, but that apps which are actively stopped (by the system somehow or by the user) could age out of all snapshots if the user is not careful to make sure they occasionally launch every app that is important to them, and verify that these apps are properly restored from one or more snapshots with a restore. I just feel that's too much expectation to put on the user.

When switching to new storage that doesn't yet have any snapshots, we would otherwise keep the old latest snapshot around.
* activity now can be launched from notification
* better logging
* app data restore continues even after activity died
The fake package manager package is essential for the backup, but when its data doesn't change and we request a normal incremental backup, it doesn't get included, because our transport doesn't even get called for it. Only the BackupMonitor gets a hint that it had no (new?) data via LOG_EVENT_ID_NO_DATA_TO_SEND.
This behavior started with Android 15 that fixed a bug that caused @pm@ to always backup. However, other K/V apps were probably affected before.
The system doesn't allow us to backup forced stopped apps, but if we had data for them once, we can at least carry it along.
Copy link
Collaborator

@t-m-w t-m-w left a comment

Choose a reason for hiding this comment

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

Icon backgrounds are showing as solid colors since the switch to the new icon handling, e.g. black square background. To copy from the CalyxOS-side testing issue: "UI: Restore: Reinstalling apps: Transparency is not working properly for many app icons, until the app is restored. During restoration of an app, its icon has a solid color (typically black or white) on the edges/corners, where it should be transparent. It fades into the proper appearance just before restoration is complete. Examples of apps affected are Signal and OONI Probe, but there are many."

@t-m-w
Copy link
Collaborator

t-m-w commented Oct 3, 2024

Can confirm icons are fixed!

t-m-w
t-m-w previously approved these changes Oct 3, 2024
@t-m-w t-m-w dismissed their stale review October 3, 2024 19:38

Icon changes are fixed but I didn't intend to approve the entire PR just yet

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

opening "Sicherungsort (backup location)" and selecting the existing option resets backup state
3 participants