fix(train): nothing of Train's goes to Android's backup or to another phone (ADR 0030, D53)
What Train keeps unsealed on the phone (a recording while it runs, the Loop's days before they are sealed, the body's figures the band was set up with, the maps along routes) went to the backup and to a new phone by default, outside the sealing. allowBackup and fullBackupContent are off, and from Android 12 on the extraction rules exclude every folder from both. The second WRITE_EXERCISE goes: a ride's cadence is written under the first. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
This commit is contained in:
parent
ba77248930
commit
071899ce44
3 changed files with 112 additions and 3 deletions
|
|
@ -38,8 +38,8 @@
|
|||
<uses-permission android:name="android.permission.health.WRITE_HEART_RATE"/>
|
||||
<uses-permission android:name="android.permission.health.WRITE_SPEED"/>
|
||||
<uses-permission android:name="android.permission.health.WRITE_POWER"/>
|
||||
<!-- A ride's and a run's cadence (ADR 0030, D51), asked for with writing. -->
|
||||
<uses-permission android:name="android.permission.health.WRITE_EXERCISE"/>
|
||||
<!-- A run's cadence (ADR 0030, D51), asked for with writing; a ride's is
|
||||
written under WRITE_EXERCISE above. -->
|
||||
<uses-permission android:name="android.permission.health.WRITE_STEPS"/>
|
||||
<uses-permission android:name="android.permission.health.WRITE_DISTANCE"/>
|
||||
<uses-permission android:name="android.permission.health.WRITE_ELEVATION_GAINED"/>
|
||||
|
|
@ -51,10 +51,17 @@
|
|||
<uses-feature android:name="android.hardware.location.gps" android:required="false"/>
|
||||
<uses-feature android:name="android.hardware.sensor.stepdetector" android:required="false"/>
|
||||
<uses-feature android:name="android.hardware.bluetooth_le" android:required="false"/>
|
||||
<!-- No backup and no transfer to another phone (ADR 0030, D53): through
|
||||
Android 11 allowBackup and fullBackupContent stop both, from 12 on
|
||||
the extraction rules stop the transfer. -->
|
||||
<application
|
||||
android:label="Halkyon Train"
|
||||
android:name="${applicationName}"
|
||||
android:icon="@mipmap/ic_launcher">
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:allowBackup="false"
|
||||
android:fullBackupContent="false"
|
||||
android:dataExtractionRules="@xml/data_extraction_rules"
|
||||
tools:targetApi="s">
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
android:exported="true"
|
||||
|
|
|
|||
|
|
@ -0,0 +1,29 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Nothing of Train's goes to a backup or to another phone, from Android 12
|
||||
on (ADR 0030, D53): allowBackup="false" stops the backup, and only these
|
||||
rules stop the transfer. What Train keeps unsealed stays on this phone;
|
||||
what is sealed comes back from the instance on the next. -->
|
||||
<data-extraction-rules>
|
||||
<cloud-backup>
|
||||
<exclude domain="root" path="."/>
|
||||
<exclude domain="file" path="."/>
|
||||
<exclude domain="database" path="."/>
|
||||
<exclude domain="sharedpref" path="."/>
|
||||
<exclude domain="external" path="."/>
|
||||
<exclude domain="device_root" path="."/>
|
||||
<exclude domain="device_file" path="."/>
|
||||
<exclude domain="device_database" path="."/>
|
||||
<exclude domain="device_sharedpref" path="."/>
|
||||
</cloud-backup>
|
||||
<device-transfer>
|
||||
<exclude domain="root" path="."/>
|
||||
<exclude domain="file" path="."/>
|
||||
<exclude domain="database" path="."/>
|
||||
<exclude domain="sharedpref" path="."/>
|
||||
<exclude domain="external" path="."/>
|
||||
<exclude domain="device_root" path="."/>
|
||||
<exclude domain="device_file" path="."/>
|
||||
<exclude domain="device_database" path="."/>
|
||||
<exclude domain="device_sharedpref" path="."/>
|
||||
</device-transfer>
|
||||
</data-extraction-rules>
|
||||
|
|
@ -0,0 +1,73 @@
|
|||
package app.halkyon.train
|
||||
|
||||
import java.io.File
|
||||
import javax.xml.parsers.DocumentBuilderFactory
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.junit.Test
|
||||
import org.w3c.dom.Element
|
||||
|
||||
/**
|
||||
* Nothing of Train's leaves the phone by Android's backup or a transfer to
|
||||
* another phone (ADR 0030, D53): what the app keeps unsealed (a recording,
|
||||
* the Loop's days, the body's figures, the maps along routes) would go
|
||||
* there unsealed, and what is sealed comes back from the instance anyway.
|
||||
*/
|
||||
class BackupRulesTest {
|
||||
private val android = "http://schemas.android.com/apk/res/android"
|
||||
|
||||
private fun parse(path: String) =
|
||||
DocumentBuilderFactory.newInstance()
|
||||
.apply { isNamespaceAware = true }
|
||||
.newDocumentBuilder()
|
||||
.parse(File(path))
|
||||
.documentElement
|
||||
|
||||
private val application =
|
||||
parse("src/main/AndroidManifest.xml").getElementsByTagName("application").item(0) as Element
|
||||
|
||||
@Test
|
||||
fun `backup is off, through Android 11 as from 12 on`() {
|
||||
assertEquals("false", application.getAttributeNS(android, "allowBackup"))
|
||||
assertEquals("false", application.getAttributeNS(android, "fullBackupContent"))
|
||||
assertEquals(
|
||||
"@xml/data_extraction_rules",
|
||||
application.getAttributeNS(android, "dataExtractionRules"),
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `from Android 12 on, neither a backup nor a transfer takes any of the app's folders`() {
|
||||
// allowBackup="false" leaves a transfer to another phone on from
|
||||
// Android 12 on: the rules have to exclude it too, folder by folder.
|
||||
val rules = parse("src/main/res/xml/data_extraction_rules.xml")
|
||||
for (kind in listOf("cloud-backup", "device-transfer")) {
|
||||
val section = rules.getElementsByTagName(kind).item(0) as Element?
|
||||
assertTrue("$kind is missing", section != null)
|
||||
val excluded =
|
||||
section!!.getElementsByTagName("exclude").let { list ->
|
||||
(0 until list.length)
|
||||
.map { list.item(it) as Element }
|
||||
.filter { it.getAttribute("path") == "." }
|
||||
.map { it.getAttribute("domain") }
|
||||
.toSet()
|
||||
}
|
||||
assertEquals(
|
||||
"$kind excludes",
|
||||
setOf(
|
||||
"root",
|
||||
"file",
|
||||
"database",
|
||||
"sharedpref",
|
||||
"external",
|
||||
"device_root",
|
||||
"device_file",
|
||||
"device_database",
|
||||
"device_sharedpref",
|
||||
),
|
||||
excluded,
|
||||
)
|
||||
assertEquals("$kind includes nothing", 0, section.getElementsByTagName("include").length)
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue