blob: 203d08d7937b6497a1898dd8c65b87bce4a519b7 [file] [log] [blame]
/**
*
* Copyright (c) 2022 Project CHIP Authors
*
* 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.
*/
#include "OnOffManager.h"
#include "TvApp-JNI.h"
#include <app-common/zap-generated/attributes/Accessors.h>
#include <app-common/zap-generated/ids/Clusters.h>
#include <app/util/attribute-storage.h>
#include <app/util/config.h>
#include <jni.h>
#include <lib/support/CHIPJNIError.h>
#include <lib/support/JniReferences.h>
#include <lib/support/JniTypeWrappers.h>
using namespace chip;
static constexpr size_t kOnffManagerTableSize = MATTER_DM_ON_OFF_CLUSTER_SERVER_ENDPOINT_COUNT;
namespace {
OnOffManager * gOnOffManagerTable[kOnffManagerTableSize] = { nullptr };
static_assert(kOnffManagerTableSize <= kEmberInvalidEndpointIndex, "gOnOffManagerTable table size error");
} // namespace
void emberAfOnOffClusterInitCallback(EndpointId endpoint)
{
ChipLogProgress(Zcl, "TV Android App::OnOff::PostClusterInit");
TvAppJNIMgr().PostClusterInit(chip::app::Clusters::OnOff::Id, endpoint);
}
void OnOffManager::NewManager(jint endpoint, jobject manager)
{
ChipLogProgress(Zcl, "TV Android App: OnOffManager::NewManager");
uint16_t ep = emberAfGetClusterServerEndpointIndex(static_cast<chip::EndpointId>(endpoint), app::Clusters::OnOff::Id,
MATTER_DM_ON_OFF_CLUSTER_SERVER_ENDPOINT_COUNT);
VerifyOrReturn(ep < kOnffManagerTableSize,
ChipLogError(Zcl, "TV Android App::OnOff::NewManager: endpoint %d not found", endpoint));
VerifyOrReturn(gOnOffManagerTable[ep] == nullptr,
ChipLogError(Zcl, "TV Android App::OnOff::NewManager: endpoint %d already has a manager", endpoint));
OnOffManager * mgr = new OnOffManager();
CHIP_ERROR err = mgr->InitializeWithObjects(manager);
if (err != CHIP_NO_ERROR)
{
ChipLogError(Zcl, "TV Android App::OnOff::NewManager: failed to initialize manager for endpoint %d", endpoint);
delete mgr;
}
else
{
gOnOffManagerTable[ep] = mgr;
}
}
OnOffManager * GetOnOffManager(EndpointId endpoint)
{
uint16_t ep =
emberAfGetClusterServerEndpointIndex(endpoint, app::Clusters::OnOff::Id, MATTER_DM_ON_OFF_CLUSTER_SERVER_ENDPOINT_COUNT);
return (ep >= kOnffManagerTableSize ? nullptr : gOnOffManagerTable[ep]);
}
void OnOffManager::PostOnOffChanged(chip::EndpointId endpoint, bool value)
{
ChipLogProgress(Zcl, "TV Android App: OnOffManager::PostOnOffChange");
OnOffManager * mgr = GetOnOffManager(endpoint);
VerifyOrReturn(mgr != nullptr, ChipLogError(Zcl, "OnOffManager null"));
mgr->HandleOnOffChanged(value);
}
jboolean OnOffManager::SetOnOff(jint endpoint, bool value)
{
chip::DeviceLayer::StackLock stack;
chip::Protocols::InteractionModel::Status status =
app::Clusters::OnOff::Attributes::OnOff::Set(static_cast<chip::EndpointId>(endpoint), value);
return status == chip::Protocols::InteractionModel::Status::Success;
}
CHIP_ERROR OnOffManager::InitializeWithObjects(jobject managerObject)
{
JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread();
VerifyOrReturnError(env != nullptr, CHIP_JNI_ERROR_NO_ENV, ChipLogError(Zcl, "Could not get JNIEnv for current thread"));
JniLocalReferenceScope scope(env);
ReturnLogErrorOnFailure(mOnOffManagerObject.Init(managerObject));
jclass OnOffManagerClass = env->GetObjectClass(managerObject);
VerifyOrReturnLogError(OnOffManagerClass != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
mHandleOnOffChangedMethod = env->GetMethodID(OnOffManagerClass, "HandleOnOffChanged", "(Z)V");
if (mHandleOnOffChangedMethod == nullptr)
{
ChipLogError(Zcl, "Failed to access OnOffManager 'HandleOnOffChanged' method");
env->ExceptionClear();
return CHIP_ERROR_INVALID_ARGUMENT;
}
return CHIP_NO_ERROR;
}
void OnOffManager::HandleOnOffChanged(bool value)
{
DeviceLayer::StackUnlock unlock;
ChipLogProgress(Zcl, "OnOffManager::HandleOnOffChanged");
JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread();
VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNIEnv for current thread"));
JniLocalReferenceScope scope(env);
VerifyOrReturn(mOnOffManagerObject.HasValidObjectRef(), ChipLogProgress(Zcl, "mOnOffManagerObject null"));
VerifyOrReturn(mHandleOnOffChangedMethod != nullptr, ChipLogProgress(Zcl, "mHandleOnOffChangedMethod null"));
env->ExceptionClear();
env->CallVoidMethod(mOnOffManagerObject.ObjectRef(), mHandleOnOffChangedMethod, static_cast<jboolean>(value));
if (env->ExceptionCheck())
{
ChipLogError(AppServer, "Java exception in OnOffManager::HandleOnOffChanged");
env->ExceptionDescribe();
env->ExceptionClear();
}
}