From ee2eade791f30965718fe648cf5c8d5367681a00 Mon Sep 17 00:00:00 2001
From: stcb <21@stcb.cc>
Date: Sun, 2 Mar 2025 22:29:02 +0200
Subject: [PATCH 01/36] Init
---
protocol_prototype/main.py | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
create mode 100644 protocol_prototype/main.py
diff --git a/protocol_prototype/main.py b/protocol_prototype/main.py
new file mode 100644
index 0000000..5596b44
--- /dev/null
+++ b/protocol_prototype/main.py
@@ -0,0 +1,16 @@
+# This is a sample Python script.
+
+# Press Shift+F10 to execute it or replace it with your code.
+# Press Double Shift to search everywhere for classes, files, tool windows, actions, and settings.
+
+
+def print_hi(name):
+ # Use a breakpoint in the code line below to debug your script.
+ print(f'Hi, {name}') # Press Ctrl+F8 to toggle the breakpoint.
+
+
+# Press the green button in the gutter to run the script.
+if __name__ == '__main__':
+ print_hi('PyCharm')
+
+# See PyCharm help at https://www.jetbrains.com/help/pycharm/
--
2.45.2
From b1f95a85e942a178b79fa87a032fdfb6a0e6e32e Mon Sep 17 00:00:00 2001
From: stcb <21@stcb.cc>
Date: Sun, 2 Mar 2025 23:20:59 +0200
Subject: [PATCH 02/36] Drawio Handshake logic
---
protocol_prototype/IcingProtocol.drawio | 262 ++++++++++++++++++++++++
1 file changed, 262 insertions(+)
create mode 100644 protocol_prototype/IcingProtocol.drawio
diff --git a/protocol_prototype/IcingProtocol.drawio b/protocol_prototype/IcingProtocol.drawio
new file mode 100644
index 0000000..06c3cb0
--- /dev/null
+++ b/protocol_prototype/IcingProtocol.drawio
@@ -0,0 +1,262 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
--
2.45.2
From 7c7a4f28f4446224efb838132d58e0c94a649ae5 Mon Sep 17 00:00:00 2001
From: Florian Griffon
Date: Tue, 4 Mar 2025 14:20:56 +0100
Subject: [PATCH 03/36] feat: call page UI
---
dialer/android/.gitignore | 1 +
.../android/app/src/main/AndroidManifest.xml | 61 ++--
.../icing/dialer/activities/MainActivity.kt | 96 ++++--
.../dialer/services/CallConnectionService.kt | 53 +++
.../com/icing/dialer/services/CallService.kt | 51 ++-
dialer/lib/features/call/call_page.dart | 324 ++++++++++++++++++
.../lib/features/composition/composition.dart | 2 +-
.../contacts/widgets/contact_modal.dart | 2 +-
dialer/lib/services/call_service.dart | 38 +-
9 files changed, 550 insertions(+), 78 deletions(-)
create mode 100644 dialer/android/app/src/main/kotlin/com/icing/dialer/services/CallConnectionService.kt
create mode 100644 dialer/lib/features/call/call_page.dart
diff --git a/dialer/android/.gitignore b/dialer/android/.gitignore
index e6d71b3..ebc61c7 100644
--- a/dialer/android/.gitignore
+++ b/dialer/android/.gitignore
@@ -7,6 +7,7 @@ gradle-wrapper.jar
/gradle.properties
GeneratedPluginRegistrant.java
gradle.properties
+.cxx
# Remember to never publicly share your keystore.
# See https://flutter.dev/to/reference-keystore
diff --git a/dialer/android/app/src/main/AndroidManifest.xml b/dialer/android/app/src/main/AndroidManifest.xml
index e0de6a4..cc51efb 100644
--- a/dialer/android/app/src/main/AndroidManifest.xml
+++ b/dialer/android/app/src/main/AndroidManifest.xml
@@ -1,13 +1,15 @@
-
-
+
+
-
-
-
+
+
+
+
+
-
+ android:name="io.flutter.embedding.android.NormalTheme"
+ android:resource="@style/NormalTheme" />
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
-
-
+
+
-
+
\ No newline at end of file
diff --git a/dialer/android/app/src/main/kotlin/com/icing/dialer/activities/MainActivity.kt b/dialer/android/app/src/main/kotlin/com/icing/dialer/activities/MainActivity.kt
index a2397d6..53f93d7 100644
--- a/dialer/android/app/src/main/kotlin/com/icing/dialer/activities/MainActivity.kt
+++ b/dialer/android/app/src/main/kotlin/com/icing/dialer/activities/MainActivity.kt
@@ -3,52 +3,77 @@ package com.icing.dialer.activities
import android.database.Cursor
import android.os.Bundle
import android.provider.CallLog
+import android.telecom.TelecomManager
+import android.telecom.PhoneAccountHandle
+import android.telecom.PhoneAccount
+import android.content.Intent
+import android.content.ComponentName
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
import com.icing.dialer.KeystoreHelper
import com.icing.dialer.services.CallService
+import com.icing.dialer.services.CallConnectionService
-class MainActivity: FlutterActivity() {
- // Existing channel for keystore operations.
+class MainActivity : FlutterActivity() {
private val KEYSTORE_CHANNEL = "com.example.keystore"
- // New channel for call log access.
private val CALLLOG_CHANNEL = "com.example.calllog"
-
private val CALL_CHANNEL = "call_service"
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ registerPhoneAccount()
+ checkAndRequestDefaultDialer()
+ }
+
+ private fun registerPhoneAccount() {
+ val telecomManager = getSystemService(TELECOM_SERVICE) as TelecomManager
+ val phoneAccountHandle = PhoneAccountHandle(
+ ComponentName(this, CallConnectionService::class.java),
+ "IcingDialerAccount"
+ )
+ val phoneAccount = PhoneAccount.builder(phoneAccountHandle, "Icing Dialer")
+ .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)
+ .build()
+ telecomManager.registerPhoneAccount(phoneAccount)
+ }
+
override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
- // Call service channel
MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CALL_CHANNEL).setMethodCallHandler { call, result ->
when (call.method) {
"makeGsmCall" -> {
val phoneNumber = call.argument("phoneNumber")
if (phoneNumber != null) {
- CallService.makeGsmCall(this, phoneNumber)
- result.success("Calling $phoneNumber")
+ val success = CallService.makeGsmCall(this, phoneNumber)
+ if (success) {
+ result.success(mapOf("status" to "calling", "phoneNumber" to phoneNumber))
+ } else {
+ result.error("CALL_FAILED", "Failed to initiate call", null)
+ }
} else {
result.error("INVALID_PHONE_NUMBER", "Phone number is required", null)
}
}
"hangUpCall" -> {
- CallService.hangUpCall(this)
- result.success("Call ended")
+ val success = CallService.hangUpCall(this)
+ if (success) {
+ result.success(mapOf("status" to "ended"))
+ } else {
+ result.error("HANGUP_FAILED", "Failed to end call", null)
+ }
}
else -> result.notImplemented()
}
}
- // Set up the keystore channel.
MethodChannel(flutterEngine.dartExecutor.binaryMessenger, KEYSTORE_CHANNEL)
.setMethodCallHandler { call, result ->
- // Delegate method calls to KeystoreHelper.
KeystoreHelper(call, result).handleMethodCall()
}
- // Set up the call log channel.
MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CALLLOG_CHANNEL)
.setMethodCallHandler { call, result ->
if (call.method == "getCallLogs") {
@@ -60,35 +85,38 @@ class MainActivity: FlutterActivity() {
}
}
- /**
- * Queries the Android call log and returns a list of maps.
- * Each map contains keys: "number", "type", "date", and "duration".
- */
+ private fun checkAndRequestDefaultDialer() {
+ val tm = getSystemService(TELECOM_SERVICE) as TelecomManager
+ tm.defaultDialerPackage?.let {
+ if (it != packageName) {
+ val intent = Intent(TelecomManager.ACTION_CHANGE_DEFAULT_DIALER)
+ .putExtra(TelecomManager.EXTRA_CHANGE_DEFAULT_DIALER_PACKAGE_NAME, packageName)
+ startActivity(intent)
+ }
+ }
+ }
+
private fun getCallLogs(): List