Skip to content

Latest commit

 

History

History
428 lines (334 loc) · 13.4 KB

File metadata and controls

428 lines (334 loc) · 13.4 KB

Phase 2 Implementation: Code-Level Guide

This document explains exactly how Phase 2 was implemented with specific line numbers and code snippets.


Overview

Phase 2 adds real-time notification monitoring to detect phishing URLs in notifications from any app (Gmail, WhatsApp, SMS, etc.).


File 1: NotificationMonitorService.kt

Location: NotificationMonitorService.kt
Purpose: Core service that monitors all system notifications

Key Components

1. Service Setup (Lines 1-47)

// Line 6: Import PhishingRepository interface
import com.droid.cybershield.domain.repository.PhishingRepository

// Line 7: Enable Hilt dependency injection
import dagger.hilt.android.AndroidEntryPoint

// Line 28: Mark service for Hilt injection
@AndroidEntryPoint
class NotificationMonitorService : NotificationListenerService() {

    // Lines 44-45: Inject PhishingRepository from Phase 1
    @Inject
    lateinit var phishingRepository: PhishingRepository
    
    // Line 47: Create coroutine scope for async operations
    private val scope = CoroutineScope(Dispatchers.Default + SupervisorJob())
}

What this does: Sets up the service with dependency injection to access Phase 1's phishing detection system.


2. Notification Detection (Lines 57-109)

// Lines 57-58: Called when ANY notification arrives
override fun onNotificationPosted(sbn: StatusBarNotification) {
    super.onNotificationPosted(sbn)

    // Lines 69-75: Ignore CyberShield's own notifications
    val packageName = sbn.packageName
    if (packageName == this.packageName) {
        Log.d(TAG, "⏭️ Skipping: Self notification (CyberShield)")
        return
    }

    // Lines 77-83: Extract text from notification
    val notificationText = extractNotificationText(sbn)
    if (notificationText.isNullOrEmpty()) {
        Log.d(TAG, "⏭️ Skipping: No text content in notification")
        return
    }

    // Lines 87-93: Find URLs in the text
    val urls = extractUrls(notificationText)
    if (urls.isEmpty()) {
        Log.d(TAG, "⏭️ Skipping: No URLs found in notification")
        return
    }

    // Lines 100-105: Check each URL for phishing
    scope.launch {
        urls.forEach { url ->
            checkUrlAndAlert(url, packageName, sbn.id)
        }
    }
}

What this does: Listens for notifications, extracts text, finds URLs, and triggers phishing checks.


3. Text Extraction (Lines 132-151)

// Lines 132-151: Extract text from notification
private fun extractNotificationText(sbn: StatusBarNotification): String? {
    return try {
        val extras = sbn.notification.extras
        
        // Line 135: Get notification title
        val title = extras.getCharSequence("android.title")?.toString() ?: ""
        
        // Line 136: Get notification text
        val text = extras.getCharSequence("android.text")?.toString() ?: ""
        
        // Line 137: Get expanded text
        val bigText = extras.getCharSequence("android.bigText")?.toString() ?: ""

        // Line 139: Combine all text fields
        val combined = "$title $text $bigText".trim()
        
        if (combined.isNotEmpty()) combined else null
    } catch (e: Exception) {
        Log.e(TAG, "Error extracting notification text", e)
        null
    }
}

What this does: Extracts all text content from notification (title, body, expanded text).


4. URL Extraction (Lines 157-170)

// Lines 38-41: Regex pattern to find URLs
private val URL_PATTERN = Regex(
    """https?://[^\s<>"']+""",
    RegexOption.IGNORE_CASE
)

// Lines 157-170: Extract URLs from text
private fun extractUrls(text: String): List<String> {
    return try {
        URL_PATTERN.findAll(text)
            .map { matchResult ->
                // Line 162: Clean trailing punctuation
                matchResult.value.trimEnd('.', ',', ')', ']', '}', '!', '?', ';')
            }
            .distinct()  // Line 164: Remove duplicates
            .toList()
    } catch (e: Exception) {
        Log.e(TAG, "Error extracting URLs", e)
        emptyList()
    }
}

What this does: Uses regex to find all HTTP/HTTPS URLs and cleans them.


5. Phishing Check (Lines 179-226)

