diff --git a/README.md b/README.md
index 3f97ac35..b396a5a5 100644
--- a/README.md
+++ b/README.md
@@ -46,6 +46,7 @@ It uses the same internal APIs as `adb backup` which is deprecated and thus need
* `android.permission.MANAGE_USB` to access the serial number of USB mass storage devices.
* `android.permission.WRITE_SECURE_SETTINGS` to change system backup settings and enable call log backup.
* `android.permission.QUERY_ALL_PACKAGES` to get information about all installed apps for backup.
+* `android.permission.QUERY_USERS` to get the name of the user profile that gets backed up.
* `android.permission.INSTALL_PACKAGES` to re-install apps when restoring from backup.
* `android.permission.MANAGE_EXTERNAL_STORAGE` to backup and restore files from device storage.
* `android.permission.ACCESS_MEDIA_LOCATION` to backup original media files e.g. without stripped EXIF metadata.
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index c3bd194c..f2278814 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -64,6 +64,10 @@
android:name="android.permission.READ_LOGS"
tools:ignore="ProtectedPermissions" />
+
+
+
diff --git a/app/src/main/java/com/stevesoltys/seedvault/metadata/MetadataManager.kt b/app/src/main/java/com/stevesoltys/seedvault/metadata/MetadataManager.kt
index 6c09ac8f..2346adb6 100644
--- a/app/src/main/java/com/stevesoltys/seedvault/metadata/MetadataManager.kt
+++ b/app/src/main/java/com/stevesoltys/seedvault/metadata/MetadataManager.kt
@@ -3,6 +3,9 @@ package com.stevesoltys.seedvault.metadata
import android.content.Context
import android.content.Context.MODE_PRIVATE
import android.content.pm.PackageInfo
+import android.content.pm.PackageManager.PERMISSION_GRANTED
+import android.os.Build
+import android.os.UserManager
import android.util.Log
import androidx.annotation.VisibleForTesting
import androidx.annotation.WorkerThread
@@ -67,7 +70,16 @@ internal class MetadataManager(
fun onDeviceInitialization(token: Long) {
val salt = crypto.getRandomBytes(METADATA_SALT_SIZE).encodeBase64()
modifyCachedMetadata {
- metadata = BackupMetadata(token = token, salt = salt)
+ val userName = getUserName()
+ metadata = BackupMetadata(
+ token = token,
+ salt = salt,
+ deviceName = if (userName == null) {
+ "${Build.MANUFACTURER} ${Build.MODEL}"
+ } else {
+ "${Build.MANUFACTURER} ${Build.MODEL} - $userName"
+ },
+ )
}
}
@@ -297,4 +309,12 @@ internal class MetadataManager(
}
}
+ private fun getUserName(): String? {
+ val perm = "android.permission.QUERY_USERS"
+ return if (context.checkSelfPermission(perm) == PERMISSION_GRANTED) {
+ val userManager = context.getSystemService(UserManager::class.java)
+ userManager.userName
+ } else null
+ }
+
}
diff --git a/app/src/test/java/com/stevesoltys/seedvault/metadata/MetadataManagerTest.kt b/app/src/test/java/com/stevesoltys/seedvault/metadata/MetadataManagerTest.kt
index 62300e76..308f9105 100644
--- a/app/src/test/java/com/stevesoltys/seedvault/metadata/MetadataManagerTest.kt
+++ b/app/src/test/java/com/stevesoltys/seedvault/metadata/MetadataManagerTest.kt
@@ -6,6 +6,8 @@ import android.content.pm.ApplicationInfo
import android.content.pm.ApplicationInfo.FLAG_ALLOW_BACKUP
import android.content.pm.ApplicationInfo.FLAG_SYSTEM
import android.content.pm.PackageInfo
+import android.content.pm.PackageManager
+import android.os.UserManager
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.stevesoltys.seedvault.Clock
import com.stevesoltys.seedvault.TestApp
@@ -94,12 +96,16 @@ class MetadataManagerTest {
}
@Test
- fun `test onDeviceInitialization()`() {
+ fun `test onDeviceInitialization() without user permission`() {
every { clock.time() } returns time
every { crypto.getRandomBytes(METADATA_SALT_SIZE) } returns saltBytes
expectReadFromCache()
expectModifyMetadata(initialMetadata)
+ every {
+ context.checkSelfPermission("android.permission.QUERY_USERS")
+ } returns PackageManager.PERMISSION_DENIED
+
manager.onDeviceInitialization(token)
assertEquals(token, manager.getBackupToken())
@@ -111,6 +117,37 @@ class MetadataManagerTest {
}
}
+ @Test
+ fun `test onDeviceInitialization() with user permission`() {
+ val userManager: UserManager = mockk()
+ val userName = getRandomString()
+ val newMetadata = initialMetadata.copy(
+ deviceName = initialMetadata.deviceName + " - $userName",
+ )
+
+ every { clock.time() } returns time
+ every { crypto.getRandomBytes(METADATA_SALT_SIZE) } returns saltBytes
+ expectReadFromCache()
+ expectModifyMetadata(newMetadata)
+
+ every {
+ context.checkSelfPermission("android.permission.QUERY_USERS")
+ } returns PackageManager.PERMISSION_GRANTED
+ every { context.getSystemService(UserManager::class.java) } returns userManager
+ every { userManager.userName } returns userName
+
+ manager.onDeviceInitialization(token)
+
+ assertEquals(token, manager.getBackupToken())
+ assertEquals(0L, manager.getLastBackupTime())
+
+ verify {
+ cacheInputStream.close()
+ cacheOutputStream.close()
+ userManager.userName
+ }
+ }
+
@Test
fun `test onApkBackedUp() with no prior package metadata`() {
val packageMetadata = PackageMetadata(
diff --git a/permissions_com.stevesoltys.seedvault.xml b/permissions_com.stevesoltys.seedvault.xml
index cb85ca60..f6b63de3 100644
--- a/permissions_com.stevesoltys.seedvault.xml
+++ b/permissions_com.stevesoltys.seedvault.xml
@@ -5,6 +5,7 @@
+