blob: 10d7c32e994a9eaf6c86b13f771410558c2639d2 [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.GetConnectedDeviceCallbackJni.GetConnectedDeviceCallback
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 kotlin.coroutines.resume
import kotlin.coroutines.resumeWithException
import kotlin.coroutines.suspendCoroutine
/** 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
fun getDeviceController(context: Context): ChipDeviceController {
getAndroidChipPlatform(context)
if (!this::chipDeviceController.isInitialized) {
chipDeviceController = ChipDeviceController()
}
return chipDeviceController
}
fun getAndroidChipPlatform(context: Context?): AndroidChipPlatform {
if (!this::androidPlatform.isInitialized && context != null) {
//force ChipDeviceController load jni
ChipDeviceController.loadJni()
androidPlatform = AndroidChipPlatform(AndroidBleManager(), PreferencesKeyValueStoreManager(context), PreferencesConfigurationManager(context), NsdManagerServiceResolver(context), NsdManagerServiceBrowser(context), ChipMdnsCallbackImpl(), DiagnosticDataProviderImpl(context))
}
return androidPlatform
}
/**
* 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 suspendCoroutine { 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))
}
})
}
}
}