* perf: FFT/sparse fast path for masked TM_CCOEFF_NORMED
* perf: optimize masked ccoeff matching
* perf: tune masked ccoeff dispatcher and remove fixed overhead
- sync_cache_revision: atomic acquire/release double-check avoids
taking the mutex on every preproc_and_match call. No-mask hot path
no longer pays for the singleton at all (init hoisted into the
FFT/sparse branch).
- should_fallback_to_opencv: pick whichever path is empirically
faster instead of only catching dense-mask small-result cases:
* result < 1000 && K < 2000: keep sparse (OpenCV setup dominates)
* result < 12000 && K >= 500: fallback (covers GameStart 200x120/
58x58 and 138x130/105x105 dead zones)
* K*result < 25M: fallback (covers SmileyOnWork 880x80/20x21 and
similar long-thin / small-template FFT-loses cases)
Windows MSVC x64 (min-of-2, n=803/1402):
coverage: regressions 198 -> 50, mean 10.5ms -> 7.4ms (1.40x)
perf: regressions 86 -> 3, mean 854us -> 296us (2.90x)
Android arm64-v8a NEON (single run, n=803/1402):
coverage: regressions 0, mean 125ms -> 80ms (1.72x)
perf: regressions 1 (1.20x edge), mean 6.4ms -> 2.8ms (10.95x)
* perf(masked-matcher): merge 3-channel I² into a single FFT in σ_I² compute
σ_I²(x,y) = Σ_c [(M ⋆ I_c²) - (M ⋆ I_c)² / N]
= Σ_c (M ⋆ I_c²) - (1/N) Σ_c (M ⋆ I_c)²
↑ this term is linear in I_c², so by convolution linearity
Σ_c (M ⋆ I_c²) = M ⋆ Σ_c I_c².
Precompute I_sq_sum = Σ_c I_c² in spatial domain and do a single
FFT + single IFFT instead of three. The second term Σ_c (M ⋆ I_c)²
still requires per-channel computation (squaring is non-linear).
Net: -2 FFTs and -2 IFFTs per match() call (15 → 11 transforms).
Validated min-of-3 runs on the 10 largest FFT-path cases per platform:
windows: 8/10 cases -22%, 2 cases (66x41 templ) unchanged
android: 8/10 cases -22%, 2 cases (66x41 templ) unchanged
The two unchanged cases have very small templates where FFT is not
the bottleneck (cvtColor / convertTo / split dominate). Correctness
preserved across 1800 iterations × 10 cases on both platforms.
* fix: 测试代码忘记删除了
* fix: make TemplResource::m_revision atomic
* chore: 调一下匹配参数
* feat: 在日志中标记匹配路径(优化实现 vs cv::matchTemplate)
* feat: add android controller support
* feat: add android compile options and add core static options
* fix: add __ANDROID__ macro for Android platform
* fix: move switch break into macro conditional block
* ci: add Android CMake presets (arm64, x64)
* fix: add missing Android TouchMode handling
* fix: remove unnecessary pre-check in android
* fix: restore unnecessary modifications
* fix: unified use __ANDROID__
* refactor: use interpolate_swipe_with_pause in AndroidController
* feat: add Android crash logcat output and native backtrace
* feat: only copy once from external lib screencap
* feat: add Android JNI AttachThread/DetachThread to working_proc
* fix: break control in switch
* fix: update click interval & swipe interval
* ci: restore Android build job with MaaFramework download
* fix: remove thread attach
* ci: temporarily remove MaaAndroidNativeControlUnit.so
* feat(android-ctrl): SWIPE_WITH_PAUSE 由 InstanceOption DeploymentWithPause 控制
* feat: SWIPE_WITH_PAUSE 默认启用
* feat: add android compile options and add core static options
* feat: use maafw controll unit
* fix: minor adjustments
* refactor: adapt maafw android lib
* fix: remove screencap when connect
* chore: change maafw lib use
* feat: adapt maafw control unit click & click_key
* fix: address critical issues in Android native controller
- Restore InstanceOptionKey::ClientType case in set_instance_option,
which was accidentally removed and broke client type setting on all platforms
- Enable libMaaAndroidNativeControlUnit.so copy step in CI (was commented out),
so Android artifacts actually include the required control unit library
- Fail connect() early when screen_resolution is missing or invalid in config,
preventing silent {0,0} resolution that would break swipe and screencap
- Check touch_down() return value in swipe() and abort on failure
* fix: correct bounds_check off-by-one and extract KEYCODE_ESCAPE constant
- bounds_check used <= which allowed coordinates equal to screen width/height
(off-screen); use < to match the valid range [0, dimension-1]
- Extract magic number 111 into KEYCODE_ESCAPE constexpr in press_esc()
* fix: avoid heap allocation in noexcept terminate/signal handlers
format_signal_reason was returning std::string and using std::format in
its default branch. Called from noexcept custom_terminate_handler before
the outer try block, any allocation failure would throw std::bad_alloc,
triggering recursive std::terminate and aborting crash reporting.
- Change return type to const char* noexcept, returning string literals
- Replace std::format("Signal {}", sig) with "Unknown Signal" (only the
four registered signals are ever passed, so this branch is unreachable)
- Change signal_info in custom_terminate_handler from std::string to
const char*, eliminating all allocations on the pre-try path
* fix: suppress unused-variable warning for signal_reason on non-Android