// Lines 179-226: Check URL and alert if phishing
private suspend fun checkUrlAndAlert(
    url: String,
    packageName: String,
    notificationId: Int
) {
    try {
        // Lines 192-195: Call Phase 1 phishing detection
        val result = phishingRepository.checkUrl(
            url = url,
            source = "notification:$packageName"
        )

        // Lines 206-216: Alert if phishing with high confidence
        if (result.isPhishing && result.confidence > ALERT_THRESHOLD) {
            Log.w(TAG, "⚠️ PHISHING DETECTED IN NOTIFICATION!")
            Log.w(TAG, "URL: $url")
            Log.w(TAG, "Source: $packageName")
            Log.w(TAG, "Confidence: ${(result.confidence * 100).toInt()}%")
            
            // Line 216: Show alert notification
            showPhishingAlert(url, result.confidence, packageName, notificationId)
        }
    } catch (e: Exception) {
        Log.e(TAG, "❌ Error checking URL: $url", e)
    }
}

What this does:

  • Line 192-195: Calls PhishingRepository.checkUrl() from Phase 1
  • Line 206: Checks if confidence > 70% (ALERT_THRESHOLD)
  • Line 216: Shows alert notification to user

6. Alert Display (Lines 236-263)

// Lines 236-263: Show phishing alert notification
private fun showPhishingAlert(
    url: String,
    confidence: Float,
    sourceApp: String,
    notificationId: Int
) {
    try {
        // Lines 244-249: Get human-readable app name
        val appName = try {
            val appInfo = packageManager.getApplicationInfo(sourceApp, 0)
            packageManager.getApplicationLabel(appInfo).toString()
        } catch (e: Exception) {
            sourceApp
        }

        // Lines 252-257: Create and show alert notification
        val notificationHelper = com.droid.cybershield.presentation.notification.NotificationHelper(this)
        notificationHelper.showPhishingAlertNotification(
            url = url,
            confidence = confidence,
            sourceApp = appName
        )
    } catch (e: Exception) {
        Log.e(TAG, "Error showing phishing alert", e)
    }
}

What this does: Gets app name and delegates to NotificationHelper to show alert.


File 2: NotificationHelper.kt

Location: NotificationHelper.kt
Purpose: Creates and displays alert notifications

Key Components

1. Notification Channels (Lines 30-37, 196-229)

// Lines 30-33: Define phishing alert channel
private const val PHISHING_CHANNEL_ID = "cybershield_phishing_alerts"
private const val PHISHING_CHANNEL_NAME = "Phishing Alerts"
private const val PHISHING_CHANNEL_DESCRIPTION = "Critical alerts for phishing URLs detected in notifications"

// Lines 214-227: Create high-priority channel
val phishingAlertsChannel = NotificationChannel(
    PHISHING_CHANNEL_ID,
    PHISHING_CHANNEL_NAME,
    NotificationManager.IMPORTANCE_HIGH  // Line 218: High priority
).apply {
    description = PHISHING_CHANNEL_DESCRIPTION
    enableLights(true)
    lightColor = 0xFFD32F2F.toInt()  // Line 222: Red color
    enableVibration(true)
    setShowBadge(true)
    setBypassDnd(true)  // Line 225: Bypass Do Not Disturb
}

What this does: Creates a high-priority notification channel for phishing alerts.


2. Phishing Alert Notification (Lines 122-191)

// Lines 122-191: Show phishing alert
fun showPhishingAlertNotification(url: String, confidence: Float, sourceApp: String) {
    
    // Lines 130-139: Check notification permission (Android 13+)
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
        val hasPermission = context.checkSelfPermission(
            android.Manifest.permission.POST_NOTIFICATIONS
        ) == android.content.pm.PackageManager.PERMISSION_GRANTED
        
        if (!hasPermission) {
            Log.w(TAG, "POST_NOTIFICATIONS permission not granted!")
            return
        }
    }

    // Lines 141-153: Create intent to open Phishing Prevention page
    val intent = Intent(context, MainActivity::class.java).apply {
        flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP
        putExtra("navigate_to", "phishing")
        putExtra("detected_url", url)
    }

    // Lines 159-162: Format display data
    val confidencePercent = (confidence * 100).toInt()
    val displayUrl = if (url.length > 50) url.take(47) + "..." else url

    // Lines 165-178: Build notification
    val notification = NotificationCompat.Builder(context, PHISHING_CHANNEL_ID)
        .setSmallIcon(R.drawable.logo)
        .setContentTitle("⚠️ Phishing Alert")
        .setContentText("Suspicious link detected in $sourceApp")
        .setStyle(NotificationCompat.BigTextStyle()
            .bigText("⚠️ Phishing link detected in $sourceApp\n\nURL: $displayUrl\nConfidence: $confidencePercent%\n\nDo not click this link!"))
        .setPriority(NotificationCompat.PRIORITY_HIGH)  // Line 171: High priority
        .setCategory(NotificationCompat.CATEGORY_ALARM)  // Line 172: Alarm category
        .setColor(0xFFD32F2F.toInt())  // Line 177: Red color
        .setVibrate(longArrayOf(0, 500, 200, 500))  // Line 176: Aggressive vibration
        .build()

    // Lines 180-183: Show notification
    val notificationId = generateNotificationId()
    NotificationManagerCompat.from(context).notify(notificationId, notification)
}

