diff --git a/Android.bp b/Android.bp index e5cfe7a0..3bd010f4 100644 --- a/Android.bp +++ b/Android.bp @@ -9,6 +9,8 @@ android_app { "app/src/main/java/**/*.kt", "app/src/main/java/**/*.java", "app/src/main/proto/*.proto", + // as of Android 15, there is no way to pass --kotlin_out to aprotoc compiler + "app/build/generated/source/proto/debug/kotlin/com/stevesoltys/seedvault/proto/*.kt", ], resource_dirs: [ "app/src/main/res", @@ -33,6 +35,7 @@ android_app { "kotlinx-coroutines-android", "kotlinx-coroutines-core", // app backup related libs + "seedvault-lib-protobuf-kotlin-lite", "seedvault-lib-kotlin-logging-jvm", "seedvault-lib-chunker", "seedvault-lib-zstd-jni", diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 22e6af61..db81278f 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -111,6 +111,9 @@ android { id("java") { option("lite") } + id("kotlin") { + option("lite") + } } } } @@ -177,6 +180,9 @@ dependencies { implementation(fileTree("${rootProject.rootDir}/libs/koin-android").include("*.jar")) implementation(fileTree("${rootProject.rootDir}/libs/koin-android").include("*.aar")) + implementation( + fileTree("${rootProject.rootDir}/libs").include("protobuf-kotlin-lite-3.21.12.jar") + ) implementation(fileTree("${rootProject.rootDir}/libs").include("seedvault-chunker-0.1.jar")) implementation(fileTree("${rootProject.rootDir}/libs").include("zstd-jni-1.5.6-5.aar")) implementation(fileTree("${rootProject.rootDir}/libs").include("kotlin-bip39-jvm-1.0.6.jar")) diff --git a/app/build/generated/source/proto/debug/kotlin/com/stevesoltys/seedvault/proto/SnapshotKt.kt b/app/build/generated/source/proto/debug/kotlin/com/stevesoltys/seedvault/proto/SnapshotKt.kt new file mode 100644 index 00000000..e9ec0f04 --- /dev/null +++ b/app/build/generated/source/proto/debug/kotlin/com/stevesoltys/seedvault/proto/SnapshotKt.kt @@ -0,0 +1,933 @@ +//Generated by the protocol buffer compiler. DO NOT EDIT! +// source: snapshot.proto + +package com.stevesoltys.seedvault.proto; + +@kotlin.jvm.JvmName("-initializesnapshot") +public inline fun snapshot(block: com.stevesoltys.seedvault.proto.SnapshotKt.Dsl.() -> kotlin.Unit): com.stevesoltys.seedvault.proto.Snapshot = + com.stevesoltys.seedvault.proto.SnapshotKt.Dsl._create(com.stevesoltys.seedvault.proto.Snapshot.newBuilder()).apply { block() }._build() +public object SnapshotKt { + @kotlin.OptIn(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class) + @com.google.protobuf.kotlin.ProtoDslMarker + public class Dsl private constructor( + private val _builder: com.stevesoltys.seedvault.proto.Snapshot.Builder + ) { + public companion object { + @kotlin.jvm.JvmSynthetic + @kotlin.PublishedApi + internal fun _create(builder: com.stevesoltys.seedvault.proto.Snapshot.Builder): Dsl = Dsl(builder) + } + + @kotlin.jvm.JvmSynthetic + @kotlin.PublishedApi + internal fun _build(): com.stevesoltys.seedvault.proto.Snapshot = _builder.build() + + /** + * uint32 version = 1; + */ + public var version: kotlin.Int + @JvmName("getVersion") + get() = _builder.getVersion() + @JvmName("setVersion") + set(value) { + _builder.setVersion(value) + } + /** + * uint32 version = 1; + */ + public fun clearVersion() { + _builder.clearVersion() + } + + /** + * uint64 token = 2; + */ + public var token: kotlin.Long + @JvmName("getToken") + get() = _builder.getToken() + @JvmName("setToken") + set(value) { + _builder.setToken(value) + } + /** + * uint64 token = 2; + */ + public fun clearToken() { + _builder.clearToken() + } + + /** + * string name = 3; + */ + public var name: kotlin.String + @JvmName("getName") + get() = _builder.getName() + @JvmName("setName") + set(value) { + _builder.setName(value) + } + /** + * string name = 3; + */ + public fun clearName() { + _builder.clearName() + } + + /** + * string androidId = 4; + */ + public var androidId: kotlin.String + @JvmName("getAndroidId") + get() = _builder.getAndroidId() + @JvmName("setAndroidId") + set(value) { + _builder.setAndroidId(value) + } + /** + * string androidId = 4; + */ + public fun clearAndroidId() { + _builder.clearAndroidId() + } + + /** + * uint32 sdkInt = 5; + */ + public var sdkInt: kotlin.Int + @JvmName("getSdkInt") + get() = _builder.getSdkInt() + @JvmName("setSdkInt") + set(value) { + _builder.setSdkInt(value) + } + /** + * uint32 sdkInt = 5; + */ + public fun clearSdkInt() { + _builder.clearSdkInt() + } + + /** + * string androidIncremental = 6; + */ + public var androidIncremental: kotlin.String + @JvmName("getAndroidIncremental") + get() = _builder.getAndroidIncremental() + @JvmName("setAndroidIncremental") + set(value) { + _builder.setAndroidIncremental(value) + } + /** + * string androidIncremental = 6; + */ + public fun clearAndroidIncremental() { + _builder.clearAndroidIncremental() + } + + /** + * bool d2d = 7; + */ + public var d2D: kotlin.Boolean + @JvmName("getD2D") + get() = _builder.getD2D() + @JvmName("setD2D") + set(value) { + _builder.setD2D(value) + } + /** + * bool d2d = 7; + */ + public fun clearD2D() { + _builder.clearD2D() + } + + /** + * An uninstantiable, behaviorless type to represent the field in + * generics. + */ + @kotlin.OptIn(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class) + public class AppsProxy private constructor() : com.google.protobuf.kotlin.DslProxy() + /** + * map<string, .com.stevesoltys.seedvault.proto.Snapshot.App> apps = 8; + */ + public val apps: com.google.protobuf.kotlin.DslMap + @kotlin.jvm.JvmSynthetic + @JvmName("getAppsMap") + get() = com.google.protobuf.kotlin.DslMap( + _builder.getAppsMap() + ) + /** + * map<string, .com.stevesoltys.seedvault.proto.Snapshot.App> apps = 8; + */ + @JvmName("putApps") + public fun com.google.protobuf.kotlin.DslMap + .put(key: kotlin.String, value: com.stevesoltys.seedvault.proto.Snapshot.App) { + _builder.putApps(key, value) + } + /** + * map<string, .com.stevesoltys.seedvault.proto.Snapshot.App> apps = 8; + */ + @kotlin.jvm.JvmSynthetic + @JvmName("setApps") + @Suppress("NOTHING_TO_INLINE") + public inline operator fun com.google.protobuf.kotlin.DslMap + .set(key: kotlin.String, value: com.stevesoltys.seedvault.proto.Snapshot.App) { + put(key, value) + } + /** + * map<string, .com.stevesoltys.seedvault.proto.Snapshot.App> apps = 8; + */ + @kotlin.jvm.JvmSynthetic + @JvmName("removeApps") + public fun com.google.protobuf.kotlin.DslMap + .remove(key: kotlin.String) { + _builder.removeApps(key) + } + /** + * map<string, .com.stevesoltys.seedvault.proto.Snapshot.App> apps = 8; + */ + @kotlin.jvm.JvmSynthetic + @JvmName("putAllApps") + public fun com.google.protobuf.kotlin.DslMap + .putAll(map: kotlin.collections.Map) { + _builder.putAllApps(map) + } + /** + * map<string, .com.stevesoltys.seedvault.proto.Snapshot.App> apps = 8; + */ + @kotlin.jvm.JvmSynthetic + @JvmName("clearApps") + public fun com.google.protobuf.kotlin.DslMap + .clear() { + _builder.clearApps() + } + + /** + * An uninstantiable, behaviorless type to represent the field in + * generics. + */ + @kotlin.OptIn(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class) + public class IconChunkIdsProxy private constructor() : com.google.protobuf.kotlin.DslProxy() + /** + * repeated bytes iconChunkIds = 9; + */ + public val iconChunkIds: com.google.protobuf.kotlin.DslList + @kotlin.jvm.JvmSynthetic + get() = com.google.protobuf.kotlin.DslList( + _builder.getIconChunkIdsList() + ) + /** + * repeated bytes iconChunkIds = 9; + * @param value The iconChunkIds to add. + */ + @kotlin.jvm.JvmSynthetic + @kotlin.jvm.JvmName("addIconChunkIds") + public fun com.google.protobuf.kotlin.DslList.add(value: com.google.protobuf.ByteString) { + _builder.addIconChunkIds(value) + }/** + * repeated bytes iconChunkIds = 9; + * @param value The iconChunkIds to add. + */ + @kotlin.jvm.JvmSynthetic + @kotlin.jvm.JvmName("plusAssignIconChunkIds") + @Suppress("NOTHING_TO_INLINE") + public inline operator fun com.google.protobuf.kotlin.DslList.plusAssign(value: com.google.protobuf.ByteString) { + add(value) + }/** + * repeated bytes iconChunkIds = 9; + * @param values The iconChunkIds to add. + */ + @kotlin.jvm.JvmSynthetic + @kotlin.jvm.JvmName("addAllIconChunkIds") + public fun com.google.protobuf.kotlin.DslList.addAll(values: kotlin.collections.Iterable) { + _builder.addAllIconChunkIds(values) + }/** + * repeated bytes iconChunkIds = 9; + * @param values The iconChunkIds to add. + */ + @kotlin.jvm.JvmSynthetic + @kotlin.jvm.JvmName("plusAssignAllIconChunkIds") + @Suppress("NOTHING_TO_INLINE") + public inline operator fun com.google.protobuf.kotlin.DslList.plusAssign(values: kotlin.collections.Iterable) { + addAll(values) + }/** + * repeated bytes iconChunkIds = 9; + * @param index The index to set the value at. + * @param value The iconChunkIds to set. + */ + @kotlin.jvm.JvmSynthetic + @kotlin.jvm.JvmName("setIconChunkIds") + public operator fun com.google.protobuf.kotlin.DslList.set(index: kotlin.Int, value: com.google.protobuf.ByteString) { + _builder.setIconChunkIds(index, value) + }/** + * repeated bytes iconChunkIds = 9; + */ + @kotlin.jvm.JvmSynthetic + @kotlin.jvm.JvmName("clearIconChunkIds") + public fun com.google.protobuf.kotlin.DslList.clear() { + _builder.clearIconChunkIds() + } + /** + * An uninstantiable, behaviorless type to represent the field in + * generics. + */ + @kotlin.OptIn(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class) + public class BlobsProxy private constructor() : com.google.protobuf.kotlin.DslProxy() + /** + * map<string, .com.stevesoltys.seedvault.proto.Snapshot.Blob> blobs = 10; + */ + public val blobs: com.google.protobuf.kotlin.DslMap + @kotlin.jvm.JvmSynthetic + @JvmName("getBlobsMap") + get() = com.google.protobuf.kotlin.DslMap( + _builder.getBlobsMap() + ) + /** + * map<string, .com.stevesoltys.seedvault.proto.Snapshot.Blob> blobs = 10; + */ + @JvmName("putBlobs") + public fun com.google.protobuf.kotlin.DslMap + .put(key: kotlin.String, value: com.stevesoltys.seedvault.proto.Snapshot.Blob) { + _builder.putBlobs(key, value) + } + /** + * map<string, .com.stevesoltys.seedvault.proto.Snapshot.Blob> blobs = 10; + */ + @kotlin.jvm.JvmSynthetic + @JvmName("setBlobs") + @Suppress("NOTHING_TO_INLINE") + public inline operator fun com.google.protobuf.kotlin.DslMap + .set(key: kotlin.String, value: com.stevesoltys.seedvault.proto.Snapshot.Blob) { + put(key, value) + } + /** + * map<string, .com.stevesoltys.seedvault.proto.Snapshot.Blob> blobs = 10; + */ + @kotlin.jvm.JvmSynthetic + @JvmName("removeBlobs") + public fun com.google.protobuf.kotlin.DslMap + .remove(key: kotlin.String) { + _builder.removeBlobs(key) + } + /** + * map<string, .com.stevesoltys.seedvault.proto.Snapshot.Blob> blobs = 10; + */ + @kotlin.jvm.JvmSynthetic + @JvmName("putAllBlobs") + public fun com.google.protobuf.kotlin.DslMap + .putAll(map: kotlin.collections.Map) { + _builder.putAllBlobs(map) + } + /** + * map<string, .com.stevesoltys.seedvault.proto.Snapshot.Blob> blobs = 10; + */ + @kotlin.jvm.JvmSynthetic + @JvmName("clearBlobs") + public fun com.google.protobuf.kotlin.DslMap + .clear() { + _builder.clearBlobs() + } + } + @kotlin.jvm.JvmName("-initializeapp") + public inline fun app(block: com.stevesoltys.seedvault.proto.SnapshotKt.AppKt.Dsl.() -> kotlin.Unit): com.stevesoltys.seedvault.proto.Snapshot.App = + com.stevesoltys.seedvault.proto.SnapshotKt.AppKt.Dsl._create(com.stevesoltys.seedvault.proto.Snapshot.App.newBuilder()).apply { block() }._build() + public object AppKt { + @kotlin.OptIn(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class) + @com.google.protobuf.kotlin.ProtoDslMarker + public class Dsl private constructor( + private val _builder: com.stevesoltys.seedvault.proto.Snapshot.App.Builder + ) { + public companion object { + @kotlin.jvm.JvmSynthetic + @kotlin.PublishedApi + internal fun _create(builder: com.stevesoltys.seedvault.proto.Snapshot.App.Builder): Dsl = Dsl(builder) + } + + @kotlin.jvm.JvmSynthetic + @kotlin.PublishedApi + internal fun _build(): com.stevesoltys.seedvault.proto.Snapshot.App = _builder.build() + + /** + * uint64 time = 1; + */ + public var time: kotlin.Long + @JvmName("getTime") + get() = _builder.getTime() + @JvmName("setTime") + set(value) { + _builder.setTime(value) + } + /** + * uint64 time = 1; + */ + public fun clearTime() { + _builder.clearTime() + } + + /** + * string state = 2; + */ + public var state: kotlin.String + @JvmName("getState") + get() = _builder.getState() + @JvmName("setState") + set(value) { + _builder.setState(value) + } + /** + * string state = 2; + */ + public fun clearState() { + _builder.clearState() + } + + /** + * .com.stevesoltys.seedvault.proto.Snapshot.BackupType type = 3; + */ + public var type: com.stevesoltys.seedvault.proto.Snapshot.BackupType + @JvmName("getType") + get() = _builder.getType() + @JvmName("setType") + set(value) { + _builder.setType(value) + } + /** + * .com.stevesoltys.seedvault.proto.Snapshot.BackupType type = 3; + */ + public fun clearType() { + _builder.clearType() + } + + /** + * string name = 4; + */ + public var name: kotlin.String + @JvmName("getName") + get() = _builder.getName() + @JvmName("setName") + set(value) { + _builder.setName(value) + } + /** + * string name = 4; + */ + public fun clearName() { + _builder.clearName() + } + + /** + * bool system = 5; + */ + public var system: kotlin.Boolean + @JvmName("getSystem") + get() = _builder.getSystem() + @JvmName("setSystem") + set(value) { + _builder.setSystem(value) + } + /** + * bool system = 5; + */ + public fun clearSystem() { + _builder.clearSystem() + } + + /** + * bool launchableSystemApp = 6; + */ + public var launchableSystemApp: kotlin.Boolean + @JvmName("getLaunchableSystemApp") + get() = _builder.getLaunchableSystemApp() + @JvmName("setLaunchableSystemApp") + set(value) { + _builder.setLaunchableSystemApp(value) + } + /** + * bool launchableSystemApp = 6; + */ + public fun clearLaunchableSystemApp() { + _builder.clearLaunchableSystemApp() + } + + /** + * An uninstantiable, behaviorless type to represent the field in + * generics. + */ + @kotlin.OptIn(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class) + public class ChunkIdsProxy private constructor() : com.google.protobuf.kotlin.DslProxy() + /** + * repeated bytes chunkIds = 7; + */ + public val chunkIds: com.google.protobuf.kotlin.DslList + @kotlin.jvm.JvmSynthetic + get() = com.google.protobuf.kotlin.DslList( + _builder.getChunkIdsList() + ) + /** + * repeated bytes chunkIds = 7; + * @param value The chunkIds to add. + */ + @kotlin.jvm.JvmSynthetic + @kotlin.jvm.JvmName("addChunkIds") + public fun com.google.protobuf.kotlin.DslList.add(value: com.google.protobuf.ByteString) { + _builder.addChunkIds(value) + }/** + * repeated bytes chunkIds = 7; + * @param value The chunkIds to add. + */ + @kotlin.jvm.JvmSynthetic + @kotlin.jvm.JvmName("plusAssignChunkIds") + @Suppress("NOTHING_TO_INLINE") + public inline operator fun com.google.protobuf.kotlin.DslList.plusAssign(value: com.google.protobuf.ByteString) { + add(value) + }/** + * repeated bytes chunkIds = 7; + * @param values The chunkIds to add. + */ + @kotlin.jvm.JvmSynthetic + @kotlin.jvm.JvmName("addAllChunkIds") + public fun com.google.protobuf.kotlin.DslList.addAll(values: kotlin.collections.Iterable) { + _builder.addAllChunkIds(values) + }/** + * repeated bytes chunkIds = 7; + * @param values The chunkIds to add. + */ + @kotlin.jvm.JvmSynthetic + @kotlin.jvm.JvmName("plusAssignAllChunkIds") + @Suppress("NOTHING_TO_INLINE") + public inline operator fun com.google.protobuf.kotlin.DslList.plusAssign(values: kotlin.collections.Iterable) { + addAll(values) + }/** + * repeated bytes chunkIds = 7; + * @param index The index to set the value at. + * @param value The chunkIds to set. + */ + @kotlin.jvm.JvmSynthetic + @kotlin.jvm.JvmName("setChunkIds") + public operator fun com.google.protobuf.kotlin.DslList.set(index: kotlin.Int, value: com.google.protobuf.ByteString) { + _builder.setChunkIds(index, value) + }/** + * repeated bytes chunkIds = 7; + */ + @kotlin.jvm.JvmSynthetic + @kotlin.jvm.JvmName("clearChunkIds") + public fun com.google.protobuf.kotlin.DslList.clear() { + _builder.clearChunkIds() + } + /** + * .com.stevesoltys.seedvault.proto.Snapshot.Apk apk = 8; + */ + public var apk: com.stevesoltys.seedvault.proto.Snapshot.Apk + @JvmName("getApk") + get() = _builder.getApk() + @JvmName("setApk") + set(value) { + _builder.setApk(value) + } + /** + * .com.stevesoltys.seedvault.proto.Snapshot.Apk apk = 8; + */ + public fun clearApk() { + _builder.clearApk() + } + /** + * .com.stevesoltys.seedvault.proto.Snapshot.Apk apk = 8; + * @return Whether the apk field is set. + */ + public fun hasApk(): kotlin.Boolean { + return _builder.hasApk() + } + } + } + @kotlin.jvm.JvmName("-initializeapk") + public inline fun apk(block: com.stevesoltys.seedvault.proto.SnapshotKt.ApkKt.Dsl.() -> kotlin.Unit): com.stevesoltys.seedvault.proto.Snapshot.Apk = + com.stevesoltys.seedvault.proto.SnapshotKt.ApkKt.Dsl._create(com.stevesoltys.seedvault.proto.Snapshot.Apk.newBuilder()).apply { block() }._build() + public object ApkKt { + @kotlin.OptIn(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class) + @com.google.protobuf.kotlin.ProtoDslMarker + public class Dsl private constructor( + private val _builder: com.stevesoltys.seedvault.proto.Snapshot.Apk.Builder + ) { + public companion object { + @kotlin.jvm.JvmSynthetic + @kotlin.PublishedApi + internal fun _create(builder: com.stevesoltys.seedvault.proto.Snapshot.Apk.Builder): Dsl = Dsl(builder) + } + + @kotlin.jvm.JvmSynthetic + @kotlin.PublishedApi + internal fun _build(): com.stevesoltys.seedvault.proto.Snapshot.Apk = _builder.build() + + /** + *
+       **
+       * Attention: Has default value of 0
+       * 
+ * + * uint64 versionCode = 1; + */ + public var versionCode: kotlin.Long + @JvmName("getVersionCode") + get() = _builder.getVersionCode() + @JvmName("setVersionCode") + set(value) { + _builder.setVersionCode(value) + } + /** + *
+       **
+       * Attention: Has default value of 0
+       * 
+ * + * uint64 versionCode = 1; + */ + public fun clearVersionCode() { + _builder.clearVersionCode() + } + + /** + * string installer = 2; + */ + public var installer: kotlin.String + @JvmName("getInstaller") + get() = _builder.getInstaller() + @JvmName("setInstaller") + set(value) { + _builder.setInstaller(value) + } + /** + * string installer = 2; + */ + public fun clearInstaller() { + _builder.clearInstaller() + } + + /** + * An uninstantiable, behaviorless type to represent the field in + * generics. + */ + @kotlin.OptIn(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class) + public class SignaturesProxy private constructor() : com.google.protobuf.kotlin.DslProxy() + /** + * repeated bytes signatures = 3; + */ + public val signatures: com.google.protobuf.kotlin.DslList + @kotlin.jvm.JvmSynthetic + get() = com.google.protobuf.kotlin.DslList( + _builder.getSignaturesList() + ) + /** + * repeated bytes signatures = 3; + * @param value The signatures to add. + */ + @kotlin.jvm.JvmSynthetic + @kotlin.jvm.JvmName("addSignatures") + public fun com.google.protobuf.kotlin.DslList.add(value: com.google.protobuf.ByteString) { + _builder.addSignatures(value) + }/** + * repeated bytes signatures = 3; + * @param value The signatures to add. + */ + @kotlin.jvm.JvmSynthetic + @kotlin.jvm.JvmName("plusAssignSignatures") + @Suppress("NOTHING_TO_INLINE") + public inline operator fun com.google.protobuf.kotlin.DslList.plusAssign(value: com.google.protobuf.ByteString) { + add(value) + }/** + * repeated bytes signatures = 3; + * @param values The signatures to add. + */ + @kotlin.jvm.JvmSynthetic + @kotlin.jvm.JvmName("addAllSignatures") + public fun com.google.protobuf.kotlin.DslList.addAll(values: kotlin.collections.Iterable) { + _builder.addAllSignatures(values) + }/** + * repeated bytes signatures = 3; + * @param values The signatures to add. + */ + @kotlin.jvm.JvmSynthetic + @kotlin.jvm.JvmName("plusAssignAllSignatures") + @Suppress("NOTHING_TO_INLINE") + public inline operator fun com.google.protobuf.kotlin.DslList.plusAssign(values: kotlin.collections.Iterable) { + addAll(values) + }/** + * repeated bytes signatures = 3; + * @param index The index to set the value at. + * @param value The signatures to set. + */ + @kotlin.jvm.JvmSynthetic + @kotlin.jvm.JvmName("setSignatures") + public operator fun com.google.protobuf.kotlin.DslList.set(index: kotlin.Int, value: com.google.protobuf.ByteString) { + _builder.setSignatures(index, value) + }/** + * repeated bytes signatures = 3; + */ + @kotlin.jvm.JvmSynthetic + @kotlin.jvm.JvmName("clearSignatures") + public fun com.google.protobuf.kotlin.DslList.clear() { + _builder.clearSignatures() + } + /** + * An uninstantiable, behaviorless type to represent the field in + * generics. + */ + @kotlin.OptIn(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class) + public class SplitsProxy private constructor() : com.google.protobuf.kotlin.DslProxy() + /** + * repeated .com.stevesoltys.seedvault.proto.Snapshot.Split splits = 4; + */ + public val splits: com.google.protobuf.kotlin.DslList + @kotlin.jvm.JvmSynthetic + get() = com.google.protobuf.kotlin.DslList( + _builder.getSplitsList() + ) + /** + * repeated .com.stevesoltys.seedvault.proto.Snapshot.Split splits = 4; + * @param value The splits to add. + */ + @kotlin.jvm.JvmSynthetic + @kotlin.jvm.JvmName("addSplits") + public fun com.google.protobuf.kotlin.DslList.add(value: com.stevesoltys.seedvault.proto.Snapshot.Split) { + _builder.addSplits(value) + } + /** + * repeated .com.stevesoltys.seedvault.proto.Snapshot.Split splits = 4; + * @param value The splits to add. + */ + @kotlin.jvm.JvmSynthetic + @kotlin.jvm.JvmName("plusAssignSplits") + @Suppress("NOTHING_TO_INLINE") + public inline operator fun com.google.protobuf.kotlin.DslList.plusAssign(value: com.stevesoltys.seedvault.proto.Snapshot.Split) { + add(value) + } + /** + * repeated .com.stevesoltys.seedvault.proto.Snapshot.Split splits = 4; + * @param values The splits to add. + */ + @kotlin.jvm.JvmSynthetic + @kotlin.jvm.JvmName("addAllSplits") + public fun com.google.protobuf.kotlin.DslList.addAll(values: kotlin.collections.Iterable) { + _builder.addAllSplits(values) + } + /** + * repeated .com.stevesoltys.seedvault.proto.Snapshot.Split splits = 4; + * @param values The splits to add. + */ + @kotlin.jvm.JvmSynthetic + @kotlin.jvm.JvmName("plusAssignAllSplits") + @Suppress("NOTHING_TO_INLINE") + public inline operator fun com.google.protobuf.kotlin.DslList.plusAssign(values: kotlin.collections.Iterable) { + addAll(values) + } + /** + * repeated .com.stevesoltys.seedvault.proto.Snapshot.Split splits = 4; + * @param index The index to set the value at. + * @param value The splits to set. + */ + @kotlin.jvm.JvmSynthetic + @kotlin.jvm.JvmName("setSplits") + public operator fun com.google.protobuf.kotlin.DslList.set(index: kotlin.Int, value: com.stevesoltys.seedvault.proto.Snapshot.Split) { + _builder.setSplits(index, value) + } + /** + * repeated .com.stevesoltys.seedvault.proto.Snapshot.Split splits = 4; + */ + @kotlin.jvm.JvmSynthetic + @kotlin.jvm.JvmName("clearSplits") + public fun com.google.protobuf.kotlin.DslList.clear() { + _builder.clearSplits() + } + } + } + @kotlin.jvm.JvmName("-initializesplit") + public inline fun split(block: com.stevesoltys.seedvault.proto.SnapshotKt.SplitKt.Dsl.() -> kotlin.Unit): com.stevesoltys.seedvault.proto.Snapshot.Split = + com.stevesoltys.seedvault.proto.SnapshotKt.SplitKt.Dsl._create(com.stevesoltys.seedvault.proto.Snapshot.Split.newBuilder()).apply { block() }._build() + public object SplitKt { + @kotlin.OptIn(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class) + @com.google.protobuf.kotlin.ProtoDslMarker + public class Dsl private constructor( + private val _builder: com.stevesoltys.seedvault.proto.Snapshot.Split.Builder + ) { + public companion object { + @kotlin.jvm.JvmSynthetic + @kotlin.PublishedApi + internal fun _create(builder: com.stevesoltys.seedvault.proto.Snapshot.Split.Builder): Dsl = Dsl(builder) + } + + @kotlin.jvm.JvmSynthetic + @kotlin.PublishedApi + internal fun _build(): com.stevesoltys.seedvault.proto.Snapshot.Split = _builder.build() + + /** + * string name = 1; + */ + public var name: kotlin.String + @JvmName("getName") + get() = _builder.getName() + @JvmName("setName") + set(value) { + _builder.setName(value) + } + /** + * string name = 1; + */ + public fun clearName() { + _builder.clearName() + } + + /** + * An uninstantiable, behaviorless type to represent the field in + * generics. + */ + @kotlin.OptIn(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class) + public class ChunkIdsProxy private constructor() : com.google.protobuf.kotlin.DslProxy() + /** + * repeated bytes chunkIds = 2; + */ + public val chunkIds: com.google.protobuf.kotlin.DslList + @kotlin.jvm.JvmSynthetic + get() = com.google.protobuf.kotlin.DslList( + _builder.getChunkIdsList() + ) + /** + * repeated bytes chunkIds = 2; + * @param value The chunkIds to add. + */ + @kotlin.jvm.JvmSynthetic + @kotlin.jvm.JvmName("addChunkIds") + public fun com.google.protobuf.kotlin.DslList.add(value: com.google.protobuf.ByteString) { + _builder.addChunkIds(value) + }/** + * repeated bytes chunkIds = 2; + * @param value The chunkIds to add. + */ + @kotlin.jvm.JvmSynthetic + @kotlin.jvm.JvmName("plusAssignChunkIds") + @Suppress("NOTHING_TO_INLINE") + public inline operator fun com.google.protobuf.kotlin.DslList.plusAssign(value: com.google.protobuf.ByteString) { + add(value) + }/** + * repeated bytes chunkIds = 2; + * @param values The chunkIds to add. + */ + @kotlin.jvm.JvmSynthetic + @kotlin.jvm.JvmName("addAllChunkIds") + public fun com.google.protobuf.kotlin.DslList.addAll(values: kotlin.collections.Iterable) { + _builder.addAllChunkIds(values) + }/** + * repeated bytes chunkIds = 2; + * @param values The chunkIds to add. + */ + @kotlin.jvm.JvmSynthetic + @kotlin.jvm.JvmName("plusAssignAllChunkIds") + @Suppress("NOTHING_TO_INLINE") + public inline operator fun com.google.protobuf.kotlin.DslList.plusAssign(values: kotlin.collections.Iterable) { + addAll(values) + }/** + * repeated bytes chunkIds = 2; + * @param index The index to set the value at. + * @param value The chunkIds to set. + */ + @kotlin.jvm.JvmSynthetic + @kotlin.jvm.JvmName("setChunkIds") + public operator fun com.google.protobuf.kotlin.DslList.set(index: kotlin.Int, value: com.google.protobuf.ByteString) { + _builder.setChunkIds(index, value) + }/** + * repeated bytes chunkIds = 2; + */ + @kotlin.jvm.JvmSynthetic + @kotlin.jvm.JvmName("clearChunkIds") + public fun com.google.protobuf.kotlin.DslList.clear() { + _builder.clearChunkIds() + }} + } + @kotlin.jvm.JvmName("-initializeblob") + public inline fun blob(block: com.stevesoltys.seedvault.proto.SnapshotKt.BlobKt.Dsl.() -> kotlin.Unit): com.stevesoltys.seedvault.proto.Snapshot.Blob = + com.stevesoltys.seedvault.proto.SnapshotKt.BlobKt.Dsl._create(com.stevesoltys.seedvault.proto.Snapshot.Blob.newBuilder()).apply { block() }._build() + public object BlobKt { + @kotlin.OptIn(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class) + @com.google.protobuf.kotlin.ProtoDslMarker + public class Dsl private constructor( + private val _builder: com.stevesoltys.seedvault.proto.Snapshot.Blob.Builder + ) { + public companion object { + @kotlin.jvm.JvmSynthetic + @kotlin.PublishedApi + internal fun _create(builder: com.stevesoltys.seedvault.proto.Snapshot.Blob.Builder): Dsl = Dsl(builder) + } + + @kotlin.jvm.JvmSynthetic + @kotlin.PublishedApi + internal fun _build(): com.stevesoltys.seedvault.proto.Snapshot.Blob = _builder.build() + + /** + * bytes id = 1; + */ + public var id: com.google.protobuf.ByteString + @JvmName("getId") + get() = _builder.getId() + @JvmName("setId") + set(value) { + _builder.setId(value) + } + /** + * bytes id = 1; + */ + public fun clearId() { + _builder.clearId() + } + + /** + * uint32 length = 2; + */ + public var length: kotlin.Int + @JvmName("getLength") + get() = _builder.getLength() + @JvmName("setLength") + set(value) { + _builder.setLength(value) + } + /** + * uint32 length = 2; + */ + public fun clearLength() { + _builder.clearLength() + } + + /** + * uint32 uncompressedLength = 3; + */ + public var uncompressedLength: kotlin.Int + @JvmName("getUncompressedLength") + get() = _builder.getUncompressedLength() + @JvmName("setUncompressedLength") + set(value) { + _builder.setUncompressedLength(value) + } + /** + * uint32 uncompressedLength = 3; + */ + public fun clearUncompressedLength() { + _builder.clearUncompressedLength() + } + } + } +} +public inline fun com.stevesoltys.seedvault.proto.Snapshot.copy(block: com.stevesoltys.seedvault.proto.SnapshotKt.Dsl.() -> kotlin.Unit): com.stevesoltys.seedvault.proto.Snapshot = + com.stevesoltys.seedvault.proto.SnapshotKt.Dsl._create(this.toBuilder()).apply { block() }._build() + +public inline fun com.stevesoltys.seedvault.proto.Snapshot.App.copy(block: com.stevesoltys.seedvault.proto.SnapshotKt.AppKt.Dsl.() -> kotlin.Unit): com.stevesoltys.seedvault.proto.Snapshot.App = + com.stevesoltys.seedvault.proto.SnapshotKt.AppKt.Dsl._create(this.toBuilder()).apply { block() }._build() + +public val com.stevesoltys.seedvault.proto.Snapshot.AppOrBuilder.apkOrNull: com.stevesoltys.seedvault.proto.Snapshot.Apk? + get() = if (hasApk()) getApk() else null + +public inline fun com.stevesoltys.seedvault.proto.Snapshot.Apk.copy(block: com.stevesoltys.seedvault.proto.SnapshotKt.ApkKt.Dsl.() -> kotlin.Unit): com.stevesoltys.seedvault.proto.Snapshot.Apk = + com.stevesoltys.seedvault.proto.SnapshotKt.ApkKt.Dsl._create(this.toBuilder()).apply { block() }._build() + +public inline fun com.stevesoltys.seedvault.proto.Snapshot.Split.copy(block: com.stevesoltys.seedvault.proto.SnapshotKt.SplitKt.Dsl.() -> kotlin.Unit): com.stevesoltys.seedvault.proto.Snapshot.Split = + com.stevesoltys.seedvault.proto.SnapshotKt.SplitKt.Dsl._create(this.toBuilder()).apply { block() }._build() + +public inline fun com.stevesoltys.seedvault.proto.Snapshot.Blob.copy(block: com.stevesoltys.seedvault.proto.SnapshotKt.BlobKt.Dsl.() -> kotlin.Unit): com.stevesoltys.seedvault.proto.Snapshot.Blob = + com.stevesoltys.seedvault.proto.SnapshotKt.BlobKt.Dsl._create(this.toBuilder()).apply { block() }._build() + diff --git a/app/src/androidTest/java/com/stevesoltys/seedvault/worker/IconManagerTest.kt b/app/src/androidTest/java/com/stevesoltys/seedvault/worker/IconManagerTest.kt index a16413e3..aec46369 100644 --- a/app/src/androidTest/java/com/stevesoltys/seedvault/worker/IconManagerTest.kt +++ b/app/src/androidTest/java/com/stevesoltys/seedvault/worker/IconManagerTest.kt @@ -9,7 +9,7 @@ import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.MediumTest import androidx.test.platform.app.InstrumentationRegistry import com.google.protobuf.ByteString -import com.stevesoltys.seedvault.proto.Snapshot +import com.stevesoltys.seedvault.proto.SnapshotKt.blob import com.stevesoltys.seedvault.transport.backup.AppBackupManager import com.stevesoltys.seedvault.transport.backup.BackupData import com.stevesoltys.seedvault.transport.backup.BackupReceiver @@ -66,7 +66,7 @@ class IconManagerTest : KoinComponent { val chunkId = Random.nextBytes(32).toHexString() val chunkList = listOf(chunkId) val blobId = Random.nextBytes(32).toHexString() - val blob = Snapshot.Blob.newBuilder().setId(ByteString.fromHex(blobId)).build() + val blob = blob { id = ByteString.fromHex(blobId) } // upload icons and capture plaintext bytes coEvery { backupReceiver.addBytes(capture(output)) } just Runs diff --git a/app/src/main/java/com/stevesoltys/seedvault/metadata/Metadata.kt b/app/src/main/java/com/stevesoltys/seedvault/metadata/Metadata.kt index 4311dc8f..ccf3d6ca 100644 --- a/app/src/main/java/com/stevesoltys/seedvault/metadata/Metadata.kt +++ b/app/src/main/java/com/stevesoltys/seedvault/metadata/Metadata.kt @@ -115,7 +115,7 @@ data class PackageMetadata( system = app.system, isLaunchableSystemApp = app.launchableSystemApp, version = app.apk.versionCode, - installer = app.apk.installer, + installer = app.apk.installer.takeIf { it.isNotEmpty() }, baseApkChunkIds = run { val baseChunk = app.apk.splitsList.find { it.name == BASE_SPLIT } if (baseChunk == null || baseChunk.chunkIdsCount == 0) { diff --git a/app/src/main/java/com/stevesoltys/seedvault/transport/backup/BlobCreator.kt b/app/src/main/java/com/stevesoltys/seedvault/transport/backup/BlobCreator.kt index 1a86158b..59ebeefb 100644 --- a/app/src/main/java/com/stevesoltys/seedvault/transport/backup/BlobCreator.kt +++ b/app/src/main/java/com/stevesoltys/seedvault/transport/backup/BlobCreator.kt @@ -11,6 +11,7 @@ import com.stevesoltys.seedvault.backend.BackendManager import com.stevesoltys.seedvault.crypto.Crypto import com.stevesoltys.seedvault.header.VERSION import com.stevesoltys.seedvault.proto.Snapshot.Blob +import com.stevesoltys.seedvault.proto.SnapshotKt.blob import okio.Buffer import okio.buffer import okio.sink @@ -43,10 +44,10 @@ internal class BlobCreator( outputBuffer.flush() length } - return Blob.newBuilder() - .setId(ByteString.copyFrom(sha256ByteString.asByteBuffer())) - .setLength(size.toInt()) - .setUncompressedLength(chunk.length) - .build() + return blob { + id = ByteString.copyFrom(sha256ByteString.asByteBuffer()) + length = size.toInt() + uncompressedLength = chunk.length + } } } diff --git a/app/src/main/java/com/stevesoltys/seedvault/transport/backup/SnapshotCreator.kt b/app/src/main/java/com/stevesoltys/seedvault/transport/backup/SnapshotCreator.kt index b5151552..4c5ad3d6 100644 --- a/app/src/main/java/com/stevesoltys/seedvault/transport/backup/SnapshotCreator.kt +++ b/app/src/main/java/com/stevesoltys/seedvault/transport/backup/SnapshotCreator.kt @@ -15,6 +15,7 @@ import android.provider.Settings import android.provider.Settings.Secure.ANDROID_ID import com.google.protobuf.ByteString import com.stevesoltys.seedvault.Clock +import com.stevesoltys.seedvault.header.VERSION import com.stevesoltys.seedvault.metadata.BackupType import com.stevesoltys.seedvault.metadata.PackageState.APK_AND_DATA import com.stevesoltys.seedvault.proto.Snapshot @@ -22,6 +23,7 @@ import com.stevesoltys.seedvault.proto.Snapshot.Apk import com.stevesoltys.seedvault.proto.Snapshot.App import com.stevesoltys.seedvault.proto.Snapshot.Blob import com.stevesoltys.seedvault.settings.SettingsManager +import io.github.oshai.kotlinlogging.KotlinLogging import org.calyxos.seedvault.core.backends.AppBackupFileType import org.calyxos.seedvault.core.toHexString @@ -41,8 +43,8 @@ internal class SnapshotCreator( private val settingsManager: SettingsManager, ) { + private val log = KotlinLogging.logger { } private val snapshotBuilder = Snapshot.newBuilder() - .setToken(clock.time()) private val appBuilderMap = mutableMapOf() private val blobsMap = mutableMapOf() @@ -51,37 +53,41 @@ internal class SnapshotCreator( } fun onApkBackedUp( - packageName: String, + packageInfo: PackageInfo, apk: Apk, chunkMap: Map, ) { - val appBuilder = appBuilderMap.getOrPut(packageName) { + appBuilderMap.getOrPut(packageInfo.packageName) { App.newBuilder() + }.apply { + val label = packageInfo.applicationInfo?.loadLabel(context.packageManager) + if (label != null) name = label.toString() + setApk(apk) } - appBuilder.setApk(apk) blobsMap.putAll(chunkMap) } fun onPackageBackedUp( packageInfo: PackageInfo, - type: BackupType, + backupType: BackupType, backupData: BackupData, ) { val packageName = packageInfo.packageName - val builder = appBuilderMap.getOrPut(packageName) { - App.newBuilder() - } val isSystemApp = packageInfo.isSystemApp() val chunkIds = backupData.chunks.forProto() + appBuilderMap.getOrPut(packageName) { + App.newBuilder() + }.apply { + time = clock.time() + state = APK_AND_DATA.name // TODO review those states and their usefulness for snapshot + type = backupType.forSnapshot() + val label = packageInfo.applicationInfo?.loadLabel(context.packageManager) + if (label != null) name = label.toString() + system = isSystemApp + launchableSystemApp = isSystemApp && launchableSystemApps.contains(packageName) + addAllChunkIds(chunkIds) + } blobsMap.putAll(backupData.chunkMap) - builder - .setTime(clock.time()) - .setState(APK_AND_DATA.name) - .setType(type.forSnapshot()) - .setName(packageInfo.applicationInfo?.loadLabel(context.packageManager)?.toString()) - .setSystem(isSystemApp) - .setLaunchableSystemApp(isSystemApp && launchableSystemApps.contains(packageName)) - .addAllChunkIds(chunkIds) } fun onIconsBackedUp(backupData: BackupData) { @@ -90,6 +96,7 @@ internal class SnapshotCreator( } fun finalizeSnapshot(): Snapshot { + log.info { "finalizeSnapshot()" } val userName = getUserName() val deviceName = if (userName == null) { "${Build.MANUFACTURER} ${Build.MODEL}" @@ -98,16 +105,17 @@ internal class SnapshotCreator( } @SuppressLint("HardwareIds") - val androidId = Settings.Secure.getString(context.contentResolver, ANDROID_ID) - val snapshot = snapshotBuilder - .setName(deviceName) - .setAndroidId(androidId) - .setSdkInt(Build.VERSION.SDK_INT) - .setAndroidIncremental(Build.VERSION.INCREMENTAL) - .setD2D(settingsManager.d2dBackupsEnabled()) - .putAllApps(appBuilderMap.mapValues { it.value.build() }) - .putAllBlobs(blobsMap) - .build() + val snapshot = snapshotBuilder.apply { + version = VERSION.toInt() + token = clock.time() + name = deviceName + androidId = Settings.Secure.getString(context.contentResolver, ANDROID_ID) + sdkInt = Build.VERSION.SDK_INT + androidIncremental = Build.VERSION.INCREMENTAL + d2D = settingsManager.d2dBackupsEnabled() + putAllApps(appBuilderMap.mapValues { it.value.build() }) + putAllBlobs(this@SnapshotCreator.blobsMap) + }.build() appBuilderMap.clear() snapshotBuilder.clear() return snapshot diff --git a/app/src/main/java/com/stevesoltys/seedvault/worker/ApkBackup.kt b/app/src/main/java/com/stevesoltys/seedvault/worker/ApkBackup.kt index 898cb193..1d282982 100644 --- a/app/src/main/java/com/stevesoltys/seedvault/worker/ApkBackup.kt +++ b/app/src/main/java/com/stevesoltys/seedvault/worker/ApkBackup.kt @@ -14,6 +14,7 @@ import android.util.PackageUtils.computeSha256DigestBytes import com.stevesoltys.seedvault.MAGIC_PACKAGE_MANAGER import com.stevesoltys.seedvault.metadata.PackageMetadata import com.stevesoltys.seedvault.proto.Snapshot +import com.stevesoltys.seedvault.proto.SnapshotKt.split import com.stevesoltys.seedvault.settings.SettingsManager import com.stevesoltys.seedvault.transport.SnapshotManager import com.stevesoltys.seedvault.transport.backup.AppBackupManager @@ -108,10 +109,14 @@ internal class ApkBackup( } // builder for Apk object - val apkBuilder = Snapshot.Apk.newBuilder() - .setVersionCode(version) - .setInstaller(pm.getInstallSourceInfo(packageName).installingPackageName) - .addAllSignatures(signatures.forProto()) + val apkBuilder = Snapshot.Apk.newBuilder().apply { + versionCode = version + pm.getInstallSourceInfo(packageName).installingPackageName?.let { + // protobuf doesn't support null values + installer = it + } + addAllSignatures(signatures.forProto()) + } // get an InputStream for the APK val sourceDir = packageInfo.applicationInfo?.sourceDir ?: return @@ -121,9 +126,10 @@ internal class ApkBackup( } val backupData = backupReceiver.finalize() // store base split in builder - val baseSplit = Snapshot.Split.newBuilder() - .setName(BASE_SPLIT) - .addAllChunkIds(backupData.chunks.forProto()) + val baseSplit = split { + name = BASE_SPLIT + chunkIds.addAll(backupData.chunks.forProto()) + } apkBuilder .addSplits(baseSplit) val chunkMap = backupData.chunkMap.toMutableMap() @@ -134,9 +140,8 @@ internal class ApkBackup( } else { backupSplitApks(packageInfo, chunkMap) } - apkBuilder.addAllSplits(splits) - val apk = apkBuilder.build() - snapshotCreator.onApkBackedUp(packageName, apk, chunkMap) + val apk = apkBuilder.addAllSplits(splits).build() + snapshotCreator.onApkBackedUp(packageInfo, apk, chunkMap) Log.d(TAG, "Backed up new APK of $packageName with version ${packageInfo.versionName}.") } diff --git a/app/src/test/java/com/stevesoltys/seedvault/restore/AppSelectionManagerTest.kt b/app/src/test/java/com/stevesoltys/seedvault/restore/AppSelectionManagerTest.kt index 1f00e1a8..3768f501 100644 --- a/app/src/test/java/com/stevesoltys/seedvault/restore/AppSelectionManagerTest.kt +++ b/app/src/test/java/com/stevesoltys/seedvault/restore/AppSelectionManagerTest.kt @@ -14,7 +14,6 @@ import com.stevesoltys.seedvault.getRandomString import com.stevesoltys.seedvault.metadata.BackupMetadata import com.stevesoltys.seedvault.metadata.PackageMetadata import com.stevesoltys.seedvault.metadata.PackageMetadataMap -import com.stevesoltys.seedvault.proto.Snapshot import com.stevesoltys.seedvault.transport.TransportTest import com.stevesoltys.seedvault.ui.PACKAGE_NAME_CONTACTS import com.stevesoltys.seedvault.ui.PACKAGE_NAME_SETTINGS @@ -29,7 +28,6 @@ import kotlinx.coroutines.test.UnconfinedTestDispatcher import kotlinx.coroutines.test.runTest import org.calyxos.seedvault.core.backends.Backend import org.calyxos.seedvault.core.backends.LegacyAppBackupFile -import org.calyxos.seedvault.core.toHexString import org.junit.Test import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Assertions.assertFalse @@ -61,12 +59,6 @@ internal class AppSelectionManagerTest : TransportTest() { token = Random.nextLong(), salt = getRandomString(), ) - private val repoId = Random.nextBytes(32).toHexString() - private val snapshot = Snapshot.newBuilder() - .setToken(token) - .putApps(packageInfo.packageName, Snapshot.App.getDefaultInstance()) - .putAllBlobs(emptyMap()) - .build() private val appSelectionManager = AppSelectionManager( context = context, diff --git a/app/src/test/java/com/stevesoltys/seedvault/restore/install/ApkBackupRestoreTest.kt b/app/src/test/java/com/stevesoltys/seedvault/restore/install/ApkBackupRestoreTest.kt index 1be5ab32..f613fbf8 100644 --- a/app/src/test/java/com/stevesoltys/seedvault/restore/install/ApkBackupRestoreTest.kt +++ b/app/src/test/java/com/stevesoltys/seedvault/restore/install/ApkBackupRestoreTest.kt @@ -14,13 +14,10 @@ import android.content.pm.Signature import android.graphics.drawable.Drawable import android.util.PackageUtils import app.cash.turbine.test -import com.google.protobuf.ByteString -import com.google.protobuf.ByteString.copyFromUtf8 import com.stevesoltys.seedvault.BackupStateManager import com.stevesoltys.seedvault.assertReadEquals import com.stevesoltys.seedvault.backend.BackendManager import com.stevesoltys.seedvault.backend.LegacyStoragePlugin -import com.stevesoltys.seedvault.decodeBase64 import com.stevesoltys.seedvault.getRandomString import com.stevesoltys.seedvault.metadata.PackageMetadata import com.stevesoltys.seedvault.metadata.PackageMetadataMap @@ -31,14 +28,12 @@ import com.stevesoltys.seedvault.restore.install.ApkInstallState.SUCCEEDED import com.stevesoltys.seedvault.transport.SnapshotManager import com.stevesoltys.seedvault.transport.TransportTest import com.stevesoltys.seedvault.transport.backup.AppBackupManager -import com.stevesoltys.seedvault.transport.backup.BackupData import com.stevesoltys.seedvault.transport.backup.BackupReceiver import com.stevesoltys.seedvault.transport.backup.SnapshotCreator import com.stevesoltys.seedvault.transport.backup.hexFromProto import com.stevesoltys.seedvault.transport.restore.Loader import com.stevesoltys.seedvault.transport.restore.RestorableBackup import com.stevesoltys.seedvault.worker.ApkBackup -import com.stevesoltys.seedvault.worker.BASE_SPLIT import io.mockk.Runs import io.mockk.coEvery import io.mockk.every @@ -46,11 +41,10 @@ import io.mockk.just import io.mockk.mockk import io.mockk.mockkStatic import io.mockk.slot -import kotlinx.coroutines.ExperimentalCoroutinesApi + import kotlinx.coroutines.runBlocking import org.calyxos.seedvault.core.backends.AppBackupFileType import org.calyxos.seedvault.core.backends.Backend -import org.calyxos.seedvault.core.toHexString import org.junit.jupiter.api.Assertions.assertArrayEquals import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Assertions.assertFalse @@ -64,9 +58,7 @@ import java.io.File import java.io.FileInputStream import java.io.InputStream import java.nio.file.Path -import kotlin.random.Random -@ExperimentalCoroutinesApi internal class ApkBackupRestoreTest : TransportTest() { private val pm: PackageManager = mockk() @@ -108,37 +100,6 @@ internal class ApkBackupRestoreTest : TransportTest() { private val signatureBytes = byteArrayOf(0x01, 0x02, 0x03) private val signatureHash = byteArrayOf(0x03, 0x02, 0x01) private val sigs = arrayOf(Signature(signatureBytes)) - private val packageName: String = packageInfo.packageName - private val splitName = getRandomString() - private val splitBytes = byteArrayOf(0x07, 0x08, 0x09) - private val apkChunkId = Random.nextBytes(32).toHexString() - private val splitChunkId = Random.nextBytes(32).toHexString() - private val apkBlob = - Snapshot.Blob.newBuilder().setId(ByteString.copyFrom(Random.nextBytes(32))).build() - private val splitBlob = - Snapshot.Blob.newBuilder().setId(ByteString.copyFrom(Random.nextBytes(32))).build() - private val apkBackupData = BackupData(listOf(apkChunkId), mapOf(apkChunkId to apkBlob)) - private val splitBackupData = BackupData(listOf(splitChunkId), mapOf(splitChunkId to splitBlob)) - private val chunkMap = apkBackupData.chunkMap + splitBackupData.chunkMap - private val baseSplit = Snapshot.Split.newBuilder().setName(BASE_SPLIT) - .addAllChunkIds(listOf(ByteString.fromHex(apkChunkId))).build() - private val apkSplit = Snapshot.Split.newBuilder().setName(splitName) - .addAllChunkIds(listOf(ByteString.fromHex(splitChunkId))).build() - private val apk = Snapshot.Apk.newBuilder() - .setVersionCode(packageInfo.longVersionCode - 1) - .setInstaller(getRandomString()) - .addAllSignatures(mutableListOf(copyFromUtf8("AwIB".decodeBase64()))) - .addSplits(baseSplit) - .addSplits(apkSplit) - .build() - private val app = Snapshot.App.newBuilder() - .setApk(apk) - .build() - private val snapshot = Snapshot.newBuilder() - .setToken(token) - .putApps(packageName, app) - .putAllBlobs(chunkMap) - .build() private val packageMetadataMap: PackageMetadataMap = hashMapOf(packageName to PackageMetadata.fromSnapshot(app)) private val installerName = apk.installer diff --git a/app/src/test/java/com/stevesoltys/seedvault/restore/install/ApkRestoreTest.kt b/app/src/test/java/com/stevesoltys/seedvault/restore/install/ApkRestoreTest.kt index 93bceb56..9765c35f 100644 --- a/app/src/test/java/com/stevesoltys/seedvault/restore/install/ApkRestoreTest.kt +++ b/app/src/test/java/com/stevesoltys/seedvault/restore/install/ApkRestoreTest.kt @@ -17,19 +17,18 @@ import android.content.pm.PackageManager.NameNotFoundException import android.graphics.drawable.Drawable import app.cash.turbine.TurbineTestContext import app.cash.turbine.test -import com.google.protobuf.ByteString -import com.google.protobuf.ByteString.copyFromUtf8 +import com.google.protobuf.ByteString.copyFrom import com.google.protobuf.ByteString.fromHex import com.stevesoltys.seedvault.BackupStateManager import com.stevesoltys.seedvault.backend.BackendManager -import com.stevesoltys.seedvault.backend.LegacyStoragePlugin -import com.stevesoltys.seedvault.decodeBase64 import com.stevesoltys.seedvault.getRandomBase64 import com.stevesoltys.seedvault.getRandomString import com.stevesoltys.seedvault.metadata.ApkSplit import com.stevesoltys.seedvault.metadata.PackageMetadata import com.stevesoltys.seedvault.metadata.PackageMetadataMap -import com.stevesoltys.seedvault.proto.Snapshot +import com.stevesoltys.seedvault.proto.SnapshotKt.blob +import com.stevesoltys.seedvault.proto.SnapshotKt.split +import com.stevesoltys.seedvault.proto.copy import com.stevesoltys.seedvault.restore.RestorableBackup import com.stevesoltys.seedvault.restore.install.ApkInstallState.FAILED import com.stevesoltys.seedvault.restore.install.ApkInstallState.FAILED_SYSTEM_APP @@ -37,10 +36,8 @@ import com.stevesoltys.seedvault.restore.install.ApkInstallState.IN_PROGRESS import com.stevesoltys.seedvault.restore.install.ApkInstallState.QUEUED import com.stevesoltys.seedvault.restore.install.ApkInstallState.SUCCEEDED import com.stevesoltys.seedvault.transport.TransportTest -import com.stevesoltys.seedvault.transport.backup.BackupData import com.stevesoltys.seedvault.transport.backup.hexFromProto import com.stevesoltys.seedvault.transport.restore.Loader -import com.stevesoltys.seedvault.worker.BASE_SPLIT import io.mockk.Runs import io.mockk.coEvery import io.mockk.every @@ -48,7 +45,6 @@ import io.mockk.just import io.mockk.mockk import io.mockk.mockkStatic import io.mockk.verifyOrder -import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.runBlocking import org.calyxos.seedvault.core.backends.AppBackupFileType import org.calyxos.seedvault.core.backends.Backend @@ -66,7 +62,6 @@ import java.io.IOException import java.nio.file.Path import kotlin.random.Random -@ExperimentalCoroutinesApi internal class ApkRestoreTest : TransportTest() { private val pm: PackageManager = mockk() @@ -78,7 +73,6 @@ internal class ApkRestoreTest : TransportTest() { private val backendManager: BackendManager = mockk() private val loader: Loader = mockk() private val backend: Backend = mockk() - private val legacyStoragePlugin: LegacyStoragePlugin = mockk() private val splitCompatChecker: ApkSplitCompatibilityChecker = mockk() private val apkInstaller: ApkInstaller = mockk() private val installRestriction: InstallRestriction = mockk() @@ -89,8 +83,8 @@ internal class ApkRestoreTest : TransportTest() { backupStateManager = backupStateManager, backendManager = backendManager, loader = loader, - legacyStoragePlugin = legacyStoragePlugin, - crypto = crypto, + legacyStoragePlugin = mockk(), + crypto = mockk(), splitCompatChecker = splitCompatChecker, apkInstaller = apkInstaller, installRestriction = installRestriction, @@ -99,38 +93,24 @@ internal class ApkRestoreTest : TransportTest() { private val icon: Drawable = mockk() private val deviceName = metadata.deviceName - private val packageName = packageInfo.packageName private val apkBytes = byteArrayOf(0x04, 0x05, 0x06) private val apkInputStream = ByteArrayInputStream(apkBytes) private val appName = getRandomString() - private val repoId = Random.nextBytes(32).toHexString() - private val apkChunkId = Random.nextBytes(32).toHexString() - private val apkBlob = - Snapshot.Blob.newBuilder().setId(ByteString.copyFrom(Random.nextBytes(32))).build() - private val apkBlobHandle = AppBackupFileType.Blob(repoId, apkBlob.id.hexFromProto()) - private val apkBackupData = BackupData(listOf(apkChunkId), mapOf(apkChunkId to apkBlob)) - private val baseSplit = Snapshot.Split.newBuilder().setName(BASE_SPLIT) - .addAllChunkIds(listOf(fromHex(apkChunkId))).build() - private val apk = Snapshot.Apk.newBuilder() - .setVersionCode(packageInfo.longVersionCode - 1) - .setInstaller(getRandomString()) - .addAllSignatures(mutableListOf(copyFromUtf8("AwIB".decodeBase64()))) - .addSplits(baseSplit) - .build() - private val app = Snapshot.App.newBuilder() - .setApk(apk) - .build() - private val snapshot = Snapshot.newBuilder() - .setToken(token) - .putApps(packageName, app) - .putAllBlobs(apkBackupData.chunkMap) - .build() - private val packageMetadata = PackageMetadata.fromSnapshot(app) + private val appNoSplit = app.copy { // tests that need splits bring their own + this.apk = apk.copy { + splits.clear() + splits.add(baseSplit) + } + } + private val snapshotWithoutSplit = snapshot.copy { + apps[packageName] = appNoSplit + } + private val packageMetadata = PackageMetadata.fromSnapshot(appNoSplit) private val packageMetadataMap: PackageMetadataMap = hashMapOf(packageName to packageMetadata) private val installerName = packageMetadata.installer private val backup = RestorableBackup( repoId = repoId, - snapshot = snapshot, + snapshot = snapshotWithoutSplit, backupMetadata = metadata.copy(packageMetadataMap = packageMetadataMap), ) @@ -472,7 +452,7 @@ internal class ApkRestoreTest : TransportTest() { splits = listOf(split) ) val blobHandle = AppBackupFileType.Blob(repoId, splitBlobId) - val splitBlob = Snapshot.Blob.newBuilder().setId(fromHex(splitBlobId)).build() + val splitBlob = blob { id = fromHex(splitBlobId) } val snapshot = snapshot.toBuilder().putBlobs(splitChunkId, splitBlob).build() val backup = backup.copy(snapshot = snapshot) @@ -496,27 +476,31 @@ internal class ApkRestoreTest : TransportTest() { @Test fun `splits get installed along with base APK`(@TempDir tmpDir: Path) = runBlocking { // add one APK split to metadata - val split1Name = getRandomString() - val split2Name = getRandomString() val splitChunkId1 = Random.nextBytes(32).toHexString() val splitChunkId2 = Random.nextBytes(32).toHexString() - val apkSplit1 = Snapshot.Split.newBuilder().setName(split1Name) - .addAllChunkIds(listOf(fromHex(splitChunkId1))).build() - val apkSplit2 = Snapshot.Split.newBuilder().setName(split2Name) - .addAllChunkIds(listOf(fromHex(splitChunkId2))).build() - val splitBlob1 = - Snapshot.Blob.newBuilder().setId(ByteString.copyFrom(Random.nextBytes(32))).build() - val splitBlob2 = - Snapshot.Blob.newBuilder().setId(ByteString.copyFrom(Random.nextBytes(32))).build() - val apk = apk.toBuilder().addSplits(apkSplit1).addSplits(apkSplit2).build() - val app = app.toBuilder().setApk(apk).build() + val apkSplit1 = split { + name = getRandomString() + chunkIds.add(fromHex(splitChunkId1)) + } + val apkSplit2 = split { + name = getRandomString() + chunkIds.add(fromHex(splitChunkId2)) + } + val splitBlob1 = blob { id = copyFrom(Random.nextBytes(32)) } + val splitBlob2 = blob { id = copyFrom(Random.nextBytes(32)) } val blobMap = apkBackupData.chunkMap + mapOf(splitChunkId1 to splitBlob1) + mapOf(splitChunkId2 to splitBlob2) - val snapshot = snapshot.toBuilder() - .putApps(packageName, app) - .putAllBlobs(blobMap) - .build() + val app = appNoSplit.copy { + this.apk = apk.copy { + splits.clear() + splits.addAll(listOf(baseSplit, apkSplit1, apkSplit2)) + } + } + val snapshot = snapshotWithoutSplit.copy { + apps[packageName] = app + blobs.putAll(blobMap) + } packageMetadataMap[packageName] = PackageMetadata.fromSnapshot(app) val backup = backup.copy(snapshot = snapshot) @@ -528,7 +512,7 @@ internal class ApkRestoreTest : TransportTest() { cacheBaseApkAndGetInfo(tmpDir) every { - splitCompatChecker.isCompatible(deviceName, listOf(split1Name, split2Name)) + splitCompatChecker.isCompatible(deviceName, listOf(apkSplit1.name, apkSplit2.name)) } returns true // define bytes of splits and return them as stream (matches above hashes) diff --git a/app/src/test/java/com/stevesoltys/seedvault/restore/install/ApkRestoreV1Test.kt b/app/src/test/java/com/stevesoltys/seedvault/restore/install/ApkRestoreV1Test.kt index b04351be..3abfca1d 100644 --- a/app/src/test/java/com/stevesoltys/seedvault/restore/install/ApkRestoreV1Test.kt +++ b/app/src/test/java/com/stevesoltys/seedvault/restore/install/ApkRestoreV1Test.kt @@ -41,7 +41,6 @@ import io.mockk.just import io.mockk.mockk import io.mockk.mockkStatic import io.mockk.verifyOrder -import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.runBlocking import org.calyxos.seedvault.core.backends.Backend import org.calyxos.seedvault.core.backends.LegacyAppBackupFile @@ -57,7 +56,6 @@ import java.io.IOException import java.nio.file.Path import kotlin.random.Random -@ExperimentalCoroutinesApi @Suppress("DEPRECATION") internal class ApkRestoreV1Test : TransportTest() { @@ -91,7 +89,6 @@ internal class ApkRestoreV1Test : TransportTest() { private val icon: Drawable = mockk() private val deviceName = metadata.deviceName - private val packageName = packageInfo.packageName private val packageMetadata = PackageMetadata( time = Random.nextLong(), version = packageInfo.longVersionCode - 1, diff --git a/app/src/test/java/com/stevesoltys/seedvault/transport/SnapshotManagerTest.kt b/app/src/test/java/com/stevesoltys/seedvault/transport/SnapshotManagerTest.kt index e1a1652b..61b8cee7 100644 --- a/app/src/test/java/com/stevesoltys/seedvault/transport/SnapshotManagerTest.kt +++ b/app/src/test/java/com/stevesoltys/seedvault/transport/SnapshotManagerTest.kt @@ -6,8 +6,6 @@ package com.stevesoltys.seedvault.transport import com.stevesoltys.seedvault.backend.BackendManager -import com.stevesoltys.seedvault.crypto.Crypto -import com.stevesoltys.seedvault.getRandomString import com.stevesoltys.seedvault.proto.Snapshot import com.stevesoltys.seedvault.transport.restore.Loader import io.mockk.coEvery @@ -31,9 +29,8 @@ import java.io.OutputStream import java.security.MessageDigest import kotlin.random.Random -class SnapshotManagerTest { +internal class SnapshotManagerTest : TransportTest() { - private val crypto: Crypto = mockk() private val backendManager: BackendManager = mockk() private val backend: Backend = mockk() @@ -43,14 +40,7 @@ class SnapshotManagerTest { private val ad = Random.nextBytes(1) private val passThroughOutputStream = slot() private val passThroughInputStream = slot() - private val repoId = Random.nextBytes(32).toHexString() private val snapshotHandle = slot() - private val snapshot = Snapshot.newBuilder() - .setToken(Random.nextLong()) - .setName(getRandomString()) - .setSdkInt(Random.nextInt()) - .putAllBlobs(mapOf(getRandomString() to Snapshot.Blob.getDefaultInstance())) - .build() @Test fun `test saving and loading`() = runBlocking { diff --git a/app/src/test/java/com/stevesoltys/seedvault/transport/TransportTest.kt b/app/src/test/java/com/stevesoltys/seedvault/transport/TransportTest.kt index ee0e99d7..ef14a346 100644 --- a/app/src/test/java/com/stevesoltys/seedvault/transport/TransportTest.kt +++ b/app/src/test/java/com/stevesoltys/seedvault/transport/TransportTest.kt @@ -12,9 +12,12 @@ import android.content.pm.ApplicationInfo.FLAG_INSTALLED import android.content.pm.PackageInfo import android.content.pm.SigningInfo import android.util.Log +import com.google.protobuf.ByteString +import com.google.protobuf.ByteString.copyFromUtf8 import com.stevesoltys.seedvault.Clock import com.stevesoltys.seedvault.MAGIC_PACKAGE_MANAGER import com.stevesoltys.seedvault.crypto.Crypto +import com.stevesoltys.seedvault.decodeBase64 import com.stevesoltys.seedvault.getRandomBase64 import com.stevesoltys.seedvault.getRandomString import com.stevesoltys.seedvault.metadata.BackupMetadata @@ -23,12 +26,21 @@ import com.stevesoltys.seedvault.metadata.METADATA_SALT_SIZE import com.stevesoltys.seedvault.metadata.MetadataManager import com.stevesoltys.seedvault.metadata.PackageMetadata import com.stevesoltys.seedvault.metadata.PackageMetadataMap +import com.stevesoltys.seedvault.proto.SnapshotKt +import com.stevesoltys.seedvault.proto.SnapshotKt.blob +import com.stevesoltys.seedvault.proto.SnapshotKt.split +import com.stevesoltys.seedvault.proto.snapshot import com.stevesoltys.seedvault.settings.SettingsManager +import com.stevesoltys.seedvault.transport.backup.BackupData +import com.stevesoltys.seedvault.transport.backup.hexFromProto +import com.stevesoltys.seedvault.worker.BASE_SPLIT import io.mockk.every import io.mockk.mockk import io.mockk.mockkStatic import io.mockk.slot +import org.calyxos.seedvault.core.backends.AppBackupFileType import org.calyxos.seedvault.core.backends.LegacyAppBackupFile +import org.calyxos.seedvault.core.toHexString import org.junit.jupiter.api.TestInstance import org.junit.jupiter.api.TestInstance.Lifecycle.PER_METHOD import kotlin.random.Random @@ -53,6 +65,7 @@ internal abstract class TransportTest { applicationInfo = this@TransportTest.applicationInfo signingInfo = sigInfo } + protected val packageName: String = packageInfo.packageName protected val pmPackageInfo = PackageInfo().apply { packageName = MAGIC_PACKAGE_MANAGER } @@ -76,6 +89,46 @@ internal abstract class TransportTest { protected val storageProviderPackageName = getRandomString(23) protected val handle = LegacyAppBackupFile.Blob(token, name) + protected val repoId = Random.nextBytes(32).toHexString() + protected val splitName = getRandomString() + protected val splitBytes = byteArrayOf(0x07, 0x08, 0x09) + protected val apkChunkId = Random.nextBytes(32).toHexString() + protected val splitChunkId = Random.nextBytes(32).toHexString() + protected val apkBlob = blob { + id = ByteString.copyFrom(Random.nextBytes(32)) + } + protected val splitBlob = blob { + id = ByteString.copyFrom(Random.nextBytes(32)) + } + protected val apkBlobHandle = AppBackupFileType.Blob(repoId, apkBlob.id.hexFromProto()) + protected val apkBackupData = BackupData(listOf(apkChunkId), mapOf(apkChunkId to apkBlob)) + protected val splitBackupData = + BackupData(listOf(splitChunkId), mapOf(splitChunkId to splitBlob)) + protected val chunkMap = apkBackupData.chunkMap + splitBackupData.chunkMap + protected val baseSplit = split { + name = BASE_SPLIT + chunkIds.add(ByteString.fromHex(apkChunkId)) + } + protected val apkSplit = split { + name = splitName + chunkIds.add(ByteString.fromHex(splitChunkId)) + } + protected val apk = SnapshotKt.apk { + versionCode = packageInfo.longVersionCode - 1 + installer = getRandomString() + signatures.add(copyFromUtf8("AwIB".decodeBase64())) + splits.add(baseSplit) + splits.add(apkSplit) + } + protected val app = SnapshotKt.app { + apk = this@TransportTest.apk + } + protected val snapshot = snapshot { + token = this@TransportTest.token + apps[packageName] = app + blobs.putAll(chunkMap) + } + init { mockkStatic(Log::class) val logTagSlot = slot() diff --git a/app/src/test/java/com/stevesoltys/seedvault/transport/backup/KVBackupTest.kt b/app/src/test/java/com/stevesoltys/seedvault/transport/backup/KVBackupTest.kt index 422bf71d..5c83cee0 100644 --- a/app/src/test/java/com/stevesoltys/seedvault/transport/backup/KVBackupTest.kt +++ b/app/src/test/java/com/stevesoltys/seedvault/transport/backup/KVBackupTest.kt @@ -13,11 +13,11 @@ import android.app.backup.BackupTransport.TRANSPORT_ERROR import android.app.backup.BackupTransport.TRANSPORT_NON_INCREMENTAL_BACKUP_REQUIRED import android.app.backup.BackupTransport.TRANSPORT_OK import android.content.pm.PackageInfo +import com.stevesoltys.seedvault.backend.BackendManager import com.stevesoltys.seedvault.getRandomString import com.stevesoltys.seedvault.header.MAX_KEY_LENGTH_SIZE import com.stevesoltys.seedvault.header.VERSION import com.stevesoltys.seedvault.header.getADForKV -import com.stevesoltys.seedvault.backend.BackendManager import com.stevesoltys.seedvault.ui.notification.BackupNotificationManager import io.mockk.CapturingSlot import io.mockk.Runs @@ -55,7 +55,6 @@ internal class KVBackupTest : BackupTest() { private val db = mockk() private val backend = mockk() - private val packageName = packageInfo.packageName private val key = getRandomString(MAX_KEY_LENGTH_SIZE) private val dataValue = Random.nextBytes(23) private val dbBytes = Random.nextBytes(42) diff --git a/app/src/test/java/com/stevesoltys/seedvault/transport/restore/RestoreCoordinatorTest.kt b/app/src/test/java/com/stevesoltys/seedvault/transport/restore/RestoreCoordinatorTest.kt index f187ad00..23773189 100644 --- a/app/src/test/java/com/stevesoltys/seedvault/transport/restore/RestoreCoordinatorTest.kt +++ b/app/src/test/java/com/stevesoltys/seedvault/transport/restore/RestoreCoordinatorTest.kt @@ -73,7 +73,6 @@ internal class RestoreCoordinatorTest : TransportTest() { PackageInfo().apply { packageName = "@pm@" }, packageInfo ) - private val packageName = packageInfo.packageName private val storageName = getRandomString() init { diff --git a/app/src/test/java/com/stevesoltys/seedvault/worker/ApkBackupTest.kt b/app/src/test/java/com/stevesoltys/seedvault/worker/ApkBackupTest.kt index 27ca16df..a2c012dc 100644 --- a/app/src/test/java/com/stevesoltys/seedvault/worker/ApkBackupTest.kt +++ b/app/src/test/java/com/stevesoltys/seedvault/worker/ApkBackupTest.kt @@ -13,10 +13,12 @@ import android.content.pm.PackageInfo import android.content.pm.PackageManager import android.content.pm.Signature import android.util.PackageUtils -import com.google.protobuf.ByteString +import com.google.protobuf.ByteString.copyFromUtf8 import com.stevesoltys.seedvault.MAGIC_PACKAGE_MANAGER import com.stevesoltys.seedvault.getRandomString import com.stevesoltys.seedvault.proto.Snapshot +import com.stevesoltys.seedvault.proto.SnapshotKt.app +import com.stevesoltys.seedvault.proto.copy import com.stevesoltys.seedvault.transport.SnapshotManager import com.stevesoltys.seedvault.transport.backup.AppBackupManager import com.stevesoltys.seedvault.transport.backup.BackupData @@ -56,14 +58,6 @@ internal class ApkBackupTest : BackupTest() { private val signatureBytes = byteArrayOf(0x01, 0x02, 0x03) private val signatureHash = byteArrayOf(0x03, 0x02, 0x01) private val sigs = arrayOf(Signature(signatureBytes)) - private val apk = Snapshot.Apk.newBuilder() - .setVersionCode(packageInfo.longVersionCode - 1) - .addSignatures(ByteString.copyFrom(signatureHash)) - .build() - private val snapshot = Snapshot.newBuilder() - .setToken(token) - .putApps(packageInfo.packageName, Snapshot.App.newBuilder().setApk(apk).build()) - .build() init { mockkStatic(PackageUtils::class) @@ -113,8 +107,8 @@ internal class ApkBackupTest : BackupTest() { @Test fun `does not back up the same version`() = runBlocking { packageInfo.applicationInfo!!.flags = FLAG_UPDATED_SYSTEM_APP - val apk = apk.toBuilder().setVersionCode(packageInfo.longVersionCode).build() - val app = Snapshot.App.newBuilder().setApk(apk).build() + val apk = apk.copy { versionCode = packageInfo.longVersionCode } + val app = app { this.apk = apk } expectChecks(snapshot.toBuilder().putApps(packageInfo.packageName, app).build()) apkBackup.backupApkIfNecessary(packageInfo) @@ -123,12 +117,12 @@ internal class ApkBackupTest : BackupTest() { @Test fun `does back up the same version when signatures changes`() { packageInfo.applicationInfo!!.sourceDir = "/tmp/doesNotExist" - val apk = apk.toBuilder() - .clearSignatures() - .addSignatures(ByteString.copyFromUtf8("foo")) - .setVersionCode(packageInfo.longVersionCode) - .build() - val app = Snapshot.App.newBuilder().setApk(apk).build() + val apk = apk.copy { + signatures.clear() + signatures.add(copyFromUtf8("foo")) + versionCode = packageInfo.longVersionCode + } + val app = app { this.apk = apk } expectChecks(snapshot.toBuilder().putApps(packageInfo.packageName, app).build()) every { pm.getInstallSourceInfo(packageInfo.packageName) diff --git a/libs/Android.bp b/libs/Android.bp index ae63f75a..957fd446 100644 --- a/libs/Android.bp +++ b/libs/Android.bp @@ -10,6 +10,12 @@ android_library_import { extract_jni: true, } +java_import { + name: "seedvault-lib-protobuf-kotlin-lite", + jars: ["protobuf-kotlin-lite-3.21.12.jar"], + sdk_version: "current", +} + java_import { name: "seedvault-lib-kotlin-bip39", jars: ["kotlin-bip39-jvm-1.0.6.jar"], diff --git a/libs/protobuf-kotlin-lite-3.21.12.jar b/libs/protobuf-kotlin-lite-3.21.12.jar new file mode 100644 index 00000000..a16c4cab Binary files /dev/null and b/libs/protobuf-kotlin-lite-3.21.12.jar differ