Include user profile name in backup name
so it is easier to identify the right backup if more users backup to the same storage medium. Change-Id: I56fa93899da3764e20b6aee40adfd52722a05a9f
This commit is contained in:
parent
6e63d9bac0
commit
87db20e45f
5 changed files with 65 additions and 2 deletions
|
@ -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.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.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_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.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.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.
|
* `android.permission.ACCESS_MEDIA_LOCATION` to backup original media files e.g. without stripped EXIF metadata.
|
||||||
|
|
|
@ -64,6 +64,10 @@
|
||||||
android:name="android.permission.READ_LOGS"
|
android:name="android.permission.READ_LOGS"
|
||||||
tools:ignore="ProtectedPermissions" />
|
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 -->
|
<!-- Used for periodic storage backups -->
|
||||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC" />
|
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC" />
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,9 @@ package com.stevesoltys.seedvault.metadata
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Context.MODE_PRIVATE
|
import android.content.Context.MODE_PRIVATE
|
||||||
import android.content.pm.PackageInfo
|
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 android.util.Log
|
||||||
import androidx.annotation.VisibleForTesting
|
import androidx.annotation.VisibleForTesting
|
||||||
import androidx.annotation.WorkerThread
|
import androidx.annotation.WorkerThread
|
||||||
|
@ -67,7 +70,16 @@ internal class MetadataManager(
|
||||||
fun onDeviceInitialization(token: Long) {
|
fun onDeviceInitialization(token: Long) {
|
||||||
val salt = crypto.getRandomBytes(METADATA_SALT_SIZE).encodeBase64()
|
val salt = crypto.getRandomBytes(METADATA_SALT_SIZE).encodeBase64()
|
||||||
modifyCachedMetadata {
|
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
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,8 @@ 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.ApplicationInfo.FLAG_SYSTEM
|
||||||
import android.content.pm.PackageInfo
|
import android.content.pm.PackageInfo
|
||||||
|
import android.content.pm.PackageManager
|
||||||
|
import android.os.UserManager
|
||||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||||
import com.stevesoltys.seedvault.Clock
|
import com.stevesoltys.seedvault.Clock
|
||||||
import com.stevesoltys.seedvault.TestApp
|
import com.stevesoltys.seedvault.TestApp
|
||||||
|
@ -94,12 +96,16 @@ class MetadataManagerTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `test onDeviceInitialization()`() {
|
fun `test onDeviceInitialization() without user permission`() {
|
||||||
every { clock.time() } returns time
|
every { clock.time() } returns time
|
||||||
every { crypto.getRandomBytes(METADATA_SALT_SIZE) } returns saltBytes
|
every { crypto.getRandomBytes(METADATA_SALT_SIZE) } returns saltBytes
|
||||||
expectReadFromCache()
|
expectReadFromCache()
|
||||||
expectModifyMetadata(initialMetadata)
|
expectModifyMetadata(initialMetadata)
|
||||||
|
|
||||||
|
every {
|
||||||
|
context.checkSelfPermission("android.permission.QUERY_USERS")
|
||||||
|
} returns PackageManager.PERMISSION_DENIED
|
||||||
|
|
||||||
manager.onDeviceInitialization(token)
|
manager.onDeviceInitialization(token)
|
||||||
|
|
||||||
assertEquals(token, manager.getBackupToken())
|
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
|
@Test
|
||||||
fun `test onApkBackedUp() with no prior package metadata`() {
|
fun `test onApkBackedUp() with no prior package metadata`() {
|
||||||
val packageMetadata = PackageMetadata(
|
val packageMetadata = PackageMetadata(
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
<permission name="android.permission.MANAGE_USB"/>
|
<permission name="android.permission.MANAGE_USB"/>
|
||||||
<permission name="android.permission.INSTALL_PACKAGES"/>
|
<permission name="android.permission.INSTALL_PACKAGES"/>
|
||||||
<permission name="android.permission.INTERACT_ACROSS_USERS_FULL"/>
|
<permission name="android.permission.INTERACT_ACROSS_USERS_FULL"/>
|
||||||
|
<permission name="android.permission.QUERY_USERS" />
|
||||||
<permission name="android.permission.READ_LOGS"/>
|
<permission name="android.permission.READ_LOGS"/>
|
||||||
<permission name="android.permission.WRITE_SECURE_SETTINGS"/>
|
<permission name="android.permission.WRITE_SECURE_SETTINGS"/>
|
||||||
<permission name="android.permission.MANAGE_EXTERNAL_STORAGE"/>
|
<permission name="android.permission.MANAGE_EXTERNAL_STORAGE"/>
|
||||||
|
|
Loading…
Reference in a new issue