feat: implement ADB wrapper and device management backend

Adds full ADB client, device manager, static DeviceInfo fetcher, and
live DeviceLiveStats poller. Exposes ListDevices, ConnectDevice,
DisconnectDevice, GetDeviceInfo, GetDeviceLiveStats as Wails-bound
methods with a 1s devices:changed event loop. Bundles ADB binary
infrastructure via //go:embed all:bin with runtime fallback chain.
This commit is contained in:
achmad
2026-05-06 14:51:34 +07:00
parent 6a53f87e03
commit 14935db63e
14 changed files with 610 additions and 14 deletions
+80 -9
View File
@@ -2,26 +2,97 @@ package main
import (
"context"
"fmt"
"time"
"git.achmad.dev/admin/droidscope/backend/adb"
"git.achmad.dev/admin/droidscope/backend/device"
"github.com/wailsapp/wails/v2/pkg/runtime"
"git.achmad.dev/admin/droidscope/desktop/internal/adbembed"
)
// App struct
type App struct {
ctx context.Context
ctx context.Context
deviceManager *device.Manager
}
// NewApp creates a new App application struct
func NewApp() *App {
return &App{}
}
// startup is called when the app starts. The context is saved
// so we can call the runtime methods
func (a *App) startup(ctx context.Context) {
a.ctx = ctx
adbPath, err := adbembed.Resolve()
if err != nil {
runtime.LogErrorf(ctx, "ADB not found: %v", err)
return
}
runtime.LogInfof(ctx, "Using ADB at: %s", adbPath)
client := adb.New(adbPath)
if err := client.StartServer(ctx); err != nil {
runtime.LogWarningf(ctx, "ADB start-server: %v", err)
}
a.deviceManager = device.NewManager(client)
go a.pollDevices()
}
// Greet returns a greeting for the given name
func (a *App) Greet(name string) string {
return fmt.Sprintf("Hello %s, It's show time!", name)
func (a *App) pollDevices() {
ticker := time.NewTicker(1 * time.Second)
defer ticker.Stop()
for {
select {
case <-a.ctx.Done():
return
case <-ticker.C:
devices, err := a.deviceManager.List(a.ctx)
if err != nil {
runtime.LogWarningf(a.ctx, "device poll: %v", err)
continue
}
runtime.EventsEmit(a.ctx, "devices:changed", devices)
}
}
}
// ListDevices returns the current list of connected devices.
func (a *App) ListDevices() ([]device.Device, error) {
if a.deviceManager == nil {
return nil, nil
}
return a.deviceManager.List(a.ctx)
}
// ConnectDevice connects to a wireless ADB device by address (e.g. "192.168.1.5:5555").
func (a *App) ConnectDevice(address string) error {
if a.deviceManager == nil {
return nil
}
return a.deviceManager.Connect(a.ctx, address)
}
// DisconnectDevice disconnects a device by its serial ID.
func (a *App) DisconnectDevice(deviceID string) error {
if a.deviceManager == nil {
return nil
}
return a.deviceManager.Disconnect(a.ctx, deviceID)
}
// GetDeviceInfo fetches static device information for the given device ID.
func (a *App) GetDeviceInfo(deviceID string) (*device.DeviceInfo, error) {
if a.deviceManager == nil {
return nil, nil
}
return a.deviceManager.Info(a.ctx, deviceID)
}
// GetDeviceLiveStats fetches dynamic device stats (RAM, battery, thermal, storage, IP).
func (a *App) GetDeviceLiveStats(deviceID string) (*device.DeviceLiveStats, error) {
if a.deviceManager == nil {
return nil, nil
}
return a.deviceManager.LiveStats(a.ctx, deviceID)
}