What this does: Creates and displays a high-priority red alert notification with vibration.


File 3: AndroidManifest.xml

Location: AndroidManifest.xml
Purpose: Register the notification listener service

Service Registration (Lines 97-111)

<!-- Lines 97-111: Register NotificationListenerService -->
<service
    android:name=".service.NotificationMonitorService"
    android:label="CyberShield Notification Monitor"
    android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE"
    android:exported="true">
    <intent-filter>
        <action android:name="android.service.notification.NotificationListenerService" />
    </intent-filter>
</service>

What this does:

  • Line 104: Sets service name
  • Line 106: Requires system permission to bind notification listener
  • Line 107: Allows system to bind to service
  • Line 109: Declares service as NotificationListenerService

How Phase 2 Integrates with Phase 1

Integration Point: PhishingRepository

NotificationMonitorService (Phase 2)
    ↓ Line 192-195
phishingRepository.checkUrl(url, source)
    ↓
PhishingRepositoryImpl (Phase 1)
    ↓ Lines 25-168
├── Whitelist check (Lines 31-54)
├── Google Safe Browsing (Lines 56-83)
├── ONNX ML Model (Line 86)
├── Adaptive threshold (Line 91)
└── Smart decision (Lines 94-112)

Phase 2 does NOT modify Phase 1 code - it only consumes the existing checkUrl() API.


Critical Lines Summary

File Lines Purpose
NotificationMonitorService.kt 44-45 Inject PhishingRepository
57-109 Detect notifications and extract URLs
132-151 Extract notification text
157-170 Extract URLs with regex
192-195 Call Phase 1 phishing check
206-216 Alert if phishing detected
236-263 Show alert notification
NotificationHelper.kt 122-191 Create phishing alert notification
165-178 Build high-priority notification
214-227 Create notification channel
AndroidManifest.xml 103-111 Register NotificationListenerService

Execution Flow

1. Notification arrives → onNotificationPosted() [Line 57]
2. Extract text → extractNotificationText() [Line 78]
3. Find URLs → extractUrls() [Line 88]
4. For each URL → checkUrlAndAlert() [Line 103]
5. Check phishing → phishingRepository.checkUrl() [Line 192]
6. If phishing → showPhishingAlert() [Line 216]
7. Display alert → NotificationHelper.showPhishingAlertNotification() [Line 253]

Key Design Decisions

1. Why Hilt Injection? (Lines 44-45)

  • Reuses existing PhishingRepository singleton from Phase 1
  • No need to recreate dependencies
  • Clean separation of concerns

2. Why Coroutines? (Line 101)

  • Non-blocking async processing
  • Prevents ANR (Application Not Responding)
  • Can check multiple URLs in parallel

3. Why 70% Threshold? (Line 35)

private const val ALERT_THRESHOLD = 0.7f
  • Balances security vs. user annoyance
  • Prevents alert fatigue from low-confidence detections

4. Why Separate Notification Channel? (Lines 214-227)

  • High priority (IMPORTANCE_HIGH)
  • Can bypass Do Not Disturb
  • User can customize per channel

Summary

Total Implementation: 3 files, ~500 lines of code

Core Logic:

  • NotificationMonitorService listens for notifications
  • Extracts URLs using regex
  • Calls Phase 1's PhishingRepository.checkUrl()
  • Shows high-priority alert if phishing detected

Integration: Phase 2 is a pure extension that consumes Phase 1's API without modifying it.