Skip to content

Commit

Permalink
Include user profile name in backup name
Browse files Browse the repository at this point in the history
so it is easier to identify the right backup if more users backup to the same storage medium.

Change-Id: I56fa93899da3764e20b6aee40adfd52722a05a9f
  • Loading branch information
grote committed Apr 15, 2024
1 parent 6e63d9b commit 4f27a59
Show file tree
Hide file tree
Showing 5 changed files with 65 additions and 2 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
4 changes: 4 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,10 @@
android:name="android.permission.READ_LOGS"
tools:ignore="ProtectedPermissions" />

<!-- Used to get the name of the current profile -->
<uses-permission android:name="android.permission.QUERY_USERS"
tools:ignore="ProtectedPermissions" />

<!-- Used for periodic storage backups -->
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC" />

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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"
},
)
}
}

Expand Down Expand Up @@ -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
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -94,12 +96,46 @@ 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())
assertEquals(0L, manager.getLastBackupTime())

verify {
cacheInputStream.close()
cacheOutputStream.close()
}
}

@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())
Expand All @@ -108,6 +144,7 @@ class MetadataManagerTest {
verify {
cacheInputStream.close()
cacheOutputStream.close()
userManager.userName
}
}

Expand Down
1 change: 1 addition & 0 deletions permissions_com.stevesoltys.seedvault.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
<permission name="android.permission.MANAGE_USB"/>
<permission name="android.permission.INSTALL_PACKAGES"/>
<permission name="android.permission.INTERACT_ACROSS_USERS_FULL"/>
<permission name="android.permission.QUERY_USERS" />
<permission name="android.permission.READ_LOGS"/>
<permission name="android.permission.WRITE_SECURE_SETTINGS"/>
<permission name="android.permission.MANAGE_EXTERNAL_STORAGE"/>
Expand Down

0 comments on commit 4f27a59

Please sign in to comment.