diff --git a/internal/memory/modify/freeze.go b/internal/memory/modify/freeze.go index 1dbe85e..b8bc463 100644 --- a/internal/memory/modify/freeze.go +++ b/internal/memory/modify/freeze.go @@ -9,7 +9,7 @@ import ( "memodroid/internal/memory/search" ) -const freezeInterval = 100 * time.Millisecond +const defaultFreezeInterval = 100 * time.Millisecond type freezeEntry struct { drv driver.Driver @@ -21,15 +21,33 @@ type freezeEntry struct { // Freezer manages a set of frozen addresses. type Freezer struct { - mu sync.Mutex - entries map[uintptr]*freezeEntry + mu sync.Mutex + entries map[uintptr]*freezeEntry + interval time.Duration } func NewFreezer() *Freezer { - return &Freezer{entries: make(map[uintptr]*freezeEntry)} + return &Freezer{ + entries: make(map[uintptr]*freezeEntry), + interval: defaultFreezeInterval, + } +} + +// SetInterval changes the freeze write interval for newly frozen addresses. +func (f *Freezer) SetInterval(d time.Duration) { + f.mu.Lock() + defer f.mu.Unlock() + f.interval = d +} + +// GetInterval returns the current freeze interval. +func (f *Freezer) GetInterval() time.Duration { + f.mu.Lock() + defer f.mu.Unlock() + return f.interval } -// Freeze starts a goroutine that repeatedly writes value to addr every 100ms. +// Freeze starts a goroutine that repeatedly writes value to addr at the configured interval. // Returns an error if addr is already frozen. func (f *Freezer) Freeze(drv driver.Driver, pid int, addr uintptr, value []byte) error { f.mu.Lock() @@ -42,11 +60,12 @@ func (f *Freezer) Freeze(drv driver.Driver, pid int, addr uintptr, value []byte) val := make([]byte, len(value)) copy(val, value) + iv := f.interval e := &freezeEntry{drv: drv, pid: pid, addr: addr, value: val, stop: make(chan struct{})} f.entries[addr] = e go func() { - ticker := time.NewTicker(freezeInterval) + ticker := time.NewTicker(iv) defer ticker.Stop() for { select { diff --git a/internal/server/handlers.go b/internal/server/handlers.go index 0fe6492..b65c5f5 100644 --- a/internal/server/handlers.go +++ b/internal/server/handlers.go @@ -5,6 +5,7 @@ import ( "fmt" "net/http" "strconv" + "time" "memodroid/internal/app" "memodroid/internal/driver/adb" @@ -522,6 +523,22 @@ func (h *handler) memoryFreeze(w http.ResponseWriter, r *http.Request) { writeJSON(w, map[string]any{"ok": true}) } +func (h *handler) freezeSetInterval(w http.ResponseWriter, r *http.Request) { + var req struct { + IntervalMs int `json:"interval_ms"` + } + if err := decode(r, &req); err != nil { + writeError(w, 400, err.Error()) + return + } + if req.IntervalMs <= 0 { + writeError(w, 400, "interval_ms must be positive") + return + } + h.state.Freezer.SetInterval(time.Duration(req.IntervalMs) * time.Millisecond) + writeJSON(w, map[string]any{"ok": true, "interval_ms": req.IntervalMs}) +} + func (h *handler) memoryFreezeAll(w http.ResponseWriter, _ *http.Request) { sess := h.state.GetSession() if sess == nil || !sess.HasCandidates() { diff --git a/internal/server/server.go b/internal/server/server.go index a35a594..6415d98 100644 --- a/internal/server/server.go +++ b/internal/server/server.go @@ -76,6 +76,7 @@ func Start(addr string, state *app.State, d *adb.ADB) error { mux.HandleFunc("/api/memory/modify", h.memoryModify) mux.HandleFunc("/api/memory/undo", h.memoryUndo) mux.HandleFunc("/api/memory/freeze", h.memoryFreeze) + mux.HandleFunc("/api/memory/freeze-interval", h.freezeSetInterval) mux.HandleFunc("/api/memory/freeze-all", h.memoryFreezeAll) mux.HandleFunc("/api/memory/unfreeze", h.memoryUnfreeze) mux.HandleFunc("/api/memory/frozen", h.memoryFrozen) diff --git a/internal/server/static/index.html b/internal/server/static/index.html index 0e10775..ec71cd5 100644 --- a/internal/server/static/index.html +++ b/internal/server/static/index.html @@ -391,6 +391,10 @@ +