blob: bee06caf2b50d6ec7c7de6124661d1260afe2adf [file] [log] [blame]
/*
* Copyright (c) 2020 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
import android.content.Context
import android.util.Log
import chip.devicecontroller.ChipDeviceController
import chip.devicecontroller.ControllerParams
import chip.devicecontroller.GetConnectedDeviceCallbackJni.GetConnectedDeviceCallback
import chip.devicecontroller.ICDCheckInDelegate
import chip.devicecontroller.ICDClientInfo
import chip.platform.AndroidBleManager
import chip.platform.AndroidChipPlatform
import chip.platform.ChipMdnsCallbackImpl
import chip.platform.DiagnosticDataProviderImpl
import chip.platform.NsdManagerServiceBrowser
import chip.platform.NsdManagerServiceResolver
import chip.platform.PreferencesConfigurationManager
import chip.platform.PreferencesKeyValueStoreManager
import com.google.chip.chiptool.attestation.ExampleAttestationTrustStoreDelegate
import com.google.chip.chiptool.clusterclient.ICDCheckInCallback
import kotlin.coroutines.resume
import kotlin.coroutines.resumeWithException
import kotlinx.coroutines.suspendCancellableCoroutine
/** Lazily instantiates [ChipDeviceController] and holds a reference to it. */
object ChipClient {
private const val TAG = "ChipClient"
private lateinit var chipDeviceController: ChipDeviceController
private lateinit var androidPlatform: AndroidChipPlatform
/* 0xFFF4 is a test vendor ID, replace with your assigned company ID */
const val VENDOR_ID = 0xFFF4
private var icdCheckInCallback: ICDCheckInCallback? = null
fun getDeviceController(context: Context): ChipDeviceController {
getAndroidChipPlatform(context)
if (!this::chipDeviceController.isInitialized) {
chipDeviceController =
ChipDeviceController(
ControllerParams.newBuilder()
.setControllerVendorId(VENDOR_ID)
.setEnableServerInteractions(true)
.build()
)
// Set delegate for attestation trust store for device attestation verifier.
// It will replace the default attestation trust store.
chipDeviceController.setAttestationTrustStoreDelegate(
ExampleAttestationTrustStoreDelegate(chipDeviceController)
)
chipDeviceController.setICDCheckInDelegate(
object : ICDCheckInDelegate {
override fun onCheckInComplete(info: ICDClientInfo) {
Log.d(TAG, "onCheckInComplete : $info")
icdCheckInCallback?.notifyCheckInMessage(info)
}
override fun onKeyRefreshNeeded(info: ICDClientInfo): ByteArray? {
Log.d(TAG, "onKeyRefreshNeeded : $info")
return null
}
override fun onKeyRefreshDone(errorCode: Long) {
Log.d(TAG, "onKeyRefreshDone : $errorCode")
}
}
)
}
return chipDeviceController
}
fun getAndroidChipPlatform(context: Context?): AndroidChipPlatform {
if (!this::androidPlatform.isInitialized && context != null) {
// force ChipDeviceController load jni
ChipDeviceController.loadJni()
androidPlatform =
AndroidChipPlatform(
AndroidBleManager(context),
PreferencesKeyValueStoreManager(context),
PreferencesConfigurationManager(context),
NsdManagerServiceResolver(
context,
NsdManagerServiceResolver.NsdManagerResolverAvailState()
),
NsdManagerServiceBrowser(context),
ChipMdnsCallbackImpl(),
DiagnosticDataProviderImpl(context)
)
}
return androidPlatform
}
fun setICDCheckInCallback(callback: ICDCheckInCallback) {
icdCheckInCallback = callback
}
/**
* Wrapper around [ChipDeviceController.getConnectedDevicePointer] to return the value directly.
*/
suspend fun getConnectedDevicePointer(context: Context, nodeId: Long): Long {
// TODO (#21539) This is a memory leak because we currently never call
// releaseConnectedDevicePointer
// once we are done with the returned device pointer. Memory leak was introduced since the
// refactor
// that introduced it was very large in order to fix a use after free, which was considered
// to be
// worse than the memory leak that was introduced.
return suspendCancellableCoroutine { continuation ->
getDeviceController(context)
.getConnectedDevicePointer(
nodeId,
object : GetConnectedDeviceCallback {
override fun onDeviceConnected(devicePointer: Long) {
Log.d(TAG, "Got connected device pointer")
continuation.resume(devicePointer)
}
override fun onConnectionFailure(nodeId: Long, error: Exception) {
val errorMessage = "Unable to get connected device with nodeId $nodeId"
Log.e(TAG, errorMessage, error)
continuation.resumeWithException(IllegalStateException(errorMessage))
}
}
)
}
}
}