Polish SnapshotCreator and write tests
This commit is contained in:
parent
463fc33230
commit
7702fb7bd8
8 changed files with 252 additions and 120 deletions
|
@ -74,7 +74,24 @@ public object SnapshotKt {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <code>string androidId = 4;</code>
|
* <code>string user = 4;</code>
|
||||||
|
*/
|
||||||
|
public var user: kotlin.String
|
||||||
|
@JvmName("getUser")
|
||||||
|
get() = _builder.getUser()
|
||||||
|
@JvmName("setUser")
|
||||||
|
set(value) {
|
||||||
|
_builder.setUser(value)
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* <code>string user = 4;</code>
|
||||||
|
*/
|
||||||
|
public fun clearUser() {
|
||||||
|
_builder.clearUser()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <code>string androidId = 5;</code>
|
||||||
*/
|
*/
|
||||||
public var androidId: kotlin.String
|
public var androidId: kotlin.String
|
||||||
@JvmName("getAndroidId")
|
@JvmName("getAndroidId")
|
||||||
|
@ -84,14 +101,14 @@ public object SnapshotKt {
|
||||||
_builder.setAndroidId(value)
|
_builder.setAndroidId(value)
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* <code>string androidId = 4;</code>
|
* <code>string androidId = 5;</code>
|
||||||
*/
|
*/
|
||||||
public fun clearAndroidId() {
|
public fun clearAndroidId() {
|
||||||
_builder.clearAndroidId()
|
_builder.clearAndroidId()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <code>uint32 sdkInt = 5;</code>
|
* <code>uint32 sdkInt = 6;</code>
|
||||||
*/
|
*/
|
||||||
public var sdkInt: kotlin.Int
|
public var sdkInt: kotlin.Int
|
||||||
@JvmName("getSdkInt")
|
@JvmName("getSdkInt")
|
||||||
|
@ -101,14 +118,14 @@ public object SnapshotKt {
|
||||||
_builder.setSdkInt(value)
|
_builder.setSdkInt(value)
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* <code>uint32 sdkInt = 5;</code>
|
* <code>uint32 sdkInt = 6;</code>
|
||||||
*/
|
*/
|
||||||
public fun clearSdkInt() {
|
public fun clearSdkInt() {
|
||||||
_builder.clearSdkInt()
|
_builder.clearSdkInt()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <code>string androidIncremental = 6;</code>
|
* <code>string androidIncremental = 7;</code>
|
||||||
*/
|
*/
|
||||||
public var androidIncremental: kotlin.String
|
public var androidIncremental: kotlin.String
|
||||||
@JvmName("getAndroidIncremental")
|
@JvmName("getAndroidIncremental")
|
||||||
|
@ -118,14 +135,14 @@ public object SnapshotKt {
|
||||||
_builder.setAndroidIncremental(value)
|
_builder.setAndroidIncremental(value)
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* <code>string androidIncremental = 6;</code>
|
* <code>string androidIncremental = 7;</code>
|
||||||
*/
|
*/
|
||||||
public fun clearAndroidIncremental() {
|
public fun clearAndroidIncremental() {
|
||||||
_builder.clearAndroidIncremental()
|
_builder.clearAndroidIncremental()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <code>bool d2d = 7;</code>
|
* <code>bool d2d = 8;</code>
|
||||||
*/
|
*/
|
||||||
public var d2D: kotlin.Boolean
|
public var d2D: kotlin.Boolean
|
||||||
@JvmName("getD2D")
|
@JvmName("getD2D")
|
||||||
|
@ -135,7 +152,7 @@ public object SnapshotKt {
|
||||||
_builder.setD2D(value)
|
_builder.setD2D(value)
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* <code>bool d2d = 7;</code>
|
* <code>bool d2d = 8;</code>
|
||||||
*/
|
*/
|
||||||
public fun clearD2D() {
|
public fun clearD2D() {
|
||||||
_builder.clearD2D()
|
_builder.clearD2D()
|
||||||
|
@ -148,7 +165,7 @@ public object SnapshotKt {
|
||||||
@kotlin.OptIn(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)
|
@kotlin.OptIn(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)
|
||||||
public class AppsProxy private constructor() : com.google.protobuf.kotlin.DslProxy()
|
public class AppsProxy private constructor() : com.google.protobuf.kotlin.DslProxy()
|
||||||
/**
|
/**
|
||||||
* <code>map<string, .com.stevesoltys.seedvault.proto.Snapshot.App> apps = 8;</code>
|
* <code>map<string, .com.stevesoltys.seedvault.proto.Snapshot.App> apps = 9;</code>
|
||||||
*/
|
*/
|
||||||
public val apps: com.google.protobuf.kotlin.DslMap<kotlin.String, com.stevesoltys.seedvault.proto.Snapshot.App, AppsProxy>
|
public val apps: com.google.protobuf.kotlin.DslMap<kotlin.String, com.stevesoltys.seedvault.proto.Snapshot.App, AppsProxy>
|
||||||
@kotlin.jvm.JvmSynthetic
|
@kotlin.jvm.JvmSynthetic
|
||||||
|
@ -157,7 +174,7 @@ public object SnapshotKt {
|
||||||
_builder.getAppsMap()
|
_builder.getAppsMap()
|
||||||
)
|
)
|
||||||
/**
|
/**
|
||||||
* <code>map<string, .com.stevesoltys.seedvault.proto.Snapshot.App> apps = 8;</code>
|
* <code>map<string, .com.stevesoltys.seedvault.proto.Snapshot.App> apps = 9;</code>
|
||||||
*/
|
*/
|
||||||
@JvmName("putApps")
|
@JvmName("putApps")
|
||||||
public fun com.google.protobuf.kotlin.DslMap<kotlin.String, com.stevesoltys.seedvault.proto.Snapshot.App, AppsProxy>
|
public fun com.google.protobuf.kotlin.DslMap<kotlin.String, com.stevesoltys.seedvault.proto.Snapshot.App, AppsProxy>
|
||||||
|
@ -165,7 +182,7 @@ public object SnapshotKt {
|
||||||
_builder.putApps(key, value)
|
_builder.putApps(key, value)
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* <code>map<string, .com.stevesoltys.seedvault.proto.Snapshot.App> apps = 8;</code>
|
* <code>map<string, .com.stevesoltys.seedvault.proto.Snapshot.App> apps = 9;</code>
|
||||||
*/
|
*/
|
||||||
@kotlin.jvm.JvmSynthetic
|
@kotlin.jvm.JvmSynthetic
|
||||||
@JvmName("setApps")
|
@JvmName("setApps")
|
||||||
|
@ -175,7 +192,7 @@ public object SnapshotKt {
|
||||||
put(key, value)
|
put(key, value)
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* <code>map<string, .com.stevesoltys.seedvault.proto.Snapshot.App> apps = 8;</code>
|
* <code>map<string, .com.stevesoltys.seedvault.proto.Snapshot.App> apps = 9;</code>
|
||||||
*/
|
*/
|
||||||
@kotlin.jvm.JvmSynthetic
|
@kotlin.jvm.JvmSynthetic
|
||||||
@JvmName("removeApps")
|
@JvmName("removeApps")
|
||||||
|
@ -184,7 +201,7 @@ public object SnapshotKt {
|
||||||
_builder.removeApps(key)
|
_builder.removeApps(key)
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* <code>map<string, .com.stevesoltys.seedvault.proto.Snapshot.App> apps = 8;</code>
|
* <code>map<string, .com.stevesoltys.seedvault.proto.Snapshot.App> apps = 9;</code>
|
||||||
*/
|
*/
|
||||||
@kotlin.jvm.JvmSynthetic
|
@kotlin.jvm.JvmSynthetic
|
||||||
@JvmName("putAllApps")
|
@JvmName("putAllApps")
|
||||||
|
@ -193,7 +210,7 @@ public object SnapshotKt {
|
||||||
_builder.putAllApps(map)
|
_builder.putAllApps(map)
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* <code>map<string, .com.stevesoltys.seedvault.proto.Snapshot.App> apps = 8;</code>
|
* <code>map<string, .com.stevesoltys.seedvault.proto.Snapshot.App> apps = 9;</code>
|
||||||
*/
|
*/
|
||||||
@kotlin.jvm.JvmSynthetic
|
@kotlin.jvm.JvmSynthetic
|
||||||
@JvmName("clearApps")
|
@JvmName("clearApps")
|
||||||
|
@ -209,7 +226,7 @@ public object SnapshotKt {
|
||||||
@kotlin.OptIn(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)
|
@kotlin.OptIn(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)
|
||||||
public class IconChunkIdsProxy private constructor() : com.google.protobuf.kotlin.DslProxy()
|
public class IconChunkIdsProxy private constructor() : com.google.protobuf.kotlin.DslProxy()
|
||||||
/**
|
/**
|
||||||
* <code>repeated bytes iconChunkIds = 9;</code>
|
* <code>repeated bytes iconChunkIds = 10;</code>
|
||||||
*/
|
*/
|
||||||
public val iconChunkIds: com.google.protobuf.kotlin.DslList<com.google.protobuf.ByteString, IconChunkIdsProxy>
|
public val iconChunkIds: com.google.protobuf.kotlin.DslList<com.google.protobuf.ByteString, IconChunkIdsProxy>
|
||||||
@kotlin.jvm.JvmSynthetic
|
@kotlin.jvm.JvmSynthetic
|
||||||
|
@ -217,7 +234,7 @@ public object SnapshotKt {
|
||||||
_builder.getIconChunkIdsList()
|
_builder.getIconChunkIdsList()
|
||||||
)
|
)
|
||||||
/**
|
/**
|
||||||
* <code>repeated bytes iconChunkIds = 9;</code>
|
* <code>repeated bytes iconChunkIds = 10;</code>
|
||||||
* @param value The iconChunkIds to add.
|
* @param value The iconChunkIds to add.
|
||||||
*/
|
*/
|
||||||
@kotlin.jvm.JvmSynthetic
|
@kotlin.jvm.JvmSynthetic
|
||||||
|
@ -225,7 +242,7 @@ public object SnapshotKt {
|
||||||
public fun com.google.protobuf.kotlin.DslList<com.google.protobuf.ByteString, IconChunkIdsProxy>.add(value: com.google.protobuf.ByteString) {
|
public fun com.google.protobuf.kotlin.DslList<com.google.protobuf.ByteString, IconChunkIdsProxy>.add(value: com.google.protobuf.ByteString) {
|
||||||
_builder.addIconChunkIds(value)
|
_builder.addIconChunkIds(value)
|
||||||
}/**
|
}/**
|
||||||
* <code>repeated bytes iconChunkIds = 9;</code>
|
* <code>repeated bytes iconChunkIds = 10;</code>
|
||||||
* @param value The iconChunkIds to add.
|
* @param value The iconChunkIds to add.
|
||||||
*/
|
*/
|
||||||
@kotlin.jvm.JvmSynthetic
|
@kotlin.jvm.JvmSynthetic
|
||||||
|
@ -234,7 +251,7 @@ public object SnapshotKt {
|
||||||
public inline operator fun com.google.protobuf.kotlin.DslList<com.google.protobuf.ByteString, IconChunkIdsProxy>.plusAssign(value: com.google.protobuf.ByteString) {
|
public inline operator fun com.google.protobuf.kotlin.DslList<com.google.protobuf.ByteString, IconChunkIdsProxy>.plusAssign(value: com.google.protobuf.ByteString) {
|
||||||
add(value)
|
add(value)
|
||||||
}/**
|
}/**
|
||||||
* <code>repeated bytes iconChunkIds = 9;</code>
|
* <code>repeated bytes iconChunkIds = 10;</code>
|
||||||
* @param values The iconChunkIds to add.
|
* @param values The iconChunkIds to add.
|
||||||
*/
|
*/
|
||||||
@kotlin.jvm.JvmSynthetic
|
@kotlin.jvm.JvmSynthetic
|
||||||
|
@ -242,7 +259,7 @@ public object SnapshotKt {
|
||||||
public fun com.google.protobuf.kotlin.DslList<com.google.protobuf.ByteString, IconChunkIdsProxy>.addAll(values: kotlin.collections.Iterable<com.google.protobuf.ByteString>) {
|
public fun com.google.protobuf.kotlin.DslList<com.google.protobuf.ByteString, IconChunkIdsProxy>.addAll(values: kotlin.collections.Iterable<com.google.protobuf.ByteString>) {
|
||||||
_builder.addAllIconChunkIds(values)
|
_builder.addAllIconChunkIds(values)
|
||||||
}/**
|
}/**
|
||||||
* <code>repeated bytes iconChunkIds = 9;</code>
|
* <code>repeated bytes iconChunkIds = 10;</code>
|
||||||
* @param values The iconChunkIds to add.
|
* @param values The iconChunkIds to add.
|
||||||
*/
|
*/
|
||||||
@kotlin.jvm.JvmSynthetic
|
@kotlin.jvm.JvmSynthetic
|
||||||
|
@ -251,7 +268,7 @@ public object SnapshotKt {
|
||||||
public inline operator fun com.google.protobuf.kotlin.DslList<com.google.protobuf.ByteString, IconChunkIdsProxy>.plusAssign(values: kotlin.collections.Iterable<com.google.protobuf.ByteString>) {
|
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)
|
addAll(values)
|
||||||
}/**
|
}/**
|
||||||
* <code>repeated bytes iconChunkIds = 9;</code>
|
* <code>repeated bytes iconChunkIds = 10;</code>
|
||||||
* @param index The index to set the value at.
|
* @param index The index to set the value at.
|
||||||
* @param value The iconChunkIds to set.
|
* @param value The iconChunkIds to set.
|
||||||
*/
|
*/
|
||||||
|
@ -260,7 +277,7 @@ public object SnapshotKt {
|
||||||
public operator fun com.google.protobuf.kotlin.DslList<com.google.protobuf.ByteString, IconChunkIdsProxy>.set(index: kotlin.Int, value: com.google.protobuf.ByteString) {
|
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)
|
_builder.setIconChunkIds(index, value)
|
||||||
}/**
|
}/**
|
||||||
* <code>repeated bytes iconChunkIds = 9;</code>
|
* <code>repeated bytes iconChunkIds = 10;</code>
|
||||||
*/
|
*/
|
||||||
@kotlin.jvm.JvmSynthetic
|
@kotlin.jvm.JvmSynthetic
|
||||||
@kotlin.jvm.JvmName("clearIconChunkIds")
|
@kotlin.jvm.JvmName("clearIconChunkIds")
|
||||||
|
@ -274,7 +291,7 @@ public object SnapshotKt {
|
||||||
@kotlin.OptIn(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)
|
@kotlin.OptIn(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)
|
||||||
public class BlobsProxy private constructor() : com.google.protobuf.kotlin.DslProxy()
|
public class BlobsProxy private constructor() : com.google.protobuf.kotlin.DslProxy()
|
||||||
/**
|
/**
|
||||||
* <code>map<string, .com.stevesoltys.seedvault.proto.Snapshot.Blob> blobs = 10;</code>
|
* <code>map<string, .com.stevesoltys.seedvault.proto.Snapshot.Blob> blobs = 11;</code>
|
||||||
*/
|
*/
|
||||||
public val blobs: com.google.protobuf.kotlin.DslMap<kotlin.String, com.stevesoltys.seedvault.proto.Snapshot.Blob, BlobsProxy>
|
public val blobs: com.google.protobuf.kotlin.DslMap<kotlin.String, com.stevesoltys.seedvault.proto.Snapshot.Blob, BlobsProxy>
|
||||||
@kotlin.jvm.JvmSynthetic
|
@kotlin.jvm.JvmSynthetic
|
||||||
|
@ -283,7 +300,7 @@ public object SnapshotKt {
|
||||||
_builder.getBlobsMap()
|
_builder.getBlobsMap()
|
||||||
)
|
)
|
||||||
/**
|
/**
|
||||||
* <code>map<string, .com.stevesoltys.seedvault.proto.Snapshot.Blob> blobs = 10;</code>
|
* <code>map<string, .com.stevesoltys.seedvault.proto.Snapshot.Blob> blobs = 11;</code>
|
||||||
*/
|
*/
|
||||||
@JvmName("putBlobs")
|
@JvmName("putBlobs")
|
||||||
public fun com.google.protobuf.kotlin.DslMap<kotlin.String, com.stevesoltys.seedvault.proto.Snapshot.Blob, BlobsProxy>
|
public fun com.google.protobuf.kotlin.DslMap<kotlin.String, com.stevesoltys.seedvault.proto.Snapshot.Blob, BlobsProxy>
|
||||||
|
@ -291,7 +308,7 @@ public object SnapshotKt {
|
||||||
_builder.putBlobs(key, value)
|
_builder.putBlobs(key, value)
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* <code>map<string, .com.stevesoltys.seedvault.proto.Snapshot.Blob> blobs = 10;</code>
|
* <code>map<string, .com.stevesoltys.seedvault.proto.Snapshot.Blob> blobs = 11;</code>
|
||||||
*/
|
*/
|
||||||
@kotlin.jvm.JvmSynthetic
|
@kotlin.jvm.JvmSynthetic
|
||||||
@JvmName("setBlobs")
|
@JvmName("setBlobs")
|
||||||
|
@ -301,7 +318,7 @@ public object SnapshotKt {
|
||||||
put(key, value)
|
put(key, value)
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* <code>map<string, .com.stevesoltys.seedvault.proto.Snapshot.Blob> blobs = 10;</code>
|
* <code>map<string, .com.stevesoltys.seedvault.proto.Snapshot.Blob> blobs = 11;</code>
|
||||||
*/
|
*/
|
||||||
@kotlin.jvm.JvmSynthetic
|
@kotlin.jvm.JvmSynthetic
|
||||||
@JvmName("removeBlobs")
|
@JvmName("removeBlobs")
|
||||||
|
@ -310,7 +327,7 @@ public object SnapshotKt {
|
||||||
_builder.removeBlobs(key)
|
_builder.removeBlobs(key)
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* <code>map<string, .com.stevesoltys.seedvault.proto.Snapshot.Blob> blobs = 10;</code>
|
* <code>map<string, .com.stevesoltys.seedvault.proto.Snapshot.Blob> blobs = 11;</code>
|
||||||
*/
|
*/
|
||||||
@kotlin.jvm.JvmSynthetic
|
@kotlin.jvm.JvmSynthetic
|
||||||
@JvmName("putAllBlobs")
|
@JvmName("putAllBlobs")
|
||||||
|
@ -319,7 +336,7 @@ public object SnapshotKt {
|
||||||
_builder.putAllBlobs(map)
|
_builder.putAllBlobs(map)
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* <code>map<string, .com.stevesoltys.seedvault.proto.Snapshot.Blob> blobs = 10;</code>
|
* <code>map<string, .com.stevesoltys.seedvault.proto.Snapshot.Blob> blobs = 11;</code>
|
||||||
*/
|
*/
|
||||||
@kotlin.jvm.JvmSynthetic
|
@kotlin.jvm.JvmSynthetic
|
||||||
@JvmName("clearBlobs")
|
@JvmName("clearBlobs")
|
||||||
|
@ -365,24 +382,7 @@ public object SnapshotKt {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <code>string state = 2;</code>
|
* <code>.com.stevesoltys.seedvault.proto.Snapshot.BackupType type = 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
|
public var type: com.stevesoltys.seedvault.proto.Snapshot.BackupType
|
||||||
@JvmName("getType")
|
@JvmName("getType")
|
||||||
|
@ -392,14 +392,14 @@ public object SnapshotKt {
|
||||||
_builder.setType(value)
|
_builder.setType(value)
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* <code>.com.stevesoltys.seedvault.proto.Snapshot.BackupType type = 3;</code>
|
* <code>.com.stevesoltys.seedvault.proto.Snapshot.BackupType type = 2;</code>
|
||||||
*/
|
*/
|
||||||
public fun clearType() {
|
public fun clearType() {
|
||||||
_builder.clearType()
|
_builder.clearType()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <code>string name = 4;</code>
|
* <code>string name = 3;</code>
|
||||||
*/
|
*/
|
||||||
public var name: kotlin.String
|
public var name: kotlin.String
|
||||||
@JvmName("getName")
|
@JvmName("getName")
|
||||||
|
@ -409,14 +409,14 @@ public object SnapshotKt {
|
||||||
_builder.setName(value)
|
_builder.setName(value)
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* <code>string name = 4;</code>
|
* <code>string name = 3;</code>
|
||||||
*/
|
*/
|
||||||
public fun clearName() {
|
public fun clearName() {
|
||||||
_builder.clearName()
|
_builder.clearName()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <code>bool system = 5;</code>
|
* <code>bool system = 4;</code>
|
||||||
*/
|
*/
|
||||||
public var system: kotlin.Boolean
|
public var system: kotlin.Boolean
|
||||||
@JvmName("getSystem")
|
@JvmName("getSystem")
|
||||||
|
@ -426,14 +426,14 @@ public object SnapshotKt {
|
||||||
_builder.setSystem(value)
|
_builder.setSystem(value)
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* <code>bool system = 5;</code>
|
* <code>bool system = 4;</code>
|
||||||
*/
|
*/
|
||||||
public fun clearSystem() {
|
public fun clearSystem() {
|
||||||
_builder.clearSystem()
|
_builder.clearSystem()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <code>bool launchableSystemApp = 6;</code>
|
* <code>bool launchableSystemApp = 5;</code>
|
||||||
*/
|
*/
|
||||||
public var launchableSystemApp: kotlin.Boolean
|
public var launchableSystemApp: kotlin.Boolean
|
||||||
@JvmName("getLaunchableSystemApp")
|
@JvmName("getLaunchableSystemApp")
|
||||||
|
@ -443,7 +443,7 @@ public object SnapshotKt {
|
||||||
_builder.setLaunchableSystemApp(value)
|
_builder.setLaunchableSystemApp(value)
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* <code>bool launchableSystemApp = 6;</code>
|
* <code>bool launchableSystemApp = 5;</code>
|
||||||
*/
|
*/
|
||||||
public fun clearLaunchableSystemApp() {
|
public fun clearLaunchableSystemApp() {
|
||||||
_builder.clearLaunchableSystemApp()
|
_builder.clearLaunchableSystemApp()
|
||||||
|
@ -456,7 +456,7 @@ public object SnapshotKt {
|
||||||
@kotlin.OptIn(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)
|
@kotlin.OptIn(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)
|
||||||
public class ChunkIdsProxy private constructor() : com.google.protobuf.kotlin.DslProxy()
|
public class ChunkIdsProxy private constructor() : com.google.protobuf.kotlin.DslProxy()
|
||||||
/**
|
/**
|
||||||
* <code>repeated bytes chunkIds = 7;</code>
|
* <code>repeated bytes chunkIds = 6;</code>
|
||||||
*/
|
*/
|
||||||
public val chunkIds: com.google.protobuf.kotlin.DslList<com.google.protobuf.ByteString, ChunkIdsProxy>
|
public val chunkIds: com.google.protobuf.kotlin.DslList<com.google.protobuf.ByteString, ChunkIdsProxy>
|
||||||
@kotlin.jvm.JvmSynthetic
|
@kotlin.jvm.JvmSynthetic
|
||||||
|
@ -464,7 +464,7 @@ public object SnapshotKt {
|
||||||
_builder.getChunkIdsList()
|
_builder.getChunkIdsList()
|
||||||
)
|
)
|
||||||
/**
|
/**
|
||||||
* <code>repeated bytes chunkIds = 7;</code>
|
* <code>repeated bytes chunkIds = 6;</code>
|
||||||
* @param value The chunkIds to add.
|
* @param value The chunkIds to add.
|
||||||
*/
|
*/
|
||||||
@kotlin.jvm.JvmSynthetic
|
@kotlin.jvm.JvmSynthetic
|
||||||
|
@ -472,7 +472,7 @@ public object SnapshotKt {
|
||||||
public fun com.google.protobuf.kotlin.DslList<com.google.protobuf.ByteString, ChunkIdsProxy>.add(value: com.google.protobuf.ByteString) {
|
public fun com.google.protobuf.kotlin.DslList<com.google.protobuf.ByteString, ChunkIdsProxy>.add(value: com.google.protobuf.ByteString) {
|
||||||
_builder.addChunkIds(value)
|
_builder.addChunkIds(value)
|
||||||
}/**
|
}/**
|
||||||
* <code>repeated bytes chunkIds = 7;</code>
|
* <code>repeated bytes chunkIds = 6;</code>
|
||||||
* @param value The chunkIds to add.
|
* @param value The chunkIds to add.
|
||||||
*/
|
*/
|
||||||
@kotlin.jvm.JvmSynthetic
|
@kotlin.jvm.JvmSynthetic
|
||||||
|
@ -481,7 +481,7 @@ public object SnapshotKt {
|
||||||
public inline operator fun com.google.protobuf.kotlin.DslList<com.google.protobuf.ByteString, ChunkIdsProxy>.plusAssign(value: com.google.protobuf.ByteString) {
|
public inline operator fun com.google.protobuf.kotlin.DslList<com.google.protobuf.ByteString, ChunkIdsProxy>.plusAssign(value: com.google.protobuf.ByteString) {
|
||||||
add(value)
|
add(value)
|
||||||
}/**
|
}/**
|
||||||
* <code>repeated bytes chunkIds = 7;</code>
|
* <code>repeated bytes chunkIds = 6;</code>
|
||||||
* @param values The chunkIds to add.
|
* @param values The chunkIds to add.
|
||||||
*/
|
*/
|
||||||
@kotlin.jvm.JvmSynthetic
|
@kotlin.jvm.JvmSynthetic
|
||||||
|
@ -489,7 +489,7 @@ public object SnapshotKt {
|
||||||
public fun com.google.protobuf.kotlin.DslList<com.google.protobuf.ByteString, ChunkIdsProxy>.addAll(values: kotlin.collections.Iterable<com.google.protobuf.ByteString>) {
|
public fun com.google.protobuf.kotlin.DslList<com.google.protobuf.ByteString, ChunkIdsProxy>.addAll(values: kotlin.collections.Iterable<com.google.protobuf.ByteString>) {
|
||||||
_builder.addAllChunkIds(values)
|
_builder.addAllChunkIds(values)
|
||||||
}/**
|
}/**
|
||||||
* <code>repeated bytes chunkIds = 7;</code>
|
* <code>repeated bytes chunkIds = 6;</code>
|
||||||
* @param values The chunkIds to add.
|
* @param values The chunkIds to add.
|
||||||
*/
|
*/
|
||||||
@kotlin.jvm.JvmSynthetic
|
@kotlin.jvm.JvmSynthetic
|
||||||
|
@ -498,7 +498,7 @@ public object SnapshotKt {
|
||||||
public inline operator fun com.google.protobuf.kotlin.DslList<com.google.protobuf.ByteString, ChunkIdsProxy>.plusAssign(values: kotlin.collections.Iterable<com.google.protobuf.ByteString>) {
|
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)
|
addAll(values)
|
||||||
}/**
|
}/**
|
||||||
* <code>repeated bytes chunkIds = 7;</code>
|
* <code>repeated bytes chunkIds = 6;</code>
|
||||||
* @param index The index to set the value at.
|
* @param index The index to set the value at.
|
||||||
* @param value The chunkIds to set.
|
* @param value The chunkIds to set.
|
||||||
*/
|
*/
|
||||||
|
@ -507,7 +507,7 @@ public object SnapshotKt {
|
||||||
public operator fun com.google.protobuf.kotlin.DslList<com.google.protobuf.ByteString, ChunkIdsProxy>.set(index: kotlin.Int, value: com.google.protobuf.ByteString) {
|
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)
|
_builder.setChunkIds(index, value)
|
||||||
}/**
|
}/**
|
||||||
* <code>repeated bytes chunkIds = 7;</code>
|
* <code>repeated bytes chunkIds = 6;</code>
|
||||||
*/
|
*/
|
||||||
@kotlin.jvm.JvmSynthetic
|
@kotlin.jvm.JvmSynthetic
|
||||||
@kotlin.jvm.JvmName("clearChunkIds")
|
@kotlin.jvm.JvmName("clearChunkIds")
|
||||||
|
@ -515,7 +515,7 @@ public object SnapshotKt {
|
||||||
_builder.clearChunkIds()
|
_builder.clearChunkIds()
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* <code>.com.stevesoltys.seedvault.proto.Snapshot.Apk apk = 8;</code>
|
* <code>.com.stevesoltys.seedvault.proto.Snapshot.Apk apk = 7;</code>
|
||||||
*/
|
*/
|
||||||
public var apk: com.stevesoltys.seedvault.proto.Snapshot.Apk
|
public var apk: com.stevesoltys.seedvault.proto.Snapshot.Apk
|
||||||
@JvmName("getApk")
|
@JvmName("getApk")
|
||||||
|
@ -525,13 +525,13 @@ public object SnapshotKt {
|
||||||
_builder.setApk(value)
|
_builder.setApk(value)
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* <code>.com.stevesoltys.seedvault.proto.Snapshot.Apk apk = 8;</code>
|
* <code>.com.stevesoltys.seedvault.proto.Snapshot.Apk apk = 7;</code>
|
||||||
*/
|
*/
|
||||||
public fun clearApk() {
|
public fun clearApk() {
|
||||||
_builder.clearApk()
|
_builder.clearApk()
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* <code>.com.stevesoltys.seedvault.proto.Snapshot.Apk apk = 8;</code>
|
* <code>.com.stevesoltys.seedvault.proto.Snapshot.Apk apk = 7;</code>
|
||||||
* @return Whether the apk field is set.
|
* @return Whether the apk field is set.
|
||||||
*/
|
*/
|
||||||
public fun hasApk(): kotlin.Boolean {
|
public fun hasApk(): kotlin.Boolean {
|
||||||
|
|
|
@ -39,7 +39,7 @@ data class BackupMetadata(
|
||||||
time = s.token,
|
time = s.token,
|
||||||
androidVersion = s.sdkInt,
|
androidVersion = s.sdkInt,
|
||||||
androidIncremental = s.androidIncremental,
|
androidIncremental = s.androidIncremental,
|
||||||
deviceName = s.name,
|
deviceName = "${s.name} - ${s.user}",
|
||||||
d2dBackup = s.d2D,
|
d2dBackup = s.d2D,
|
||||||
packageMetadataMap = s.appsMap.mapValues { (_, app) ->
|
packageMetadataMap = s.appsMap.mapValues { (_, app) ->
|
||||||
PackageMetadata.fromSnapshot(app)
|
PackageMetadata.fromSnapshot(app)
|
||||||
|
@ -121,7 +121,6 @@ data class PackageMetadata(
|
||||||
companion object {
|
companion object {
|
||||||
fun fromSnapshot(app: Snapshot.App) = PackageMetadata(
|
fun fromSnapshot(app: Snapshot.App) = PackageMetadata(
|
||||||
time = app.time,
|
time = app.time,
|
||||||
state = if (app.state.isBlank()) UNKNOWN_ERROR else PackageState.valueOf(app.state),
|
|
||||||
backupType = when (app.type) {
|
backupType = when (app.type) {
|
||||||
Snapshot.BackupType.FULL -> BackupType.FULL
|
Snapshot.BackupType.FULL -> BackupType.FULL
|
||||||
Snapshot.BackupType.KV -> BackupType.KV
|
Snapshot.BackupType.KV -> BackupType.KV
|
||||||
|
|
|
@ -13,8 +13,6 @@ import androidx.annotation.VisibleForTesting
|
||||||
import androidx.annotation.WorkerThread
|
import androidx.annotation.WorkerThread
|
||||||
import com.stevesoltys.seedvault.Clock
|
import com.stevesoltys.seedvault.Clock
|
||||||
import com.stevesoltys.seedvault.metadata.PackageState.APK_AND_DATA
|
import com.stevesoltys.seedvault.metadata.PackageState.APK_AND_DATA
|
||||||
import com.stevesoltys.seedvault.transport.backup.PackageService
|
|
||||||
import com.stevesoltys.seedvault.transport.backup.isSystemApp
|
|
||||||
import java.io.FileNotFoundException
|
import java.io.FileNotFoundException
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import java.io.OutputStream
|
import java.io.OutputStream
|
||||||
|
@ -31,7 +29,6 @@ internal class MetadataManager(
|
||||||
private val clock: Clock,
|
private val clock: Clock,
|
||||||
private val metadataWriter: MetadataWriter,
|
private val metadataWriter: MetadataWriter,
|
||||||
private val metadataReader: MetadataReader,
|
private val metadataReader: MetadataReader,
|
||||||
private val packageService: PackageService,
|
|
||||||
) {
|
) {
|
||||||
|
|
||||||
private val uninitializedMetadata = BackupMetadata(token = -42L, salt = "foo bar")
|
private val uninitializedMetadata = BackupMetadata(token = -42L, salt = "foo bar")
|
||||||
|
@ -52,10 +49,6 @@ internal class MetadataManager(
|
||||||
return field
|
return field
|
||||||
}
|
}
|
||||||
|
|
||||||
private val launchableSystemApps by lazy {
|
|
||||||
packageService.launchableSystemApps.map { it.activityInfo.packageName }.toSet()
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Call this after a package has been backed up successfully.
|
* Call this after a package has been backed up successfully.
|
||||||
*
|
*
|
||||||
|
@ -75,15 +68,11 @@ internal class MetadataManager(
|
||||||
modifyCachedMetadata {
|
modifyCachedMetadata {
|
||||||
val now = clock.time()
|
val now = clock.time()
|
||||||
metadata.packageMetadataMap.getOrPut(packageName) {
|
metadata.packageMetadataMap.getOrPut(packageName) {
|
||||||
val isSystemApp = packageInfo.isSystemApp()
|
|
||||||
PackageMetadata(
|
PackageMetadata(
|
||||||
time = now,
|
time = now,
|
||||||
state = APK_AND_DATA,
|
state = APK_AND_DATA,
|
||||||
backupType = type,
|
backupType = type,
|
||||||
size = size,
|
size = size,
|
||||||
system = isSystemApp,
|
|
||||||
isLaunchableSystemApp = isSystemApp &&
|
|
||||||
launchableSystemApps.contains(packageName),
|
|
||||||
)
|
)
|
||||||
}.apply {
|
}.apply {
|
||||||
time = now
|
time = now
|
||||||
|
@ -111,15 +100,11 @@ internal class MetadataManager(
|
||||||
check(packageState != APK_AND_DATA) { "Backup Error with non-error package state." }
|
check(packageState != APK_AND_DATA) { "Backup Error with non-error package state." }
|
||||||
modifyCachedMetadata {
|
modifyCachedMetadata {
|
||||||
metadata.packageMetadataMap.getOrPut(packageInfo.packageName) {
|
metadata.packageMetadataMap.getOrPut(packageInfo.packageName) {
|
||||||
val isSystemApp = packageInfo.isSystemApp()
|
|
||||||
PackageMetadata(
|
PackageMetadata(
|
||||||
time = 0L,
|
time = 0L,
|
||||||
state = packageState,
|
state = packageState,
|
||||||
backupType = backupType,
|
backupType = backupType,
|
||||||
name = packageInfo.applicationInfo?.loadLabel(context.packageManager),
|
name = packageInfo.applicationInfo?.loadLabel(context.packageManager),
|
||||||
system = isSystemApp,
|
|
||||||
isLaunchableSystemApp = isSystemApp &&
|
|
||||||
launchableSystemApps.contains(packageInfo.packageName),
|
|
||||||
)
|
)
|
||||||
}.state = packageState
|
}.state = packageState
|
||||||
}
|
}
|
||||||
|
@ -137,14 +122,10 @@ internal class MetadataManager(
|
||||||
packageState: PackageState,
|
packageState: PackageState,
|
||||||
) = modifyCachedMetadata {
|
) = modifyCachedMetadata {
|
||||||
metadata.packageMetadataMap.getOrPut(packageInfo.packageName) {
|
metadata.packageMetadataMap.getOrPut(packageInfo.packageName) {
|
||||||
val isSystemApp = packageInfo.isSystemApp()
|
|
||||||
PackageMetadata(
|
PackageMetadata(
|
||||||
time = 0L,
|
time = 0L,
|
||||||
state = packageState,
|
state = packageState,
|
||||||
name = packageInfo.applicationInfo?.loadLabel(context.packageManager),
|
name = packageInfo.applicationInfo?.loadLabel(context.packageManager),
|
||||||
system = isSystemApp,
|
|
||||||
isLaunchableSystemApp = isSystemApp &&
|
|
||||||
launchableSystemApps.contains(packageInfo.packageName),
|
|
||||||
)
|
)
|
||||||
}.apply {
|
}.apply {
|
||||||
state = packageState
|
state = packageState
|
||||||
|
|
|
@ -9,7 +9,7 @@ import org.koin.android.ext.koin.androidContext
|
||||||
import org.koin.dsl.module
|
import org.koin.dsl.module
|
||||||
|
|
||||||
val metadataModule = module {
|
val metadataModule = module {
|
||||||
single { MetadataManager(androidContext(), get(), get(), get(), get()) }
|
single { MetadataManager(androidContext(), get(), get(), get()) }
|
||||||
single<MetadataWriter> { MetadataWriterImpl() }
|
single<MetadataWriter> { MetadataWriterImpl() }
|
||||||
single<MetadataReader> { MetadataReaderImpl(get()) }
|
single<MetadataReader> { MetadataReaderImpl(get()) }
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
|
|
||||||
package com.stevesoltys.seedvault.transport.backup
|
package com.stevesoltys.seedvault.transport.backup
|
||||||
|
|
||||||
|
import android.Manifest
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.pm.PackageInfo
|
import android.content.pm.PackageInfo
|
||||||
|
@ -18,7 +19,6 @@ import com.stevesoltys.seedvault.Clock
|
||||||
import com.stevesoltys.seedvault.header.VERSION
|
import com.stevesoltys.seedvault.header.VERSION
|
||||||
import com.stevesoltys.seedvault.metadata.BackupType
|
import com.stevesoltys.seedvault.metadata.BackupType
|
||||||
import com.stevesoltys.seedvault.metadata.MetadataManager
|
import com.stevesoltys.seedvault.metadata.MetadataManager
|
||||||
import com.stevesoltys.seedvault.metadata.PackageState.APK_AND_DATA
|
|
||||||
import com.stevesoltys.seedvault.proto.Snapshot
|
import com.stevesoltys.seedvault.proto.Snapshot
|
||||||
import com.stevesoltys.seedvault.proto.Snapshot.Apk
|
import com.stevesoltys.seedvault.proto.Snapshot.Apk
|
||||||
import com.stevesoltys.seedvault.proto.Snapshot.App
|
import com.stevesoltys.seedvault.proto.Snapshot.App
|
||||||
|
@ -28,6 +28,9 @@ import io.github.oshai.kotlinlogging.KotlinLogging
|
||||||
import org.calyxos.seedvault.core.backends.AppBackupFileType
|
import org.calyxos.seedvault.core.backends.AppBackupFileType
|
||||||
import org.calyxos.seedvault.core.toHexString
|
import org.calyxos.seedvault.core.toHexString
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new [SnapshotCreator], because one is only valid for a single backup run.
|
||||||
|
*/
|
||||||
internal class SnapshotCreatorFactory(
|
internal class SnapshotCreatorFactory(
|
||||||
private val context: Context,
|
private val context: Context,
|
||||||
private val clock: Clock,
|
private val clock: Clock,
|
||||||
|
@ -39,6 +42,10 @@ internal class SnapshotCreatorFactory(
|
||||||
SnapshotCreator(context, clock, packageService, settingsManager, metadataManager)
|
SnapshotCreator(context, clock, packageService, settingsManager, metadataManager)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Assembles snapshot information over the course of a single backup run
|
||||||
|
* and creates a [Snapshot] object in the end by calling [finalizeSnapshot].
|
||||||
|
*/
|
||||||
internal class SnapshotCreator(
|
internal class SnapshotCreator(
|
||||||
private val context: Context,
|
private val context: Context,
|
||||||
private val clock: Clock,
|
private val clock: Clock,
|
||||||
|
@ -48,14 +55,21 @@ internal class SnapshotCreator(
|
||||||
) {
|
) {
|
||||||
|
|
||||||
private val log = KotlinLogging.logger { }
|
private val log = KotlinLogging.logger { }
|
||||||
|
|
||||||
private val snapshotBuilder = Snapshot.newBuilder()
|
private val snapshotBuilder = Snapshot.newBuilder()
|
||||||
private val appBuilderMap = mutableMapOf<String, App.Builder>()
|
private val appBuilderMap = mutableMapOf<String, App.Builder>()
|
||||||
private val blobsMap = mutableMapOf<String, Blob>()
|
private val blobsMap = mutableMapOf<String, Blob>()
|
||||||
|
|
||||||
private val launchableSystemApps by lazy {
|
private val launchableSystemApps by lazy {
|
||||||
|
// as we can't ask [PackageInfo] for this, we keep a set of packages around
|
||||||
packageService.launchableSystemApps.map { it.activityInfo.packageName }.toSet()
|
packageService.launchableSystemApps.map { it.activityInfo.packageName }.toSet()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call this after all blobs for the given [apk] have been saved to the backend.
|
||||||
|
* The [apk] must contain the ordered list of chunk IDs
|
||||||
|
* and the given [blobMap] must have one [Blob] per chunk ID.
|
||||||
|
*/
|
||||||
fun onApkBackedUp(
|
fun onApkBackedUp(
|
||||||
packageInfo: PackageInfo,
|
packageInfo: PackageInfo,
|
||||||
apk: Apk,
|
apk: Apk,
|
||||||
|
@ -71,6 +85,14 @@ internal class SnapshotCreator(
|
||||||
blobsMap.putAll(blobMap)
|
blobsMap.putAll(blobMap)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call this after all blobs for the package identified by the given [packageInfo]
|
||||||
|
* have been saved to the backend.
|
||||||
|
* The given [backupData] must contain the full ordered list of [BackupData.chunkIds]
|
||||||
|
* and the [BackupData.blobMap] must have one [Blob] per chunk ID.
|
||||||
|
*
|
||||||
|
* Failure to call this method results in the package effectively not getting backed up.
|
||||||
|
*/
|
||||||
fun onPackageBackedUp(
|
fun onPackageBackedUp(
|
||||||
packageInfo: PackageInfo,
|
packageInfo: PackageInfo,
|
||||||
backupType: BackupType,
|
backupType: BackupType,
|
||||||
|
@ -83,7 +105,6 @@ internal class SnapshotCreator(
|
||||||
App.newBuilder()
|
App.newBuilder()
|
||||||
}.apply {
|
}.apply {
|
||||||
time = clock.time()
|
time = clock.time()
|
||||||
state = APK_AND_DATA.name // TODO review those states and their usefulness for snapshot
|
|
||||||
type = backupType.forSnapshot()
|
type = backupType.forSnapshot()
|
||||||
val label = packageInfo.applicationInfo?.loadLabel(context.packageManager)
|
val label = packageInfo.applicationInfo?.loadLabel(context.packageManager)
|
||||||
if (label != null) name = label.toString()
|
if (label != null) name = label.toString()
|
||||||
|
@ -95,26 +116,31 @@ internal class SnapshotCreator(
|
||||||
metadataManager.onPackageBackedUp(packageInfo, backupType, backupData.size)
|
metadataManager.onPackageBackedUp(packageInfo, backupType, backupData.size)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call this after all blobs for the app icons have been saved to the backend.
|
||||||
|
*/
|
||||||
fun onIconsBackedUp(backupData: BackupData) {
|
fun onIconsBackedUp(backupData: BackupData) {
|
||||||
snapshotBuilder.addAllIconChunkIds(backupData.chunkIds.forProto())
|
snapshotBuilder.addAllIconChunkIds(backupData.chunkIds.forProto())
|
||||||
blobsMap.putAll(backupData.blobMap)
|
blobsMap.putAll(backupData.blobMap)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Must get called after all backup data was saved to the backend.
|
||||||
|
* Returns the assembled [Snapshot] which must be saved to the backend as well
|
||||||
|
* to complete the current backup run.
|
||||||
|
*
|
||||||
|
* Internal state will be cleared to free up memory.
|
||||||
|
* Still, it isn't safe to re-use an instance of this class, after it has been finalized.
|
||||||
|
*/
|
||||||
fun finalizeSnapshot(): Snapshot {
|
fun finalizeSnapshot(): Snapshot {
|
||||||
log.info { "finalizeSnapshot()" }
|
log.info { "finalizeSnapshot()" }
|
||||||
val userName = getUserName()
|
|
||||||
val deviceName = if (userName == null) {
|
|
||||||
"${Build.MANUFACTURER} ${Build.MODEL}"
|
|
||||||
} else {
|
|
||||||
"${Build.MANUFACTURER} ${Build.MODEL} - $userName"
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressLint("HardwareIds")
|
@SuppressLint("HardwareIds")
|
||||||
val snapshot = snapshotBuilder.apply {
|
val snapshot = snapshotBuilder.apply {
|
||||||
version = VERSION.toInt()
|
version = VERSION.toInt()
|
||||||
token = clock.time()
|
token = clock.time()
|
||||||
name = deviceName
|
name = "${Build.MANUFACTURER} ${Build.MODEL}"
|
||||||
androidId = Settings.Secure.getString(context.contentResolver, ANDROID_ID)
|
user = getUserName() ?: ""
|
||||||
|
androidId = Settings.Secure.getString(context.contentResolver, ANDROID_ID) ?: ""
|
||||||
sdkInt = Build.VERSION.SDK_INT
|
sdkInt = Build.VERSION.SDK_INT
|
||||||
androidIncremental = Build.VERSION.INCREMENTAL
|
androidIncremental = Build.VERSION.INCREMENTAL
|
||||||
d2D = settingsManager.d2dBackupsEnabled()
|
d2D = settingsManager.d2dBackupsEnabled()
|
||||||
|
@ -123,11 +149,13 @@ internal class SnapshotCreator(
|
||||||
}.build()
|
}.build()
|
||||||
appBuilderMap.clear()
|
appBuilderMap.clear()
|
||||||
snapshotBuilder.clear()
|
snapshotBuilder.clear()
|
||||||
|
blobsMap.clear()
|
||||||
return snapshot
|
return snapshot
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getUserName(): String? {
|
private fun getUserName(): String? {
|
||||||
val perm = "android.permission.QUERY_USERS"
|
@Suppress("UNRESOLVED_REFERENCE") // hidden AOSP API
|
||||||
|
val perm = Manifest.permission.QUERY_USERS
|
||||||
return if (context.checkSelfPermission(perm) == PERMISSION_GRANTED) {
|
return if (context.checkSelfPermission(perm) == PERMISSION_GRANTED) {
|
||||||
val userManager = context.getSystemService(UserManager::class.java) ?: return null
|
val userManager = context.getSystemService(UserManager::class.java) ?: return null
|
||||||
userManager.userName
|
userManager.userName
|
||||||
|
|
|
@ -8,23 +8,23 @@ message Snapshot {
|
||||||
uint32 version = 1;
|
uint32 version = 1;
|
||||||
uint64 token = 2;
|
uint64 token = 2;
|
||||||
string name = 3;
|
string name = 3;
|
||||||
string androidId = 4;
|
string user = 4;
|
||||||
uint32 sdkInt = 5;
|
string androidId = 5;
|
||||||
string androidIncremental = 6;
|
uint32 sdkInt = 6;
|
||||||
bool d2d = 7;
|
string androidIncremental = 7;
|
||||||
map<string, App> apps = 8;
|
bool d2d = 8;
|
||||||
repeated bytes iconChunkIds = 9;
|
map<string, App> apps = 9;
|
||||||
map<string, Blob> blobs = 10;
|
repeated bytes iconChunkIds = 10;
|
||||||
|
map<string, Blob> blobs = 11;
|
||||||
|
|
||||||
message App {
|
message App {
|
||||||
uint64 time = 1;
|
uint64 time = 1;
|
||||||
string state = 2;
|
BackupType type = 2;
|
||||||
BackupType type = 3;
|
string name = 3;
|
||||||
string name = 4;
|
bool system = 4;
|
||||||
bool system = 5;
|
bool launchableSystemApp = 5;
|
||||||
bool launchableSystemApp = 6;
|
repeated bytes chunkIds = 6;
|
||||||
repeated bytes chunkIds = 7;
|
Apk apk = 7;
|
||||||
Apk apk = 8;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
enum BackupType {
|
enum BackupType {
|
||||||
|
|
|
@ -9,7 +9,6 @@ import android.content.Context
|
||||||
import android.content.Context.MODE_PRIVATE
|
import android.content.Context.MODE_PRIVATE
|
||||||
import android.content.pm.ApplicationInfo
|
import android.content.pm.ApplicationInfo
|
||||||
import android.content.pm.ApplicationInfo.FLAG_ALLOW_BACKUP
|
import android.content.pm.ApplicationInfo.FLAG_ALLOW_BACKUP
|
||||||
import android.content.pm.ApplicationInfo.FLAG_SYSTEM
|
|
||||||
import android.content.pm.PackageInfo
|
import android.content.pm.PackageInfo
|
||||||
import android.content.pm.PackageManager
|
import android.content.pm.PackageManager
|
||||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||||
|
@ -23,7 +22,6 @@ import com.stevesoltys.seedvault.metadata.PackageState.NOT_ALLOWED
|
||||||
import com.stevesoltys.seedvault.metadata.PackageState.NO_DATA
|
import com.stevesoltys.seedvault.metadata.PackageState.NO_DATA
|
||||||
import com.stevesoltys.seedvault.metadata.PackageState.WAS_STOPPED
|
import com.stevesoltys.seedvault.metadata.PackageState.WAS_STOPPED
|
||||||
import com.stevesoltys.seedvault.settings.SettingsManager
|
import com.stevesoltys.seedvault.settings.SettingsManager
|
||||||
import com.stevesoltys.seedvault.transport.backup.PackageService
|
|
||||||
import io.mockk.Runs
|
import io.mockk.Runs
|
||||||
import io.mockk.every
|
import io.mockk.every
|
||||||
import io.mockk.just
|
import io.mockk.just
|
||||||
|
@ -37,7 +35,6 @@ import org.junit.Test
|
||||||
import org.junit.runner.RunWith
|
import org.junit.runner.RunWith
|
||||||
import org.koin.core.context.stopKoin
|
import org.koin.core.context.stopKoin
|
||||||
import org.robolectric.annotation.Config
|
import org.robolectric.annotation.Config
|
||||||
import java.io.ByteArrayOutputStream
|
|
||||||
import java.io.FileInputStream
|
import java.io.FileInputStream
|
||||||
import java.io.FileOutputStream
|
import java.io.FileOutputStream
|
||||||
import kotlin.random.Random
|
import kotlin.random.Random
|
||||||
|
@ -53,7 +50,6 @@ class MetadataManagerTest {
|
||||||
private val clock: Clock = mockk()
|
private val clock: Clock = mockk()
|
||||||
private val metadataWriter: MetadataWriter = mockk()
|
private val metadataWriter: MetadataWriter = mockk()
|
||||||
private val metadataReader: MetadataReader = mockk()
|
private val metadataReader: MetadataReader = mockk()
|
||||||
private val packageService: PackageService = mockk()
|
|
||||||
private val settingsManager: SettingsManager = mockk()
|
private val settingsManager: SettingsManager = mockk()
|
||||||
|
|
||||||
private val manager = MetadataManager(
|
private val manager = MetadataManager(
|
||||||
|
@ -61,7 +57,6 @@ class MetadataManagerTest {
|
||||||
clock = clock,
|
clock = clock,
|
||||||
metadataWriter = metadataWriter,
|
metadataWriter = metadataWriter,
|
||||||
metadataReader = metadataReader,
|
metadataReader = metadataReader,
|
||||||
packageService = packageService,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
private val packageManager: PackageManager = mockk()
|
private val packageManager: PackageManager = mockk()
|
||||||
|
@ -76,7 +71,6 @@ class MetadataManagerTest {
|
||||||
private val saltBytes = Random.nextBytes(METADATA_SALT_SIZE)
|
private val saltBytes = Random.nextBytes(METADATA_SALT_SIZE)
|
||||||
private val salt = saltBytes.encodeBase64()
|
private val salt = saltBytes.encodeBase64()
|
||||||
private val initialMetadata = BackupMetadata(token = token, salt = salt)
|
private val initialMetadata = BackupMetadata(token = token, salt = salt)
|
||||||
private val storageOutputStream = ByteArrayOutputStream()
|
|
||||||
private val cacheOutputStream: FileOutputStream = mockk()
|
private val cacheOutputStream: FileOutputStream = mockk()
|
||||||
private val cacheInputStream: FileInputStream = mockk()
|
private val cacheInputStream: FileInputStream = mockk()
|
||||||
private val encodedMetadata = getRandomByteArray()
|
private val encodedMetadata = getRandomByteArray()
|
||||||
|
@ -93,7 +87,6 @@ class MetadataManagerTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `test onPackageBackedUp()`() {
|
fun `test onPackageBackedUp()`() {
|
||||||
packageInfo.applicationInfo!!.flags = FLAG_SYSTEM
|
|
||||||
val updatedMetadata = initialMetadata.copy(
|
val updatedMetadata = initialMetadata.copy(
|
||||||
time = time,
|
time = time,
|
||||||
packageMetadataMap = PackageMetadataMap() // otherwise this isn't copied, but referenced
|
packageMetadataMap = PackageMetadataMap() // otherwise this isn't copied, but referenced
|
||||||
|
@ -103,7 +96,6 @@ class MetadataManagerTest {
|
||||||
updatedMetadata.packageMetadataMap[packageName] = packageMetadata
|
updatedMetadata.packageMetadataMap[packageName] = packageMetadata
|
||||||
|
|
||||||
every { context.packageManager } returns packageManager
|
every { context.packageManager } returns packageManager
|
||||||
every { packageService.launchableSystemApps } returns emptyList()
|
|
||||||
expectReadFromCache()
|
expectReadFromCache()
|
||||||
every { clock.time() } returns time
|
every { clock.time() } returns time
|
||||||
expectWriteToCache(initialMetadata)
|
expectWriteToCache(initialMetadata)
|
||||||
|
@ -115,8 +107,6 @@ class MetadataManagerTest {
|
||||||
state = APK_AND_DATA,
|
state = APK_AND_DATA,
|
||||||
backupType = BackupType.FULL,
|
backupType = BackupType.FULL,
|
||||||
size = size,
|
size = size,
|
||||||
system = true,
|
|
||||||
isLaunchableSystemApp = false,
|
|
||||||
),
|
),
|
||||||
manager.getPackageMetadata(packageName)
|
manager.getPackageMetadata(packageName)
|
||||||
)
|
)
|
||||||
|
|
|
@ -0,0 +1,134 @@
|
||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2024 The Calyx Institute
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.stevesoltys.seedvault.transport.backup
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.pm.ActivityInfo
|
||||||
|
import android.content.pm.ApplicationInfo
|
||||||
|
import android.content.pm.ApplicationInfo.FLAG_SYSTEM
|
||||||
|
import android.content.pm.ResolveInfo
|
||||||
|
import androidx.test.core.app.ApplicationProvider
|
||||||
|
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||||
|
import com.stevesoltys.seedvault.TestApp
|
||||||
|
import com.stevesoltys.seedvault.header.VERSION
|
||||||
|
import com.stevesoltys.seedvault.metadata.BackupType
|
||||||
|
import com.stevesoltys.seedvault.proto.Snapshot
|
||||||
|
import com.stevesoltys.seedvault.transport.TransportTest
|
||||||
|
import io.mockk.Runs
|
||||||
|
import io.mockk.every
|
||||||
|
import io.mockk.just
|
||||||
|
import io.mockk.mockk
|
||||||
|
import org.junit.Assert.assertEquals
|
||||||
|
import org.junit.Test
|
||||||
|
import org.junit.runner.RunWith
|
||||||
|
import org.robolectric.annotation.Config
|
||||||
|
import kotlin.random.Random
|
||||||
|
|
||||||
|
@RunWith(AndroidJUnit4::class)
|
||||||
|
@Config(
|
||||||
|
sdk = [34], // TODO: Drop once robolectric supports 35
|
||||||
|
application = TestApp::class
|
||||||
|
)
|
||||||
|
internal class SnapshotCreatorTest : TransportTest() {
|
||||||
|
|
||||||
|
private val ctx: Context = ApplicationProvider.getApplicationContext()
|
||||||
|
private val packageService: PackageService = mockk()
|
||||||
|
private val snapshotCreator =
|
||||||
|
SnapshotCreator(ctx, clock, packageService, settingsManager, metadataManager)
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `test onApkBackedUp`() {
|
||||||
|
every { applicationInfo.loadLabel(any()) } returns name
|
||||||
|
every { clock.time() } returns token
|
||||||
|
every { settingsManager.d2dBackupsEnabled() } returns Random.nextBoolean()
|
||||||
|
|
||||||
|
snapshotCreator.onApkBackedUp(packageInfo, apk, blobMap)
|
||||||
|
val s = snapshotCreator.finalizeSnapshot()
|
||||||
|
|
||||||
|
assertEquals(apk, s.appsMap[packageName]?.apk)
|
||||||
|
assertEquals(name, s.appsMap[packageName]?.name)
|
||||||
|
assertEquals(blobMap, s.blobsMap)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `test onPackageBackedUp`() {
|
||||||
|
val size = apkBackupData.size
|
||||||
|
val isSystem = Random.nextBoolean()
|
||||||
|
val appInfo = mockk<ApplicationInfo> {
|
||||||
|
flags = if (isSystem) FLAG_SYSTEM else 0
|
||||||
|
}
|
||||||
|
packageInfo.applicationInfo = appInfo
|
||||||
|
val resolveInfo = ResolveInfo().apply { // if isSystem, then it will be launchable
|
||||||
|
activityInfo = ActivityInfo().apply {
|
||||||
|
packageName = this@SnapshotCreatorTest.packageName
|
||||||
|
}
|
||||||
|
}
|
||||||
|
every { appInfo.loadLabel(any()) } returns name
|
||||||
|
every { metadataManager.onPackageBackedUp(packageInfo, BackupType.FULL, size) } just Runs
|
||||||
|
every { clock.time() } returns token andThen token + 1
|
||||||
|
every { settingsManager.d2dBackupsEnabled() } returns Random.nextBoolean()
|
||||||
|
every { packageService.launchableSystemApps } returns listOf(resolveInfo)
|
||||||
|
|
||||||
|
snapshotCreator.onPackageBackedUp(packageInfo, BackupType.FULL, apkBackupData)
|
||||||
|
val s = snapshotCreator.finalizeSnapshot()
|
||||||
|
|
||||||
|
assertEquals(name, s.appsMap[packageName]?.name)
|
||||||
|
assertEquals(token, s.appsMap[packageName]?.time)
|
||||||
|
assertEquals(Snapshot.BackupType.FULL, s.appsMap[packageName]?.type)
|
||||||
|
assertEquals(isSystem, s.appsMap[packageName]?.system)
|
||||||
|
assertEquals(isSystem, s.appsMap[packageName]?.launchableSystemApp)
|
||||||
|
assertEquals(apkBackupData.chunkIds.forProto(), s.appsMap[packageName]?.chunkIdsList)
|
||||||
|
assertEquals(apkBackupData.blobMap, s.blobsMap)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `test onPackageBackedUp handles no application info`() {
|
||||||
|
packageInfo.applicationInfo = null
|
||||||
|
|
||||||
|
val size = apkBackupData.size
|
||||||
|
every { metadataManager.onPackageBackedUp(packageInfo, BackupType.FULL, size) } just Runs
|
||||||
|
every { clock.time() } returns token andThen token + 1
|
||||||
|
every { settingsManager.d2dBackupsEnabled() } returns Random.nextBoolean()
|
||||||
|
every { packageService.launchableSystemApps } returns emptyList()
|
||||||
|
|
||||||
|
snapshotCreator.onPackageBackedUp(packageInfo, BackupType.FULL, apkBackupData)
|
||||||
|
snapshotCreator.finalizeSnapshot()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `test onIconsBackedUp`() {
|
||||||
|
every { clock.time() } returns token andThen token + 1
|
||||||
|
every { settingsManager.d2dBackupsEnabled() } returns Random.nextBoolean()
|
||||||
|
|
||||||
|
snapshotCreator.onIconsBackedUp(apkBackupData)
|
||||||
|
val s = snapshotCreator.finalizeSnapshot()
|
||||||
|
|
||||||
|
assertEquals(apkBackupData.chunkIds.forProto(), s.iconChunkIdsList)
|
||||||
|
assertEquals(apkBackupData.blobMap, s.blobsMap)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `test finalize`() {
|
||||||
|
val d2d = Random.nextBoolean()
|
||||||
|
every { clock.time() } returns token
|
||||||
|
every { settingsManager.d2dBackupsEnabled() } returns d2d
|
||||||
|
|
||||||
|
val s = snapshotCreator.finalizeSnapshot()
|
||||||
|
|
||||||
|
assertEquals(VERSION, s.version.toByte())
|
||||||
|
assertEquals(token, s.token)
|
||||||
|
assertEquals("robolectric robolectric", s.name)
|
||||||
|
assertEquals("", s.user) // no perm
|
||||||
|
assertEquals("", s.androidId) // not mocked
|
||||||
|
assertEquals(34, s.sdkInt) // as per config above, needs bump once possible
|
||||||
|
assertEquals("unknown", s.androidIncremental)
|
||||||
|
assertEquals(d2d, s.d2D)
|
||||||
|
assertEquals(0, s.appsCount)
|
||||||
|
assertEquals(0, s.iconChunkIdsCount)
|
||||||
|
assertEquals(emptyMap<String, Snapshot.Blob>(), s.blobsMap)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in a new issue