├── .cirrus.yml
├── .editorconfig
├── .github
├── scripts
│ ├── build_aosp.sh
│ └── run_tests.sh
└── workflows
│ ├── build.yml
│ ├── codacy.yml
│ ├── mobsf.yml
│ └── test.yml
├── .gitignore
├── .idea
├── .name
├── codeStyles
│ ├── Project.xml
│ └── codeStyleConfig.xml
├── copyright
│ ├── Apache_2_0.xml
│ └── profiles_settings.xml
├── dictionaries
│ └── user.xml
├── inspectionProfiles
│ └── Project_Default.xml
├── runConfigurations
│ ├── All_unit_tests.xml
│ ├── Instrumentation_tests__app.xml
│ ├── Unit_tests__app.xml
│ ├── Unit_tests__contactsbackup.xml
│ ├── Unit_tests__storage_lib.xml
│ ├── app.xml
│ ├── app_emulator.xml
│ └── seedvault_storage_lib__assembleRelease_.xml
└── scopes
│ ├── Kotlin_Files.xml
│ └── XML_Files.xml
├── .reuse
└── dep5
├── Android.bp
├── CHANGELOG.md
├── LICENSES
├── AGPL-3.0-or-later.txt
├── Apache-2.0.txt
├── CC-BY-SA-3.0.txt
├── GPL-3.0-only.txt
├── MIT.txt
└── MPL-2.0.txt
├── README.md
├── SECURITY.md
├── allowlist_com.stevesoltys.seedvault.xml
├── app
├── build.gradle.kts
├── build
│ └── generated
│ │ └── source
│ │ └── proto
│ │ └── debug
│ │ └── kotlin
│ │ └── com
│ │ └── stevesoltys
│ │ └── seedvault
│ │ └── proto
│ │ └── SnapshotKt.kt
├── development
│ ├── DEVELOPMENT.md
│ ├── platform.jks
│ └── scripts
│ │ ├── clear_app_data.sh
│ │ ├── install_app.sh
│ │ ├── provision_emulator.sh
│ │ └── start_emulator.sh
├── lint.xml
└── src
│ ├── androidTest
│ ├── AndroidManifest.xml
│ └── java
│ │ └── com
│ │ └── stevesoltys
│ │ └── seedvault
│ │ ├── KoinInstrumentationTestApp.kt
│ │ ├── KoinInstrumentationTestRunner.kt
│ │ ├── PluginTest.kt
│ │ ├── backend
│ │ └── saf
│ │ │ └── SafBackendTest.kt
│ │ ├── e2e
│ │ ├── LargeBackupTestBase.kt
│ │ ├── LargeRestoreTestBase.kt
│ │ ├── LargeTestBase.kt
│ │ ├── SeedvaultLargeTest.kt
│ │ ├── SeedvaultLargeTestResult.kt
│ │ ├── impl
│ │ │ └── BackupRestoreTest.kt
│ │ ├── io
│ │ │ ├── BackupDataInputIntercept.kt
│ │ │ └── BackupDataOutputIntercept.kt
│ │ └── screen
│ │ │ ├── UiDeviceScreen.kt
│ │ │ └── impl
│ │ │ ├── BackupScreen.kt
│ │ │ ├── DocumentPickerScreen.kt
│ │ │ ├── RecoveryCodeScreen.kt
│ │ │ └── RestoreScreen.kt
│ │ ├── transport
│ │ └── backup
│ │ │ ├── KvBackupInstrumentationTest.kt
│ │ │ └── PackageServiceTest.kt
│ │ └── worker
│ │ └── IconManagerTest.kt
│ ├── debug
│ ├── AndroidManifest.xml
│ └── res
│ │ └── values
│ │ ├── arrays.xml
│ │ └── config.xml
│ ├── main
│ ├── AndroidManifest.xml
│ ├── assets
│ │ └── logback.xml
│ ├── java
│ │ └── com
│ │ │ └── stevesoltys
│ │ │ └── seedvault
│ │ │ ├── App.kt
│ │ │ ├── BackupMonitor.kt
│ │ │ ├── BackupStateManager.kt
│ │ │ ├── Base64Utils.kt
│ │ │ ├── Clock.kt
│ │ │ ├── UsbIntentReceiver.kt
│ │ │ ├── UsbMonitorService.kt
│ │ │ ├── backend
│ │ │ ├── BackendManager.kt
│ │ │ ├── LegacyStoragePlugin.kt
│ │ │ ├── saf
│ │ │ │ ├── DocumentsProviderLegacyPlugin.kt
│ │ │ │ ├── DocumentsProviderModule.kt
│ │ │ │ ├── DocumentsStorage.kt
│ │ │ │ ├── SafHandler.kt
│ │ │ │ ├── SafStorageOptions.kt
│ │ │ │ └── StorageRootResolver.kt
│ │ │ └── webdav
│ │ │ │ ├── WebDavHandler.kt
│ │ │ │ └── WebDavModule.kt
│ │ │ ├── crypto
│ │ │ ├── CipherFactory.kt
│ │ │ ├── Crypto.kt
│ │ │ ├── CryptoModule.kt
│ │ │ └── KeyManager.kt
│ │ │ ├── header
│ │ │ ├── Header.kt
│ │ │ ├── HeaderModule.kt
│ │ │ └── HeaderReader.kt
│ │ │ ├── metadata
│ │ │ ├── Metadata.kt
│ │ │ ├── MetadataManager.kt
│ │ │ ├── MetadataModule.kt
│ │ │ ├── MetadataReader.kt
│ │ │ └── MetadataWriter.kt
│ │ │ ├── repo
│ │ │ ├── AppBackupManager.kt
│ │ │ ├── BackupData.kt
│ │ │ ├── BackupReceiver.kt
│ │ │ ├── BlobCache.kt
│ │ │ ├── BlobCreator.kt
│ │ │ ├── Checker.kt
│ │ │ ├── CheckerResult.kt
│ │ │ ├── Loader.kt
│ │ │ ├── PaddedInputStream.kt
│ │ │ ├── Padding.kt
│ │ │ ├── Pruner.kt
│ │ │ ├── RepoModule.kt
│ │ │ ├── SnapshotCreator.kt
│ │ │ ├── SnapshotCreatorFactory.kt
│ │ │ └── SnapshotManager.kt
│ │ │ ├── restore
│ │ │ ├── AppDataRestoreManager.kt
│ │ │ ├── AppSelectionAdapter.kt
│ │ │ ├── AppSelectionFragment.kt
│ │ │ ├── AppSelectionManager.kt
│ │ │ ├── FilesSelectionFragment.kt
│ │ │ ├── RecycleBackupFragment.kt
│ │ │ ├── RestoreActivity.kt
│ │ │ ├── RestoreErrorBroadcastReceiver.kt
│ │ │ ├── RestoreFilesFragment.kt
│ │ │ ├── RestoreProgressAdapter.kt
│ │ │ ├── RestoreProgressFragment.kt
│ │ │ ├── RestoreService.kt
│ │ │ ├── RestoreSetAdapter.kt
│ │ │ ├── RestoreSetFragment.kt
│ │ │ ├── RestoreUiModule.kt
│ │ │ ├── RestoreViewModel.kt
│ │ │ └── install
│ │ │ │ ├── ApkInstaller.kt
│ │ │ │ ├── ApkRestore.kt
│ │ │ │ ├── ApkSplitCompatibilityChecker.kt
│ │ │ │ ├── DeviceInfo.kt
│ │ │ │ ├── InstallIntentCreator.kt
│ │ │ │ ├── InstallModule.kt
│ │ │ │ ├── InstallProgressAdapter.kt
│ │ │ │ ├── InstallProgressFragment.kt
│ │ │ │ ├── InstallRestriction.kt
│ │ │ │ └── InstallResult.kt
│ │ │ ├── settings
│ │ │ ├── AboutDialogFragment.kt
│ │ │ ├── AppListRetriever.kt
│ │ │ ├── AppStatusAdapter.kt
│ │ │ ├── AppStatusFragment.kt
│ │ │ ├── ExpertSettingsFragment.kt
│ │ │ ├── FirstRunFragment.kt
│ │ │ ├── SchedulingFragment.kt
│ │ │ ├── SettingsActivity.kt
│ │ │ ├── SettingsFragment.kt
│ │ │ ├── SettingsManager.kt
│ │ │ ├── SettingsViewModel.kt
│ │ │ ├── TryAgainBroadcastReceiver.kt
│ │ │ └── preference
│ │ │ │ └── M3ListPreference.kt
│ │ │ ├── storage
│ │ │ ├── StorageModule.kt
│ │ │ └── StorageRestoreService.kt
│ │ │ ├── transport
│ │ │ ├── ConfigurableBackupTransport.kt
│ │ │ ├── ConfigurableBackupTransportService.kt
│ │ │ ├── backup
│ │ │ │ ├── BackupCoordinator.kt
│ │ │ │ ├── BackupInitializer.kt
│ │ │ │ ├── BackupModule.kt
│ │ │ │ ├── BackupTransportMonitor.kt
│ │ │ │ ├── FinalizeBackupService.kt
│ │ │ │ ├── FullBackup.kt
│ │ │ │ ├── InputFactory.kt
│ │ │ │ ├── KVBackup.kt
│ │ │ │ ├── KVDbManager.kt
│ │ │ │ └── PackageService.kt
│ │ │ └── restore
│ │ │ │ ├── FullRestore.kt
│ │ │ │ ├── KVRestore.kt
│ │ │ │ ├── OutputFactory.kt
│ │ │ │ ├── RestorableBackup.kt
│ │ │ │ ├── RestoreCoordinator.kt
│ │ │ │ └── RestoreModule.kt
│ │ │ ├── ui
│ │ │ ├── AppBackupState.kt
│ │ │ ├── AppViewHolder.kt
│ │ │ ├── BackupActivity.kt
│ │ │ ├── LiveEvent.kt
│ │ │ ├── LiveEventHandler.java
│ │ │ ├── MutableLiveEvent.kt
│ │ │ ├── RequireProvisioningActivity.kt
│ │ │ ├── RequireProvisioningViewModel.kt
│ │ │ ├── SystemData.kt
│ │ │ ├── UiUtils.kt
│ │ │ ├── check
│ │ │ │ ├── AppCheckFragment.kt
│ │ │ │ ├── AppCheckResultActivity.kt
│ │ │ │ ├── FileCheckFragment.kt
│ │ │ │ └── FileCheckResultActivity.kt
│ │ │ ├── files
│ │ │ │ ├── FileSelectionFragment.kt
│ │ │ │ └── FileSelectionViewModel.kt
│ │ │ ├── notification
│ │ │ │ ├── BackupNotificationManager.kt
│ │ │ │ └── NotificationBackupObserver.kt
│ │ │ ├── recoverycode
│ │ │ │ ├── RecoveryCodeActivity.kt
│ │ │ │ ├── RecoveryCodeAdapter.kt
│ │ │ │ ├── RecoveryCodeInputFragment.kt
│ │ │ │ ├── RecoveryCodeOutputFragment.kt
│ │ │ │ └── RecoveryCodeViewModel.kt
│ │ │ └── storage
│ │ │ │ ├── BackupStorageViewModel.kt
│ │ │ │ ├── PermissionGrantActivity.kt
│ │ │ │ ├── RestoreStorageViewModel.kt
│ │ │ │ ├── StorageActivity.kt
│ │ │ │ ├── StorageCheckFragment.kt
│ │ │ │ ├── StorageOption.kt
│ │ │ │ ├── StorageOptionAdapter.kt
│ │ │ │ ├── StorageOptionFetcher.kt
│ │ │ │ ├── StorageOptionsFragment.kt
│ │ │ │ ├── StorageViewModel.kt
│ │ │ │ └── WebDavConfigFragment.kt
│ │ │ └── worker
│ │ │ ├── ApkBackup.kt
│ │ │ ├── ApkBackupManager.kt
│ │ │ ├── AppBackupPruneWorker.kt
│ │ │ ├── AppBackupWorker.kt
│ │ │ ├── AppCheckerWorker.kt
│ │ │ ├── BackupRequester.kt
│ │ │ ├── FileBackupWorker.kt
│ │ │ ├── FileCheckerWorker.kt
│ │ │ ├── IconManager.kt
│ │ │ └── WorkerModule.kt
│ ├── proto
│ │ └── snapshot.proto
│ ├── res
│ │ ├── drawable
│ │ │ ├── davx5.xml
│ │ │ ├── davx5_foreground.xml
│ │ │ ├── ic_access_time.xml
│ │ │ ├── ic_app_settings.xml
│ │ │ ├── ic_apps.xml
│ │ │ ├── ic_battery_charging_full.xml
│ │ │ ├── ic_bug_report.xml
│ │ │ ├── ic_call.xml
│ │ │ ├── ic_check_green.xml
│ │ │ ├── ic_cloud_circle.xml
│ │ │ ├── ic_cloud_done.xml
│ │ │ ├── ic_cloud_download.xml
│ │ │ ├── ic_cloud_error.xml
│ │ │ ├── ic_cloud_reuse.xml
│ │ │ ├── ic_cloud_search.xml
│ │ │ ├── ic_cloud_upload.xml
│ │ │ ├── ic_contacts.xml
│ │ │ ├── ic_error_red.xml
│ │ │ ├── ic_info_outline.xml
│ │ │ ├── ic_launcher_default.xml
│ │ │ ├── ic_launcher_default_background.xml
│ │ │ ├── ic_launcher_default_foreground.xml
│ │ │ ├── ic_launcher_foreground.xml
│ │ │ ├── ic_library_add.xml
│ │ │ ├── ic_message.xml
│ │ │ ├── ic_network_warning.xml
│ │ │ ├── ic_phone_android.xml
│ │ │ ├── ic_save_alt.xml
│ │ │ ├── ic_settings.xml
│ │ │ ├── ic_storage.xml
│ │ │ ├── ic_usb.xml
│ │ │ ├── ic_vpn_key.xml
│ │ │ ├── ic_warning.xml
│ │ │ ├── ic_warning_yellow.xml
│ │ │ ├── nextcloud.xml
│ │ │ ├── nextcloud_background.xml
│ │ │ ├── nextcloud_foreground.xml
│ │ │ ├── round_sync.xml
│ │ │ └── round_sync_foreground.xml
│ │ ├── layout
│ │ │ ├── activity_check_result.xml
│ │ │ ├── activity_fragment_container.xml
│ │ │ ├── activity_recovery_code.xml
│ │ │ ├── footer_files_selection.xml
│ │ │ ├── footer_snapshots.xml
│ │ │ ├── fragment_about.xml
│ │ │ ├── fragment_app_check.xml
│ │ │ ├── fragment_app_status.xml
│ │ │ ├── fragment_recovery_code_input.xml
│ │ │ ├── fragment_recovery_code_output.xml
│ │ │ ├── fragment_recycle_backup.xml
│ │ │ ├── fragment_restore_app_selection.xml
│ │ │ ├── fragment_restore_files_started.xml
│ │ │ ├── fragment_restore_progress.xml
│ │ │ ├── fragment_restore_set.xml
│ │ │ ├── fragment_settings.xml
│ │ │ ├── fragment_storage_check.xml
│ │ │ ├── fragment_storage_options.xml
│ │ │ ├── fragment_webdav_config.xml
│ │ │ ├── header_files_selection.xml
│ │ │ ├── header_snapshots.xml
│ │ │ ├── list_item_app_section_title.xml
│ │ │ ├── list_item_app_status.xml
│ │ │ ├── list_item_recovery_code_output.xml
│ │ │ ├── list_item_restore_set.xml
│ │ │ ├── list_item_storage_root.xml
│ │ │ ├── preference_switch.xml
│ │ │ └── recovery_code_input.xml
│ │ ├── menu
│ │ │ ├── app_status_menu.xml
│ │ │ └── settings_menu.xml
│ │ ├── mipmap-anydpi
│ │ │ └── ic_launcher.xml
│ │ ├── values-af
│ │ │ └── strings.xml
│ │ ├── values-am
│ │ │ └── strings.xml
│ │ ├── values-ar
│ │ │ └── strings.xml
│ │ ├── values-as
│ │ │ └── strings.xml
│ │ ├── values-ast
│ │ │ └── strings.xml
│ │ ├── values-az
│ │ │ └── strings.xml
│ │ ├── values-b+sr+Latn
│ │ │ └── strings.xml
│ │ ├── values-b+zh+Hant+HK
│ │ │ └── strings.xml
│ │ ├── values-be
│ │ │ └── strings.xml
│ │ ├── values-bg
│ │ │ └── strings.xml
│ │ ├── values-bn
│ │ │ └── strings.xml
│ │ ├── values-bs
│ │ │ └── strings.xml
│ │ ├── values-ca
│ │ │ └── strings.xml
│ │ ├── values-cs
│ │ │ └── strings.xml
│ │ ├── values-cy
│ │ │ └── strings.xml
│ │ ├── values-da
│ │ │ └── strings.xml
│ │ ├── values-de
│ │ │ └── strings.xml
│ │ ├── values-el
│ │ │ └── strings.xml
│ │ ├── values-en-rAU
│ │ │ └── strings.xml
│ │ ├── values-en-rCA
│ │ │ └── strings.xml
│ │ ├── values-en-rGB
│ │ │ └── strings.xml
│ │ ├── values-en-rIN
│ │ │ └── strings.xml
│ │ ├── values-eo
│ │ │ └── strings.xml
│ │ ├── values-es-rUS
│ │ │ └── strings.xml
│ │ ├── values-es
│ │ │ └── strings.xml
│ │ ├── values-et
│ │ │ └── strings.xml
│ │ ├── values-eu
│ │ │ └── strings.xml
│ │ ├── values-fa
│ │ │ └── strings.xml
│ │ ├── values-fi
│ │ │ └── strings.xml
│ │ ├── values-fr-rCA
│ │ │ └── strings.xml
│ │ ├── values-fr
│ │ │ └── strings.xml
│ │ ├── values-gd
│ │ │ └── strings.xml
│ │ ├── values-gl
│ │ │ └── strings.xml
│ │ ├── values-gu
│ │ │ └── strings.xml
│ │ ├── values-hi
│ │ │ └── strings.xml
│ │ ├── values-hr
│ │ │ └── strings.xml
│ │ ├── values-hu
│ │ │ └── strings.xml
│ │ ├── values-hy
│ │ │ └── strings.xml
│ │ ├── values-in
│ │ │ └── strings.xml
│ │ ├── values-is
│ │ │ └── strings.xml
│ │ ├── values-it
│ │ │ └── strings.xml
│ │ ├── values-iw
│ │ │ └── strings.xml
│ │ ├── values-ja
│ │ │ └── strings.xml
│ │ ├── values-ka
│ │ │ └── strings.xml
│ │ ├── values-kk
│ │ │ └── strings.xml
│ │ ├── values-km
│ │ │ └── strings.xml
│ │ ├── values-kn
│ │ │ └── strings.xml
│ │ ├── values-ko
│ │ │ └── strings.xml
│ │ ├── values-ky
│ │ │ └── strings.xml
│ │ ├── values-lo
│ │ │ └── strings.xml
│ │ ├── values-lt
│ │ │ └── strings.xml
│ │ ├── values-lv
│ │ │ └── strings.xml
│ │ ├── values-mk
│ │ │ └── strings.xml
│ │ ├── values-ml
│ │ │ └── strings.xml
│ │ ├── values-mn
│ │ │ └── strings.xml
│ │ ├── values-mr
│ │ │ └── strings.xml
│ │ ├── values-ms
│ │ │ └── strings.xml
│ │ ├── values-my
│ │ │ └── strings.xml
│ │ ├── values-nb-rNO
│ │ │ └── strings.xml
│ │ ├── values-ne
│ │ │ └── strings.xml
│ │ ├── values-night
│ │ │ ├── bools.xml
│ │ │ └── colors.xml
│ │ ├── values-nl
│ │ │ └── strings.xml
│ │ ├── values-or
│ │ │ └── strings.xml
│ │ ├── values-pa
│ │ │ └── strings.xml
│ │ ├── values-pl
│ │ │ └── strings.xml
│ │ ├── values-pt-rBR
│ │ │ └── strings.xml
│ │ ├── values-pt-rPT
│ │ │ └── strings.xml
│ │ ├── values-pt
│ │ │ └── strings.xml
│ │ ├── values-ro
│ │ │ └── strings.xml
│ │ ├── values-ru
│ │ │ └── strings.xml
│ │ ├── values-si
│ │ │ └── strings.xml
│ │ ├── values-sk
│ │ │ └── strings.xml
│ │ ├── values-sl
│ │ │ └── strings.xml
│ │ ├── values-sq
│ │ │ └── strings.xml
│ │ ├── values-sr
│ │ │ └── strings.xml
│ │ ├── values-sv
│ │ │ └── strings.xml
│ │ ├── values-sw
│ │ │ └── strings.xml
│ │ ├── values-ta
│ │ │ └── strings.xml
│ │ ├── values-te
│ │ │ └── strings.xml
│ │ ├── values-th
│ │ │ └── strings.xml
│ │ ├── values-tl
│ │ │ └── strings.xml
│ │ ├── values-tr
│ │ │ └── strings.xml
│ │ ├── values-ug
│ │ │ └── strings.xml
│ │ ├── values-uk
│ │ │ └── strings.xml
│ │ ├── values-ur
│ │ │ └── strings.xml
│ │ ├── values-uz
│ │ │ └── strings.xml
│ │ ├── values-vi
│ │ │ └── strings.xml
│ │ ├── values-zh-rCN
│ │ │ └── strings.xml
│ │ ├── values-zh-rTW
│ │ │ └── strings.xml
│ │ ├── values-zu
│ │ │ └── strings.xml
│ │ ├── values
│ │ │ ├── arrays.xml
│ │ │ ├── bools.xml
│ │ │ ├── colors.xml
│ │ │ ├── config.xml
│ │ │ ├── strings.xml
│ │ │ └── themes.xml
│ │ └── xml
│ │ │ ├── device_filter.xml
│ │ │ ├── network_security_config.xml
│ │ │ ├── settings.xml
│ │ │ ├── settings_expert.xml
│ │ │ └── settings_scheduling.xml
│ └── resources
│ │ └── simplelogger.properties
│ ├── sharedTest
│ └── java
│ │ └── com
│ │ └── stevesoltys
│ │ └── seedvault
│ │ ├── TestUtils.kt
│ │ └── crypto
│ │ └── KeyManagerTestImpl.kt
│ └── test
│ ├── java
│ └── com
│ │ └── stevesoltys
│ │ └── seedvault
│ │ ├── TestApp.kt
│ │ ├── backend
│ │ └── saf
│ │ │ └── DocumentFileTest.kt
│ │ ├── crypto
│ │ ├── Bip39ComparisonTest.kt
│ │ ├── CryptoImplTest.kt
│ │ ├── CryptoIntegrationTest.kt
│ │ ├── CryptoTest.kt
│ │ ├── KeyManagerImplTest.kt
│ │ └── WordListTest.kt
│ │ ├── header
│ │ └── HeaderReaderTest.kt
│ │ ├── metadata
│ │ ├── MetadataManagerTest.kt
│ │ ├── MetadataReaderTest.kt
│ │ └── MetadataV0ReadTest.kt
│ │ ├── repo
│ │ ├── AppBackupManagerTest.kt
│ │ ├── BackupReceiverTest.kt
│ │ ├── BlobCacheTest.kt
│ │ ├── BlobCreatorTest.kt
│ │ ├── CheckerTest.kt
│ │ ├── PaddingTest.kt
│ │ ├── PrunerTest.kt
│ │ ├── SnapshotCreatorTest.kt
│ │ └── SnapshotManagerTest.kt
│ │ ├── restore
│ │ ├── AppSelectionManagerTest.kt
│ │ └── install
│ │ │ ├── ApkBackupRestoreTest.kt
│ │ │ ├── ApkRestoreTest.kt
│ │ │ ├── ApkRestoreV1Test.kt
│ │ │ ├── ApkSplitCompatibilityCheckerTest.kt
│ │ │ └── DeviceInfoTest.kt
│ │ ├── transport
│ │ ├── CoordinatorIntegrationTest.kt
│ │ ├── TransportTest.kt
│ │ ├── backup
│ │ │ ├── BackupCoordinatorTest.kt
│ │ │ ├── BackupCreationTest.kt
│ │ │ ├── BackupTest.kt
│ │ │ ├── FullBackupTest.kt
│ │ │ ├── KVBackupTest.kt
│ │ │ └── TestKvDbManager.kt
│ │ └── restore
│ │ │ ├── FullRestoreTest.kt
│ │ │ ├── FullRestoreV1Test.kt
│ │ │ ├── KVRestoreTest.kt
│ │ │ ├── KVRestoreV1Test.kt
│ │ │ ├── RestoreCoordinatorTest.kt
│ │ │ ├── RestoreTest.kt
│ │ │ ├── RestoreV0IntegrationTest.kt
│ │ │ └── RestoreV1IntegrationTest.kt
│ │ └── worker
│ │ ├── ApkBackupManagerTest.kt
│ │ └── ApkBackupTest.kt
│ └── resources
│ └── simplelogger.properties
├── build.gradle.kts
├── contactsbackup
├── .gitignore
├── Android.bp
├── README.md
├── build.gradle.kts
├── default-permissions_org.calyxos.backup.contacts.xml
├── libs
│ └── com.android.vcard.jar
├── lint.xml
├── src
│ ├── androidTest
│ │ ├── AndroidManifest.xml
│ │ └── java
│ │ │ └── org
│ │ │ └── calyxos
│ │ │ └── backup
│ │ │ └── contacts
│ │ │ ├── BackupRestoreTest.kt
│ │ │ └── ContactUtils.kt
│ ├── main
│ │ ├── AndroidManifest.xml
│ │ ├── java
│ │ │ └── org
│ │ │ │ └── calyxos
│ │ │ │ └── backup
│ │ │ │ └── contacts
│ │ │ │ ├── ContactsBackupAgent.java
│ │ │ │ ├── FullBackupFileHandler.java
│ │ │ │ ├── StartBroadcastReceiver.java
│ │ │ │ ├── VCardExporter.java
│ │ │ │ └── VCardImporter.java
│ │ └── res
│ │ │ ├── values-af
│ │ │ └── strings.xml
│ │ │ ├── values-am
│ │ │ └── strings.xml
│ │ │ ├── values-ar
│ │ │ └── strings.xml
│ │ │ ├── values-as
│ │ │ └── strings.xml
│ │ │ ├── values-ast
│ │ │ └── strings.xml
│ │ │ ├── values-az
│ │ │ └── strings.xml
│ │ │ ├── values-b+sr+Latn
│ │ │ └── strings.xml
│ │ │ ├── values-b+zh+Hant+HK
│ │ │ └── strings.xml
│ │ │ ├── values-be
│ │ │ └── strings.xml
│ │ │ ├── values-bg
│ │ │ └── strings.xml
│ │ │ ├── values-bn
│ │ │ └── strings.xml
│ │ │ ├── values-bs
│ │ │ └── strings.xml
│ │ │ ├── values-ca
│ │ │ └── strings.xml
│ │ │ ├── values-cs
│ │ │ └── strings.xml
│ │ │ ├── values-cy
│ │ │ └── strings.xml
│ │ │ ├── values-da
│ │ │ └── strings.xml
│ │ │ ├── values-de
│ │ │ └── strings.xml
│ │ │ ├── values-el
│ │ │ └── strings.xml
│ │ │ ├── values-en-rAU
│ │ │ └── strings.xml
│ │ │ ├── values-en-rCA
│ │ │ └── strings.xml
│ │ │ ├── values-en-rGB
│ │ │ └── strings.xml
│ │ │ ├── values-en-rIN
│ │ │ └── strings.xml
│ │ │ ├── values-eo
│ │ │ └── strings.xml
│ │ │ ├── values-es-rUS
│ │ │ └── strings.xml
│ │ │ ├── values-es
│ │ │ └── strings.xml
│ │ │ ├── values-et
│ │ │ └── strings.xml
│ │ │ ├── values-eu
│ │ │ └── strings.xml
│ │ │ ├── values-fa
│ │ │ └── strings.xml
│ │ │ ├── values-fi
│ │ │ └── strings.xml
│ │ │ ├── values-fr-rCA
│ │ │ └── strings.xml
│ │ │ ├── values-fr
│ │ │ └── strings.xml
│ │ │ ├── values-gd
│ │ │ └── strings.xml
│ │ │ ├── values-gl
│ │ │ └── strings.xml
│ │ │ ├── values-gu
│ │ │ └── strings.xml
│ │ │ ├── values-hi
│ │ │ └── strings.xml
│ │ │ ├── values-hr
│ │ │ └── strings.xml
│ │ │ ├── values-hu
│ │ │ └── strings.xml
│ │ │ ├── values-hy
│ │ │ └── strings.xml
│ │ │ ├── values-in
│ │ │ └── strings.xml
│ │ │ ├── values-is
│ │ │ └── strings.xml
│ │ │ ├── values-it
│ │ │ └── strings.xml
│ │ │ ├── values-iw
│ │ │ └── strings.xml
│ │ │ ├── values-ja
│ │ │ └── strings.xml
│ │ │ ├── values-ka
│ │ │ └── strings.xml
│ │ │ ├── values-kk
│ │ │ └── strings.xml
│ │ │ ├── values-km
│ │ │ └── strings.xml
│ │ │ ├── values-kn
│ │ │ └── strings.xml
│ │ │ ├── values-ko
│ │ │ └── strings.xml
│ │ │ ├── values-ky
│ │ │ └── strings.xml
│ │ │ ├── values-lo
│ │ │ └── strings.xml
│ │ │ ├── values-lt
│ │ │ └── strings.xml
│ │ │ ├── values-lv
│ │ │ └── strings.xml
│ │ │ ├── values-mk
│ │ │ └── strings.xml
│ │ │ ├── values-ml
│ │ │ └── strings.xml
│ │ │ ├── values-mn
│ │ │ └── strings.xml
│ │ │ ├── values-mr
│ │ │ └── strings.xml
│ │ │ ├── values-ms
│ │ │ └── strings.xml
│ │ │ ├── values-my
│ │ │ └── strings.xml
│ │ │ ├── values-nb-rNO
│ │ │ └── strings.xml
│ │ │ ├── values-ne
│ │ │ └── strings.xml
│ │ │ ├── values-nl
│ │ │ └── strings.xml
│ │ │ ├── values-or
│ │ │ └── strings.xml
│ │ │ ├── values-pa
│ │ │ └── strings.xml
│ │ │ ├── values-pl
│ │ │ └── strings.xml
│ │ │ ├── values-pt-rBR
│ │ │ └── strings.xml
│ │ │ ├── values-pt-rPT
│ │ │ └── strings.xml
│ │ │ ├── values-pt
│ │ │ └── strings.xml
│ │ │ ├── values-ro
│ │ │ └── strings.xml
│ │ │ ├── values-ru
│ │ │ └── strings.xml
│ │ │ ├── values-si
│ │ │ └── strings.xml
│ │ │ ├── values-sk
│ │ │ └── strings.xml
│ │ │ ├── values-sl
│ │ │ └── strings.xml
│ │ │ ├── values-sq
│ │ │ └── strings.xml
│ │ │ ├── values-sr
│ │ │ └── strings.xml
│ │ │ ├── values-sv
│ │ │ └── strings.xml
│ │ │ ├── values-sw
│ │ │ └── strings.xml
│ │ │ ├── values-ta
│ │ │ └── strings.xml
│ │ │ ├── values-te
│ │ │ └── strings.xml
│ │ │ ├── values-th
│ │ │ └── strings.xml
│ │ │ ├── values-tl
│ │ │ └── strings.xml
│ │ │ ├── values-tr
│ │ │ └── strings.xml
│ │ │ ├── values-ug
│ │ │ └── strings.xml
│ │ │ ├── values-uk
│ │ │ └── strings.xml
│ │ │ ├── values-ur
│ │ │ └── strings.xml
│ │ │ ├── values-uz
│ │ │ └── strings.xml
│ │ │ ├── values-vi
│ │ │ └── strings.xml
│ │ │ ├── values-zh-rCN
│ │ │ └── strings.xml
│ │ │ ├── values-zh-rTW
│ │ │ └── strings.xml
│ │ │ ├── values-zu
│ │ │ └── strings.xml
│ │ │ └── values
│ │ │ └── strings.xml
│ └── test
│ │ └── java
│ │ └── org
│ │ └── calyxos
│ │ └── backup
│ │ └── contacts
│ │ └── ContactsBackupAgentTest.kt
└── testkey.jks
├── core
├── .gitignore
├── Android.bp
├── build.gradle.kts
├── libs
│ ├── Android.bp
│ ├── dav4jvm
│ │ ├── Android.bp
│ │ ├── dav4jvm-c1bc143.jar
│ │ └── okhttp-4.12.0.jar
│ ├── kotlin-logging-jvm-6.0.3.jar
│ ├── slf4j-api-2.0.16.jar
│ └── tink-android-1.15.0.jar
└── src
│ ├── main
│ ├── AndroidManifest.xml
│ ├── java
│ │ └── org
│ │ │ └── calyxos
│ │ │ └── seedvault
│ │ │ └── core
│ │ │ ├── ByteArrayUtils.kt
│ │ │ ├── MemoryLogger.kt
│ │ │ ├── backends
│ │ │ ├── Backend.kt
│ │ │ ├── BackendFactory.kt
│ │ │ ├── BackendProperties.kt
│ │ │ ├── BackendSaver.kt
│ │ │ ├── BackendTest.kt
│ │ │ ├── Constants.kt
│ │ │ ├── FileHandle.kt
│ │ │ ├── IBackendManager.kt
│ │ │ ├── RetryBackend.kt
│ │ │ ├── saf
│ │ │ │ ├── DocumentFileCache.kt
│ │ │ │ ├── SafBackend.kt
│ │ │ │ ├── SafHelper.kt
│ │ │ │ ├── SafProperties.kt
│ │ │ │ └── UriUtils.kt
│ │ │ └── webdav
│ │ │ │ ├── WebDavBackend.kt
│ │ │ │ ├── WebDavConfig.kt
│ │ │ │ ├── WebDavHelper.kt
│ │ │ │ └── WebDavProperties.kt
│ │ │ └── crypto
│ │ │ ├── CoreCrypto.kt
│ │ │ ├── Hkdf.kt
│ │ │ └── KeyManager.kt
│ └── res
│ │ ├── values-night
│ │ └── colors.xml
│ │ └── values
│ │ ├── colors.xml
│ │ └── styles.xml
│ └── test
│ ├── java
│ └── org
│ │ └── calyxos
│ │ └── seedvault
│ │ └── core
│ │ ├── backends
│ │ ├── RetryBackendTest.kt
│ │ └── webdav
│ │ │ ├── WebDavBackendTest.kt
│ │ │ └── WebDavTestConfig.kt
│ │ └── crypto
│ │ └── HkdfTest.kt
│ └── resources
│ └── simplelogger.properties
├── default-permissions_com.stevesoltys.seedvault.xml
├── doc
└── README.md
├── gradle.properties
├── gradle
├── libs.versions.toml
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── libs
├── Android.bp
├── aosp
│ ├── android.jar
│ └── libcore.jar
├── koin-android
│ ├── Android.bp
│ ├── koin-android-3.5.6.aar
│ └── koin-core-jvm-3.5.6.jar
├── kotlin-bip39-jvm-1.0.8.jar
├── logback-android-3.0.0.aar
├── protobuf-kotlin-lite-3.21.12.jar
├── seedvault-chunker-0.1.jar
└── zstd-jni-1.5.6-5.aar
├── logcat-verbose.sh
├── permissions_com.stevesoltys.seedvault.xml
├── settings.gradle.kts
└── storage
├── .gitignore
├── README.md
├── artwork
├── ic_cloud_restore.svg
└── ic_download_library.svg
├── demo
├── .gitignore
├── build.gradle.kts
├── proguard-rules.pro
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── assets
│ └── test.jpg
│ ├── ic_launcher-playstore.png
│ ├── java
│ └── de
│ │ └── grobox
│ │ └── storagebackuptester
│ │ ├── App.kt
│ │ ├── Job.kt
│ │ ├── LogAdapter.kt
│ │ ├── LogFragment.kt
│ │ ├── MainActivity.kt
│ │ ├── MainViewModel.kt
│ │ ├── backup
│ │ └── BackupStats.kt
│ │ ├── crypto
│ │ └── KeyManager.kt
│ │ ├── plugin
│ │ └── TestSafBackend.kt
│ │ ├── restore
│ │ ├── DemoFileSelectionFragment.kt
│ │ ├── DemoSnapshotFragment.kt
│ │ ├── RestoreFragment.kt
│ │ └── RestoreStats.kt
│ │ ├── scanner
│ │ ├── DocumentScanFragment.kt
│ │ ├── DocumentScanner.kt
│ │ ├── MediaScanFragment.kt
│ │ └── MediaScanner.kt
│ │ └── settings
│ │ ├── InfoFragment.kt
│ │ ├── SettingsFragment.kt
│ │ └── SettingsManager.kt
│ └── res
│ ├── drawable
│ ├── ic_info.xml
│ ├── ic_launcher_background.xml
│ ├── ic_launcher_foreground.xml
│ ├── ic_refresh.xml
│ ├── ic_settings.xml
│ └── ic_share.xml
│ ├── layout
│ ├── activity_main.xml
│ ├── footer_files.xml
│ ├── footer_snapshot.xml
│ ├── fragment_content.xml
│ ├── fragment_log.xml
│ ├── fragment_scan.xml
│ ├── header_file_select.xml
│ └── item_log.xml
│ ├── menu
│ ├── fragment_main.xml
│ ├── fragment_scan.xml
│ └── fragment_settings.xml
│ ├── mipmap-anydpi-v26
│ └── ic_launcher.xml
│ ├── values-night
│ └── themes.xml
│ └── values
│ ├── colors.xml
│ ├── strings.xml
│ └── themes.xml
├── doc
└── design.md
├── lib
├── .gitignore
├── Android.bp
├── build.gradle.kts
├── consumer-rules.pro
├── proguard-rules.pro
├── schemas
│ └── org.calyxos.backup.storage.db.Db
│ │ ├── 1.json
│ │ └── 2.json
└── src
│ ├── androidTest
│ └── java
│ │ └── org
│ │ └── calyxos
│ │ └── backup
│ │ └── storage
│ │ └── db
│ │ ├── ChunksCacheTest.kt
│ │ ├── FilesCacheTest.kt
│ │ ├── MigrationTest.kt
│ │ └── UriStoreTest.kt
│ ├── main
│ ├── AndroidManifest.xml
│ ├── java
│ │ └── org
│ │ │ └── calyxos
│ │ │ └── backup
│ │ │ └── storage
│ │ │ ├── SnapshotRetriever.kt
│ │ │ ├── TimeUtils.kt
│ │ │ ├── UriUtils.kt
│ │ │ ├── api
│ │ │ ├── BackupContentType.kt
│ │ │ ├── BackupFile.kt
│ │ │ ├── BackupObserver.kt
│ │ │ ├── CheckObserver.kt
│ │ │ ├── CheckResult.kt
│ │ │ ├── RestoreObserver.kt
│ │ │ ├── Snapshot.kt
│ │ │ ├── StorageBackup.kt
│ │ │ └── StoragePlugin.kt
│ │ │ ├── backup
│ │ │ ├── Backup.kt
│ │ │ ├── BackupJobService.kt
│ │ │ ├── BackupService.kt
│ │ │ ├── BackupWorker.kt
│ │ │ ├── ChunkWriter.kt
│ │ │ ├── Chunker.kt
│ │ │ ├── ChunksCacheRepopulater.kt
│ │ │ ├── FileBackup.kt
│ │ │ ├── NotificationBackupObserver.kt
│ │ │ ├── SmallFileBackup.kt
│ │ │ └── ZipChunker.kt
│ │ │ ├── check
│ │ │ ├── Checker.kt
│ │ │ ├── CheckerWorker.kt
│ │ │ └── NotificationCheckObserver.kt
│ │ │ ├── content
│ │ │ └── ContentFile.kt
│ │ │ ├── crypto
│ │ │ ├── ChunkCrypto.kt
│ │ │ └── StreamCrypto.kt
│ │ │ ├── db
│ │ │ ├── ChunksCache.kt
│ │ │ ├── Db.kt
│ │ │ ├── FilesCache.kt
│ │ │ └── UriStore.kt
│ │ │ ├── prune
│ │ │ ├── Pruner.kt
│ │ │ └── RetentionManager.kt
│ │ │ ├── restore
│ │ │ ├── AbstractChunkRestore.kt
│ │ │ ├── FileRestore.kt
│ │ │ ├── FileSplitter.kt
│ │ │ ├── MultiChunkRestore.kt
│ │ │ ├── NotificationRestoreObserver.kt
│ │ │ ├── Restore.kt
│ │ │ ├── RestoreService.kt
│ │ │ ├── SingleChunkRestore.kt
│ │ │ └── ZipChunkRestore.kt
│ │ │ ├── scanner
│ │ │ ├── DocumentScanner.kt
│ │ │ ├── FileScanner.kt
│ │ │ └── MediaScanner.kt
│ │ │ └── ui
│ │ │ ├── Notifications.kt
│ │ │ ├── backup
│ │ │ ├── BackupContentAdapter.kt
│ │ │ ├── BackupContentFragment.kt
│ │ │ ├── BackupContentItem.kt
│ │ │ └── BackupContentViewModel.kt
│ │ │ ├── check
│ │ │ ├── CheckResultActivity.kt
│ │ │ ├── CheckResultFragment.kt
│ │ │ └── SnapshotFilesFragment.kt
│ │ │ └── restore
│ │ │ ├── FileSelectionFragment.kt
│ │ │ ├── FileSelectionManager.kt
│ │ │ ├── FilesAdapter.kt
│ │ │ ├── FilesItem.kt
│ │ │ ├── SnapshotAdapter.kt
│ │ │ └── SnapshotFragment.kt
│ ├── proto
│ │ ├── backup_document_file.proto
│ │ ├── backup_media_file.proto
│ │ └── backup_snapshot.proto
│ └── res
│ │ ├── drawable
│ │ ├── ic_add.xml
│ │ ├── ic_audio_file.xml
│ │ ├── ic_auto_delete.xml
│ │ ├── ic_chevron_right.xml
│ │ ├── ic_cloud_done.xml
│ │ ├── ic_cloud_error.xml
│ │ ├── ic_cloud_restore.xml
│ │ ├── ic_cloud_search.xml
│ │ ├── ic_cloud_upload.xml
│ │ ├── ic_download_library.xml
│ │ ├── ic_folder.xml
│ │ ├── ic_image.xml
│ │ ├── ic_indeterminate_check_box.xml
│ │ ├── ic_insert_drive_file.xml
│ │ ├── ic_keyboard_arrow_down.xml
│ │ ├── ic_more_vert.xml
│ │ ├── ic_music_library.xml
│ │ ├── ic_photo_library.xml
│ │ ├── ic_video_file.xml
│ │ ├── ic_video_library.xml
│ │ └── ic_warning.xml
│ │ ├── layout
│ │ ├── activity_check_results.xml
│ │ ├── fragment_backup_content.xml
│ │ ├── fragment_check_results.xml
│ │ ├── fragment_select_files.xml
│ │ ├── fragment_snapshot.xml
│ │ ├── header_snapshot_files.xml
│ │ ├── item_custom.xml
│ │ ├── item_file.xml
│ │ ├── item_media.xml
│ │ └── item_snapshot.xml
│ │ ├── menu
│ │ └── item_custom.xml
│ │ ├── values-af
│ │ └── strings.xml
│ │ ├── values-am
│ │ └── strings.xml
│ │ ├── values-ar
│ │ └── strings.xml
│ │ ├── values-as
│ │ └── strings.xml
│ │ ├── values-ast
│ │ └── strings.xml
│ │ ├── values-az
│ │ └── strings.xml
│ │ ├── values-b+sr+Latn
│ │ └── strings.xml
│ │ ├── values-b+zh+Hant+HK
│ │ └── strings.xml
│ │ ├── values-be
│ │ └── strings.xml
│ │ ├── values-bg
│ │ └── strings.xml
│ │ ├── values-bn
│ │ └── strings.xml
│ │ ├── values-bs
│ │ └── strings.xml
│ │ ├── values-ca
│ │ └── strings.xml
│ │ ├── values-cs
│ │ └── strings.xml
│ │ ├── values-cy
│ │ └── strings.xml
│ │ ├── values-da
│ │ └── strings.xml
│ │ ├── values-de
│ │ └── strings.xml
│ │ ├── values-el
│ │ └── strings.xml
│ │ ├── values-en-rAU
│ │ └── strings.xml
│ │ ├── values-en-rCA
│ │ └── strings.xml
│ │ ├── values-en-rGB
│ │ └── strings.xml
│ │ ├── values-en-rIN
│ │ └── strings.xml
│ │ ├── values-eo
│ │ └── strings.xml
│ │ ├── values-es-rUS
│ │ └── strings.xml
│ │ ├── values-es
│ │ └── strings.xml
│ │ ├── values-et
│ │ └── strings.xml
│ │ ├── values-eu
│ │ └── strings.xml
│ │ ├── values-fa
│ │ └── strings.xml
│ │ ├── values-fi
│ │ └── strings.xml
│ │ ├── values-fr-rCA
│ │ └── strings.xml
│ │ ├── values-fr
│ │ └── strings.xml
│ │ ├── values-gd
│ │ └── strings.xml
│ │ ├── values-gl
│ │ └── strings.xml
│ │ ├── values-gu
│ │ └── strings.xml
│ │ ├── values-hi
│ │ └── strings.xml
│ │ ├── values-hr
│ │ └── strings.xml
│ │ ├── values-hu
│ │ └── strings.xml
│ │ ├── values-hy
│ │ └── strings.xml
│ │ ├── values-in
│ │ └── strings.xml
│ │ ├── values-is
│ │ └── strings.xml
│ │ ├── values-it
│ │ └── strings.xml
│ │ ├── values-iw
│ │ └── strings.xml
│ │ ├── values-ja
│ │ └── strings.xml
│ │ ├── values-ka
│ │ └── strings.xml
│ │ ├── values-kk
│ │ └── strings.xml
│ │ ├── values-km
│ │ └── strings.xml
│ │ ├── values-kn
│ │ └── strings.xml
│ │ ├── values-ko
│ │ └── strings.xml
│ │ ├── values-ky
│ │ └── strings.xml
│ │ ├── values-lo
│ │ └── strings.xml
│ │ ├── values-lt
│ │ └── strings.xml
│ │ ├── values-lv
│ │ └── strings.xml
│ │ ├── values-mk
│ │ └── strings.xml
│ │ ├── values-ml
│ │ └── strings.xml
│ │ ├── values-mn
│ │ └── strings.xml
│ │ ├── values-mr
│ │ └── strings.xml
│ │ ├── values-ms
│ │ └── strings.xml
│ │ ├── values-my
│ │ └── strings.xml
│ │ ├── values-nb-rNO
│ │ └── strings.xml
│ │ ├── values-ne
│ │ └── strings.xml
│ │ ├── values-nl
│ │ └── strings.xml
│ │ ├── values-or
│ │ └── strings.xml
│ │ ├── values-pa
│ │ └── strings.xml
│ │ ├── values-pl
│ │ └── strings.xml
│ │ ├── values-pt-rBR
│ │ └── strings.xml
│ │ ├── values-pt-rPT
│ │ └── strings.xml
│ │ ├── values-pt
│ │ └── strings.xml
│ │ ├── values-ro
│ │ └── strings.xml
│ │ ├── values-ru
│ │ └── strings.xml
│ │ ├── values-si
│ │ └── strings.xml
│ │ ├── values-sk
│ │ └── strings.xml
│ │ ├── values-sl
│ │ └── strings.xml
│ │ ├── values-sq
│ │ └── strings.xml
│ │ ├── values-sr
│ │ └── strings.xml
│ │ ├── values-sv
│ │ └── strings.xml
│ │ ├── values-sw
│ │ └── strings.xml
│ │ ├── values-ta
│ │ └── strings.xml
│ │ ├── values-te
│ │ └── strings.xml
│ │ ├── values-th
│ │ └── strings.xml
│ │ ├── values-tl
│ │ └── strings.xml
│ │ ├── values-tr
│ │ └── strings.xml
│ │ ├── values-ug
│ │ └── strings.xml
│ │ ├── values-uk
│ │ └── strings.xml
│ │ ├── values-ur
│ │ └── strings.xml
│ │ ├── values-uz
│ │ └── strings.xml
│ │ ├── values-vi
│ │ └── strings.xml
│ │ ├── values-zh-rCN
│ │ └── strings.xml
│ │ ├── values-zh-rTW
│ │ └── strings.xml
│ │ ├── values-zu
│ │ └── strings.xml
│ │ └── values
│ │ └── strings.xml
│ └── test
│ └── java
│ └── org
│ └── calyxos
│ └── backup
│ └── storage
│ ├── BackupRestoreTest.kt
│ ├── TestUtils.kt
│ ├── backup
│ ├── BackupTest.kt
│ ├── ChunkWriterTest.kt
│ ├── ChunkerTest.kt
│ ├── ChunksCacheRepopulaterTest.kt
│ ├── SmallFileBackupIntegrationTest.kt
│ ├── SmallFileBackupTest.kt
│ └── ZipChunkerTest.kt
│ ├── prune
│ ├── PrunerTest.kt
│ └── RetentionManagerTest.kt
│ └── restore
│ └── FileSplitterTest.kt
├── lint.xml
└── logcat-verbose.sh
/.editorconfig:
--------------------------------------------------------------------------------
1 | [*]
2 | charset = utf-8
3 | end_of_line = lf
4 | insert_final_newline = true
5 | trim_trailing_whitespace = true
6 |
7 | [*.{kt,kts}]
8 | indent_size = 4
9 | max_line_length = 100
10 |
11 | [app/src/main/res/values-*/strings.xml]
12 | insert_final_newline = unset
13 | trim_trailing_whitespace = unset
14 |
15 | [*.md]
16 | trim_trailing_whitespace = false
17 |
18 | [gradlew.bat]
19 | charset = latin1
20 | end_of_line = crlf
21 | insert_final_newline = false
22 |
23 | [.editorconfig]
24 | ij_editorconfig_spaces_around_assignment_operators = true
25 |
--------------------------------------------------------------------------------
/.github/scripts/run_tests.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | # SPDX-FileCopyrightText: 2023 The Calyx Institute
3 | # SPDX-License-Identifier: Apache-2.0
4 | #
5 |
6 | echo "Disable auto-restore"
7 | adb shell bmgr autorestore false
8 |
9 | echo "Installing Seedvault app..."
10 | ./gradlew --stacktrace :app:installDebugAndroidTest
11 | sleep 60
12 |
13 | large_test_exit_code=0
14 | ./gradlew --stacktrace -Pinstrumented_test_size=large :app:connectedAndroidTest || large_test_exit_code=$?
15 |
16 | adb pull /sdcard/seedvault_test_results
17 |
18 | if [ "$large_test_exit_code" -ne 0 ]; then
19 | echo 'Large tests failed.'
20 | exit 1
21 | fi
22 |
23 | medium_test_exit_code=0
24 | ./gradlew --stacktrace -Pinstrumented_test_size=medium :app:connectedAndroidTest || medium_test_exit_code=$?
25 |
26 | if [ "$medium_test_exit_code" -ne 0 ]; then
27 | echo 'Medium tests failed.'
28 | exit 1
29 | fi
30 |
31 | exit 0
32 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Java
2 | *.class
3 | *.war
4 | *.ear
5 | hs_err_pid*
6 |
7 | ## Intellij
8 | out/
9 | build/
10 | storage/build/
11 | contactsbackup/build/
12 | /lib/
13 | .idea/*
14 | !.idea/runConfigurations*
15 | !.idea/inspectionProfiles*
16 | !.idea/codeStyles*
17 | !.idea/copyright*
18 | !.idea/dictionaries*
19 | !.idea/scopes*
20 | !.idea/.name
21 | *.ipr
22 | *.iws
23 | *.iml
24 |
25 | ## Eclipse
26 | .classpath
27 | .project
28 | .metadata
29 | **/bin/
30 | tmp/
31 | *.tmp
32 | *.bak
33 | *.swp
34 | *~.nib
35 | local.properties
36 | .settings/
37 | .loadpath
38 | .externalToolBuilders/
39 | *.launch
40 |
41 | ## NetBeans
42 | **/nbproject/private/
43 | /build/
44 | /app/build/
45 | nbbuild/
46 | dist/
47 | nbdist/
48 | nbactions.xml
49 | nb-configuration.xml
50 |
51 | ## Gradle
52 | .gradle
53 | keystore.properties
54 | gradle-app.setting
55 |
56 | ## OS Specific
57 | .DS_Store
58 |
59 | ## Android
60 | gen/
61 |
--------------------------------------------------------------------------------
/.idea/.name:
--------------------------------------------------------------------------------
1 | Seedvault
--------------------------------------------------------------------------------
/.idea/codeStyles/codeStyleConfig.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/copyright/Apache_2_0.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/copyright/profiles_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/dictionaries/user.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | apk
5 | chunker
6 | davx
7 | ejectable
8 | hasher
9 | hkdf
10 | launchable
11 | repopulater
12 | restorable
13 | seedvault
14 | snowden
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/.idea/inspectionProfiles/Project_Default.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/.idea/runConfigurations/All_unit_tests.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.idea/runConfigurations/Unit_tests__app.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/.idea/runConfigurations/Unit_tests__contactsbackup.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/.idea/runConfigurations/Unit_tests__storage_lib.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/.idea/runConfigurations/seedvault_storage_lib__assembleRelease_.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
11 |
16 |
17 |
18 | true
19 |
20 |
21 |
--------------------------------------------------------------------------------
/.idea/scopes/Kotlin_Files.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/.idea/scopes/XML_Files.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/LICENSES/MIT.txt:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c)
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6 |
7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8 |
9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
10 |
--------------------------------------------------------------------------------
/SECURITY.md:
--------------------------------------------------------------------------------
1 | # Reporting Security Issues
2 |
3 | The Seedvault team and community take security bugs seriously.
4 | We appreciate your efforts to responsibly disclose your findings,
5 | and will make every effort to acknowledge your contributions.
6 |
7 | To report a security issue,
8 | please send an email to `security@seedvault.app`
9 | or use the GitHub Security Advisory
10 | ["Report a Vulnerability"](https://github.com/seedvault-app/seedvault/security/advisories/new) tab.
11 |
12 | The Seedvault team will send a response indicating the next steps in handling your report.
13 | After the initial reply to your report,
14 | we will keep you informed of the progress towards a fix and full announcement,
15 | and may ask for additional information or guidance.
16 |
17 | # Older platform branches
18 |
19 | Due to API breakage in AOSP versions, we have one branch per major AOSP release,
20 | e.g. `android14` and `android15`.
21 | Note that typically only the latest branch is maintained.
22 | This means that fixes for **security issues do not get backported** to older branches automatically.
23 | Please get in touch if you want to maintain an older branch.
24 |
--------------------------------------------------------------------------------
/allowlist_com.stevesoltys.seedvault.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/app/development/platform.jks:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seedvault-app/seedvault/cdc31be96d492b8c0d269f07d6a86afe9b678f3e/app/development/platform.jks
--------------------------------------------------------------------------------
/app/development/scripts/clear_app_data.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | #
3 | # SPDX-FileCopyrightText: 2023 The Calyx Institute
4 | # SPDX-License-Identifier: Apache-2.0
5 | #
6 |
7 | # assert ANDROID_HOME is set
8 | if [ -z "$ANDROID_HOME" ]; then
9 | echo "ANDROID_HOME is not set"
10 | exit 1
11 | fi
12 |
13 | SCRIPT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &>/dev/null && pwd)
14 | DEVELOPMENT_DIR=$SCRIPT_DIR/..
15 | ROOT_PROJECT_DIR=$SCRIPT_DIR/../../..
16 |
17 | EMULATOR_DEVICE_NAME=$($ANDROID_HOME/platform-tools/adb devices | grep emulator | cut -f1)
18 |
19 | if [ -z "$EMULATOR_DEVICE_NAME" ]; then
20 | echo "Emulator device name not found"
21 | exit 1
22 | fi
23 |
24 | ADB="$ANDROID_HOME/platform-tools/adb -s $EMULATOR_DEVICE_NAME"
25 |
26 | $ADB shell pm clear com.stevesoltys.seedvault
27 |
--------------------------------------------------------------------------------
/app/development/scripts/start_emulator.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | #
3 | # SPDX-FileCopyrightText: 2023 The Calyx Institute
4 | # SPDX-License-Identifier: Apache-2.0
5 | #
6 |
7 | # assert ANDROID_HOME is set
8 | if [ -z "$ANDROID_HOME" ]; then
9 | echo "ANDROID_HOME is not set"
10 | exit 1
11 | fi
12 |
13 | # assert 1 parameter is provided
14 | if [ $# -ne 1 ]; then
15 | echo "Usage: $0 "
16 | exit 1
17 | fi
18 |
19 | EMULATOR_NAME=$1
20 |
21 | echo "Starting emulator..."
22 | nohup $ANDROID_HOME/emulator/emulator -avd "$EMULATOR_NAME" -gpu swiftshader_indirect -writable-system >/dev/null 2>&1 &
23 |
--------------------------------------------------------------------------------
/app/lint.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/androidTest/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/app/src/androidTest/java/com/stevesoltys/seedvault/KoinInstrumentationTestRunner.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * SPDX-FileCopyrightText: 2023 The Calyx Institute
3 | * SPDX-License-Identifier: Apache-2.0
4 | */
5 |
6 | package com.stevesoltys.seedvault
7 |
8 | import android.app.Application
9 | import android.content.Context
10 | import androidx.test.runner.AndroidJUnitRunner
11 |
12 | class KoinInstrumentationTestRunner : AndroidJUnitRunner() {
13 |
14 | override fun newApplication(
15 | classLoader: ClassLoader?,
16 | className: String?,
17 | context: Context?,
18 | ): Application {
19 | return super.newApplication(
20 | classLoader,
21 | KoinInstrumentationTestApp::class.java.name,
22 | context
23 | )
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/app/src/androidTest/java/com/stevesoltys/seedvault/e2e/SeedvaultLargeTestResult.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * SPDX-FileCopyrightText: 2023 The Calyx Institute
3 | * SPDX-License-Identifier: Apache-2.0
4 | */
5 |
6 | package com.stevesoltys.seedvault.e2e
7 |
8 | import android.content.pm.PackageInfo
9 | import com.stevesoltys.seedvault.metadata.PackageMetadata
10 | import com.stevesoltys.seedvault.restore.AppRestoreResult
11 |
12 | /**
13 | * Contains maps of (package name -> SHA-256 hashes) of application data.
14 | *
15 | * During backups and restores, we intercept the package data and store the result here.
16 | * We can use this to validate that the restored app data actually matches the backed up data.
17 | *
18 | * For full backups, the mapping is: Map
19 | * For K/V backups, the mapping is: Map>
20 | */
21 | internal data class SeedvaultLargeTestResult(
22 | val backupResults: Map = emptyMap(),
23 | val restoreResults: Map = emptyMap(),
24 | val full: MutableMap,
25 | val kv: MutableMap>,
26 | val userApps: List,
27 | ) {
28 | fun allUserApps() = userApps
29 | }
30 |
--------------------------------------------------------------------------------
/app/src/androidTest/java/com/stevesoltys/seedvault/e2e/io/BackupDataInputIntercept.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * SPDX-FileCopyrightText: 2023 The Calyx Institute
3 | * SPDX-License-Identifier: Apache-2.0
4 | */
5 |
6 | package com.stevesoltys.seedvault.e2e.io
7 |
8 | import android.app.backup.BackupDataInput
9 | import java.io.FileDescriptor
10 |
11 | class BackupDataInputIntercept(
12 | fileDescriptor: FileDescriptor,
13 | private val callback: (String, ByteArray) -> Unit,
14 | ) : BackupDataInput(fileDescriptor) {
15 |
16 | var currentKey: String? = null
17 |
18 | override fun getKey(): String? {
19 | currentKey = super.getKey()
20 | return currentKey
21 | }
22 |
23 | override fun readEntityData(data: ByteArray, offset: Int, size: Int): Int {
24 | val result = super.readEntityData(data, offset, size)
25 |
26 | callback(currentKey!!, data.copyOf(result))
27 | return result
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/app/src/androidTest/java/com/stevesoltys/seedvault/e2e/io/BackupDataOutputIntercept.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * SPDX-FileCopyrightText: 2023 The Calyx Institute
3 | * SPDX-License-Identifier: Apache-2.0
4 | */
5 |
6 | package com.stevesoltys.seedvault.e2e.io
7 |
8 | import android.app.backup.BackupDataOutput
9 | import java.io.FileDescriptor
10 |
11 | class BackupDataOutputIntercept(
12 | fileDescriptor: FileDescriptor,
13 | private val callback: (String, ByteArray) -> Unit,
14 | ) : BackupDataOutput(fileDescriptor) {
15 |
16 | private var currentKey: String? = null
17 |
18 | override fun writeEntityHeader(key: String, dataSize: Int): Int {
19 | currentKey = key
20 | return super.writeEntityHeader(key, dataSize)
21 | }
22 |
23 | override fun writeEntityData(data: ByteArray, size: Int): Int {
24 | callback(currentKey!!, data.copyOf())
25 |
26 | return super.writeEntityData(data, size)
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/app/src/androidTest/java/com/stevesoltys/seedvault/e2e/screen/impl/BackupScreen.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * SPDX-FileCopyrightText: 2023 The Calyx Institute
3 | * SPDX-License-Identifier: Apache-2.0
4 | */
5 |
6 | package com.stevesoltys.seedvault.e2e.screen.impl
7 |
8 | import android.os.Build
9 | import androidx.test.uiautomator.By
10 | import androidx.test.uiautomator.BySelector
11 | import com.stevesoltys.seedvault.e2e.screen.UiDeviceScreen
12 |
13 | object BackupScreen : UiDeviceScreen() {
14 |
15 | val backupMenu = findObject { description("More options") }
16 |
17 | val backupNowButton = findObject { text("Backup now") }
18 |
19 | val backupStatusButton = findObject { text("Backup status") }
20 |
21 | val backupLocationButton = findObject { text("Backup location") }
22 |
23 | val backupSwitch = findObject { text("Backup my apps") }
24 |
25 | val internalStorageButton = findObject { textContains(Build.MODEL) }
26 |
27 | val useAnywayButton = findObject { text("Use anyway") }
28 |
29 | val initializingText: BySelector = By.textContains("Initializing backup location")
30 | }
31 |
--------------------------------------------------------------------------------
/app/src/androidTest/java/com/stevesoltys/seedvault/e2e/screen/impl/DocumentPickerScreen.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * SPDX-FileCopyrightText: 2023 The Calyx Institute
3 | * SPDX-License-Identifier: Apache-2.0
4 | */
5 |
6 | package com.stevesoltys.seedvault.e2e.screen.impl
7 |
8 | import android.widget.EditText
9 | import com.stevesoltys.seedvault.e2e.screen.UiDeviceScreen
10 |
11 | object DocumentPickerScreen : UiDeviceScreen() {
12 |
13 | val createNewFolderButton = findObject { text("CREATE NEW FOLDER") }
14 |
15 | val useThisFolderButton = findObject { text("USE THIS FOLDER") }
16 |
17 | val textBox = findObject { className(EditText::class.java) }
18 |
19 | val okButton = findObject { text("OK") }
20 |
21 | val allowButton = findObject { text("ALLOW") }
22 |
23 | fun existingFolder(folderName: String) = findObject { text(folderName) }
24 | }
25 |
--------------------------------------------------------------------------------
/app/src/androidTest/java/com/stevesoltys/seedvault/e2e/screen/impl/RecoveryCodeScreen.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * SPDX-FileCopyrightText: 2023 The Calyx Institute
3 | * SPDX-License-Identifier: Apache-2.0
4 | */
5 |
6 | package com.stevesoltys.seedvault.e2e.screen.impl
7 |
8 | import com.stevesoltys.seedvault.e2e.screen.UiDeviceScreen
9 |
10 | object RecoveryCodeScreen : UiDeviceScreen() {
11 |
12 | val startNewBackupButton = findObject { text("Start new") }
13 |
14 | val confirmCodeButton = findObject { text("Confirm code") }
15 |
16 | val verifyCodeButton = findObject { text("Verify") }
17 |
18 | fun wordTextField(index: Int) = findObject { text("Word ${index + 1}") }
19 | }
20 |
--------------------------------------------------------------------------------
/app/src/androidTest/java/com/stevesoltys/seedvault/e2e/screen/impl/RestoreScreen.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * SPDX-FileCopyrightText: 2023 The Calyx Institute
3 | * SPDX-License-Identifier: Apache-2.0
4 | */
5 |
6 | package com.stevesoltys.seedvault.e2e.screen.impl
7 |
8 | import com.stevesoltys.seedvault.e2e.screen.UiDeviceScreen
9 |
10 | object RestoreScreen : UiDeviceScreen() {
11 |
12 | val backupListItem = findObject {
13 | textContains("Android SDK") // device name of test backups
14 | }
15 |
16 | val appsSelectedButton = findObject { text("Restore backup") }
17 |
18 | val nextButton = findObject { text("Next") }
19 |
20 | val finishButton = findObject { text("Finish") }
21 |
22 | val skipButton = findObject { text("Skip restoring files") }
23 |
24 | val someAppsNotInstalledText = findObject { textContains("Some apps") }
25 |
26 | val someAppsNotRestoredText = findObject { textContains("some apps") }
27 | }
28 |
--------------------------------------------------------------------------------
/app/src/debug/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
8 |
9 |
10 |
11 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/app/src/debug/res/values/arrays.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 | - Every 15 minutes
9 | - @string/settings_scheduling_frequency_12_hours
10 | - @string/settings_scheduling_frequency_daily
11 | - @string/settings_scheduling_frequency_3_days
12 | - @string/settings_scheduling_frequency_weekly
13 |
14 |
15 |
16 | - 900000
17 | - 43200000
18 | - 86400000
19 | - 259200000
20 | - 604800000
21 |
22 |
23 |
--------------------------------------------------------------------------------
/app/src/debug/res/values/config.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 | - com.android.externalstorage.documents
9 | - org.nextcloud.documents
10 | - org.nextcloud.beta.documents
11 | - at.bitfire.davdroid.webdav
12 | - de.felixnuesse.extract.vcp
13 |
14 |
15 | - com.android.externalstorage.documents
16 | - org.nextcloud.documents
17 | - org.nextcloud.beta.documents
18 | - at.bitfire.davdroid.webdav
19 | - de.felixnuesse.extract.vcp
20 |
21 |
22 |
--------------------------------------------------------------------------------
/app/src/main/assets/logback.xml:
--------------------------------------------------------------------------------
1 |
5 |
10 |
11 |
12 | %logger{12}
13 |
14 |
15 | [%-20thread] %msg
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/app/src/main/java/com/stevesoltys/seedvault/Base64Utils.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * SPDX-FileCopyrightText: 2020 The Calyx Institute
3 | * SPDX-License-Identifier: Apache-2.0
4 | */
5 |
6 | package com.stevesoltys.seedvault
7 |
8 | import java.nio.charset.Charset
9 | import java.util.Base64
10 |
11 | val Utf8: Charset = Charset.forName("UTF-8")
12 |
13 | fun ByteArray.encodeBase64(): String {
14 | return Base64.getUrlEncoder().withoutPadding().encodeToString(this)
15 | }
16 |
17 | fun String.encodeBase64(): String {
18 | return toByteArray(Utf8).encodeBase64()
19 | }
20 |
21 | fun String.decodeBase64(): String {
22 | return String(Base64.getUrlDecoder().decode(this))
23 | }
24 |
--------------------------------------------------------------------------------
/app/src/main/java/com/stevesoltys/seedvault/Clock.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * SPDX-FileCopyrightText: 2020 The Calyx Institute
3 | * SPDX-License-Identifier: Apache-2.0
4 | */
5 |
6 | package com.stevesoltys.seedvault
7 |
8 | /**
9 | * This class only exists, so we can mock the time in tests.
10 | */
11 | class Clock {
12 | /**
13 | * Returns the current time in milliseconds (Unix time).
14 | */
15 | fun time(): Long {
16 | return System.currentTimeMillis()
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/app/src/main/java/com/stevesoltys/seedvault/backend/saf/DocumentsProviderModule.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * SPDX-FileCopyrightText: 2020 The Calyx Institute
3 | * SPDX-License-Identifier: Apache-2.0
4 | */
5 |
6 | package com.stevesoltys.seedvault.backend.saf
7 |
8 | import com.stevesoltys.seedvault.backend.LegacyStoragePlugin
9 | import com.stevesoltys.seedvault.settings.SettingsManager
10 | import org.koin.android.ext.koin.androidContext
11 | import org.koin.dsl.module
12 |
13 | val storagePluginModuleSaf = module {
14 | single { SafHandler(androidContext(), get(), get(), get()) }
15 |
16 | @Suppress("Deprecation")
17 | single {
18 | DocumentsProviderLegacyPlugin(
19 | context = androidContext(),
20 | storageGetter = {
21 | val safProperties = get().getSafProperties()
22 | ?: error("No SAF storage")
23 | DocumentsStorage(androidContext(), safProperties)
24 | },
25 | )
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/app/src/main/java/com/stevesoltys/seedvault/backend/webdav/WebDavModule.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * SPDX-FileCopyrightText: 2024 The Calyx Institute
3 | * SPDX-License-Identifier: Apache-2.0
4 | */
5 |
6 | package com.stevesoltys.seedvault.backend.webdav
7 |
8 | import org.koin.android.ext.koin.androidContext
9 | import org.koin.dsl.module
10 |
11 | val storagePluginModuleWebDav = module {
12 | single { WebDavHandler(androidContext(), get(), get(), get()) }
13 | }
14 |
--------------------------------------------------------------------------------
/app/src/main/java/com/stevesoltys/seedvault/crypto/CryptoModule.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * SPDX-FileCopyrightText: 2020 The Calyx Institute
3 | * SPDX-License-Identifier: Apache-2.0
4 | */
5 |
6 | package com.stevesoltys.seedvault.crypto
7 |
8 | import org.koin.android.ext.koin.androidContext
9 | import org.koin.dsl.module
10 | import java.security.KeyStore
11 |
12 | const val ANDROID_KEY_STORE = "AndroidKeyStore"
13 |
14 | val cryptoModule = module {
15 | factory { CipherFactoryImpl(get()) }
16 | single {
17 | val keyStore by lazy {
18 | KeyStore.getInstance(ANDROID_KEY_STORE).apply {
19 | load(null)
20 | }
21 | }
22 | KeyManagerImpl(keyStore)
23 | }
24 | single { CryptoImpl(androidContext(), get(), get(), get()) }
25 | }
26 |
--------------------------------------------------------------------------------
/app/src/main/java/com/stevesoltys/seedvault/header/HeaderModule.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * SPDX-FileCopyrightText: 2020 The Calyx Institute
3 | * SPDX-License-Identifier: Apache-2.0
4 | */
5 |
6 | package com.stevesoltys.seedvault.header
7 |
8 | import org.koin.dsl.module
9 |
10 | val headerModule = module {
11 | single { HeaderReaderImpl() }
12 | }
13 |
--------------------------------------------------------------------------------
/app/src/main/java/com/stevesoltys/seedvault/metadata/MetadataModule.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * SPDX-FileCopyrightText: 2020 The Calyx Institute
3 | * SPDX-License-Identifier: Apache-2.0
4 | */
5 |
6 | package com.stevesoltys.seedvault.metadata
7 |
8 | import org.koin.android.ext.koin.androidContext
9 | import org.koin.dsl.module
10 |
11 | val metadataModule = module {
12 | single { MetadataManager(androidContext(), get(), get(), get()) }
13 | single { MetadataWriterImpl() }
14 | single { MetadataReaderImpl(get()) }
15 | }
16 |
--------------------------------------------------------------------------------
/app/src/main/java/com/stevesoltys/seedvault/repo/BackupData.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * SPDX-FileCopyrightText: 2024 The Calyx Institute
3 | * SPDX-License-Identifier: Apache-2.0
4 | */
5 |
6 | package com.stevesoltys.seedvault.repo
7 |
8 | import com.stevesoltys.seedvault.proto.Snapshot.Blob
9 |
10 | /**
11 | * Essential metadata returned when storing backup data.
12 | *
13 | * @param chunkIds an ordered(!) list of the chunk IDs required to re-assemble the backup data.
14 | * @param blobMap a mapping from chunk ID to [Blob] on the backend.
15 | * Needed for fetching blobs from the backend for re-assembly.
16 | */
17 | data class BackupData(
18 | val chunkIds: List,
19 | val blobMap: Map,
20 | ) {
21 | /**
22 | * The uncompressed plaintext size of all blobs.
23 | */
24 | val size get() = blobMap.values.sumOf { it.uncompressedLength }.toLong()
25 | }
26 |
--------------------------------------------------------------------------------
/app/src/main/java/com/stevesoltys/seedvault/repo/Padding.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * SPDX-FileCopyrightText: 2024 The Calyx Institute
3 | * SPDX-License-Identifier: Apache-2.0
4 | */
5 |
6 | package com.stevesoltys.seedvault.repo
7 |
8 | import kotlin.math.floor
9 | import kotlin.math.log2
10 | import kotlin.math.pow
11 |
12 | object Padding {
13 |
14 | /**
15 | * Pads the given [size] using the [Padmé algorithm](https://lbarman.ch/blog/padme/).
16 | *
17 | * @param size unpadded object length
18 | * @return the padded object length
19 | */
20 | fun getPadTo(size: Int): Int {
21 | val e = floor(log2(size.toFloat()))
22 | val s = floor(log2(e)) + 1
23 | val lastBits = e - s
24 | val bitMask = (2.toFloat().pow(lastBits) - 1).toInt()
25 | return (size + bitMask) and bitMask.inv()
26 | }
27 |
28 | }
29 |
--------------------------------------------------------------------------------
/app/src/main/java/com/stevesoltys/seedvault/repo/RepoModule.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * SPDX-FileCopyrightText: 2024 The Calyx Institute
3 | * SPDX-License-Identifier: Apache-2.0
4 | */
5 |
6 | package com.stevesoltys.seedvault.repo
7 |
8 | import org.koin.android.ext.koin.androidContext
9 | import org.koin.dsl.module
10 | import java.io.File
11 |
12 | val repoModule = module {
13 | single { AppBackupManager(get(), get(), get(), get(), get(), get()) }
14 | single { BackupReceiver(get(), get(), get()) }
15 | single { BlobCache(androidContext()) }
16 | single { BlobCreator(get(), get()) }
17 | single { Loader(get(), get()) }
18 | single {
19 | val snapshotFolder = File(androidContext().filesDir, FOLDER_SNAPSHOTS)
20 | SnapshotManager(snapshotFolder, get(), get(), get())
21 | }
22 | factory { SnapshotCreatorFactory(androidContext(), get(), get(), get(), get()) }
23 | factory { Pruner(get(), get(), get(), get()) }
24 | single { Checker(get(), get(), get(), get(), get(), get()) }
25 | }
26 |
--------------------------------------------------------------------------------
/app/src/main/java/com/stevesoltys/seedvault/repo/SnapshotCreatorFactory.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * SPDX-FileCopyrightText: 2024 The Calyx Institute
3 | * SPDX-License-Identifier: Apache-2.0
4 | */
5 |
6 | package com.stevesoltys.seedvault.repo
7 |
8 | import android.content.Context
9 | import com.stevesoltys.seedvault.Clock
10 | import com.stevesoltys.seedvault.metadata.MetadataManager
11 | import com.stevesoltys.seedvault.transport.backup.BackupInitializer
12 | import com.stevesoltys.seedvault.transport.backup.PackageService
13 |
14 | /**
15 | * Creates a new [SnapshotCreator], because one is only valid for a single backup run.
16 | */
17 | internal class SnapshotCreatorFactory(
18 | private val context: Context,
19 | private val clock: Clock,
20 | private val packageService: PackageService,
21 | private val metadataManager: MetadataManager,
22 | private val backupInitializer: BackupInitializer,
23 | ) {
24 | fun createSnapshotCreator() =
25 | SnapshotCreator(context, clock, packageService, metadataManager, backupInitializer)
26 | }
27 |
--------------------------------------------------------------------------------
/app/src/main/java/com/stevesoltys/seedvault/restore/RestoreUiModule.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * SPDX-FileCopyrightText: 2020 The Calyx Institute
3 | * SPDX-License-Identifier: Apache-2.0
4 | */
5 |
6 | package com.stevesoltys.seedvault.restore
7 |
8 | import com.stevesoltys.seedvault.ui.files.FileSelectionViewModel
9 | import org.calyxos.backup.storage.ui.restore.FileSelectionManager
10 | import org.koin.android.ext.koin.androidApplication
11 | import org.koin.androidx.viewmodel.dsl.viewModel
12 | import org.koin.dsl.module
13 |
14 | val restoreUiModule = module {
15 | single { FileSelectionManager() }
16 | viewModel {
17 | RestoreViewModel(
18 | app = androidApplication(),
19 | settingsManager = get(),
20 | keyManager = get(),
21 | backupManager = get(),
22 | appBackupManager = get(),
23 | restoreCoordinator = get(),
24 | apkRestore = get(),
25 | iconManager = get(),
26 | storageBackup = get(),
27 | backendManager = get(),
28 | fileSelectionManager = get(),
29 | )
30 | }
31 | viewModel { FileSelectionViewModel(androidApplication(), get()) }
32 | }
33 |
--------------------------------------------------------------------------------
/app/src/main/java/com/stevesoltys/seedvault/restore/install/InstallModule.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * SPDX-FileCopyrightText: 2020 The Calyx Institute
3 | * SPDX-License-Identifier: Apache-2.0
4 | */
5 |
6 | package com.stevesoltys.seedvault.restore.install
7 |
8 | import android.os.UserManager
9 | import org.koin.android.ext.koin.androidContext
10 | import org.koin.dsl.module
11 |
12 | val installModule = module {
13 | factory { ApkInstaller(androidContext()) }
14 | factory { DeviceInfo(androidContext()) }
15 | factory { ApkSplitCompatibilityChecker(get()) }
16 | factory {
17 | ApkRestore(androidContext(), get(), get(), get(), get(), get(), get(), get(), get()) {
18 | androidContext().getSystemService(UserManager::class.java)!!.isAllowedToInstallApks()
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/app/src/main/java/com/stevesoltys/seedvault/restore/install/InstallRestriction.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * SPDX-FileCopyrightText: 2023 The Calyx Institute
3 | * SPDX-License-Identifier: Apache-2.0
4 | */
5 |
6 | package com.stevesoltys.seedvault.restore.install
7 |
8 | import android.os.UserManager
9 | import android.os.UserManager.DISALLOW_INSTALL_APPS
10 | import android.os.UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES
11 | import android.os.UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES_GLOBALLY
12 |
13 | internal fun interface InstallRestriction {
14 | fun isAllowedToInstallApks(): Boolean
15 | }
16 |
17 | private fun UserManager.isDisallowed(restriction: String): Boolean {
18 | return userRestrictions.getBoolean(restriction, false)
19 | }
20 |
21 | internal fun UserManager.isAllowedToInstallApks(): Boolean {
22 | // install isn't allowed if one of those user restrictions is set
23 | val disallowed = isDisallowed(DISALLOW_INSTALL_APPS) ||
24 | isDisallowed(DISALLOW_INSTALL_UNKNOWN_SOURCES) ||
25 | isDisallowed(DISALLOW_INSTALL_UNKNOWN_SOURCES_GLOBALLY)
26 | // install is allowed, if it isn't disallowed
27 | return !disallowed
28 | }
29 |
--------------------------------------------------------------------------------
/app/src/main/java/com/stevesoltys/seedvault/storage/StorageModule.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * SPDX-FileCopyrightText: 2020 The Calyx Institute
3 | * SPDX-License-Identifier: Apache-2.0
4 | */
5 |
6 | package com.stevesoltys.seedvault.storage
7 |
8 | import com.stevesoltys.seedvault.backend.BackendManager
9 | import com.stevesoltys.seedvault.crypto.KeyManager
10 | import org.calyxos.backup.storage.api.StorageBackup
11 | import org.koin.android.ext.koin.androidContext
12 | import org.koin.dsl.module
13 |
14 | val storageModule = module {
15 | single { StorageBackup(androidContext(), get(), get()) }
16 | }
17 |
--------------------------------------------------------------------------------
/app/src/main/java/com/stevesoltys/seedvault/storage/StorageRestoreService.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * SPDX-FileCopyrightText: 2020 The Calyx Institute
3 | * SPDX-License-Identifier: Apache-2.0
4 | */
5 |
6 | package com.stevesoltys.seedvault.storage
7 |
8 | import org.calyxos.backup.storage.api.RestoreObserver
9 | import org.calyxos.backup.storage.api.StorageBackup
10 | import org.calyxos.backup.storage.restore.NotificationRestoreObserver
11 | import org.calyxos.backup.storage.restore.RestoreService
12 | import org.calyxos.backup.storage.ui.restore.FileSelectionManager
13 | import org.koin.android.ext.android.inject
14 |
15 | internal class StorageRestoreService : RestoreService() {
16 | override val storageBackup: StorageBackup by inject()
17 | override val fileSelectionManager: FileSelectionManager by inject()
18 |
19 | // use lazy delegate because context isn't available during construction time
20 | override val restoreObserver: RestoreObserver by lazy {
21 | NotificationRestoreObserver(applicationContext)
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/app/src/main/java/com/stevesoltys/seedvault/transport/backup/InputFactory.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * SPDX-FileCopyrightText: 2020 The Calyx Institute
3 | * SPDX-License-Identifier: Apache-2.0
4 | */
5 |
6 | package com.stevesoltys.seedvault.transport.backup
7 |
8 | import android.app.backup.BackupDataInput
9 | import android.os.ParcelFileDescriptor
10 | import java.io.FileInputStream
11 | import java.io.InputStream
12 |
13 | /**
14 | * This class exists for easier testing, so we can mock it and return custom data inputs.
15 | */
16 | internal class InputFactory {
17 |
18 | fun getBackupDataInput(inputFileDescriptor: ParcelFileDescriptor): BackupDataInput {
19 | return BackupDataInput(inputFileDescriptor.fileDescriptor)
20 | }
21 |
22 | fun getInputStream(inputFileDescriptor: ParcelFileDescriptor): InputStream {
23 | return FileInputStream(inputFileDescriptor.fileDescriptor)
24 | }
25 |
26 | }
27 |
--------------------------------------------------------------------------------
/app/src/main/java/com/stevesoltys/seedvault/transport/restore/OutputFactory.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * SPDX-FileCopyrightText: 2020 The Calyx Institute
3 | * SPDX-License-Identifier: Apache-2.0
4 | */
5 |
6 | package com.stevesoltys.seedvault.transport.restore
7 |
8 | import android.app.backup.BackupDataOutput
9 | import android.os.ParcelFileDescriptor
10 | import java.io.FileOutputStream
11 | import java.io.OutputStream
12 |
13 | /**
14 | * This class exists for easier testing, so we can mock it and return custom data outputs.
15 | */
16 | internal class OutputFactory {
17 |
18 | fun getBackupDataOutput(outputFileDescriptor: ParcelFileDescriptor): BackupDataOutput {
19 | return BackupDataOutput(outputFileDescriptor.fileDescriptor)
20 | }
21 |
22 | fun getOutputStream(outputFileDescriptor: ParcelFileDescriptor): OutputStream {
23 | return FileOutputStream(outputFileDescriptor.fileDescriptor)
24 | }
25 |
26 | }
27 |
--------------------------------------------------------------------------------
/app/src/main/java/com/stevesoltys/seedvault/transport/restore/RestoreModule.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * SPDX-FileCopyrightText: 2020 The Calyx Institute
3 | * SPDX-License-Identifier: Apache-2.0
4 | */
5 |
6 | package com.stevesoltys.seedvault.transport.restore
7 |
8 | import org.koin.android.ext.koin.androidContext
9 | import org.koin.dsl.module
10 |
11 | val restoreModule = module {
12 | single { OutputFactory() }
13 | single { KVRestore(get(), get(), get(), get(), get(), get(), get()) }
14 | single { FullRestore(get(), get(), get(), get(), get(), get()) }
15 | single {
16 | RestoreCoordinator(
17 | context = androidContext(),
18 | crypto = get(),
19 | settingsManager = get(),
20 | metadataManager = get(),
21 | notificationManager = get(),
22 | backendManager = get(),
23 | snapshotManager = get(),
24 | kv = get(),
25 | full = get(),
26 | metadataReader = get(),
27 | )
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/app/src/main/java/com/stevesoltys/seedvault/ui/BackupActivity.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * SPDX-FileCopyrightText: 2020 The Calyx Institute
3 | * SPDX-License-Identifier: Apache-2.0
4 | */
5 |
6 | package com.stevesoltys.seedvault.ui
7 |
8 | import android.os.Bundle
9 | import androidx.appcompat.app.AppCompatActivity
10 | import androidx.fragment.app.Fragment
11 | import com.stevesoltys.seedvault.R
12 |
13 | abstract class BackupActivity : AppCompatActivity() {
14 |
15 | override fun onCreate(savedInstanceState: Bundle?) {
16 | setupEdgeToEdge()
17 | super.onCreate(savedInstanceState)
18 | }
19 |
20 | protected fun showFragment(f: Fragment, addToBackStack: Boolean = false, tag: String? = null) {
21 | supportFragmentManager.beginTransaction().apply {
22 | replace(R.id.fragment, f, tag)
23 | if (addToBackStack) addToBackStack(null)
24 | commit()
25 | }
26 | }
27 |
28 | }
29 |
--------------------------------------------------------------------------------
/app/src/main/java/com/stevesoltys/seedvault/ui/LiveEventHandler.java:
--------------------------------------------------------------------------------
1 | /*
2 | * SPDX-FileCopyrightText: 2020 The Calyx Institute
3 | * SPDX-License-Identifier: Apache-2.0
4 | */
5 |
6 | package com.stevesoltys.seedvault.ui;
7 |
8 | public interface LiveEventHandler {
9 | void onEvent(T t);
10 | }
11 |
--------------------------------------------------------------------------------
/app/src/main/java/com/stevesoltys/seedvault/ui/MutableLiveEvent.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * SPDX-FileCopyrightText: 2020 The Calyx Institute
3 | * SPDX-License-Identifier: Apache-2.0
4 | */
5 |
6 | package com.stevesoltys.seedvault.ui
7 |
8 | class MutableLiveEvent : LiveEvent() {
9 |
10 | fun postEvent(value: T) {
11 | super.postValue(ConsumableEvent(value))
12 | }
13 |
14 | fun setEvent(value: T) {
15 | super.setValue(ConsumableEvent(value))
16 | }
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/app/src/main/java/com/stevesoltys/seedvault/ui/SystemData.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * SPDX-FileCopyrightText: 2024 The Calyx Institute
3 | * SPDX-License-Identifier: Apache-2.0
4 | */
5 |
6 | package com.stevesoltys.seedvault.ui
7 |
8 | import androidx.annotation.DrawableRes
9 | import androidx.annotation.StringRes
10 | import com.stevesoltys.seedvault.R
11 |
12 | internal const val PACKAGE_NAME_SMS = "com.android.providers.telephony"
13 | internal const val PACKAGE_NAME_SETTINGS = "com.android.providers.settings"
14 | internal const val PACKAGE_NAME_CALL_LOG = "com.android.calllogbackup"
15 | internal const val PACKAGE_NAME_CONTACTS = "org.calyxos.backup.contacts"
16 | internal const val PACKAGE_NAME_SYSTEM = "@org.calyxos.system@"
17 |
18 | val systemData = mapOf(
19 | PACKAGE_NAME_SMS to SystemData(R.string.backup_sms, R.drawable.ic_message),
20 | PACKAGE_NAME_SETTINGS to SystemData(R.string.backup_settings, R.drawable.ic_settings),
21 | PACKAGE_NAME_CALL_LOG to SystemData(R.string.backup_call_log, R.drawable.ic_call),
22 | PACKAGE_NAME_CONTACTS to SystemData(R.string.backup_contacts, R.drawable.ic_contacts),
23 | )
24 |
25 | data class SystemData(
26 | @StringRes val nameRes: Int,
27 | @DrawableRes val iconRes: Int,
28 | )
29 |
--------------------------------------------------------------------------------
/app/src/main/java/com/stevesoltys/seedvault/ui/check/FileCheckResultActivity.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * SPDX-FileCopyrightText: 2024 The Calyx Institute
3 | * SPDX-License-Identifier: Apache-2.0
4 | */
5 |
6 | package com.stevesoltys.seedvault.ui.check
7 |
8 | import android.os.Bundle
9 | import com.stevesoltys.seedvault.ui.setupEdgeToEdge
10 | import org.calyxos.backup.storage.api.StorageBackup
11 | import org.calyxos.backup.storage.ui.check.CheckResultActivity
12 | import org.calyxos.backup.storage.ui.restore.FileSelectionManager
13 | import org.koin.android.ext.android.inject
14 |
15 | class FileCheckResultActivity : CheckResultActivity() {
16 |
17 | override val storageBackup: StorageBackup by inject()
18 | override val fileSelectionManager: FileSelectionManager by inject()
19 |
20 | override fun onCreate(savedInstanceState: Bundle?) {
21 | setupEdgeToEdge()
22 | super.onCreate(savedInstanceState)
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/app/src/main/java/com/stevesoltys/seedvault/ui/files/FileSelectionViewModel.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * SPDX-FileCopyrightText: 2020 The Calyx Institute
3 | * SPDX-License-Identifier: Apache-2.0
4 | */
5 |
6 | package com.stevesoltys.seedvault.ui.files
7 |
8 | import android.app.Application
9 | import androidx.lifecycle.viewModelScope
10 | import kotlinx.coroutines.launch
11 | import org.calyxos.backup.storage.api.StorageBackup
12 | import org.calyxos.backup.storage.ui.backup.BackupContentViewModel
13 |
14 | class FileSelectionViewModel(
15 | app: Application,
16 | override val storageBackup: StorageBackup,
17 | ) : BackupContentViewModel(app) {
18 |
19 | init {
20 | viewModelScope.launch { loadContent() }
21 | }
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/app/src/main/java/com/stevesoltys/seedvault/ui/storage/PermissionGrantActivity.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * SPDX-FileCopyrightText: 2020 The Calyx Institute
3 | * SPDX-License-Identifier: Apache-2.0
4 | */
5 |
6 | package com.stevesoltys.seedvault.ui.storage
7 |
8 | import android.content.Intent.FLAG_GRANT_PREFIX_URI_PERMISSION
9 | import android.os.Bundle
10 | import androidx.appcompat.app.AppCompatActivity
11 | import com.stevesoltys.seedvault.ui.setupEdgeToEdge
12 |
13 | class PermissionGrantActivity : AppCompatActivity() {
14 |
15 | override fun onCreate(savedInstanceState: Bundle?) {
16 | setupEdgeToEdge()
17 | super.onCreate(savedInstanceState)
18 |
19 | if (intent?.data != null) {
20 | intent.addFlags(FLAG_GRANT_PREFIX_URI_PERMISSION)
21 | setResult(RESULT_OK, intent)
22 | }
23 | finish()
24 | }
25 |
26 | }
27 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/davx5.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_access_time.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
12 |
15 |
16 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_apps.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
12 |
15 |
16 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_battery_charging_full.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
12 |
15 |
16 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_bug_report.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
12 |
15 |
16 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_call.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
12 |
15 |
16 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_check_green.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
11 |
14 |
15 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_cloud_circle.xml:
--------------------------------------------------------------------------------
1 |
5 |
11 |
12 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_cloud_done.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
12 |
15 |
16 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_cloud_download.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
12 |
15 |
16 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_cloud_error.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
12 |
15 |
16 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_cloud_search.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_cloud_upload.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
12 |
15 |
16 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_contacts.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
12 |
15 |
16 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_error_red.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
11 |
14 |
15 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_info_outline.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
12 |
15 |
16 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_launcher_default.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
11 |
15 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_library_add.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
12 |
15 |
16 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_message.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
12 |
15 |
16 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_network_warning.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
12 |
15 |
16 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_phone_android.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
12 |
15 |
16 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_save_alt.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
12 |
15 |
16 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_storage.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
12 |
15 |
16 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_usb.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
12 |
15 |
16 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_vpn_key.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
12 |
15 |
16 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_warning.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
12 |
15 |
16 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_warning_yellow.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
11 |
14 |
15 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/nextcloud.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/round_sync.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_fragment_container.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
10 |
11 |
16 |
17 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_recovery_code.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/footer_files_selection.xml:
--------------------------------------------------------------------------------
1 |
5 |
17 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/footer_snapshots.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
10 |
11 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
13 |
14 |
20 |
21 |
22 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/list_item_app_section_title.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
16 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/preference_switch.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/app_status_menu.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
15 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/settings_menu.xml:
--------------------------------------------------------------------------------
1 |
5 |
31 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/values-af/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/values-am/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/values-as/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/values-ast/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/values-az/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/values-b+sr+Latn/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Lokacija rezervne kopije
4 | Napravi rezervnu kopiju mojih podataka
5 | Vrati rezervnu kopiju
6 | Status i podešavanja rezervne kopije
7 | Rezervna kopija Seedvault
8 | Rezervna kopija
9 |
--------------------------------------------------------------------------------
/app/src/main/res/values-b+zh+Hant+HK/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/values-be/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/values-bg/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/values-bn/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | আমার ডাটা ব্যাকআপ করো
4 | ব্যাকআপ পুনরুদ্ধার
5 | ব্যাকআপ
6 |
--------------------------------------------------------------------------------
/app/src/main/res/values-bs/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/values-cy/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/values-da/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/values-en-rCA/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/values-en-rIN/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/values-eo/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/values-eu/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/values-fa/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/values-fr-rCA/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/app/src/main/res/values-gd/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/values-gl/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/app/src/main/res/values-gu/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/values-hi/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/values-hy/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/values-ka/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/values-kk/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/values-km/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/values-kn/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/values-ky/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/values-lo/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/values-lv/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/values-mk/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/values-mn/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/values-mr/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/values-ms/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/values-ne/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/values-night/bools.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 | false
8 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/values-night/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
9 | @android:color/system_accent1_100
10 |
11 | @android:color/system_neutral1_50
12 |
13 |
--------------------------------------------------------------------------------
/app/src/main/res/values-or/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/values-pa/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/values-si/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/values-sl/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/values-sq/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/values-sr/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/values-sw/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/values-th/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/values-tl/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/values-ur/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/values-uz/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/values-zu/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/values/arrays.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 | - @string/settings_scheduling_frequency_12_hours
9 | - @string/settings_scheduling_frequency_daily
10 | - @string/settings_scheduling_frequency_3_days
11 | - @string/settings_scheduling_frequency_weekly
12 |
13 |
14 |
15 | - 43200000
16 | - 86400000
17 | - 259200000
18 | - 604800000
19 |
20 |
21 |
--------------------------------------------------------------------------------
/app/src/main/res/values/bools.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 | true
8 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/xml/device_filter.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/main/res/xml/network_security_config.xml:
--------------------------------------------------------------------------------
1 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/app/src/main/res/xml/settings_expert.xml:
--------------------------------------------------------------------------------
1 |
5 |
6 |
12 |
13 |
18 |
19 |
--------------------------------------------------------------------------------
/app/src/main/resources/simplelogger.properties:
--------------------------------------------------------------------------------
1 | org.slf4j.simpleLogger.defaultLogLevel=debug
2 |
--------------------------------------------------------------------------------
/app/src/test/java/com/stevesoltys/seedvault/repo/PaddingTest.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * SPDX-FileCopyrightText: 2024 The Calyx Institute
3 | * SPDX-License-Identifier: Apache-2.0
4 | */
5 |
6 | package com.stevesoltys.seedvault.repo
7 |
8 | import com.stevesoltys.seedvault.repo.Padding.getPadTo
9 | import kotlinx.coroutines.runBlocking
10 | import org.junit.jupiter.api.Assertions.assertEquals
11 | import org.junit.jupiter.api.Test
12 |
13 | class PaddingTest {
14 | @Test
15 | fun test() = runBlocking {
16 | assertEquals(52, getPadTo(49))
17 | assertEquals(52, getPadTo(50))
18 | assertEquals(60, getPadTo(60))
19 | assertEquals(4096, getPadTo(4000))
20 | assertEquals(8192, getPadTo(8000))
21 | assertEquals(12288, getPadTo(12000))
22 | assertEquals(12288, getPadTo(12000))
23 | assertEquals(61440, getPadTo(60000))
24 | assertEquals(12288, getPadTo(12000))
25 | assertEquals(638976, getPadTo(634000))
26 | assertEquals(1277952, getPadTo(1250000))
27 | assertEquals(8388608, getPadTo(8260000))
28 | assertEquals(8388608, getPadTo(8380000))
29 | assertEquals(8388608, getPadTo(8388608))
30 | assertEquals(8650752, getPadTo(8388609))
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/app/src/test/java/com/stevesoltys/seedvault/transport/restore/RestoreTest.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * SPDX-FileCopyrightText: 2020 The Calyx Institute
3 | * SPDX-License-Identifier: Apache-2.0
4 | */
5 |
6 | package com.stevesoltys.seedvault.transport.restore
7 |
8 | import android.os.ParcelFileDescriptor
9 | import com.stevesoltys.seedvault.getRandomByteArray
10 | import com.stevesoltys.seedvault.header.HeaderReader
11 | import com.stevesoltys.seedvault.header.VERSION
12 | import com.stevesoltys.seedvault.transport.TransportTest
13 | import io.mockk.mockk
14 | import java.io.InputStream
15 |
16 | internal abstract class RestoreTest : TransportTest() {
17 |
18 | protected val outputFactory = mockk()
19 | protected val headerReader = mockk()
20 | protected val fileDescriptor = mockk()
21 |
22 | protected val data = getRandomByteArray()
23 | protected val inputStream = mockk()
24 | protected val decryptedInputStream = mockk()
25 |
26 | protected val unsupportedVersion = (VERSION + 1).toByte()
27 |
28 | }
29 |
--------------------------------------------------------------------------------
/app/src/test/resources/simplelogger.properties:
--------------------------------------------------------------------------------
1 | #org.slf4j.simpleLogger.defaultLogLevel=debug
2 |
--------------------------------------------------------------------------------
/contactsbackup/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/contactsbackup/Android.bp:
--------------------------------------------------------------------------------
1 | //
2 | // SPDX-FileCopyrightText: 2020 The Calyx Institute
3 | // SPDX-License-Identifier: Apache-2.0
4 | //
5 |
6 | android_app {
7 | name: "LocalContactsBackup",
8 | srcs: [
9 | "src/main/java/**/*.java",
10 | ],
11 | resource_dirs: [
12 | "src/main/res",
13 | ],
14 | manifest: "src/main/AndroidManifest.xml",
15 | static_libs: [
16 | "com.android.vcard",
17 | ],
18 | required: [
19 | "default-permissions_org.calyxos.backup.contacts",
20 | ],
21 | product_specific: true,
22 | sdk_version: "current",
23 | }
24 |
25 | prebuilt_etc {
26 | name: "default-permissions_org.calyxos.backup.contacts",
27 | product_specific: true,
28 | sub_dir: "default-permissions",
29 | src: "default-permissions_org.calyxos.backup.contacts.xml",
30 | filename_from_src: true,
31 | }
32 |
--------------------------------------------------------------------------------
/contactsbackup/README.md:
--------------------------------------------------------------------------------
1 | # Local Contacts Backup
2 |
3 | A backup application that backs up local on-device contacts via the system's backup API.
4 | This explicitly excludes contacts that are synced via sync accounts
5 | such as [DAVx⁵](https://www.davx5.com/).
6 |
7 | ## Permissions
8 |
9 | * `android.permission.READ_CONTACTS` to back up local contacts.
10 | * `android.permission.WRITE_CONTACTS` to restore local contacts to the device.
11 |
--------------------------------------------------------------------------------
/contactsbackup/default-permissions_org.calyxos.backup.contacts.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/contactsbackup/libs/com.android.vcard.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seedvault-app/seedvault/cdc31be96d492b8c0d269f07d6a86afe9b678f3e/contactsbackup/libs/com.android.vcard.jar
--------------------------------------------------------------------------------
/contactsbackup/lint.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/contactsbackup/src/androidTest/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/contactsbackup/src/main/java/org/calyxos/backup/contacts/FullBackupFileHandler.java:
--------------------------------------------------------------------------------
1 | /*
2 | * SPDX-FileCopyrightText: 2020 The Calyx Institute
3 | * SPDX-License-Identifier: Apache-2.0
4 | */
5 |
6 | package org.calyxos.backup.contacts;
7 |
8 | import android.app.backup.FullBackupDataOutput;
9 |
10 | import java.io.File;
11 |
12 | interface FullBackupFileHandler {
13 |
14 | void fullBackupFile(File file, FullBackupDataOutput output);
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/contactsbackup/src/main/res/values-af/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/contactsbackup/src/main/res/values-am/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/contactsbackup/src/main/res/values-ar/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | النسخ الاحتياطي لجهات الاتصال المحلية
4 |
--------------------------------------------------------------------------------
/contactsbackup/src/main/res/values-as/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/contactsbackup/src/main/res/values-ast/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/contactsbackup/src/main/res/values-az/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/contactsbackup/src/main/res/values-b+sr+Latn/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/contactsbackup/src/main/res/values-b+zh+Hant+HK/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/contactsbackup/src/main/res/values-be/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/contactsbackup/src/main/res/values-bg/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/contactsbackup/src/main/res/values-bn/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/contactsbackup/src/main/res/values-bs/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/contactsbackup/src/main/res/values-ca/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Còpia de Seguretat Local dels Contactes
4 |
--------------------------------------------------------------------------------
/contactsbackup/src/main/res/values-cs/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Lokální záloha kontaktů
4 |
--------------------------------------------------------------------------------
/contactsbackup/src/main/res/values-cy/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/contactsbackup/src/main/res/values-da/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Sikkerhedskopiering af lokale kontakter
4 |
--------------------------------------------------------------------------------
/contactsbackup/src/main/res/values-de/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Sicherung lokaler Kontakte
4 |
--------------------------------------------------------------------------------
/contactsbackup/src/main/res/values-el/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Αντίγραφα ασφαλείας τοπικών επαφών
4 |
--------------------------------------------------------------------------------
/contactsbackup/src/main/res/values-en-rAU/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Local Contacts Backup
4 |
--------------------------------------------------------------------------------
/contactsbackup/src/main/res/values-en-rCA/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/contactsbackup/src/main/res/values-en-rGB/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Local Contacts Backup
4 |
--------------------------------------------------------------------------------
/contactsbackup/src/main/res/values-en-rIN/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/contactsbackup/src/main/res/values-eo/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/contactsbackup/src/main/res/values-es-rUS/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Copia de seguridad de contactos locales
4 |
--------------------------------------------------------------------------------
/contactsbackup/src/main/res/values-es/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Copia de seguridad de contactos local
4 |
--------------------------------------------------------------------------------
/contactsbackup/src/main/res/values-et/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Kohalike kontaktide varundamine
4 |
5 |
--------------------------------------------------------------------------------
/contactsbackup/src/main/res/values-eu/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/contactsbackup/src/main/res/values-fa/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/contactsbackup/src/main/res/values-fi/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/contactsbackup/src/main/res/values-fr-rCA/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Sauvegarde local des contacts
4 |
--------------------------------------------------------------------------------
/contactsbackup/src/main/res/values-fr/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Sauvegarde locale des contacts
4 |
--------------------------------------------------------------------------------
/contactsbackup/src/main/res/values-gd/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/contactsbackup/src/main/res/values-gl/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Copia de seguranza dos contactos locais
4 |
--------------------------------------------------------------------------------
/contactsbackup/src/main/res/values-gu/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/contactsbackup/src/main/res/values-hi/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/contactsbackup/src/main/res/values-hr/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Sigurnosna kopija lokalnih kontakta
4 |
--------------------------------------------------------------------------------
/contactsbackup/src/main/res/values-hu/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Helyi Kapcsolatok Mentése
4 |
5 |
--------------------------------------------------------------------------------
/contactsbackup/src/main/res/values-hy/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/contactsbackup/src/main/res/values-in/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/contactsbackup/src/main/res/values-is/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/contactsbackup/src/main/res/values-it/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Backup contatti locale
4 |
--------------------------------------------------------------------------------
/contactsbackup/src/main/res/values-iw/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | גיבוי אנשי הקשר המקומיים
4 |
--------------------------------------------------------------------------------
/contactsbackup/src/main/res/values-ja/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | ローカル連絡先のバックアップ
4 |
--------------------------------------------------------------------------------
/contactsbackup/src/main/res/values-ka/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | ლოკალური კონტაქტების მარქაფი
4 |
--------------------------------------------------------------------------------
/contactsbackup/src/main/res/values-kk/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/contactsbackup/src/main/res/values-km/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/contactsbackup/src/main/res/values-kn/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/contactsbackup/src/main/res/values-ko/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 기기 주소록 백업
4 |
--------------------------------------------------------------------------------
/contactsbackup/src/main/res/values-ky/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/contactsbackup/src/main/res/values-lo/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/contactsbackup/src/main/res/values-lt/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Vietinių kontaktų atsarginė kopija
4 |
--------------------------------------------------------------------------------
/contactsbackup/src/main/res/values-lv/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/contactsbackup/src/main/res/values-mk/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/contactsbackup/src/main/res/values-ml/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | പ്രാദേശിക കോൺടാക്റ്റുകളുടെ ബാക്കപ്പ്
4 |
--------------------------------------------------------------------------------
/contactsbackup/src/main/res/values-mn/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/contactsbackup/src/main/res/values-mr/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | लोकल संपर्क बॅकअप
4 |
--------------------------------------------------------------------------------
/contactsbackup/src/main/res/values-ms/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/contactsbackup/src/main/res/values-my/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/contactsbackup/src/main/res/values-nb-rNO/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Sikkerhetskopiering av lokale kontakter
4 |
--------------------------------------------------------------------------------
/contactsbackup/src/main/res/values-ne/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/contactsbackup/src/main/res/values-nl/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Lokale contactenback-up
4 |
--------------------------------------------------------------------------------
/contactsbackup/src/main/res/values-or/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/contactsbackup/src/main/res/values-pa/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/contactsbackup/src/main/res/values-pl/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Kopia zapasowa kontaktów lokalnych
4 |
--------------------------------------------------------------------------------
/contactsbackup/src/main/res/values-pt-rBR/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Backup de Contatos Locais
4 |
5 |
--------------------------------------------------------------------------------
/contactsbackup/src/main/res/values-pt-rPT/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Backup de contactos locais
4 |
5 |
--------------------------------------------------------------------------------
/contactsbackup/src/main/res/values-pt/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Backup de contactos locais
4 |
5 |
--------------------------------------------------------------------------------
/contactsbackup/src/main/res/values-ro/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Backup local pentru contacte
4 |
--------------------------------------------------------------------------------
/contactsbackup/src/main/res/values-ru/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Резервное копирование локальных контактов
4 |
--------------------------------------------------------------------------------
/contactsbackup/src/main/res/values-si/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/contactsbackup/src/main/res/values-sk/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Lokálna záloha kontaktov
4 |
--------------------------------------------------------------------------------
/contactsbackup/src/main/res/values-sl/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/contactsbackup/src/main/res/values-sq/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/contactsbackup/src/main/res/values-sr/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/contactsbackup/src/main/res/values-sv/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Lokal säkerhetskopia av kontakter
4 |
--------------------------------------------------------------------------------
/contactsbackup/src/main/res/values-sw/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/contactsbackup/src/main/res/values-ta/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | உள்ளக தொடர்புகள் காப்புப்பிரதி
4 |
--------------------------------------------------------------------------------
/contactsbackup/src/main/res/values-te/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/contactsbackup/src/main/res/values-th/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/contactsbackup/src/main/res/values-tl/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/contactsbackup/src/main/res/values-tr/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Yerel Kişileri Yedekle
4 |
--------------------------------------------------------------------------------
/contactsbackup/src/main/res/values-ug/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | يەرلىك ئالاقەداش زاپاسلاش
4 |
5 |
--------------------------------------------------------------------------------
/contactsbackup/src/main/res/values-uk/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Резервне копіювання локальних контактів
4 |
--------------------------------------------------------------------------------
/contactsbackup/src/main/res/values-ur/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/contactsbackup/src/main/res/values-uz/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/contactsbackup/src/main/res/values-vi/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/contactsbackup/src/main/res/values-zh-rCN/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 本地联系人备份
4 |
--------------------------------------------------------------------------------
/contactsbackup/src/main/res/values-zh-rTW/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/contactsbackup/src/main/res/values-zu/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/contactsbackup/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 | Local Contacts Backup
8 |
9 |
--------------------------------------------------------------------------------
/contactsbackup/testkey.jks:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seedvault-app/seedvault/cdc31be96d492b8c0d269f07d6a86afe9b678f3e/contactsbackup/testkey.jks
--------------------------------------------------------------------------------
/core/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/core/Android.bp:
--------------------------------------------------------------------------------
1 | //
2 | // SPDX-FileCopyrightText: 2021 The Calyx Institute
3 | // SPDX-License-Identifier: Apache-2.0
4 | //
5 |
6 | android_library {
7 | name: "seedvault-lib-core",
8 | sdk_version: "current",
9 | srcs: [
10 | "src/main/java/**/*.kt",
11 | "src/main/java/**/*.java",
12 | ],
13 | resource_dirs: [
14 | "src/main/res",
15 | ],
16 | exclude_srcs: [
17 | "src/main/java/org/calyxos/seedvault/core/backends/BackendTest.kt",
18 | ],
19 | static_libs: [
20 | "androidx.core_core-ktx",
21 | "androidx.documentfile_documentfile",
22 | "kotlinx-coroutines-android",
23 | "kotlinx-coroutines-core",
24 | // Crypto
25 | "seedvault-lib-tink-android",
26 | // Logging
27 | "seedvault-lib-kotlin-logging-jvm",
28 | "seedvault-lib-slf4j-api",
29 | // WebDAV
30 | "seedvault-lib-dav4jvm",
31 | "seedvault-lib-okhttp",
32 | "okio-lib",
33 | ],
34 | manifest: "src/main/AndroidManifest.xml",
35 | optimize: {
36 | enabled: false,
37 | },
38 | kotlincflags: [
39 | "-opt-in=kotlin.RequiresOptIn",
40 | ],
41 | }
42 |
--------------------------------------------------------------------------------
/core/libs/Android.bp:
--------------------------------------------------------------------------------
1 | //
2 | // SPDX-FileCopyrightText: 2024 The Calyx Institute
3 | // SPDX-License-Identifier: Apache-2.0
4 | //
5 |
6 | java_import {
7 | name: "seedvault-lib-tink-android",
8 | jars: ["tink-android-1.15.0.jar"],
9 | sdk_version: "current",
10 | }
11 |
12 | java_import {
13 | name: "seedvault-lib-kotlin-logging-jvm",
14 | jars: ["kotlin-logging-jvm-6.0.3.jar"],
15 | sdk_version: "current",
16 | }
17 |
18 | java_import {
19 | name: "seedvault-lib-slf4j-api",
20 | jars: ["slf4j-api-2.0.16.jar"],
21 | sdk_version: "current",
22 | }
23 |
--------------------------------------------------------------------------------
/core/libs/dav4jvm/Android.bp:
--------------------------------------------------------------------------------
1 | //
2 | // SPDX-FileCopyrightText: 2024 The Calyx Institute
3 | // SPDX-License-Identifier: Apache-2.0
4 | //
5 |
6 | java_import {
7 | name: "seedvault-lib-dav4jvm",
8 | jars: ["dav4jvm-c1bc143.jar"],
9 | sdk_version: "current",
10 | }
11 |
12 | java_import {
13 | name: "seedvault-lib-okhttp",
14 | jars: ["okhttp-4.12.0.jar"],
15 | sdk_version: "current",
16 | }
17 |
--------------------------------------------------------------------------------
/core/libs/dav4jvm/dav4jvm-c1bc143.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seedvault-app/seedvault/cdc31be96d492b8c0d269f07d6a86afe9b678f3e/core/libs/dav4jvm/dav4jvm-c1bc143.jar
--------------------------------------------------------------------------------
/core/libs/dav4jvm/okhttp-4.12.0.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seedvault-app/seedvault/cdc31be96d492b8c0d269f07d6a86afe9b678f3e/core/libs/dav4jvm/okhttp-4.12.0.jar
--------------------------------------------------------------------------------
/core/libs/kotlin-logging-jvm-6.0.3.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seedvault-app/seedvault/cdc31be96d492b8c0d269f07d6a86afe9b678f3e/core/libs/kotlin-logging-jvm-6.0.3.jar
--------------------------------------------------------------------------------
/core/libs/slf4j-api-2.0.16.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seedvault-app/seedvault/cdc31be96d492b8c0d269f07d6a86afe9b678f3e/core/libs/slf4j-api-2.0.16.jar
--------------------------------------------------------------------------------
/core/libs/tink-android-1.15.0.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seedvault-app/seedvault/cdc31be96d492b8c0d269f07d6a86afe9b678f3e/core/libs/tink-android-1.15.0.jar
--------------------------------------------------------------------------------
/core/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
5 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/core/src/main/java/org/calyxos/seedvault/core/ByteArrayUtils.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * SPDX-FileCopyrightText: 2021 The Calyx Institute
3 | * SPDX-License-Identifier: Apache-2.0
4 | */
5 |
6 | package org.calyxos.seedvault.core
7 |
8 | public fun ByteArray.toHexString(): String = joinToString("") { "%02x".format(it) }
9 |
10 | public fun String.toByteArrayFromHex(): ByteArray =
11 | chunked(2).map { it.toInt(16).toByte() }.toByteArray()
12 |
--------------------------------------------------------------------------------
/core/src/main/java/org/calyxos/seedvault/core/MemoryLogger.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * SPDX-FileCopyrightText: 2024 The Calyx Institute
3 | * SPDX-License-Identifier: Apache-2.0
4 | */
5 |
6 | package org.calyxos.seedvault.core
7 |
8 | import android.util.Log
9 |
10 | public object MemoryLogger {
11 |
12 | public fun log() {
13 | Log.d("MemoryLogger", getMemStr())
14 | }
15 |
16 | public fun getMemStr(): String {
17 | val r = Runtime.getRuntime()
18 | val total = r.totalMemory() / 1024 / 1024
19 | val free = r.freeMemory() / 1024 / 1024
20 | val max = r.maxMemory() / 1024 / 1024
21 | val used = total - free
22 | return "$free MiB free - $used of $total (max $max)"
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/core/src/main/java/org/calyxos/seedvault/core/backends/BackendFactory.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * SPDX-FileCopyrightText: 2024 The Calyx Institute
3 | * SPDX-License-Identifier: Apache-2.0
4 | */
5 |
6 | package org.calyxos.seedvault.core.backends
7 |
8 | import android.content.Context
9 | import org.calyxos.seedvault.core.backends.saf.SafBackend
10 | import org.calyxos.seedvault.core.backends.saf.SafProperties
11 | import org.calyxos.seedvault.core.backends.webdav.WebDavBackend
12 | import org.calyxos.seedvault.core.backends.webdav.WebDavConfig
13 |
14 | public class BackendFactory {
15 | public fun createSafBackend(context: Context, config: SafProperties): Backend =
16 | RetryBackend(SafBackend(context, config))
17 |
18 | public fun createWebDavBackend(config: WebDavConfig): Backend =
19 | RetryBackend(WebDavBackend(config))
20 | }
21 |
--------------------------------------------------------------------------------
/core/src/main/java/org/calyxos/seedvault/core/backends/BackendSaver.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * SPDX-FileCopyrightText: 2024 The Calyx Institute
3 | * SPDX-License-Identifier: Apache-2.0
4 | */
5 |
6 | package org.calyxos.seedvault.core.backends
7 |
8 | import java.io.OutputStream
9 |
10 | /**
11 | * Used to save data with [Backend]s.
12 | *
13 | * Attention: Ensure that [save] can safely called more than once and still saves the same data.
14 | */
15 | public interface BackendSaver {
16 | /**
17 | * The number of bytes that will be saved or `null` if unknown.
18 | */
19 | public val size: Long
20 |
21 | /**
22 | * The SHA256 hash (in lower-case hex string representation) the bytes to be saved have,
23 | * or `null` if it isn't known.
24 | */
25 | public val sha256: String?
26 |
27 | /**
28 | * Called by the backend when it wants to save the data to the provided [outputStream].
29 | * Can be called more than once, in case the backend encountered an error saving.
30 | *
31 | * @return the number of bytes saved. Should be equal to [size].
32 | */
33 | public fun save(outputStream: OutputStream): Long
34 | }
35 |
--------------------------------------------------------------------------------
/core/src/main/java/org/calyxos/seedvault/core/backends/IBackendManager.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * SPDX-FileCopyrightText: 2024 The Calyx Institute
3 | * SPDX-License-Identifier: Apache-2.0
4 | */
5 |
6 | package org.calyxos.seedvault.core.backends
7 |
8 | public interface IBackendManager {
9 | public val backend: Backend
10 | public val isOnRemovableDrive: Boolean
11 | public val requiresNetwork: Boolean
12 | public fun canDoBackupNow(): Boolean
13 | }
14 |
15 | public enum class BackendId {
16 | SAF,
17 | WEBDAV,
18 | }
19 |
--------------------------------------------------------------------------------
/core/src/main/java/org/calyxos/seedvault/core/backends/webdav/WebDavConfig.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * SPDX-FileCopyrightText: 2024 The Calyx Institute
3 | * SPDX-License-Identifier: Apache-2.0
4 | */
5 |
6 | package org.calyxos.seedvault.core.backends.webdav
7 |
8 | public data class WebDavConfig(
9 | val url: String,
10 | val username: String,
11 | val password: String,
12 | )
13 |
--------------------------------------------------------------------------------
/core/src/main/java/org/calyxos/seedvault/core/backends/webdav/WebDavProperties.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * SPDX-FileCopyrightText: 2024 The Calyx Institute
3 | * SPDX-License-Identifier: Apache-2.0
4 | */
5 |
6 | package org.calyxos.seedvault.core.backends.webdav
7 |
8 | import android.content.Context
9 | import org.calyxos.seedvault.core.backends.BackendProperties
10 |
11 | public data class WebDavProperties(
12 | override val config: WebDavConfig,
13 | override val name: String,
14 | ) : BackendProperties() {
15 | override val isUsb: Boolean = false
16 | override val requiresNetwork: Boolean = true
17 | override fun isUnavailableUsb(context: Context): Boolean = false
18 | }
19 |
--------------------------------------------------------------------------------
/core/src/main/java/org/calyxos/seedvault/core/crypto/KeyManager.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * SPDX-FileCopyrightText: 2024 The Calyx Institute
3 | * SPDX-License-Identifier: Apache-2.0
4 | */
5 |
6 | package org.calyxos.seedvault.core.crypto
7 |
8 | import java.security.KeyStore
9 | import javax.crypto.SecretKey
10 |
11 | public interface KeyManager {
12 | /**
13 | * Returns the main key, so it can be used for deriving sub-keys.
14 | *
15 | * Note that any attempt to export the key will return null or an empty [ByteArray],
16 | * because the key can not leave the [KeyStore]'s hardware security module.
17 | */
18 | public fun getMainKey(): SecretKey
19 | }
20 |
--------------------------------------------------------------------------------
/core/src/main/res/values-night/colors.xml:
--------------------------------------------------------------------------------
1 |
5 |
6 |
7 | @android:color/system_neutral1_900
8 |
9 |
--------------------------------------------------------------------------------
/core/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
5 |
6 |
7 | @android:color/system_neutral1_50
8 |
9 |
--------------------------------------------------------------------------------
/core/src/test/java/org/calyxos/seedvault/core/backends/webdav/WebDavBackendTest.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * SPDX-FileCopyrightText: 2024 The Calyx Institute
3 | * SPDX-License-Identifier: Apache-2.0
4 | */
5 |
6 | package org.calyxos.seedvault.core.backends.webdav
7 |
8 | import kotlinx.coroutines.runBlocking
9 | import org.calyxos.seedvault.core.backends.Backend
10 | import org.calyxos.seedvault.core.backends.BackendTest
11 | import kotlin.test.Test
12 |
13 | public class WebDavBackendTest : BackendTest() {
14 | override val backend: Backend = WebDavBackend(WebDavTestConfig.getConfig(), ".SeedvaultTest")
15 |
16 | @Test
17 | public fun `test write, list, read, rename, delete`(): Unit = runBlocking {
18 | testWriteListReadRenameDelete()
19 | }
20 |
21 | @Test
22 | public fun `test remove, create, write file`(): Unit = runBlocking {
23 | testRemoveCreateWriteFile()
24 | }
25 |
26 | @Test
27 | public fun `test, free space and create app blob without root folder`(): Unit = runBlocking {
28 | testTestFreeSpaceAndCreateBlob()
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/core/src/test/java/org/calyxos/seedvault/core/backends/webdav/WebDavTestConfig.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * SPDX-FileCopyrightText: 2024 The Calyx Institute
3 | * SPDX-License-Identifier: Apache-2.0
4 | */
5 |
6 | package org.calyxos.seedvault.core.backends.webdav
7 |
8 | import org.junit.Assume.assumeFalse
9 | import kotlin.test.fail
10 |
11 | internal object WebDavTestConfig {
12 |
13 | fun getConfig(): WebDavConfig {
14 | assumeFalse(System.getenv("NEXTCLOUD_URL").isNullOrEmpty())
15 | return WebDavConfig(
16 | url = System.getenv("NEXTCLOUD_URL") ?: fail(),
17 | username = System.getenv("NEXTCLOUD_USER") ?: fail(),
18 | password = System.getenv("NEXTCLOUD_PASS") ?: fail(),
19 | )
20 | }
21 |
22 | }
23 |
--------------------------------------------------------------------------------
/core/src/test/resources/simplelogger.properties:
--------------------------------------------------------------------------------
1 | org.slf4j.simpleLogger.defaultLogLevel=trace
2 |
--------------------------------------------------------------------------------
/default-permissions_com.stevesoltys.seedvault.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2020 The Calyx Institute
2 | # SPDX-License-Identifier: Apache-2.0
3 |
4 | org.gradle.jvmargs=-Xmx4g
5 | org.gradle.configureondemand=true
6 | org.gradle.caching=true
7 | org.gradle.parallel=true
8 | org.gradle.daemon=true
9 | android.useAndroidX=true
10 | android.enableJetifier=false
11 | kotlin.code.style=official
12 | android.nonTransitiveRClass=true
13 | android.enableR8.fullMode=false
14 | android.injected.androidTest.leaveApksInstalledAfterRun = true
15 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seedvault-app/seedvault/cdc31be96d492b8c0d269f07d6a86afe9b678f3e/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Mon Sep 09 11:23:59 IST 2024
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | distributionSha256Sum=5b9c5eb3f9fc2c94abaea57d90bd78747ca117ddbbf96c859d3741181a12bf2a
5 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.10-bin.zip
6 | networkTimeout=10000
7 | validateDistributionUrl=true
8 | zipStoreBase=GRADLE_USER_HOME
9 | zipStorePath=wrapper/dists
10 |
--------------------------------------------------------------------------------
/libs/Android.bp:
--------------------------------------------------------------------------------
1 | //
2 | // SPDX-FileCopyrightText: 2021 The Calyx Institute
3 | // SPDX-License-Identifier: Apache-2.0
4 | //
5 |
6 | android_library_import {
7 | name: "seedvault-lib-zstd-jni",
8 | aars: ["zstd-jni-1.5.6-5.aar"],
9 | sdk_version: "current",
10 | extract_jni: true,
11 | }
12 |
13 | android_library_import {
14 | name: "seedvault-logback-android",
15 | aars: ["logback-android-3.0.0.aar"],
16 | sdk_version: "current",
17 | }
18 |
19 | java_import {
20 | name: "seedvault-lib-protobuf-kotlin-lite",
21 | jars: ["protobuf-kotlin-lite-3.21.12.jar"],
22 | sdk_version: "current",
23 | }
24 |
25 | java_import {
26 | name: "seedvault-lib-kotlin-bip39",
27 | jars: ["kotlin-bip39-jvm-1.0.8.jar"],
28 | sdk_version: "current",
29 | }
30 |
31 | java_import {
32 | name: "seedvault-lib-chunker",
33 | jars: ["seedvault-chunker-0.1.jar"],
34 | sdk_version: "current",
35 | }
36 |
--------------------------------------------------------------------------------
/libs/aosp/android.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seedvault-app/seedvault/cdc31be96d492b8c0d269f07d6a86afe9b678f3e/libs/aosp/android.jar
--------------------------------------------------------------------------------
/libs/aosp/libcore.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seedvault-app/seedvault/cdc31be96d492b8c0d269f07d6a86afe9b678f3e/libs/aosp/libcore.jar
--------------------------------------------------------------------------------
/libs/koin-android/Android.bp:
--------------------------------------------------------------------------------
1 | //
2 | // SPDX-FileCopyrightText: 2020 The Calyx Institute
3 | // SPDX-License-Identifier: Apache-2.0
4 | //
5 |
6 | android_library_import {
7 | name: "seedvault-lib-koin-android",
8 | aars: ["koin-android-3.5.6.aar"],
9 | sdk_version: "current",
10 | }
11 |
12 | java_import {
13 | name: "seedvault-lib-koin-core-jvm",
14 | jars: ["koin-core-jvm-3.5.6.jar"],
15 | sdk_version: "current",
16 | }
17 |
--------------------------------------------------------------------------------
/libs/koin-android/koin-android-3.5.6.aar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seedvault-app/seedvault/cdc31be96d492b8c0d269f07d6a86afe9b678f3e/libs/koin-android/koin-android-3.5.6.aar
--------------------------------------------------------------------------------
/libs/koin-android/koin-core-jvm-3.5.6.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seedvault-app/seedvault/cdc31be96d492b8c0d269f07d6a86afe9b678f3e/libs/koin-android/koin-core-jvm-3.5.6.jar
--------------------------------------------------------------------------------
/libs/kotlin-bip39-jvm-1.0.8.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seedvault-app/seedvault/cdc31be96d492b8c0d269f07d6a86afe9b678f3e/libs/kotlin-bip39-jvm-1.0.8.jar
--------------------------------------------------------------------------------
/libs/logback-android-3.0.0.aar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seedvault-app/seedvault/cdc31be96d492b8c0d269f07d6a86afe9b678f3e/libs/logback-android-3.0.0.aar
--------------------------------------------------------------------------------
/libs/protobuf-kotlin-lite-3.21.12.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seedvault-app/seedvault/cdc31be96d492b8c0d269f07d6a86afe9b678f3e/libs/protobuf-kotlin-lite-3.21.12.jar
--------------------------------------------------------------------------------
/libs/seedvault-chunker-0.1.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seedvault-app/seedvault/cdc31be96d492b8c0d269f07d6a86afe9b678f3e/libs/seedvault-chunker-0.1.jar
--------------------------------------------------------------------------------
/libs/zstd-jni-1.5.6-5.aar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seedvault-app/seedvault/cdc31be96d492b8c0d269f07d6a86afe9b678f3e/libs/zstd-jni-1.5.6-5.aar
--------------------------------------------------------------------------------
/logcat-verbose.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | #
3 | # SPDX-FileCopyrightText: 2020 The Calyx Institute
4 | # SPDX-License-Identifier: Apache-2.0
5 | #
6 |
7 | set -ex
8 |
9 | adb shell setprop log.tag.BackupManagerService VERBOSE
10 | adb shell setprop log.tag.BackupManagerConstants VERBOSE
11 | adb shell setprop log.tag.BackupTransportManager VERBOSE
12 | adb shell setprop log.tag.KeyValueBackupJob VERBOSE
13 | adb shell setprop log.tag.KeyValueBackupTask VERBOSE
14 | adb shell setprop log.tag.TransportClient VERBOSE
15 | adb shell setprop log.tag.BackupAgent VERBOSE
16 | adb shell setprop log.tag.PMBA VERBOSE
17 |
--------------------------------------------------------------------------------
/permissions_com.stevesoltys.seedvault.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/settings.gradle.kts:
--------------------------------------------------------------------------------
1 | //
2 | // SPDX-FileCopyrightText: 2023 The Calyx Institute
3 | // SPDX-License-Identifier: Apache-2.0
4 | //
5 |
6 | pluginManagement {
7 | repositories {
8 | gradlePluginPortal()
9 | google()
10 | mavenCentral()
11 | }
12 | }
13 |
14 | dependencyResolutionManagement {
15 | repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
16 | repositories {
17 | google()
18 | mavenCentral()
19 | maven("https://jitpack.io")
20 | }
21 | }
22 |
23 | rootProject.name = "Seedvault"
24 | include(":core")
25 | include(":app")
26 | include(":contactsbackup")
27 | include(":storage:lib")
28 | include(":storage:demo")
29 |
--------------------------------------------------------------------------------
/storage/.gitignore:
--------------------------------------------------------------------------------
1 | release.sh
2 |
--------------------------------------------------------------------------------
/storage/README.md:
--------------------------------------------------------------------------------
1 | # Seedvault Storage
2 |
3 | This is a library for Seedvault storage backup.
4 | It can also be used by other apps wanting to provide storage backup feature.
5 |
6 | Please see the [design document](doc/design.md) for more information.
7 |
8 | There is also a [demo app](demo) that illustrates the working of the library
9 | and does not need to be a system app with elevated permissions.
10 | It can be built and installed as a regular app requesting permissions at runtime.
11 |
12 | ## Limitations
13 |
14 | The design document mentions several limitations of this initial implementation.
15 | One of them is that you cannot backup more than one device to the same storage location.
16 |
--------------------------------------------------------------------------------
/storage/demo/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 | /debug
3 |
--------------------------------------------------------------------------------
/storage/demo/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2021 The Calyx Institute
2 | # SPDX-License-Identifier: Apache-2.0
3 |
4 | # Add project specific ProGuard rules here.
5 | # You can control the set of applied configuration files using the
6 | # proguardFiles setting in build.gradle.
7 | #
8 | # For more details, see
9 | # http://developer.android.com/guide/developing/tools/proguard.html
10 |
11 | # If your project uses WebView with JS, uncomment the following
12 | # and specify the fully qualified class name to the JavaScript interface
13 | # class:
14 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
15 | # public *;
16 | #}
17 |
18 | # Uncomment this to preserve the line number information for
19 | # debugging stack traces.
20 | #-keepattributes SourceFile,LineNumberTable
21 |
22 | # If you keep the line number information, uncomment this to
23 | # hide the original source file name.
24 | #-renamesourcefileattribute SourceFile
25 |
26 | -dontobfuscate
27 |
--------------------------------------------------------------------------------
/storage/demo/src/main/assets/test.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seedvault-app/seedvault/cdc31be96d492b8c0d269f07d6a86afe9b678f3e/storage/demo/src/main/assets/test.jpg
--------------------------------------------------------------------------------
/storage/demo/src/main/ic_launcher-playstore.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seedvault-app/seedvault/cdc31be96d492b8c0d269f07d6a86afe9b678f3e/storage/demo/src/main/ic_launcher-playstore.png
--------------------------------------------------------------------------------
/storage/demo/src/main/java/de/grobox/storagebackuptester/scanner/DocumentScanFragment.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * SPDX-FileCopyrightText: 2021 The Calyx Institute
3 | * SPDX-License-Identifier: Apache-2.0
4 | */
5 |
6 | package de.grobox.storagebackuptester.scanner
7 |
8 | import android.net.Uri
9 | import android.os.Bundle
10 |
11 | class DocumentScanFragment : MediaScanFragment() {
12 |
13 | companion object {
14 | fun newInstance(name: String, uri: Uri) = DocumentScanFragment().apply {
15 | arguments = Bundle().apply {
16 | putString("name", name)
17 | putString("uri", uri.toString())
18 | }
19 | }
20 | }
21 |
22 | override suspend fun getText(): String {
23 | return viewModel.scanDocumentUri(getUri())
24 | }
25 |
26 | }
27 |
--------------------------------------------------------------------------------
/storage/demo/src/main/res/drawable/ic_info.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
12 |
15 |
16 |
--------------------------------------------------------------------------------
/storage/demo/src/main/res/drawable/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
12 |
17 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/storage/demo/src/main/res/drawable/ic_refresh.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
12 |
15 |
16 |
--------------------------------------------------------------------------------
/storage/demo/src/main/res/drawable/ic_share.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
12 |
15 |
16 |
--------------------------------------------------------------------------------
/storage/demo/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
12 |
--------------------------------------------------------------------------------
/storage/demo/src/main/res/layout/footer_files.xml:
--------------------------------------------------------------------------------
1 |
5 |
18 |
--------------------------------------------------------------------------------
/storage/demo/src/main/res/layout/footer_snapshot.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
11 |
12 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/storage/demo/src/main/res/layout/header_file_select.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
11 |
12 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/storage/demo/src/main/res/layout/item_log.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
18 |
--------------------------------------------------------------------------------
/storage/demo/src/main/res/menu/fragment_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
22 |
--------------------------------------------------------------------------------
/storage/demo/src/main/res/menu/fragment_scan.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
22 |
--------------------------------------------------------------------------------
/storage/demo/src/main/res/menu/fragment_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
36 |
--------------------------------------------------------------------------------
/storage/demo/src/main/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/storage/demo/src/main/res/values-night/themes.xml:
--------------------------------------------------------------------------------
1 |
5 |
6 |
7 |
21 |
22 |
--------------------------------------------------------------------------------
/storage/demo/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 | #FF3700B3
8 | #FF03DAC5
9 | #FF018786
10 | #151515
11 | #FAFAFA
12 | #689F38
13 |
14 |
--------------------------------------------------------------------------------
/storage/demo/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
5 |
6 | Storage Backup Tester
7 |
8 |
--------------------------------------------------------------------------------
/storage/demo/src/main/res/values/themes.xml:
--------------------------------------------------------------------------------
1 |
5 |
6 |
7 |
18 |
19 |
--------------------------------------------------------------------------------
/storage/lib/.gitignore:
--------------------------------------------------------------------------------
1 | build/*
2 |
--------------------------------------------------------------------------------
/storage/lib/consumer-rules.pro:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seedvault-app/seedvault/cdc31be96d492b8c0d269f07d6a86afe9b678f3e/storage/lib/consumer-rules.pro
--------------------------------------------------------------------------------
/storage/lib/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2021 The Calyx Institute
2 | # SPDX-License-Identifier: Apache-2.0
3 |
4 | # Add project specific ProGuard rules here.
5 | # You can control the set of applied configuration files using the
6 | # proguardFiles setting in build.gradle.
7 | #
8 | # For more details, see
9 | # http://developer.android.com/guide/developing/tools/proguard.html
10 |
11 | # If your project uses WebView with JS, uncomment the following
12 | # and specify the fully qualified class name to the JavaScript interface
13 | # class:
14 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
15 | # public *;
16 | #}
17 |
18 | # Uncomment this to preserve the line number information for
19 | # debugging stack traces.
20 | #-keepattributes SourceFile,LineNumberTable
21 |
22 | # If you keep the line number information, uncomment this to
23 | # hide the original source file name.
24 | #-renamesourcefileattribute SourceFile
25 |
26 | -keep class org.calyxos.backup.storage.** {*;}
27 |
28 | # Ignore StringConcatFactory
29 | -dontwarn java.lang.invoke.StringConcatFactory
30 |
--------------------------------------------------------------------------------
/storage/lib/src/main/java/org/calyxos/backup/storage/UriUtils.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * SPDX-FileCopyrightText: 2021 The Calyx Institute
3 | * SPDX-License-Identifier: Apache-2.0
4 | */
5 |
6 | package org.calyxos.backup.storage
7 |
8 | import android.net.Uri
9 | import org.calyxos.backup.storage.api.MediaType
10 | import org.calyxos.backup.storage.api.mediaItems
11 | import org.calyxos.backup.storage.backup.BackupMediaFile
12 | import org.calyxos.backup.storage.db.StoredUri
13 |
14 | internal fun Uri.toStoredUri(): StoredUri = StoredUri(this)
15 |
16 | internal fun Uri.getMediaType(): MediaType? {
17 | val str = toString()
18 | for (item in mediaItems) {
19 | if (str.startsWith(item.contentUri.toString())) return item
20 | }
21 | return null
22 | }
23 |
24 | internal fun Uri.getBackupMediaType(): BackupMediaFile.MediaType? {
25 | return getMediaType()?.backupType
26 | }
27 |
--------------------------------------------------------------------------------
/storage/lib/src/main/java/org/calyxos/backup/storage/api/BackupFile.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * SPDX-FileCopyrightText: 2021 The Calyx Institute
3 | * SPDX-License-Identifier: Apache-2.0
4 | */
5 |
6 | package org.calyxos.backup.storage.api
7 |
8 | import android.provider.MediaStore
9 |
10 | public interface BackupFile {
11 | public val path: String
12 |
13 | /**
14 | * empty string for [MediaStore.VOLUME_EXTERNAL_PRIMARY]
15 | */
16 | public val volume: String
17 | public val size: Long
18 | public val lastModified: Long?
19 | }
20 |
--------------------------------------------------------------------------------
/storage/lib/src/main/java/org/calyxos/backup/storage/api/CheckObserver.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * SPDX-FileCopyrightText: 2024 The Calyx Institute
3 | * SPDX-License-Identifier: Apache-2.0
4 | */
5 |
6 | package org.calyxos.backup.storage.api
7 |
8 | public interface CheckObserver {
9 |
10 | public fun onStartChecking()
11 | public fun onCheckUpdate(speed: Long, thousandth: Int)
12 | public fun onCheckSuccess(size: Long, speed: Long)
13 | public fun onCheckFoundErrors(size: Long, speed: Long)
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/storage/lib/src/main/java/org/calyxos/backup/storage/api/RestoreObserver.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * SPDX-FileCopyrightText: 2021 The Calyx Institute
3 | * SPDX-License-Identifier: Apache-2.0
4 | */
5 |
6 | package org.calyxos.backup.storage.api
7 |
8 | public interface RestoreObserver {
9 | public fun onRestoreStart(numFiles: Int, totalSize: Long)
10 | public fun onFileDuplicatesRemoved(num: Int)
11 | public fun onFileRestored(file: BackupFile, bytesWritten: Long, tag: String)
12 |
13 | /**
14 | * Called when a file failed to restore.
15 | * You might want to inform the user about this.
16 | * The exception already gets logged.
17 | */
18 | public fun onFileRestoreError(file: BackupFile, e: Exception)
19 |
20 | public fun onRestoreComplete(restoreDuration: Long)
21 | }
22 |
--------------------------------------------------------------------------------
/storage/lib/src/main/java/org/calyxos/backup/storage/db/UriStore.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * SPDX-FileCopyrightText: 2021 The Calyx Institute
3 | * SPDX-License-Identifier: Apache-2.0
4 | */
5 |
6 | package org.calyxos.backup.storage.db
7 |
8 | import android.net.Uri
9 | import androidx.room.Dao
10 | import androidx.room.Delete
11 | import androidx.room.Entity
12 | import androidx.room.Insert
13 | import androidx.room.OnConflictStrategy
14 | import androidx.room.PrimaryKey
15 | import androidx.room.Query
16 |
17 | @Entity
18 | internal data class StoredUri(
19 | @PrimaryKey val uri: Uri,
20 | )
21 |
22 | @Dao
23 | internal interface UriStore {
24 |
25 | @Insert(onConflict = OnConflictStrategy.IGNORE)
26 | fun addStoredUri(uri: StoredUri)
27 |
28 | @Delete
29 | fun removeStoredUri(uri: StoredUri)
30 |
31 | @Query("SELECT * FROM StoredUri")
32 | fun getStoredUris(): List
33 |
34 | }
35 |
--------------------------------------------------------------------------------
/storage/lib/src/main/java/org/calyxos/backup/storage/ui/backup/BackupContentItem.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * SPDX-FileCopyrightText: 2021 The Calyx Institute
3 | * SPDX-License-Identifier: Apache-2.0
4 | */
5 |
6 | package org.calyxos.backup.storage.ui.backup
7 |
8 | import android.content.Context
9 | import android.net.Uri
10 | import org.calyxos.backup.storage.api.BackupContentType
11 | import org.calyxos.backup.storage.api.MediaType
12 |
13 | public data class BackupContentItem(
14 | val uri: Uri,
15 | val contentType: BackupContentType,
16 | val enabled: Boolean,
17 | ) {
18 | public fun getName(context: Context): String = when (contentType) {
19 | is BackupContentType.Custom -> BackupContentType.Custom.getName(uri)
20 | is MediaType -> context.getString(contentType.nameRes)
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/storage/lib/src/main/proto/backup_document_file.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package org.calyxos.backup.storage.backup;
4 |
5 | option java_multiple_files = true;
6 |
7 | /**
8 | * A file in Android's DocumentsProvider.
9 | *
10 | * Excluded for now, but maybe interesting for later:
11 | * - DocumentsContract.Document.COLUMN_MIME_TYPE
12 | * - DocumentsContract.Document.COLUMN_SUMMARY
13 | */
14 | message BackupDocumentFile {
15 | string name = 1;
16 | string path = 2;
17 | int64 last_modified = 3;
18 | int64 size = 4;
19 | /**
20 | * This is empty for MediaStore.VOLUME_EXTERNAL_PRIMARY or "primary"
21 | */
22 | string volume = 5;
23 | /**
24 | * An ordered list of chunk IDs whose chunks that make up the file's content.
25 | */
26 | repeated string chunk_ids = 6;
27 | /**
28 | * If there is a single chunk ID and this is not 0, then the chunk ID refers to a zip chunk
29 | * and this file can be found at the zip entry with this index name.
30 | */
31 | int32 zip_index = 7;
32 | }
33 |
--------------------------------------------------------------------------------
/storage/lib/src/main/proto/backup_snapshot.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package org.calyxos.backup.storage.backup;
4 |
5 | import "backup_media_file.proto";
6 | import "backup_document_file.proto";
7 |
8 | option java_multiple_files = true;
9 |
10 | message BackupSnapshot {
11 | int32 version = 1;
12 | string name = 2;
13 | repeated BackupMediaFile media_files = 3;
14 | repeated BackupDocumentFile document_files = 4;
15 | int64 size = 5;
16 | int64 time_start = 6;
17 | int64 time_end = 7;
18 | }
19 |
--------------------------------------------------------------------------------
/storage/lib/src/main/res/drawable/ic_add.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
12 |
15 |
16 |
--------------------------------------------------------------------------------
/storage/lib/src/main/res/drawable/ic_audio_file.xml:
--------------------------------------------------------------------------------
1 |
5 |
11 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/storage/lib/src/main/res/drawable/ic_auto_delete.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
12 |
15 |
18 |
21 |
22 |
--------------------------------------------------------------------------------
/storage/lib/src/main/res/drawable/ic_chevron_right.xml:
--------------------------------------------------------------------------------
1 |
5 |
11 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/storage/lib/src/main/res/drawable/ic_cloud_done.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
12 |
15 |
16 |
--------------------------------------------------------------------------------
/storage/lib/src/main/res/drawable/ic_cloud_error.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
12 |
15 |
16 |
--------------------------------------------------------------------------------
/storage/lib/src/main/res/drawable/ic_cloud_search.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/storage/lib/src/main/res/drawable/ic_cloud_upload.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
12 |
15 |
16 |
--------------------------------------------------------------------------------
/storage/lib/src/main/res/drawable/ic_download_library.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
13 |
16 |
19 |
20 |
--------------------------------------------------------------------------------
/storage/lib/src/main/res/drawable/ic_folder.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
12 |
15 |
16 |
--------------------------------------------------------------------------------
/storage/lib/src/main/res/drawable/ic_image.xml:
--------------------------------------------------------------------------------
1 |
5 |
11 |
14 |
15 |
--------------------------------------------------------------------------------
/storage/lib/src/main/res/drawable/ic_indeterminate_check_box.xml:
--------------------------------------------------------------------------------
1 |
5 |
11 |
17 |
21 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/storage/lib/src/main/res/drawable/ic_insert_drive_file.xml:
--------------------------------------------------------------------------------
1 |
5 |
11 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/storage/lib/src/main/res/drawable/ic_keyboard_arrow_down.xml:
--------------------------------------------------------------------------------
1 |
5 |
11 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/storage/lib/src/main/res/drawable/ic_more_vert.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
12 |
15 |
16 |
--------------------------------------------------------------------------------
/storage/lib/src/main/res/drawable/ic_music_library.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
12 |
15 |
16 |
--------------------------------------------------------------------------------
/storage/lib/src/main/res/drawable/ic_photo_library.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
12 |
15 |
16 |
--------------------------------------------------------------------------------
/storage/lib/src/main/res/drawable/ic_video_file.xml:
--------------------------------------------------------------------------------
1 |
5 |
11 |
14 |
15 |
--------------------------------------------------------------------------------
/storage/lib/src/main/res/drawable/ic_video_library.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
12 |
15 |
16 |
--------------------------------------------------------------------------------
/storage/lib/src/main/res/drawable/ic_warning.xml:
--------------------------------------------------------------------------------
1 |
5 |
11 |
12 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/storage/lib/src/main/res/layout/activity_check_results.xml:
--------------------------------------------------------------------------------
1 |
5 |
10 |
--------------------------------------------------------------------------------
/storage/lib/src/main/res/menu/item_custom.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
13 |
--------------------------------------------------------------------------------
/storage/lib/src/main/res/values-af/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/storage/lib/src/main/res/values-am/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/storage/lib/src/main/res/values-as/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/storage/lib/src/main/res/values-ast/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/storage/lib/src/main/res/values-az/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/storage/lib/src/main/res/values-b+sr+Latn/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/storage/lib/src/main/res/values-b+zh+Hant+HK/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/storage/lib/src/main/res/values-be/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/storage/lib/src/main/res/values-bg/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/storage/lib/src/main/res/values-bn/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/storage/lib/src/main/res/values-bs/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/storage/lib/src/main/res/values-cy/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/storage/lib/src/main/res/values-da/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/storage/lib/src/main/res/values-en-rCA/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/storage/lib/src/main/res/values-en-rIN/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/storage/lib/src/main/res/values-eo/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/storage/lib/src/main/res/values-et/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/storage/lib/src/main/res/values-eu/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/storage/lib/src/main/res/values-fa/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/storage/lib/src/main/res/values-fi/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/storage/lib/src/main/res/values-fr-rCA/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/storage/lib/src/main/res/values-gd/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/storage/lib/src/main/res/values-gu/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/storage/lib/src/main/res/values-hi/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/storage/lib/src/main/res/values-hr/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/storage/lib/src/main/res/values-hy/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/storage/lib/src/main/res/values-in/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/storage/lib/src/main/res/values-is/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/storage/lib/src/main/res/values-ka/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/storage/lib/src/main/res/values-kk/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/storage/lib/src/main/res/values-km/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/storage/lib/src/main/res/values-kn/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/storage/lib/src/main/res/values-ko/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 사진과 이미지
4 | 비디오
5 | 오디오 파일
6 | 추가
7 | 저장소 백업
8 | 다운로드
9 | 파일 스캐닝중…
10 | 파일 백업중…
11 | 예전 백업 삭제하는 중…
12 | 저장소 복원
13 | 파일 복원중…
14 | %1$d/%2$d
15 | %2$d개 중 %1$d개의 파일이 복원됨
16 | 사용가능한 저장소 백업
17 | 저장소 백업을 찾을 수 없습니다 \n \n복원할 수 있는 것이 없습니다.
18 | 스냅샷 로딩하는 중에 에러 발생
19 | 옵션
20 |
21 |
--------------------------------------------------------------------------------
/storage/lib/src/main/res/values-ky/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/storage/lib/src/main/res/values-lo/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/storage/lib/src/main/res/values-lv/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/storage/lib/src/main/res/values-mk/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/storage/lib/src/main/res/values-ml/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | ചേർക്കുക
4 | %1$d/%2$d
5 | ഫയലുകൾ പുനഃസ്ഥാപിക്കുന്നു…
6 | സംഭരണം പുനഃസ്ഥാപിക്കുക
7 | സംഭരണ ബാക്കപ്പുകളൊന്നും കണ്ടെത്തിയില്ല \n \nക്ഷമിക്കണം, പുനഃസ്ഥാപിക്കാൻ കഴിയുന്ന ഒന്നുമില്ല.
8 | വീഡിയോകൾ
9 | ഡൗൺലോഡുകൾ
10 |
11 |
--------------------------------------------------------------------------------
/storage/lib/src/main/res/values-mn/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/storage/lib/src/main/res/values-mr/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/storage/lib/src/main/res/values-ms/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/storage/lib/src/main/res/values-my/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/storage/lib/src/main/res/values-ne/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/storage/lib/src/main/res/values-or/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/storage/lib/src/main/res/values-pa/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/storage/lib/src/main/res/values-si/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/storage/lib/src/main/res/values-sl/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/storage/lib/src/main/res/values-sq/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/storage/lib/src/main/res/values-sr/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/storage/lib/src/main/res/values-sw/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/storage/lib/src/main/res/values-te/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/storage/lib/src/main/res/values-th/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/storage/lib/src/main/res/values-tl/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/storage/lib/src/main/res/values-ur/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/storage/lib/src/main/res/values-uz/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/storage/lib/src/main/res/values-vi/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/storage/lib/src/main/res/values-zh-rTW/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/storage/lib/src/main/res/values-zu/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/storage/lint.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/storage/logcat-verbose.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | #
3 | # SPDX-FileCopyrightText: 2021 The Calyx Institute
4 | # SPDX-License-Identifier: Apache-2.0
5 | #
6 |
7 | adb shell setprop log.tag.JobScheduler DEBUG
8 | adb shell setprop log.tag.JobScheduler.ContentObserver DEBUG
9 |
--------------------------------------------------------------------------------