Add protobuf-kotlin-lite and use new builders

This commit is contained in:
Torsten Grote 2024-09-06 10:48:10 -03:00
parent 897ae48b44
commit 8ce79f4195
No known key found for this signature in database
GPG key ID: 3E5F77D92CF891FF
19 changed files with 1112 additions and 181 deletions

View file

@ -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",

View file

@ -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"))

View file

@ -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()
/**
* <code>uint32 version = 1;</code>
*/
public var version: kotlin.Int
@JvmName("getVersion")
get() = _builder.getVersion()
@JvmName("setVersion")
set(value) {
_builder.setVersion(value)
}
/**
* <code>uint32 version = 1;</code>
*/
public fun clearVersion() {
_builder.clearVersion()
}
/**
* <code>uint64 token = 2;</code>
*/
public var token: kotlin.Long
@JvmName("getToken")
get() = _builder.getToken()
@JvmName("setToken")
set(value) {
_builder.setToken(value)
}
/**
* <code>uint64 token = 2;</code>
*/
public fun clearToken() {
_builder.clearToken()
}
/**
* <code>string name = 3;</code>
*/
public var name: kotlin.String
@JvmName("getName")
get() = _builder.getName()
@JvmName("setName")
set(value) {
_builder.setName(value)
}
/**
* <code>string name = 3;</code>
*/
public fun clearName() {
_builder.clearName()
}
/**
* <code>string androidId = 4;</code>
*/
public var androidId: kotlin.String
@JvmName("getAndroidId")
get() = _builder.getAndroidId()
@JvmName("setAndroidId")
set(value) {
_builder.setAndroidId(value)
}
/**
* <code>string androidId = 4;</code>
*/
public fun clearAndroidId() {
_builder.clearAndroidId()
}
/**
* <code>uint32 sdkInt = 5;</code>
*/
public var sdkInt: kotlin.Int
@JvmName("getSdkInt")
get() = _builder.getSdkInt()
@JvmName("setSdkInt")
set(value) {
_builder.setSdkInt(value)
}
/**
* <code>uint32 sdkInt = 5;</code>
*/
public fun clearSdkInt() {
_builder.clearSdkInt()
}
/**
* <code>string androidIncremental = 6;</code>
*/
public var androidIncremental: kotlin.String
@JvmName("getAndroidIncremental")
get() = _builder.getAndroidIncremental()
@JvmName("setAndroidIncremental")
set(value) {
_builder.setAndroidIncremental(value)
}
/**
* <code>string androidIncremental = 6;</code>
*/
public fun clearAndroidIncremental() {
_builder.clearAndroidIncremental()
}
/**
* <code>bool d2d = 7;</code>
*/
public var d2D: kotlin.Boolean
@JvmName("getD2D")
get() = _builder.getD2D()
@JvmName("setD2D")
set(value) {
_builder.setD2D(value)
}
/**
* <code>bool d2d = 7;</code>
*/
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()
/**
* <code>map&lt;string, .com.stevesoltys.seedvault.proto.Snapshot.App&gt; apps = 8;</code>
*/
public val apps: com.google.protobuf.kotlin.DslMap<kotlin.String, com.stevesoltys.seedvault.proto.Snapshot.App, AppsProxy>
@kotlin.jvm.JvmSynthetic
@JvmName("getAppsMap")
get() = com.google.protobuf.kotlin.DslMap(
_builder.getAppsMap()
)
/**
* <code>map&lt;string, .com.stevesoltys.seedvault.proto.Snapshot.App&gt; apps = 8;</code>
*/
@JvmName("putApps")
public fun com.google.protobuf.kotlin.DslMap<kotlin.String, com.stevesoltys.seedvault.proto.Snapshot.App, AppsProxy>
.put(key: kotlin.String, value: com.stevesoltys.seedvault.proto.Snapshot.App) {
_builder.putApps(key, value)
}
/**
* <code>map&lt;string, .com.stevesoltys.seedvault.proto.Snapshot.App&gt; apps = 8;</code>
*/
@kotlin.jvm.JvmSynthetic
@JvmName("setApps")
@Suppress("NOTHING_TO_INLINE")
public inline operator fun com.google.protobuf.kotlin.DslMap<kotlin.String, com.stevesoltys.seedvault.proto.Snapshot.App, AppsProxy>
.set(key: kotlin.String, value: com.stevesoltys.seedvault.proto.Snapshot.App) {
put(key, value)
}
/**
* <code>map&lt;string, .com.stevesoltys.seedvault.proto.Snapshot.App&gt; apps = 8;</code>
*/
@kotlin.jvm.JvmSynthetic
@JvmName("removeApps")
public fun com.google.protobuf.kotlin.DslMap<kotlin.String, com.stevesoltys.seedvault.proto.Snapshot.App, AppsProxy>
.remove(key: kotlin.String) {
_builder.removeApps(key)
}
/**
* <code>map&lt;string, .com.stevesoltys.seedvault.proto.Snapshot.App&gt; apps = 8;</code>
*/
@kotlin.jvm.JvmSynthetic
@JvmName("putAllApps")
public fun com.google.protobuf.kotlin.DslMap<kotlin.String, com.stevesoltys.seedvault.proto.Snapshot.App, AppsProxy>
.putAll(map: kotlin.collections.Map<kotlin.String, com.stevesoltys.seedvault.proto.Snapshot.App>) {
_builder.putAllApps(map)
}
/**
* <code>map&lt;string, .com.stevesoltys.seedvault.proto.Snapshot.App&gt; apps = 8;</code>
*/
@kotlin.jvm.JvmSynthetic
@JvmName("clearApps")
public fun com.google.protobuf.kotlin.DslMap<kotlin.String, com.stevesoltys.seedvault.proto.Snapshot.App, AppsProxy>
.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()
/**
* <code>repeated bytes iconChunkIds = 9;</code>
*/
public val iconChunkIds: com.google.protobuf.kotlin.DslList<com.google.protobuf.ByteString, IconChunkIdsProxy>
@kotlin.jvm.JvmSynthetic
get() = com.google.protobuf.kotlin.DslList(
_builder.getIconChunkIdsList()
)
/**
* <code>repeated bytes iconChunkIds = 9;</code>
* @param value The iconChunkIds to add.
*/
@kotlin.jvm.JvmSynthetic
@kotlin.jvm.JvmName("addIconChunkIds")
public fun com.google.protobuf.kotlin.DslList<com.google.protobuf.ByteString, IconChunkIdsProxy>.add(value: com.google.protobuf.ByteString) {
_builder.addIconChunkIds(value)
}/**
* <code>repeated bytes iconChunkIds = 9;</code>
* @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<com.google.protobuf.ByteString, IconChunkIdsProxy>.plusAssign(value: com.google.protobuf.ByteString) {
add(value)
}/**
* <code>repeated bytes iconChunkIds = 9;</code>
* @param values The iconChunkIds to add.
*/
@kotlin.jvm.JvmSynthetic
@kotlin.jvm.JvmName("addAllIconChunkIds")
public fun com.google.protobuf.kotlin.DslList<com.google.protobuf.ByteString, IconChunkIdsProxy>.addAll(values: kotlin.collections.Iterable<com.google.protobuf.ByteString>) {
_builder.addAllIconChunkIds(values)
}/**
* <code>repeated bytes iconChunkIds = 9;</code>
* @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<com.google.protobuf.ByteString, IconChunkIdsProxy>.plusAssign(values: kotlin.collections.Iterable<com.google.protobuf.ByteString>) {
addAll(values)
}/**
* <code>repeated bytes iconChunkIds = 9;</code>
* @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<com.google.protobuf.ByteString, IconChunkIdsProxy>.set(index: kotlin.Int, value: com.google.protobuf.ByteString) {
_builder.setIconChunkIds(index, value)
}/**
* <code>repeated bytes iconChunkIds = 9;</code>
*/
@kotlin.jvm.JvmSynthetic
@kotlin.jvm.JvmName("clearIconChunkIds")
public fun com.google.protobuf.kotlin.DslList<com.google.protobuf.ByteString, IconChunkIdsProxy>.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()
/**
* <code>map&lt;string, .com.stevesoltys.seedvault.proto.Snapshot.Blob&gt; blobs = 10;</code>
*/
public val blobs: com.google.protobuf.kotlin.DslMap<kotlin.String, com.stevesoltys.seedvault.proto.Snapshot.Blob, BlobsProxy>
@kotlin.jvm.JvmSynthetic
@JvmName("getBlobsMap")
get() = com.google.protobuf.kotlin.DslMap(
_builder.getBlobsMap()
)
/**
* <code>map&lt;string, .com.stevesoltys.seedvault.proto.Snapshot.Blob&gt; blobs = 10;</code>
*/
@JvmName("putBlobs")
public fun com.google.protobuf.kotlin.DslMap<kotlin.String, com.stevesoltys.seedvault.proto.Snapshot.Blob, BlobsProxy>
.put(key: kotlin.String, value: com.stevesoltys.seedvault.proto.Snapshot.Blob) {
_builder.putBlobs(key, value)
}
/**
* <code>map&lt;string, .com.stevesoltys.seedvault.proto.Snapshot.Blob&gt; blobs = 10;</code>
*/
@kotlin.jvm.JvmSynthetic
@JvmName("setBlobs")
@Suppress("NOTHING_TO_INLINE")
public inline operator fun com.google.protobuf.kotlin.DslMap<kotlin.String, com.stevesoltys.seedvault.proto.Snapshot.Blob, BlobsProxy>
.set(key: kotlin.String, value: com.stevesoltys.seedvault.proto.Snapshot.Blob) {
put(key, value)
}
/**
* <code>map&lt;string, .com.stevesoltys.seedvault.proto.Snapshot.Blob&gt; blobs = 10;</code>
*/
@kotlin.jvm.JvmSynthetic
@JvmName("removeBlobs")
public fun com.google.protobuf.kotlin.DslMap<kotlin.String, com.stevesoltys.seedvault.proto.Snapshot.Blob, BlobsProxy>
.remove(key: kotlin.String) {
_builder.removeBlobs(key)
}
/**
* <code>map&lt;string, .com.stevesoltys.seedvault.proto.Snapshot.Blob&gt; blobs = 10;</code>
*/
@kotlin.jvm.JvmSynthetic
@JvmName("putAllBlobs")
public fun com.google.protobuf.kotlin.DslMap<kotlin.String, com.stevesoltys.seedvault.proto.Snapshot.Blob, BlobsProxy>
.putAll(map: kotlin.collections.Map<kotlin.String, com.stevesoltys.seedvault.proto.Snapshot.Blob>) {
_builder.putAllBlobs(map)
}
/**
* <code>map&lt;string, .com.stevesoltys.seedvault.proto.Snapshot.Blob&gt; blobs = 10;</code>
*/
@kotlin.jvm.JvmSynthetic
@JvmName("clearBlobs")
public fun com.google.protobuf.kotlin.DslMap<kotlin.String, com.stevesoltys.seedvault.proto.Snapshot.Blob, BlobsProxy>
.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()
/**
* <code>uint64 time = 1;</code>
*/
public var time: kotlin.Long
@JvmName("getTime")
get() = _builder.getTime()
@JvmName("setTime")
set(value) {
_builder.setTime(value)
}
/**
* <code>uint64 time = 1;</code>
*/
public fun clearTime() {
_builder.clearTime()
}
/**
* <code>string state = 2;</code>
*/
public var state: kotlin.String
@JvmName("getState")
get() = _builder.getState()
@JvmName("setState")
set(value) {
_builder.setState(value)
}
/**
* <code>string state = 2;</code>
*/
public fun clearState() {
_builder.clearState()
}
/**
* <code>.com.stevesoltys.seedvault.proto.Snapshot.BackupType type = 3;</code>
*/
public var type: com.stevesoltys.seedvault.proto.Snapshot.BackupType
@JvmName("getType")
get() = _builder.getType()
@JvmName("setType")
set(value) {
_builder.setType(value)
}
/**
* <code>.com.stevesoltys.seedvault.proto.Snapshot.BackupType type = 3;</code>
*/
public fun clearType() {
_builder.clearType()
}
/**
* <code>string name = 4;</code>
*/
public var name: kotlin.String
@JvmName("getName")
get() = _builder.getName()
@JvmName("setName")
set(value) {
_builder.setName(value)
}
/**
* <code>string name = 4;</code>
*/
public fun clearName() {
_builder.clearName()
}
/**
* <code>bool system = 5;</code>
*/
public var system: kotlin.Boolean
@JvmName("getSystem")
get() = _builder.getSystem()
@JvmName("setSystem")
set(value) {
_builder.setSystem(value)
}
/**
* <code>bool system = 5;</code>
*/
public fun clearSystem() {
_builder.clearSystem()
}
/**
* <code>bool launchableSystemApp = 6;</code>
*/
public var launchableSystemApp: kotlin.Boolean
@JvmName("getLaunchableSystemApp")
get() = _builder.getLaunchableSystemApp()
@JvmName("setLaunchableSystemApp")
set(value) {
_builder.setLaunchableSystemApp(value)
}
/**
* <code>bool launchableSystemApp = 6;</code>
*/
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()
/**
* <code>repeated bytes chunkIds = 7;</code>
*/
public val chunkIds: com.google.protobuf.kotlin.DslList<com.google.protobuf.ByteString, ChunkIdsProxy>
@kotlin.jvm.JvmSynthetic
get() = com.google.protobuf.kotlin.DslList(
_builder.getChunkIdsList()
)
/**
* <code>repeated bytes chunkIds = 7;</code>
* @param value The chunkIds to add.
*/
@kotlin.jvm.JvmSynthetic
@kotlin.jvm.JvmName("addChunkIds")
public fun com.google.protobuf.kotlin.DslList<com.google.protobuf.ByteString, ChunkIdsProxy>.add(value: com.google.protobuf.ByteString) {
_builder.addChunkIds(value)
}/**
* <code>repeated bytes chunkIds = 7;</code>
* @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<com.google.protobuf.ByteString, ChunkIdsProxy>.plusAssign(value: com.google.protobuf.ByteString) {
add(value)
}/**
* <code>repeated bytes chunkIds = 7;</code>
* @param values The chunkIds to add.
*/
@kotlin.jvm.JvmSynthetic
@kotlin.jvm.JvmName("addAllChunkIds")
public fun com.google.protobuf.kotlin.DslList<com.google.protobuf.ByteString, ChunkIdsProxy>.addAll(values: kotlin.collections.Iterable<com.google.protobuf.ByteString>) {
_builder.addAllChunkIds(values)
}/**
* <code>repeated bytes chunkIds = 7;</code>
* @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<com.google.protobuf.ByteString, ChunkIdsProxy>.plusAssign(values: kotlin.collections.Iterable<com.google.protobuf.ByteString>) {
addAll(values)
}/**
* <code>repeated bytes chunkIds = 7;</code>
* @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<com.google.protobuf.ByteString, ChunkIdsProxy>.set(index: kotlin.Int, value: com.google.protobuf.ByteString) {
_builder.setChunkIds(index, value)
}/**
* <code>repeated bytes chunkIds = 7;</code>
*/
@kotlin.jvm.JvmSynthetic
@kotlin.jvm.JvmName("clearChunkIds")
public fun com.google.protobuf.kotlin.DslList<com.google.protobuf.ByteString, ChunkIdsProxy>.clear() {
_builder.clearChunkIds()
}
/**
* <code>.com.stevesoltys.seedvault.proto.Snapshot.Apk apk = 8;</code>
*/
public var apk: com.stevesoltys.seedvault.proto.Snapshot.Apk
@JvmName("getApk")
get() = _builder.getApk()
@JvmName("setApk")
set(value) {
_builder.setApk(value)
}
/**
* <code>.com.stevesoltys.seedvault.proto.Snapshot.Apk apk = 8;</code>
*/
public fun clearApk() {
_builder.clearApk()
}
/**
* <code>.com.stevesoltys.seedvault.proto.Snapshot.Apk apk = 8;</code>
* @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()
/**
* <pre>
**
* Attention: Has default value of 0
* </pre>
*
* <code>uint64 versionCode = 1;</code>
*/
public var versionCode: kotlin.Long
@JvmName("getVersionCode")
get() = _builder.getVersionCode()
@JvmName("setVersionCode")
set(value) {
_builder.setVersionCode(value)
}
/**
* <pre>
**
* Attention: Has default value of 0
* </pre>
*
* <code>uint64 versionCode = 1;</code>
*/
public fun clearVersionCode() {
_builder.clearVersionCode()
}
/**
* <code>string installer = 2;</code>
*/
public var installer: kotlin.String
@JvmName("getInstaller")
get() = _builder.getInstaller()
@JvmName("setInstaller")
set(value) {
_builder.setInstaller(value)
}
/**
* <code>string installer = 2;</code>
*/
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()
/**
* <code>repeated bytes signatures = 3;</code>
*/
public val signatures: com.google.protobuf.kotlin.DslList<com.google.protobuf.ByteString, SignaturesProxy>
@kotlin.jvm.JvmSynthetic
get() = com.google.protobuf.kotlin.DslList(
_builder.getSignaturesList()
)
/**
* <code>repeated bytes signatures = 3;</code>
* @param value The signatures to add.
*/
@kotlin.jvm.JvmSynthetic
@kotlin.jvm.JvmName("addSignatures")
public fun com.google.protobuf.kotlin.DslList<com.google.protobuf.ByteString, SignaturesProxy>.add(value: com.google.protobuf.ByteString) {
_builder.addSignatures(value)
}/**
* <code>repeated bytes signatures = 3;</code>
* @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<com.google.protobuf.ByteString, SignaturesProxy>.plusAssign(value: com.google.protobuf.ByteString) {
add(value)
}/**
* <code>repeated bytes signatures = 3;</code>
* @param values The signatures to add.
*/
@kotlin.jvm.JvmSynthetic
@kotlin.jvm.JvmName("addAllSignatures")
public fun com.google.protobuf.kotlin.DslList<com.google.protobuf.ByteString, SignaturesProxy>.addAll(values: kotlin.collections.Iterable<com.google.protobuf.ByteString>) {
_builder.addAllSignatures(values)
}/**
* <code>repeated bytes signatures = 3;</code>
* @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<com.google.protobuf.ByteString, SignaturesProxy>.plusAssign(values: kotlin.collections.Iterable<com.google.protobuf.ByteString>) {
addAll(values)
}/**
* <code>repeated bytes signatures = 3;</code>
* @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<com.google.protobuf.ByteString, SignaturesProxy>.set(index: kotlin.Int, value: com.google.protobuf.ByteString) {
_builder.setSignatures(index, value)
}/**
* <code>repeated bytes signatures = 3;</code>
*/
@kotlin.jvm.JvmSynthetic
@kotlin.jvm.JvmName("clearSignatures")
public fun com.google.protobuf.kotlin.DslList<com.google.protobuf.ByteString, SignaturesProxy>.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()
/**
* <code>repeated .com.stevesoltys.seedvault.proto.Snapshot.Split splits = 4;</code>
*/
public val splits: com.google.protobuf.kotlin.DslList<com.stevesoltys.seedvault.proto.Snapshot.Split, SplitsProxy>
@kotlin.jvm.JvmSynthetic
get() = com.google.protobuf.kotlin.DslList(
_builder.getSplitsList()
)
/**
* <code>repeated .com.stevesoltys.seedvault.proto.Snapshot.Split splits = 4;</code>
* @param value The splits to add.
*/
@kotlin.jvm.JvmSynthetic
@kotlin.jvm.JvmName("addSplits")
public fun com.google.protobuf.kotlin.DslList<com.stevesoltys.seedvault.proto.Snapshot.Split, SplitsProxy>.add(value: com.stevesoltys.seedvault.proto.Snapshot.Split) {
_builder.addSplits(value)
}
/**
* <code>repeated .com.stevesoltys.seedvault.proto.Snapshot.Split splits = 4;</code>
* @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<com.stevesoltys.seedvault.proto.Snapshot.Split, SplitsProxy>.plusAssign(value: com.stevesoltys.seedvault.proto.Snapshot.Split) {
add(value)
}
/**
* <code>repeated .com.stevesoltys.seedvault.proto.Snapshot.Split splits = 4;</code>
* @param values The splits to add.
*/
@kotlin.jvm.JvmSynthetic
@kotlin.jvm.JvmName("addAllSplits")
public fun com.google.protobuf.kotlin.DslList<com.stevesoltys.seedvault.proto.Snapshot.Split, SplitsProxy>.addAll(values: kotlin.collections.Iterable<com.stevesoltys.seedvault.proto.Snapshot.Split>) {
_builder.addAllSplits(values)
}
/**
* <code>repeated .com.stevesoltys.seedvault.proto.Snapshot.Split splits = 4;</code>
* @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<com.stevesoltys.seedvault.proto.Snapshot.Split, SplitsProxy>.plusAssign(values: kotlin.collections.Iterable<com.stevesoltys.seedvault.proto.Snapshot.Split>) {
addAll(values)
}
/**
* <code>repeated .com.stevesoltys.seedvault.proto.Snapshot.Split splits = 4;</code>
* @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<com.stevesoltys.seedvault.proto.Snapshot.Split, SplitsProxy>.set(index: kotlin.Int, value: com.stevesoltys.seedvault.proto.Snapshot.Split) {
_builder.setSplits(index, value)
}
/**
* <code>repeated .com.stevesoltys.seedvault.proto.Snapshot.Split splits = 4;</code>
*/
@kotlin.jvm.JvmSynthetic
@kotlin.jvm.JvmName("clearSplits")
public fun com.google.protobuf.kotlin.DslList<com.stevesoltys.seedvault.proto.Snapshot.Split, SplitsProxy>.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()
/**
* <code>string name = 1;</code>
*/
public var name: kotlin.String
@JvmName("getName")
get() = _builder.getName()
@JvmName("setName")
set(value) {
_builder.setName(value)
}
/**
* <code>string name = 1;</code>
*/
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()
/**
* <code>repeated bytes chunkIds = 2;</code>
*/
public val chunkIds: com.google.protobuf.kotlin.DslList<com.google.protobuf.ByteString, ChunkIdsProxy>
@kotlin.jvm.JvmSynthetic
get() = com.google.protobuf.kotlin.DslList(
_builder.getChunkIdsList()
)
/**
* <code>repeated bytes chunkIds = 2;</code>
* @param value The chunkIds to add.
*/
@kotlin.jvm.JvmSynthetic
@kotlin.jvm.JvmName("addChunkIds")
public fun com.google.protobuf.kotlin.DslList<com.google.protobuf.ByteString, ChunkIdsProxy>.add(value: com.google.protobuf.ByteString) {
_builder.addChunkIds(value)
}/**
* <code>repeated bytes chunkIds = 2;</code>
* @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<com.google.protobuf.ByteString, ChunkIdsProxy>.plusAssign(value: com.google.protobuf.ByteString) {
add(value)
}/**
* <code>repeated bytes chunkIds = 2;</code>
* @param values The chunkIds to add.
*/
@kotlin.jvm.JvmSynthetic
@kotlin.jvm.JvmName("addAllChunkIds")
public fun com.google.protobuf.kotlin.DslList<com.google.protobuf.ByteString, ChunkIdsProxy>.addAll(values: kotlin.collections.Iterable<com.google.protobuf.ByteString>) {
_builder.addAllChunkIds(values)
}/**
* <code>repeated bytes chunkIds = 2;</code>
* @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<com.google.protobuf.ByteString, ChunkIdsProxy>.plusAssign(values: kotlin.collections.Iterable<com.google.protobuf.ByteString>) {
addAll(values)
}/**
* <code>repeated bytes chunkIds = 2;</code>
* @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<com.google.protobuf.ByteString, ChunkIdsProxy>.set(index: kotlin.Int, value: com.google.protobuf.ByteString) {
_builder.setChunkIds(index, value)
}/**
* <code>repeated bytes chunkIds = 2;</code>
*/
@kotlin.jvm.JvmSynthetic
@kotlin.jvm.JvmName("clearChunkIds")
public fun com.google.protobuf.kotlin.DslList<com.google.protobuf.ByteString, ChunkIdsProxy>.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()
/**
* <code>bytes id = 1;</code>
*/
public var id: com.google.protobuf.ByteString
@JvmName("getId")
get() = _builder.getId()
@JvmName("setId")
set(value) {
_builder.setId(value)
}
/**
* <code>bytes id = 1;</code>
*/
public fun clearId() {
_builder.clearId()
}
/**
* <code>uint32 length = 2;</code>
*/
public var length: kotlin.Int
@JvmName("getLength")
get() = _builder.getLength()
@JvmName("setLength")
set(value) {
_builder.setLength(value)
}
/**
* <code>uint32 length = 2;</code>
*/
public fun clearLength() {
_builder.clearLength()
}
/**
* <code>uint32 uncompressedLength = 3;</code>
*/
public var uncompressedLength: kotlin.Int
@JvmName("getUncompressedLength")
get() = _builder.getUncompressedLength()
@JvmName("setUncompressedLength")
set(value) {
_builder.setUncompressedLength(value)
}
/**
* <code>uint32 uncompressedLength = 3;</code>
*/
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()

View file

@ -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

View file

@ -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) {

View file

@ -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
}
}
}

View file

@ -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<String, App.Builder>()
private val blobsMap = mutableMapOf<String, Blob>()
@ -51,37 +53,41 @@ internal class SnapshotCreator(
}
fun onApkBackedUp(
packageName: String,
packageInfo: PackageInfo,
apk: Apk,
chunkMap: Map<String, Blob>,
) {
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

View file

@ -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}.")
}

View file

@ -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,

View file

@ -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

View file

@ -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)

View file

@ -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,

View file

@ -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<OutputStream>()
private val passThroughInputStream = slot<InputStream>()
private val repoId = Random.nextBytes(32).toHexString()
private val snapshotHandle = slot<AppBackupFileType.Snapshot>()
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 {

View file

@ -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<String>()

View file

@ -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<KVDb>()
private val backend = mockk<Backend>()
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)

View file

@ -73,7 +73,6 @@ internal class RestoreCoordinatorTest : TransportTest() {
PackageInfo().apply { packageName = "@pm@" },
packageInfo
)
private val packageName = packageInfo.packageName
private val storageName = getRandomString()
init {

View file

@ -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)

View file

@ -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"],

Binary file not shown.