Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Android][ICD]Implement Android ICD sending using buffer #33377

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading