# Crkl - local Android build / test / emulator .PHONY: help doctor setup-mac setup-sdk setup-emulator build test install run stop logs clean uninstall \ devices check-device push-model model-status emulator emulator-stop emulator-list wait-emulator demo \ fixtures home back recents test-env integrations gog-bridge smoke UNAME_S := $(shell uname -s) GRADLEW := ./gradlew APK := app/build/outputs/apk/debug/app-debug.apk MODEL_DEVICE_PATH := /data/local/tmp/llm/crkl.task MODEL ?= AVD_NAME ?= CrklEmulator ifeq ($(UNAME_S),Darwin) BREW_PREFIX := $(shell brew --prefix 2>/dev/null || echo /opt/homebrew) JAVA_HOME ?= $(BREW_PREFIX)/opt/openjdk@17/libexec/openjdk.jdk/Contents/Home ifeq ($(wildcard $(JAVA_HOME)/bin/java),) JAVA_HOME := $(BREW_PREFIX)/opt/openjdk@17 endif ANDROID_HOME ?= $(BREW_PREFIX)/share/android-commandlinetools AVD_ABI := google_apis;arm64-v8a EMULATOR_GPU ?= host else JAVA_HOME ?= $(JAVA_HOME) ANDROID_HOME ?= $(HOME)/android-sdk AVD_ABI := google_apis;x86_64 EMULATOR_GPU ?= swiftshader_indirect endif export JAVA_HOME export ANDROID_HOME export ANDROID_SDK_ROOT := $(ANDROID_HOME) ADB := $(ANDROID_HOME)/platform-tools/adb EMULATOR := $(ANDROID_HOME)/emulator/emulator SDKMANAGER := $(shell \ if [ -x "$(ANDROID_HOME)/cmdline-tools/latest/bin/sdkmanager" ]; then \ echo "$(ANDROID_HOME)/cmdline-tools/latest/bin/sdkmanager"; \ elif command -v sdkmanager >/dev/null 2>&1; then command -v sdkmanager; \ else echo sdkmanager; fi) AVDMANAGER := $(shell \ if [ -x "$(ANDROID_HOME)/cmdline-tools/latest/bin/avdmanager" ]; then \ echo "$(ANDROID_HOME)/cmdline-tools/latest/bin/avdmanager"; \ elif command -v avdmanager >/dev/null 2>&1; then command -v avdmanager; \ else echo avdmanager; fi) PATH := $(JAVA_HOME)/bin:$(ANDROID_HOME)/platform-tools:$(ANDROID_HOME)/emulator:$(ANDROID_HOME)/cmdline-tools/latest/bin:$(PATH) export PATH help: ## Show available commands @echo "Crkl - Android Development Commands ($(UNAME_S))" @echo "" @echo "First-time on this Mac:" @echo " make setup-mac - brew JDK17 + Android SDK + AVD + local.properties" @echo " make doctor - verify toolchain" @echo " make test - run JVM unit tests (no phone needed)" @echo " make smoke - on-device: FAB → circle → extract → Copy" @echo " make test-env - ONE SHOT: fix chrome, install, open fixtures playground" @echo " make demo - build + boot emulator + install + launch" @echo " make fixtures - open email/image/video/audio test screen" @echo " make integrations - Vikunja token + email To + calendar permission" @echo "" @echo "Emulator chrome ◀○□ broken? test-env restarts with -grpc (fixes JWT lock)." @echo " Always click the phone screen once before using rim buttons." @echo "" @echo "Everyday:" @echo " make build / test / install / run / logs / stop" @echo " make emulator / emulator-stop / check-device" @echo " make push-model MODEL=/path/to/model.task" @echo "" @echo "ANDROID_HOME=$(ANDROID_HOME)" @echo "JAVA_HOME=$(JAVA_HOME)" @echo "" doctor: ## Verify JDK + Android SDK are usable here @echo "== Java ==" @java -version @echo "== ANDROID_HOME ==" @echo "$(ANDROID_HOME)" @test -d "$(ANDROID_HOME)/platforms/android-34" || (echo "Missing platforms;android-34 — run make setup-mac" && exit 1) @test -x "$(ADB)" || (echo "Missing adb — run make setup-mac" && exit 1) @$(ADB) version | head -1 @echo "== local.properties ==" @test -f local.properties && cat local.properties || (echo "missing local.properties — run make setup-mac" && exit 1) @echo "== AVD ==" @$(AVDMANAGER) list avd 2>/dev/null | sed -n '1,20p' || true @echo "✓ doctor OK" setup-mac: ## Install toolchain on macOS (Homebrew) @test "$(UNAME_S)" = "Darwin" || (echo "setup-mac is for macOS only; use setup-sdk on Linux" && exit 1) @echo "Installing OpenJDK 17 + Android command-line tools via Homebrew..." @brew list openjdk@17 >/dev/null 2>&1 || brew install openjdk@17 @brew list --cask android-commandlinetools >/dev/null 2>&1 || brew install --cask android-commandlinetools @$(MAKE) setup-sdk @$(MAKE) setup-emulator @$(MAKE) doctor setup-sdk: ## Install Android SDK packages + write local.properties @echo "Accepting SDK licenses + installing build packages..." @yes | $(SDKMANAGER) --licenses >/dev/null 2>&1 || true @$(SDKMANAGER) \ "platform-tools" \ "platforms;android-34" \ "build-tools;34.0.0" \ "emulator" \ "system-images;android-34;$(AVD_ABI)" @printf 'sdk.dir=%s\n' "$(ANDROID_HOME)" > local.properties @echo "✓ wrote local.properties" @echo "✓ Android SDK ready at $(ANDROID_HOME)" setup-emulator: ## Create CrklEmulator AVD @echo "Creating AVD $(AVD_NAME) ($(AVD_ABI))..." @echo no | $(AVDMANAGER) create avd -n "$(AVD_NAME)" \ -k "system-images;android-34;$(AVD_ABI)" \ -d "pixel_7" --force || true @echo "✓ AVD ready. Start with: make emulator" check-device: ## List connected devices/emulators @$(ADB) devices -l devices: check-device emulator: ## Start CrklEmulator (open gRPC so rim ◀○□ chrome works) @if $(ADB) devices 2>/dev/null | awk '/emulator-/{exit 0} END{exit 1}'; then \ echo "Emulator already connected:"; $(ADB) devices -l; \ echo "Tip: if rim buttons dead, run: make test-env (restarts with -grpc)"; \ else \ echo "Starting $(AVD_NAME) (gpu=$(EMULATOR_GPU), grpc open)..."; \ if [ "$(UNAME_S)" = "Darwin" ]; then \ chmod +x scripts/start-emulator-launchd.sh; \ bash scripts/start-emulator-launchd.sh; \ else \ nohup $(EMULATOR) -avd "$(AVD_NAME)" -memory 3072 -cores 4 -no-audio \ -gpu $(EMULATOR_GPU) -accel on -no-snapshot-load -no-metrics \ -grpc 8554 \ >/tmp/crkl-emulator.log 2>&1 & echo $$! > /tmp/crkl-emulator.pid; \ echo "Emulator pid $$(cat /tmp/crkl-emulator.pid) (log: /tmp/crkl-emulator.log)"; \ fi; \ fi @echo "Next: make wait-emulator && make install run OR make test-env" wait-emulator: ## Block until emulator is fully booted @bash scripts/wait-emulator.sh "$(ADB)" emulator-stop: ## Stop emulator @$(ADB) emu kill 2>/dev/null || true @pkill -f 'qemu-system' 2>/dev/null || true @rm -f /tmp/crkl-emulator.pid @echo "✓ emulator stop requested" emulator-list: ## List AVDs @$(AVDMANAGER) list avd test: ## Run JVM unit tests @echo "Running unit tests..." @$(GRADLEW) test --console=plain smoke: ## On-device smoke (FAB → circle → extract → Copy). Needs adb device. @chmod +x scripts/smoke-circle.sh @ADB="$(ADB)" bash scripts/smoke-circle.sh build: ## Build debug APK @echo "Building Crkl..." @$(GRADLEW) assembleDebug --console=plain install: build ## Install APK to connected device/emulator @$(ADB) wait-for-device @$(ADB) install -r $(APK) @echo "✓ Installed" run: ## Launch MainActivity @$(ADB) shell am start -n com.example.crkl/.MainActivity fixtures: ## Open test fixtures (email/image/video/audio) on device/emulator @$(ADB) wait-for-device @$(ADB) shell am start -n com.example.crkl/.fixtures.TestFixturesActivity @echo "✓ Fixtures open. Tap blue C on the phone (not rim ○)." test-env: ## ONE SHOT testing playground (chrome fix + install + fixtures) @chmod +x scripts/test-env.sh @bash scripts/test-env.sh integrations: ## Open Integrations settings on device/emulator @$(ADB) wait-for-device @$(ADB) shell am start -n com.example.crkl/.IntegrationsActivity gog-bridge: ## Optional lab: host gog → Gmail (emu uses http://10.0.2.2:8765) @chmod +x scripts/gog-bridge.py @python3 scripts/gog-bridge.py home: ## Emulator/device Home (adb) — fallback if rim buttons still fail @$(ADB) shell input keyevent KEYCODE_HOME back: ## Emulator/device Back (adb) @$(ADB) shell input keyevent KEYCODE_BACK recents: ## Emulator/device Recents (adb) @$(ADB) shell input keyevent KEYCODE_APP_SWITCH demo: build emulator wait-emulator install run ## Full local demo on emulator @echo "✓ demo launched. Enable Accessibility, then: make fixtures" @echo " Nav if side buttons fail: make home | make back | make recents" @echo " make logs" logs: ## Watch Crkl logcat @$(ADB) logcat -s CrklAccessibilityService:D OverlayView:D MediaPipeLocalLlm:D AssistEngine:D RegionContentExtractor:D AndroidRuntime:E stop: ## Force-stop app @$(ADB) shell am force-stop com.example.crkl clean: ## Clean Gradle build @$(GRADLEW) clean uninstall: ## Uninstall app @$(ADB) uninstall com.example.crkl push-model: check-device ## Push MediaPipe .task model @if [ -z "$(MODEL)" ]; then \ echo "Usage: make push-model MODEL=/path/to/gemma-3-1b-it-int4.task"; \ exit 1; \ fi @test -f "$(MODEL)" || (echo "Model file not found: $(MODEL)" && exit 1) @echo "Pushing $(MODEL) → $(MODEL_DEVICE_PATH)" @$(ADB) shell mkdir -p /data/local/tmp/llm @$(ADB) push "$(MODEL)" $(MODEL_DEVICE_PATH) @echo "✓ Model on device. Toggle Crkl accessibility service to reload." model-status: check-device ## Show on-device model file @$(ADB) shell "ls -lh $(MODEL_DEVICE_PATH) /data/local/tmp/llm/ 2>/dev/null || echo 'No model at $(MODEL_DEVICE_PATH)'"