- Updated `.gitignore` and `.cursorignore` to exclude additional build artifacts and temporary files. - Enhanced `.cursorrules` with comprehensive AI guidelines and best practices. - Improved `.notes/directory_structure.md` to reflect the current project structure and module organization. - Updated `ARCHITECTURE.md` to include new insights on the system's modular design and privacy-first approach. - Refined `README.md` for clarity on project setup and usage instructions. - Added new entries in `.notes/meeting_notes.md` to document recent progress and decisions. - Ensured all changes align with the project's privacy and security standards.
97 lines
3.1 KiB
Kotlin
97 lines
3.1 KiB
Kotlin
package com.example.crkl.accessibility
|
|
|
|
import android.accessibilityservice.AccessibilityService
|
|
import android.accessibilityservice.GestureDescription
|
|
import android.graphics.PixelFormat
|
|
import android.util.Log
|
|
import android.view.Gravity
|
|
import android.view.MotionEvent
|
|
import android.view.View
|
|
import android.view.WindowManager
|
|
import android.view.accessibility.AccessibilityEvent
|
|
import kotlinx.coroutines.CoroutineScope
|
|
import kotlinx.coroutines.Dispatchers
|
|
import kotlinx.coroutines.SupervisorJob
|
|
import kotlinx.coroutines.cancel
|
|
|
|
/**
|
|
* Crkl Accessibility Service
|
|
*
|
|
* This service creates a system-wide overlay that captures user gestures
|
|
* and provides AI-powered assistance based on selected screen content.
|
|
*
|
|
* Privacy: All processing is local. No data leaves the device.
|
|
*/
|
|
class CrklAccessibilityService : AccessibilityService() {
|
|
|
|
private val TAG = "CrklAccessibilityService"
|
|
private var overlayView: OverlayView? = null
|
|
private var windowManager: WindowManager? = null
|
|
private val serviceScope = CoroutineScope(SupervisorJob() + Dispatchers.Main)
|
|
|
|
override fun onServiceConnected() {
|
|
super.onServiceConnected()
|
|
Log.d(TAG, "Crkl Accessibility Service connected")
|
|
|
|
// Initialize overlay
|
|
setupOverlay()
|
|
}
|
|
|
|
private fun setupOverlay() {
|
|
try {
|
|
windowManager = getSystemService(WINDOW_SERVICE) as WindowManager
|
|
|
|
// Create overlay view
|
|
overlayView = OverlayView(this)
|
|
|
|
// Configure window layout parameters for accessibility overlay
|
|
val params = WindowManager.LayoutParams(
|
|
WindowManager.LayoutParams.MATCH_PARENT,
|
|
WindowManager.LayoutParams.MATCH_PARENT,
|
|
WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY,
|
|
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE or
|
|
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL or
|
|
WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH,
|
|
PixelFormat.TRANSLUCENT
|
|
)
|
|
|
|
params.gravity = Gravity.TOP or Gravity.START
|
|
|
|
// Add overlay to window manager
|
|
windowManager?.addView(overlayView, params)
|
|
|
|
Log.d(TAG, "Overlay created successfully")
|
|
} catch (e: Exception) {
|
|
Log.e(TAG, "Error creating overlay", e)
|
|
}
|
|
}
|
|
|
|
override fun onAccessibilityEvent(event: AccessibilityEvent?) {
|
|
// We'll use this later for content detection
|
|
// For now, just log events
|
|
event?.let {
|
|
if (it.eventType == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {
|
|
Log.d(TAG, "Window changed: ${it.packageName}")
|
|
}
|
|
}
|
|
}
|
|
|
|
override fun onInterrupt() {
|
|
Log.d(TAG, "Service interrupted")
|
|
}
|
|
|
|
override fun onDestroy() {
|
|
super.onDestroy()
|
|
Log.d(TAG, "Service destroyed")
|
|
|
|
// Clean up overlay
|
|
overlayView?.let {
|
|
windowManager?.removeView(it)
|
|
overlayView = null
|
|
}
|
|
|
|
serviceScope.cancel()
|
|
}
|
|
}
|
|
|