Skip to content

Commit

Permalink
[Android][ICD]Implement Android ICD sending using buffer (project-chi…
Browse files Browse the repository at this point in the history
…p#33377)

* Implement Android ICD Queue sending

* Kotlin detect config
  • Loading branch information
joonhaengHeo authored May 9, 2024
1 parent 1dd9495 commit e079364
Show file tree
Hide file tree
Showing 3 changed files with 119 additions and 21 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ import com.google.chip.chiptool.ChipClient
import com.google.chip.chiptool.databinding.AddressUpdateFragmentBinding
import com.google.chip.chiptool.util.DeviceIdUtil
import kotlin.coroutines.resume
import kotlin.coroutines.resumeWithException
import kotlin.coroutines.suspendCoroutine
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
Expand Down Expand Up @@ -55,6 +54,8 @@ class AddressUpdateFragment : ICDCheckInCallback, Fragment() {

private val handler = Handler(Looper.getMainLooper())

private var externalICDCheckInMessageCallback: ICDCheckInMessageCallback? = null

override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
Expand Down Expand Up @@ -128,11 +129,12 @@ class AddressUpdateFragment : ICDCheckInCallback, Fragment() {
}

val cluster = ChipClusters.IcdManagementCluster(devicePtr, 0)
val duration = suspendCoroutine { cont ->
val retDuration = suspendCoroutine { cont ->
cluster.stayActiveRequest(
object : ChipClusters.IcdManagementCluster.StayActiveResponseCallback {
override fun onError(error: Exception) {
cont.resumeWithException(error)
Log.d(TAG, "onError", error)
cont.resume(0L)
}

override fun onSuccess(promisedActiveDuration: Long) {
Expand All @@ -143,12 +145,11 @@ class AddressUpdateFragment : ICDCheckInCallback, Fragment() {
)
}
isSendingStayActiveCommand = false
return duration
return retDuration
}

private fun updateUIForICDInteractionSwitch(isEnabled: Boolean): Boolean {
val isICD =
deviceController.icdClientInfo.firstOrNull { info -> info.peerNodeId == deviceId } != null
val isICD = isICDDevice()
if (isEnabled && !isICD) {
binding.icdInteractionSwitch.isChecked = false
return false
Expand Down Expand Up @@ -188,7 +189,13 @@ class AddressUpdateFragment : ICDCheckInCallback, Fragment() {
return binding.deviceIdEd.text.toString().toULong(16)
}

fun isICDDevice(): Boolean {
return deviceController.icdClientInfo.firstOrNull { info -> info.peerNodeId == deviceId } !=
null
}

override fun notifyCheckInMessage(info: ICDClientInfo) {
externalICDCheckInMessageCallback?.notifyCheckInMessage()
if (info.peerNodeId != icdDeviceId) {
return
}
Expand All @@ -206,6 +213,14 @@ class AddressUpdateFragment : ICDCheckInCallback, Fragment() {
}
}

fun setNotifyCheckInMessageCallback(callback: ICDCheckInMessageCallback?) {
externalICDCheckInMessageCallback = callback
}

interface ICDCheckInMessageCallback {
fun notifyCheckInMessage()
}

private fun turnOnActiveMode() {
requireActivity().runOnUiThread {
binding.icdProgressBar.max = (icdTotalRemainStayActiveTimeMs / 1000).toInt()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ import matter.tlv.AnonymousTag
import matter.tlv.TlvReader
import matter.tlv.TlvWriter

class WildcardFragment : Fragment() {
class WildcardFragment : Fragment(), AddressUpdateFragment.ICDCheckInMessageCallback {
private var _binding: WildcardFragmentBinding? = null
private val binding
get() = _binding!!
Expand All @@ -63,6 +63,23 @@ class WildcardFragment : Fragment() {
private val invokePath = ArrayList<InvokeElement>()
private val subscribeIdList = ArrayList<ULong>()

data class ReadICDConfig(val isFabricFiltered: Boolean, val eventMin: Long?)

data class SubscribeICDConfig(
val minInterval: Int,
val maxInterval: Int,
val keepSubscriptions: Boolean,
val isFabricFiltered: Boolean,
val eventMin: Long?
)

data class WriteInvokeICDConfig(val timedRequestTimeoutMs: Int, val imTimeoutMs: Int)

private var readICDConfig: ReadICDConfig? = null
private var subscribeICDConfig: SubscribeICDConfig? = null
private var writeICDConfig: WriteInvokeICDConfig? = null
private var invokeICDConfig: WriteInvokeICDConfig? = null

private val reportCallback =
object : ReportCallback {
override fun onError(
Expand Down Expand Up @@ -173,6 +190,45 @@ class WildcardFragment : Fragment() {
return binding.root
}

override fun onResume() {
super.onResume()
addressUpdateFragment.setNotifyCheckInMessageCallback(this)
}

override fun onPause() {
addressUpdateFragment.setNotifyCheckInMessageCallback(null)
super.onPause()
}

override fun notifyCheckInMessage() {
Log.d(TAG, "notifyCheckInMessage")
if (attributePath.isNotEmpty() || eventPath.isNotEmpty()) {
if (binding.readRadioBtn.isChecked && readICDConfig != null) {
scope.launch { read(readICDConfig!!.isFabricFiltered, readICDConfig!!.eventMin) }
} else if (binding.subscribeRadioBtn.isChecked && subscribeICDConfig != null) {
scope.launch {
subscribe(
subscribeICDConfig!!.minInterval,
subscribeICDConfig!!.maxInterval,
subscribeICDConfig!!.keepSubscriptions,
subscribeICDConfig!!.isFabricFiltered,
subscribeICDConfig!!.eventMin
)
}
}
} else if (
binding.writeRadioBtn.isChecked && writePath.isNotEmpty() && writeICDConfig != null
) {
scope.launch { write(writeICDConfig!!.timedRequestTimeoutMs, writeICDConfig!!.imTimeoutMs) }
} else if (
binding.invokeRadioBtn.isChecked && invokePath.isNotEmpty() && invokeICDConfig != null
) {
scope.launch {
invoke(invokeICDConfig!!.timedRequestTimeoutMs, invokeICDConfig!!.imTimeoutMs)
}
}
}

private fun setVisibilityEachView(radioBtnId: Int) {
val readBtnOn = (radioBtnId == R.id.readRadioBtn)
val subscribeBtnOn = (radioBtnId == R.id.subscribeRadioBtn)
Expand Down Expand Up @@ -520,7 +576,12 @@ class WildcardFragment : Fragment() {
if (eventPath.isNotEmpty() && eventMinEd.text.isNotBlank()) {
eventMin = eventMinEd.text.toString().toULong().toLong()
}
read(isFabricFilteredEd.selectedItem.toString().toBoolean(), eventMin)
if (addressUpdateFragment.isICDDevice()) {
readICDConfig =
ReadICDConfig(isFabricFilteredEd.selectedItem.toString().toBoolean(), eventMin)
} else {
read(isFabricFilteredEd.selectedItem.toString().toBoolean(), eventMin)
}
requireActivity().runOnUiThread { dialog.dismiss() }
}
}
Expand All @@ -537,18 +598,23 @@ class WildcardFragment : Fragment() {
dialogView.findViewById<EditText>(R.id.timedRequestTimeoutEd).text.toString()
val imTimeout = dialogView.findViewById<EditText>(R.id.imTimeoutEd).text.toString()
scope.launch {
write(
val timedRequestTimeoutInt =
if (timedRequestTimeoutMs.isEmpty()) {
0
} else {
timedRequestTimeoutMs.toInt()
},
}
val imTimeoutInt =
if (imTimeout.isEmpty()) {
0
} else {
imTimeout.toInt()
}
)
if (addressUpdateFragment.isICDDevice()) {
writeICDConfig = WriteInvokeICDConfig(timedRequestTimeoutInt, imTimeoutInt)
} else {
write(timedRequestTimeoutInt, imTimeoutInt)
}
requireActivity().runOnUiThread { dialog.dismiss() }
}
}
Expand Down Expand Up @@ -588,13 +654,24 @@ class WildcardFragment : Fragment() {
if (eventPath.isNotEmpty() && eventMinEd.text.isNotBlank()) {
eventMin = eventMinEd.text.toString().toULong().toLong()
}
subscribe(
minIntervalEd.text.toString().toInt(),
maxIntervalEd.text.toString().toInt(),
keepSubscriptionsSp.selectedItem.toString().toBoolean(),
isFabricFilteredSp.selectedItem.toString().toBoolean(),
eventMin,
)
if (addressUpdateFragment.isICDDevice()) {
subscribeICDConfig =
SubscribeICDConfig(
minIntervalEd.text.toString().toInt(),
maxIntervalEd.text.toString().toInt(),
keepSubscriptionsSp.selectedItem.toString().toBoolean(),
isFabricFilteredSp.selectedItem.toString().toBoolean(),
eventMin
)
} else {
subscribe(
minIntervalEd.text.toString().toInt(),
maxIntervalEd.text.toString().toInt(),
keepSubscriptionsSp.selectedItem.toString().toBoolean(),
isFabricFilteredSp.selectedItem.toString().toBoolean(),
eventMin
)
}
} else {
Log.e(TAG, "minInterval or maxInterval is empty!")
}
Expand All @@ -614,18 +691,23 @@ class WildcardFragment : Fragment() {
dialogView.findViewById<EditText>(R.id.timedRequestTimeoutEd).text.toString()
val imTimeout = dialogView.findViewById<EditText>(R.id.imTimeoutEd).text.toString()
scope.launch {
invoke(
val timedRequestTimeoutInt =
if (timedRequestTimeoutMs.isEmpty()) {
0
} else {
timedRequestTimeoutMs.toInt()
},
}
val imTimeoutInt =
if (imTimeout.isEmpty()) {
0
} else {
imTimeout.toInt()
}
)
if (addressUpdateFragment.isICDDevice()) {
invokeICDConfig = WriteInvokeICDConfig(timedRequestTimeoutInt, imTimeoutInt)
} else {
invoke(timedRequestTimeoutInt, imTimeoutInt)
}
requireActivity().runOnUiThread { dialog.dismiss() }
}
}
Expand Down
1 change: 1 addition & 0 deletions kotlin-detect-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,7 @@ complexity:
- "**/src/controller/java/tests/matter/tlv/TlvReaderTest.kt"
LargeClass:
excludes:
- "**/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/WildcardFragment.kt"
- "**/src/controller/java/generated/java/**/*"
- "**/src/controller/java/tests/matter/tlv/TlvReadWriteTest.kt"
- "**/src/controller/java/tests/matter/jsontlv/JsonToTlvToJsonTest.kt"
Expand Down

0 comments on commit e079364

Please sign in to comment.