Set up project skeleton (milestone 1)

- Architecture and feature overview in docs/ARCHITECTURE.md
- Gradle 9.8 / AGP 9.4 / Kotlin 2.4 with version catalog and convention plugins
- Modules :app, :core:*, :device-profiles, :feature:* (placeholder screens)
- Flavors core (no INTERNET, enforced by a build check) and full
- Material You theme, navigation, expert mode and dry-run settings (DataStore)
- Pixel 8-10 device detection, unit tests, GPLv3 license, English README with Obtainium badge

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
2026-10-15 22:02:14 +02:00
co-authored by Claude Opus 5.5
commit 0a7caf6c5f
117 changed files with 3175 additions and 0 deletions
+7
View File
@@ -0,0 +1,7 @@
plugins {
alias(libs.plugins.pixelwall.jvm.library)
}
dependencies {
api(project(":core:model"))
}
@@ -0,0 +1,21 @@
package org.pixelwall.deviceprofiles
import org.pixelwall.core.model.DeviceInfo
/** Gerätespezifisches Wissen. Settings-Keys und Deep-Links folgen ab Meilenstein 2. */
interface DeviceProfile {
val id: String
fun matches(device: DeviceInfo): Boolean
}
object DeviceProfiles {
/** Spezifischste Profile zuerst; [AospFallbackProfile] passt immer. */
val all: List<DeviceProfile> = listOf(PixelProfile, AospFallbackProfile)
fun resolve(device: DeviceInfo): DeviceProfile = all.first { it.matches(device) }
}
object AospFallbackProfile : DeviceProfile {
override val id = "aosp"
override fun matches(device: DeviceInfo) = true
}
@@ -0,0 +1,31 @@
package org.pixelwall.deviceprofiles
import org.pixelwall.core.model.DeviceInfo
object PixelProfile : DeviceProfile {
override val id = "pixel"
/** Codenamen der unterstützten Geräte (Pixel 8 bis Pixel 10). */
val supportedDevices: Map<String, String> = mapOf(
"shiba" to "Pixel 8",
"husky" to "Pixel 8 Pro",
"akita" to "Pixel 8a",
"tokay" to "Pixel 9",
"caiman" to "Pixel 9 Pro",
"komodo" to "Pixel 9 Pro XL",
"comet" to "Pixel 9 Pro Fold",
"tegu" to "Pixel 9a",
"frankel" to "Pixel 10",
"blazer" to "Pixel 10 Pro",
"mustang" to "Pixel 10 Pro XL",
"rango" to "Pixel 10 Pro Fold",
)
/** Android 15 (API 35) und Android 16 (API 36) sind getestet. */
val supportedSdkRange = 35..36
override fun matches(device: DeviceInfo): Boolean =
device.manufacturer.equals("Google", ignoreCase = true) && device.device in supportedDevices
fun isSdkSupported(device: DeviceInfo) = device.sdkInt in supportedSdkRange
}
@@ -0,0 +1,39 @@
package org.pixelwall.deviceprofiles
import com.google.common.truth.Truth.assertThat
import org.junit.Test
import org.pixelwall.core.model.DeviceInfo
class DeviceProfilesTest {
private fun device(manufacturer: String, codename: String, sdk: Int = 36) = DeviceInfo(
manufacturer = manufacturer,
brand = manufacturer.lowercase(),
device = codename,
model = codename,
sdkInt = sdk,
release = "16",
securityPatch = "2026-10-05",
)
@Test
fun pixel9IsDetected() {
assertThat(DeviceProfiles.resolve(device("Google", "tokay"))).isEqualTo(PixelProfile)
}
@Test
fun olderPixelFallsBackToAosp() {
assertThat(DeviceProfiles.resolve(device("Google", "panther"))).isEqualTo(AospFallbackProfile)
}
@Test
fun otherVendorFallsBackToAosp() {
assertThat(DeviceProfiles.resolve(device("samsung", "tokay"))).isEqualTo(AospFallbackProfile)
}
@Test
fun sdkSupportRange() {
assertThat(PixelProfile.isSdkSupported(device("Google", "shiba", sdk = 35))).isTrue()
assertThat(PixelProfile.isSdkSupported(device("Google", "shiba", sdk = 34))).isFalse()
}
}