Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ android {
minSdk = 24
targetSdk = 36
versionCode = 1
versionName = "1.0"
versionName = "1.0.1"

testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"

Expand Down Expand Up @@ -123,7 +123,7 @@ dependencies {
implementation(libs.litert.support.api)

// Gson for JSON parsing
implementation("com.google.code.gson:gson:2.10.1")
implementation("com.google.code.gson:gson:2.13.2")
implementation(libs.okhttp)

// ML Kit Text Recognition (OCR)
Expand Down
9 changes: 9 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,15 @@
<property android:name="android.app.property.FOREGROUND_SERVICE_TYPE" android:value="specialUse" />
</service>

<!-- Hardware Remote Foreground Service (keeps WiFi alive during screen-off) -->
<service
android:name=".features.cross_device_automation.engine.HardwareRemoteForegroundService"
android:enabled="true"
android:exported="false"
android:foregroundServiceType="specialUse">
<property android:name="android.app.property.FOREGROUND_SERVICE_TYPE" android:value="specialUse" />
</service>

<service
android:name=".features.gesture_recording_playback.overlay.AutomationService"
android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,11 +66,11 @@ val ALL_CATEGORIES = listOf(
accentColor = AccentBlue
),
CategorySummary(
category = LogCategory.EMERGENCY_TRIGGER,
displayName = "Emergency Trigger",
description = "Panic gestures & alerts",
icon = Icons.Default.Warning,
accentColor = AccentRed
category = LogCategory.SEMANTIC_AUTOMATION,
displayName = "Semantic Automation",
description = "Context-aware AI automation",
icon = Icons.Default.AutoAwesome,
accentColor = AccentPurple
),
CategorySummary(
category = LogCategory.CROSS_DEVICE_SYNC,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ class CrossDeviceAutomationManager(private val context: Context) : NetworkingMan
try {
val powerManager = context.getSystemService(Context.POWER_SERVICE) as android.os.PowerManager
wakeLock = powerManager.newWakeLock(android.os.PowerManager.PARTIAL_WAKE_LOCK, "AutomationCompanion::CrossDeviceWakeLock")
wakeLock?.acquire(10 * 60 * 1000L /*10 minutes timeout just in case*/)
wakeLock?.acquire() // No timeout — released explicitly in releaseLocks()/stop()

val wifiManager = context.applicationContext.getSystemService(Context.WIFI_SERVICE) as android.net.wifi.WifiManager
wifiLock = wifiManager.createWifiLock(android.net.wifi.WifiManager.WIFI_MODE_FULL_HIGH_PERF, "AutomationCompanion::CrossDeviceWifiLock")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,17 @@ import com.autonion.automationcompanion.features.cross_device_automation.domain.
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.update

class InMemoryDeviceRepository : DeviceRepository {
private val _devices = MutableStateFlow<List<Device>>(emptyList())

override fun getAllDevices(): Flow<List<Device>> = _devices.asStateFlow()

override fun getSelectedDevices(): Flow<List<Device>> =
_devices.map { list -> list.filter { it.isSelected } }

override suspend fun getDeviceById(id: String): Device? {
return _devices.value.find { it.id == id }
}
Expand All @@ -20,11 +24,19 @@ class InMemoryDeviceRepository : DeviceRepository {
_devices.update { currentList ->
val existingIndex = currentList.indexOfFirst { it.id == device.id }
if (existingIndex >= 0) {
val existing = currentList[existingIndex]
val mutableList = currentList.toMutableList()
mutableList[existingIndex] = device
// Preserve isSelected from existing device unless explicitly changed
mutableList[existingIndex] = device.copy(isSelected = existing.isSelected)
mutableList
} else {
currentList + device
// Auto-select if this is the first and only device
val updatedDevice = if (currentList.isEmpty()) {
device.copy(isSelected = true)
} else {
device
}
currentList + updatedDevice
}
}
}
Expand All @@ -34,4 +46,16 @@ class InMemoryDeviceRepository : DeviceRepository {
currentList.filterNot { it.id == id }
}
}

override suspend fun toggleDeviceSelection(id: String) {
_devices.update { currentList ->
currentList.map { device ->
if (device.id == id) {
device.copy(isSelected = !device.isSelected)
} else {
device
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,6 @@ data class Device(
val port: Int,
val status: DeviceStatus = DeviceStatus.UNKNOWN,
val lastSeen: Long = System.currentTimeMillis(),
val capabilities: List<String> = emptyList()
val capabilities: List<String> = emptyList(),
val isSelected: Boolean = false
)
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ import kotlinx.coroutines.flow.Flow

interface DeviceRepository {
fun getAllDevices(): Flow<List<Device>>
fun getSelectedDevices(): Flow<List<Device>>
suspend fun getDeviceById(id: String): Device?
suspend fun addOrUpdateDevice(device: Device)
suspend fun removeDevice(id: String)
suspend fun toggleDeviceSelection(id: String)
}
Loading
Loading