diff --git a/src/android/CHIPTool/app/build.gradle b/src/android/CHIPTool/app/build.gradle index f7ab858e706d1e..e38c8448e9bd8c 100644 --- a/src/android/CHIPTool/app/build.gradle +++ b/src/android/CHIPTool/app/build.gradle @@ -67,6 +67,7 @@ android { } dependencies { + implementation 'com.android.volley:volley:1.2.1' def room_version = "2.2.5" implementation "androidx.room:room-runtime:$room_version" diff --git a/src/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/CHIPToolActivity.kt b/src/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/CHIPToolActivity.kt index 78be3545ebd61a..f40f7e6438b952 100644 --- a/src/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/CHIPToolActivity.kt +++ b/src/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/CHIPToolActivity.kt @@ -18,6 +18,7 @@ package com.google.chip.chiptool import android.content.Intent +import android.net.Uri import android.nfc.NdefMessage import android.nfc.NfcAdapter import android.os.Bundle @@ -42,12 +43,15 @@ import com.google.chip.chiptool.provisioning.ProvisionNetworkType import com.google.chip.chiptool.setuppayloadscanner.BarcodeFragment import com.google.chip.chiptool.setuppayloadscanner.CHIPDeviceDetailsFragment import com.google.chip.chiptool.setuppayloadscanner.CHIPDeviceInfo +import com.google.chip.chiptool.setuppayloadscanner.CHIPLedgerDetailsFragment class CHIPToolActivity : AppCompatActivity(), BarcodeFragment.Callback, SelectActionFragment.Callback, - DeviceProvisioningFragment.Callback { + DeviceProvisioningFragment.Callback, + CHIPDeviceDetailsFragment.Callback, + CHIPLedgerDetailsFragment.Callback { private var networkType: ProvisionNetworkType? = null @@ -141,6 +145,15 @@ class CHIPToolActivity : showFragment(AttestationTestFragment.newInstance()) } + override fun handleReadFromLedgerClicked(deviceInfo: CHIPDeviceInfo) { + showFragment(CHIPLedgerDetailsFragment.newInstance(deviceInfo)) + } + + override fun handleCustomFlowRedirectClicked(redirectUrl: String) { + val redirectIntent = Intent(Intent.ACTION_VIEW, Uri.parse(redirectUrl)) + startActivity(redirectIntent) + } + override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { super.onActivityResult(requestCode, resultCode, data) @@ -150,6 +163,10 @@ class CHIPToolActivity : } } + override fun handleCustomFlowClicked() { + showFragment(BarcodeFragment.newInstance()) + } + private fun showFragment(fragment: Fragment, showOnBack: Boolean = true) { val fragmentTransaction = supportFragmentManager .beginTransaction() diff --git a/src/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/SelectActionFragment.kt b/src/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/SelectActionFragment.kt index 728acd794a0432..b46d640644a6fb 100644 --- a/src/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/SelectActionFragment.kt +++ b/src/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/SelectActionFragment.kt @@ -57,6 +57,7 @@ class SelectActionFragment : Fragment() { basicClusterBtn.setOnClickListener{ getCallback()?.handleBasicClicked() } attestationTestBtn.setOnClickListener { getCallback()?.handleAttestationTestClicked() } clusterInteractionBtn.setOnClickListener { getCallback()?.handleClusterInteractionClicked() } + provisionCustomFlowBtn.setOnClickListener{ getCallback()?.handleCustomFlowClicked() } } } @@ -125,6 +126,8 @@ class SelectActionFragment : Fragment() { fun onShowDeviceAddressInput() /** Notifies listener of cluster interaction button click.. */ fun handleClusterInteractionClicked() + /** Notifies listener of provision-custom-flow button click. */ + fun handleCustomFlowClicked() } companion object { diff --git a/src/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/setuppayloadscanner/CHIPDeviceDetailsFragment.kt b/src/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/setuppayloadscanner/CHIPDeviceDetailsFragment.kt index afcfb015d69f79..a36238db4ea939 100644 --- a/src/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/setuppayloadscanner/CHIPDeviceDetailsFragment.kt +++ b/src/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/setuppayloadscanner/CHIPDeviceDetailsFragment.kt @@ -25,6 +25,7 @@ import android.view.ViewGroup import android.widget.TextView import androidx.fragment.app.Fragment import com.google.chip.chiptool.R +import com.google.chip.chiptool.util.FragmentUtil import kotlinx.android.synthetic.main.chip_device_info_fragment.view.discoveryCapabilitiesTv import kotlinx.android.synthetic.main.chip_device_info_fragment.view.discriminatorTv import kotlinx.android.synthetic.main.chip_device_info_fragment.view.productIdTv @@ -33,6 +34,8 @@ import kotlinx.android.synthetic.main.chip_device_info_fragment.view.vendorIdTv import kotlinx.android.synthetic.main.chip_device_info_fragment.view.vendorTagsContainer import kotlinx.android.synthetic.main.chip_device_info_fragment.view.vendorTagsLabelTv import kotlinx.android.synthetic.main.chip_device_info_fragment.view.versionTv +import kotlinx.android.synthetic.main.chip_device_info_fragment.view.commissioningFlowTv +import kotlinx.android.synthetic.main.chip_device_info_fragment.view.customFlowBtn /** Show the [CHIPDeviceInfo]. */ class CHIPDeviceDetailsFragment : Fragment() { @@ -72,9 +75,26 @@ class CHIPDeviceDetailsFragment : Fragment() { vendorTagsContainer.addView(tv) } } + + commissioningFlowTv.text = "${deviceInfo.commissioningFlow}" + + // commissioningFlow = 2 (Custom), read device info from Ledger + if (deviceInfo.commissioningFlow == 2) { + customFlowBtn.visibility = View.VISIBLE + customFlowBtn.setOnClickListener { + FragmentUtil.getHost(this@CHIPDeviceDetailsFragment, Callback::class.java) + ?.handleReadFromLedgerClicked(deviceInfo) + } + } } } + /** Interface for notifying the host. */ + interface Callback { + /** Notifies listener of Read Device Info from Ledger button click. */ + fun handleReadFromLedgerClicked(deviceInfo: CHIPDeviceInfo) + } + companion object { private const val ARG_DEVICE_INFO = "device_info" diff --git a/src/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/setuppayloadscanner/CHIPDeviceInfo.kt b/src/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/setuppayloadscanner/CHIPDeviceInfo.kt index 523613c78f2bd7..67603917aabef5 100644 --- a/src/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/setuppayloadscanner/CHIPDeviceInfo.kt +++ b/src/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/setuppayloadscanner/CHIPDeviceInfo.kt @@ -31,10 +31,12 @@ data class CHIPDeviceInfo( val productId: Int = 0, val discriminator: Int = 0, val setupPinCode: Long = 0L, + var commissioningFlow: Int = 0, val optionalQrCodeInfoMap: Map = mapOf(), val discoveryCapabilities: Set = setOf(), val ipAddress: String? = null, -) : Parcelable { + + ) : Parcelable { companion object { fun fromSetupPayload(setupPayload: SetupPayload): CHIPDeviceInfo { @@ -44,6 +46,7 @@ data class CHIPDeviceInfo( setupPayload.productId, setupPayload.discriminator, setupPayload.setupPinCode, + setupPayload.commissioningFlow, setupPayload.optionalQRCodeInfo.mapValues { (_, info) -> QrCodeInfo( info.tag, @@ -52,7 +55,7 @@ data class CHIPDeviceInfo( info.int32 ) }, - setupPayload.discoveryCapabilities + setupPayload.discoveryCapabilities, ) } } diff --git a/src/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/setuppayloadscanner/CHIPLedgerDetailsFragment.kt b/src/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/setuppayloadscanner/CHIPLedgerDetailsFragment.kt new file mode 100644 index 00000000000000..ed8edcbc31b0ad --- /dev/null +++ b/src/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/setuppayloadscanner/CHIPLedgerDetailsFragment.kt @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2021 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.google.chip.chiptool.setuppayloadscanner + +import android.net.Uri +import android.os.Bundle +import android.util.Base64 +import android.util.Log +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.fragment.app.Fragment +import com.android.volley.Request +import com.android.volley.toolbox.JsonObjectRequest +import com.android.volley.toolbox.Volley +import com.google.chip.chiptool.R +import com.google.chip.chiptool.util.FragmentUtil +import com.google.gson.Gson +import kotlinx.android.synthetic.main.chip_ledger_info_fragment.view.vendorIdTv +import kotlinx.android.synthetic.main.chip_ledger_info_fragment.view.productIdTv +import kotlinx.android.synthetic.main.chip_ledger_info_fragment.view.commissioningFlowUrlTv +import kotlinx.android.synthetic.main.chip_ledger_info_fragment.view.redirectBtn + +/** Show the [CHIPDeviceInfo] from Ledger */ +class CHIPLedgerDetailsFragment : Fragment() { + + private lateinit var deviceInfo: CHIPDeviceInfo + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View { + + deviceInfo = checkNotNull(requireArguments().getParcelable(ARG_DEVICE_INFO)) + val queue = Volley.newRequestQueue(context) + return inflater.inflate(R.layout.chip_ledger_info_fragment, container, false).apply { + + // VID / PID + vendorIdTv.text = "${deviceInfo.vendorId}" + productIdTv.text = "${deviceInfo.productId}" + + // Ledger api url + val url = Uri.parse(context.getString(R.string.dcl_api_root_url)) + .buildUpon() + .appendPath("${deviceInfo.vendorId}") + .appendPath("${deviceInfo.productId}") + .build().toString() + Log.d(TAG, "Dcl request Url: $url") + + // Ledger API call + val jsonObjectRequest = JsonObjectRequest( + Request.Method.GET, url, null, + { response -> + Log.d(TAG, "Response from dcl $response") + + // parse redirect Url + val responseJson = response.getJSONObject(context.getString(R.string.dcl_response_key)) + val redirectUrl = responseJson.getString(context.getString(R.string.dcl_custom_flow_url_key)) + Log.d(TAG, "Redirect Url from Ledger: $redirectUrl") + commissioningFlowUrlTv.text = redirectUrl + + // generate redirect payload + val gson = Gson() + val payloadJson = gson.toJson(deviceInfo) + val payloadBase64 = Base64.encodeToString(payloadJson.toByteArray(), Base64.DEFAULT) + val redirectUrlWithPayload= Uri.parse(redirectUrl) + .buildUpon() + .appendQueryParameter("payload", payloadBase64) + .appendQueryParameter("returnUrl", context.getString(R.string.custom_flow_return_url)) + .build() + .toString() + + Log.d(TAG, "Redirect Url with Payload: $redirectUrlWithPayload") + redirectBtn.setOnClickListener { + FragmentUtil.getHost(this@CHIPLedgerDetailsFragment, Callback::class.java) + ?.handleCustomFlowRedirectClicked(redirectUrlWithPayload) + } + + // enable redirect button + redirectBtn.visibility = View.VISIBLE + }, + { error -> + Log.e(TAG, "Dcl request failed: $error") + commissioningFlowUrlTv.text = context.getString(R.string.chip_ledger_info_commissioning_flow_url_not_available) + } + ) + queue.add(jsonObjectRequest) + } + } + + /** Interface for notifying the host. */ + interface Callback { + /** Notifies listener of Custom flow redirect button click. */ + fun handleCustomFlowRedirectClicked(redirectUrl: String) + } + + companion object { + private const val TAG = "CUSTOM_FLOW" + private const val ARG_DEVICE_INFO = "device_info" + + @JvmStatic + fun newInstance(deviceInfo: CHIPDeviceInfo): CHIPLedgerDetailsFragment { + return CHIPLedgerDetailsFragment().apply { + arguments = Bundle(1).apply { putParcelable(ARG_DEVICE_INFO, deviceInfo) } + } + } + } +} diff --git a/src/android/CHIPTool/app/src/main/res/layout/chip_device_info_fragment.xml b/src/android/CHIPTool/app/src/main/res/layout/chip_device_info_fragment.xml index bbcdf5efee899b..6e326a65008edb 100644 --- a/src/android/CHIPTool/app/src/main/res/layout/chip_device_info_fragment.xml +++ b/src/android/CHIPTool/app/src/main/res/layout/chip_device_info_fragment.xml @@ -142,5 +142,37 @@ android:layout_below="@id/vendorTagsContainer" android:layout_alignParentStart="true" android:textSize="20sp"/> + + + + +