Fix for x86_64 build fail
[platform/upstream/connectedhomeip.git] / src / android / CHIPTool / app / src / main / java / com / google / chip / chiptool / CHIPToolActivity.kt
1 /*
2  *   Copyright (c) 2020 Project CHIP Authors
3  *   All rights reserved.
4  *
5  *   Licensed under the Apache License, Version 2.0 (the "License");
6  *   you may not use this file except in compliance with the License.
7  *   You may obtain a copy of the License at
8  *
9  *       http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *   Unless required by applicable law or agreed to in writing, software
12  *   distributed under the License is distributed on an "AS IS" BASIS,
13  *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *   See the License for the specific language governing permissions and
15  *   limitations under the License.
16  *
17  */
18 package com.google.chip.chiptool
19
20 import android.content.Intent
21 import android.nfc.NdefMessage
22 import android.nfc.NfcAdapter
23 import android.os.Bundle
24 import androidx.appcompat.app.AlertDialog
25 import androidx.appcompat.app.AppCompatActivity
26 import androidx.fragment.app.Fragment
27 import chip.setuppayload.SetupPayloadParser
28 import com.google.chip.chiptool.attestation.AttestationTestFragment
29 import com.google.chip.chiptool.clusterclient.OnOffClientFragment
30 import com.google.chip.chiptool.commissioner.CommissionerActivity
31 import com.google.chip.chiptool.echoclient.EchoClientFragment
32 import com.google.chip.chiptool.provisioning.DeviceProvisioningFragment
33 import com.google.chip.chiptool.provisioning.ProvisionNetworkType
34 import com.google.chip.chiptool.setuppayloadscanner.BarcodeFragment
35 import com.google.chip.chiptool.setuppayloadscanner.CHIPDeviceDetailsFragment
36 import com.google.chip.chiptool.setuppayloadscanner.CHIPDeviceInfo
37 import com.google.chip.chiptool.setuppayloadscanner.QrCodeInfo
38 import chip.devicecontroller.PersistentStorage
39
40 class CHIPToolActivity :
41     AppCompatActivity(),
42     BarcodeFragment.Callback,
43     SelectActionFragment.Callback,
44     DeviceProvisioningFragment.Callback {
45
46   private var networkType: ProvisionNetworkType? = null
47
48   override fun onCreate(savedInstanceState: Bundle?) {
49     super.onCreate(savedInstanceState)
50     setContentView(R.layout.top_activity)
51
52     PersistentStorage.initialize(this);
53
54     if (savedInstanceState == null) {
55       val fragment = SelectActionFragment.newInstance()
56       supportFragmentManager
57           .beginTransaction()
58           .add(R.id.fragment_container, fragment, fragment.javaClass.simpleName)
59           .commit()
60     } else {
61       networkType =
62           ProvisionNetworkType.fromName(savedInstanceState.getString(ARG_PROVISION_NETWORK_TYPE))
63     }
64
65     if (intent?.action == NfcAdapter.ACTION_NDEF_DISCOVERED)
66       onNfcIntent(intent)
67   }
68
69   override fun onSaveInstanceState(outState: Bundle) {
70     outState.putString(ARG_PROVISION_NETWORK_TYPE, networkType?.name)
71
72     super.onSaveInstanceState(outState)
73   }
74
75   override fun onCHIPDeviceInfoReceived(deviceInfo: CHIPDeviceInfo) {
76     if (networkType == null) {
77       showFragment(CHIPDeviceDetailsFragment.newInstance(deviceInfo))
78     } else {
79       showFragment(DeviceProvisioningFragment.newInstance(deviceInfo, networkType!!), false)
80     }
81   }
82
83   override fun onPairingComplete() {
84     showFragment(OnOffClientFragment.newInstance(), false)
85   }
86
87   override fun handleScanQrCodeClicked() {
88     showFragment(BarcodeFragment.newInstance())
89   }
90
91   override fun onProvisionWifiCredentialsClicked() {
92     networkType = ProvisionNetworkType.WIFI
93     showFragment(BarcodeFragment.newInstance(), false)
94   }
95
96   override fun onProvisionThreadCredentialsClicked() {
97     networkType = ProvisionNetworkType.THREAD
98     showFragment(BarcodeFragment.newInstance(), false)
99   }
100
101   override fun handleCommissioningClicked() {
102     var intent = Intent(this, CommissionerActivity::class.java)
103     startActivityForResult(intent, REQUEST_CODE_COMMISSIONING)
104   }
105
106   override fun handleEchoClientClicked() {
107     showFragment(EchoClientFragment.newInstance())
108   }
109
110   override fun handleOnOffClicked() {
111     showFragment(OnOffClientFragment.newInstance())
112   }
113
114   override fun handleAttestationTestClicked() {
115     showFragment(AttestationTestFragment.newInstance())
116   }
117
118   override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
119     super.onActivityResult(requestCode, resultCode, data)
120
121     if (requestCode == REQUEST_CODE_COMMISSIONING) {
122       // Simply ignore the commissioning result.
123       // TODO: tracking commissioned devices.
124     }
125   }
126
127   private fun showFragment(fragment: Fragment, showOnBack: Boolean = true) {
128     val fragmentTransaction = supportFragmentManager
129         .beginTransaction()
130         .replace(R.id.fragment_container, fragment, fragment.javaClass.simpleName)
131
132     if (showOnBack) {
133       fragmentTransaction.addToBackStack(null)
134     }
135
136     fragmentTransaction.commit()
137   }
138
139   private fun onNfcIntent(intent: Intent?) {
140     // Require 1 NDEF message containing 1 NDEF record
141     val messages = intent?.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES)
142     if (messages?.size != 1) return
143
144     val records = (messages[0] as NdefMessage).records
145     if (records.size != 1) return
146
147     // Require NDEF URI record starting with "ch:"
148     val uri = records[0].toUri()
149     if (!uri?.scheme.equals("ch", true)) return
150
151     // TODO: Issue #4504 - Remove replacing _ with spaces after problem described in #415 will be fixed.
152     val setupPayload = SetupPayloadParser().parseQrCode(uri.toString().toUpperCase().replace('_', ' '))
153     val deviceInfo = CHIPDeviceInfo(
154         setupPayload.version,
155         setupPayload.vendorId,
156         setupPayload.productId,
157         setupPayload.discriminator,
158         setupPayload.setupPinCode,
159         setupPayload.optionalQRCodeInfo.mapValues { (_, info) -> QrCodeInfo(info.tag, info.type, info.data, info.int32) }
160     )
161
162     val buttons = arrayOf(
163         getString(R.string.nfc_tag_action_show),
164         getString(R.string.nfc_tag_action_wifi),
165         getString(R.string.nfc_tag_action_thread))
166
167     AlertDialog.Builder(this)
168         .setTitle(R.string.nfc_tag_action_title)
169         .setItems(buttons) { _, which ->
170           this.networkType = when (which) {
171             1 -> ProvisionNetworkType.WIFI
172             2 -> ProvisionNetworkType.THREAD
173             else -> null
174           }
175           onCHIPDeviceInfoReceived(deviceInfo)
176         }
177         .create()
178         .show()
179   }
180
181   companion object {
182     private const val ARG_PROVISION_NETWORK_TYPE = "provision_network_type"
183
184     var REQUEST_CODE_COMMISSIONING = 0xB003
185   }
186 }