blob: 873c2e91ebb3219f82cf84f9ff13f1f16f7c3fb6 [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 "LevelManager.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 kLevelManagerTableSize = MATTER_DM_LEVEL_CONTROL_CLUSTER_SERVER_ENDPOINT_COUNT;
namespace {
LevelManager * gLevelManagerTable[kLevelManagerTableSize] = { nullptr };
static_assert(kLevelManagerTableSize <= kEmberInvalidEndpointIndex, "gLevelManagerTable table size error");
} // namespace
void emberAfLevelControlClusterInitCallback(EndpointId endpoint)
{
ChipLogProgress(Zcl, "TV Android App::Level::PostClusterInit");
TvAppJNIMgr().PostClusterInit(chip::app::Clusters::LevelControl::Id, endpoint);
}
void LevelManager::NewManager(jint endpoint, jobject manager)
{
ChipLogProgress(Zcl, "TV Android App: LevelManager::NewManager");
uint16_t ep = emberAfGetClusterServerEndpointIndex(static_cast<chip::EndpointId>(endpoint), app::Clusters::LevelControl::Id,
MATTER_DM_LEVEL_CONTROL_CLUSTER_SERVER_ENDPOINT_COUNT);
VerifyOrReturn(ep < kLevelManagerTableSize,
ChipLogError(Zcl, "TV Android App::Level::NewManager: endpoint %d not found", endpoint));
VerifyOrReturn(gLevelManagerTable[ep] == nullptr,
ChipLogError(Zcl, "TV Android App::Level::NewManager: endpoint %d already has a manager", endpoint));
LevelManager * mgr = new LevelManager();
CHIP_ERROR err = mgr->InitializeWithObjects(manager);
if (err != CHIP_NO_ERROR)
{
ChipLogError(Zcl, "TV Android App::Level::NewManager: failed to initialize manager for endpoint %d", endpoint);
delete mgr;
}
else
{
gLevelManagerTable[ep] = mgr;
}
}
LevelManager * GetLevelManager(EndpointId endpoint)
{
uint16_t ep = emberAfGetClusterServerEndpointIndex(endpoint, app::Clusters::LevelControl::Id,
MATTER_DM_LEVEL_CONTROL_CLUSTER_SERVER_ENDPOINT_COUNT);
return ((ep >= kLevelManagerTableSize) ? nullptr : gLevelManagerTable[ep]);
}
void LevelManager::PostLevelChanged(chip::EndpointId endpoint, uint8_t value)
{
ChipLogProgress(Zcl, "TV Android App: LevelManager::PostLevelChanged");
LevelManager * mgr = GetLevelManager(endpoint);
VerifyOrReturn(mgr != nullptr, ChipLogError(Zcl, "LevelManager null"));
mgr->HandleLevelChanged(value);
}
jboolean LevelManager::SetLevel(jint endpoint, jint value)
{
chip::DeviceLayer::StackLock stack;
chip::Protocols::InteractionModel::Status status = app::Clusters::LevelControl::Attributes::CurrentLevel::Set(
static_cast<chip::EndpointId>(endpoint), static_cast<uint8_t>(value));
return status == chip::Protocols::InteractionModel::Status::Success;
}
CHIP_ERROR LevelManager::InitializeWithObjects(jobject managerObject)
{
JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread();
VerifyOrReturnLogError(env != nullptr, CHIP_ERROR_INCORRECT_STATE);
JniLocalReferenceScope scope(env);
ReturnLogErrorOnFailure(mLevelManagerObject.Init(managerObject));
jclass LevelManagerClass = env->GetObjectClass(managerObject);
VerifyOrReturnLogError(LevelManagerClass != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
mHandleLevelChangedMethod = env->GetMethodID(LevelManagerClass, "HandleLevelChanged", "(I)V");
if (mHandleLevelChangedMethod == nullptr)
{
ChipLogError(Zcl, "Failed to access LevelManager 'HandleLevelChanged' method");
env->ExceptionClear();
return CHIP_ERROR_INVALID_ARGUMENT;
}
return CHIP_NO_ERROR;
}
void LevelManager::HandleLevelChanged(uint8_t value)
{
DeviceLayer::StackUnlock unlock;
ChipLogProgress(Zcl, "LevelManager::HandleLevelChanged");
JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread();
VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNIEnv for current thread"));
JniLocalReferenceScope scope(env);
VerifyOrReturn(mLevelManagerObject.HasValidObjectRef(), ChipLogError(Zcl, "mLevelManagerObject is not valid"));
VerifyOrReturn(mHandleLevelChangedMethod != nullptr, ChipLogProgress(Zcl, "mHandleLevelChangedMethod null"));
env->ExceptionClear();
env->CallVoidMethod(mLevelManagerObject.ObjectRef(), mHandleLevelChangedMethod, static_cast<jint>(value));
if (env->ExceptionCheck())
{
ChipLogError(AppServer, "Java exception in LevelManager::HandleLevelChanged");
env->ExceptionDescribe();
env->ExceptionClear();
}
}