Skip to content

Commit

Permalink
Android java endpoint and fix memory errors (#13398)
Browse files Browse the repository at this point in the history
* added endpoint support in Java

* fix jni sign error

* fix memory error in media input cluster on android

* fix restyled-io and ci errors

* fix memory issus in channel cluster

* fix memory issus in content launcher cluster

* fix memory issue in wake up on lan launcher cluster

* fix media playback cluster issue in last PR

* fix restyled-io and ci errors

* fix CI issue
  • Loading branch information
xylophone21 authored and pull[bot] committed Jan 4, 2024
1 parent c820f32 commit 1410484
Show file tree
Hide file tree
Showing 53 changed files with 1,076 additions and 499 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import chip.platform.PreferencesConfigurationManager;
import chip.platform.PreferencesKeyValueStoreManager;
import com.tcl.chip.tvapp.ChannelManagerStub;
import com.tcl.chip.tvapp.Clusters;
import com.tcl.chip.tvapp.ContentLaunchManagerStub;
import com.tcl.chip.tvapp.KeypadInputManagerStub;
import com.tcl.chip.tvapp.LowPowerManagerStub;
Expand All @@ -33,14 +34,33 @@ public static MatterServant get() {
}

public void init(@NonNull Context context) {
TvApp tvApp = new TvApp();
tvApp.setKeypadInputManager(new KeypadInputManagerStub());
tvApp.setWakeOnLanManager(new WakeOnLanManagerStub());
tvApp.setMediaInputManager(new MediaInputManagerStub());
tvApp.setContentLaunchManager(new ContentLaunchManagerStub());
tvApp.setLowPowerManager(new LowPowerManagerStub());
tvApp.setMediaPlaybackManager(new MediaPlaybackManagerStub());
tvApp.setChannelManager(new ChannelManagerStub());
TvApp tvApp =
new TvApp(
(app, clusterId, endpoint) -> {
switch (clusterId) {
case Clusters.ClusterId_KeypadInput:
app.setKeypadInputManager(endpoint, new KeypadInputManagerStub(endpoint));
break;
case Clusters.ClusterId_WakeOnLan:
app.setWakeOnLanManager(endpoint, new WakeOnLanManagerStub(endpoint));
break;
case Clusters.ClusterId_MediaInput:
app.setMediaInputManager(endpoint, new MediaInputManagerStub(endpoint));
break;
case Clusters.ClusterId_ContentLauncher:
app.setContentLaunchManager(endpoint, new ContentLaunchManagerStub(endpoint));
break;
case Clusters.ClusterId_LowPower:
app.setLowPowerManager(endpoint, new LowPowerManagerStub(endpoint));
break;
case Clusters.ClusterId_MediaPlayback:
app.setMediaPlaybackManager(endpoint, new MediaPlaybackManagerStub(endpoint));
break;
case Clusters.ClusterId_Channel:
app.setChannelManager(endpoint, new ChannelManagerStub(endpoint));
break;
}
});

Context applicationContext = context.getApplicationContext();
AndroidChipPlatform chipPlatform =
Expand Down
3 changes: 3 additions & 0 deletions examples/tv-app/android/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ android_library("java") {
"java/src/com/tcl/chip/tvapp/ChannelLineupInfo.java",
"java/src/com/tcl/chip/tvapp/ChannelManager.java",
"java/src/com/tcl/chip/tvapp/ChannelManagerStub.java",
"java/src/com/tcl/chip/tvapp/Clusters.java",
"java/src/com/tcl/chip/tvapp/ContentLaunchBrandingInformation.java",
"java/src/com/tcl/chip/tvapp/ContentLaunchManager.java",
"java/src/com/tcl/chip/tvapp/ContentLaunchManagerStub.java",
Expand All @@ -101,7 +102,9 @@ android_library("java") {
"java/src/com/tcl/chip/tvapp/MediaInputManagerStub.java",
"java/src/com/tcl/chip/tvapp/MediaPlaybackManager.java",
"java/src/com/tcl/chip/tvapp/MediaPlaybackManagerStub.java",
"java/src/com/tcl/chip/tvapp/MediaPlaybackPosition.java",
"java/src/com/tcl/chip/tvapp/TvApp.java",
"java/src/com/tcl/chip/tvapp/TvAppCallback.java",
"java/src/com/tcl/chip/tvapp/WakeOnLanManager.java",
"java/src/com/tcl/chip/tvapp/WakeOnLanManagerStub.java",
]
Expand Down
114 changes: 70 additions & 44 deletions examples/tv-app/android/java/ChannelManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@
*/

#include "ChannelManager.h"
#include "TvApp-JNI.h"
#include <app-common/zap-generated/ids/Clusters.h>
#include <jni.h>
#include <lib/core/CHIPSafeCasts.h>
#include <lib/support/CHIPJNIError.h>
#include <lib/support/JniReferences.h>
Expand All @@ -24,13 +27,31 @@
using namespace chip;
using namespace chip::app::Clusters::Channel;

namespace {
static ChannelManager channelManager;
} // namespace
/** @brief Channel Cluster Init
*
* This function is called when a specific cluster is initialized. It gives the
* application an opportunity to take care of cluster initialization procedures.
* It is called exactly once for each endpoint where cluster is present.
*
* @param endpoint Ver.: always
*
*/
void emberAfChannelClusterInitCallback(EndpointId endpoint)
{
ChipLogProgress(Zcl, "TV Android App: Channel::PostClusterInit");
TvAppJNIMgr().PostClusterInit(chip::app::Clusters::Channel::Id, endpoint);
}

std::list<chip::app::Clusters::Channel::Structs::ChannelInfo::Type> ChannelManager::HandleGetChannelList()
void ChannelManager::NewManager(jint endpoint, jobject manager)
{
ChipLogProgress(Zcl, "TV Android App: Channel::SetDefaultDelegate");
ChannelManager * mgr = new ChannelManager();
mgr->InitializeWithObjects(manager);
chip::app::Clusters::Channel::SetDefaultDelegate(static_cast<EndpointId>(endpoint), mgr);
}

CHIP_ERROR ChannelManager::HandleGetChannelList(chip::app::AttributeValueEncoder & aEncoder)
{
std::list<Structs::ChannelInfo::Type> list;
CHIP_ERROR err = CHIP_NO_ERROR;
JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread();

Expand All @@ -39,9 +60,17 @@ std::list<chip::app::Clusters::Channel::Structs::ChannelInfo::Type> ChannelManag
VerifyOrExit(mGetChannelListMethod != nullptr, err = CHIP_ERROR_INCORRECT_STATE);
VerifyOrExit(env != NULL, err = CHIP_JNI_ERROR_NO_ENV);

{
return aEncoder.EncodeList([this, env](const auto & encoder) -> CHIP_ERROR {
jobjectArray channelInfoList = (jobjectArray) env->CallObjectMethod(mChannelManagerObject, mGetChannelListMethod);
jint length = env->GetArrayLength(channelInfoList);
if (env->ExceptionCheck())
{
ChipLogError(Zcl, "Java exception in ChannelManager::HandleGetChannelList");
env->ExceptionDescribe();
env->ExceptionClear();
return CHIP_ERROR_INCORRECT_STATE;
}

jint length = env->GetArrayLength(channelInfoList);

for (jint i = 0; i < length; i++)
{
Expand All @@ -62,15 +91,15 @@ std::list<chip::app::Clusters::Channel::Structs::ChannelInfo::Type> ChannelManag
if (jname != NULL)
{
JniUtfString name(env, jname);
channelInfo.callSign = name.charSpan();
channelInfo.name = name.charSpan();
}

jfieldID getJaffiliateCallSignField = env->GetFieldID(channelClass, "affiliateCallSign", "Ljava/lang/String;");
jstring jaffiliateCallSign = static_cast<jstring>(env->GetObjectField(channelObject, getJaffiliateCallSignField));
if (jaffiliateCallSign != NULL)
{
JniUtfString affiliateCallSign(env, jaffiliateCallSign);
channelInfo.callSign = affiliateCallSign.charSpan();
channelInfo.affiliateCallSign = affiliateCallSign.charSpan();
}

jfieldID majorNumField = env->GetFieldID(channelClass, "majorNumber", "I");
Expand All @@ -79,21 +108,24 @@ std::list<chip::app::Clusters::Channel::Structs::ChannelInfo::Type> ChannelManag

jfieldID minorNumField = env->GetFieldID(channelClass, "minorNumber", "I");
jint jminorNum = env->GetIntField(channelObject, minorNumField);
channelInfo.majorNumber = static_cast<uint16_t>(jminorNum);
list.push_back(channelInfo);
channelInfo.minorNumber = static_cast<uint16_t>(jminorNum);

ReturnErrorOnFailure(encoder.Encode(channelInfo));
}
}

return CHIP_NO_ERROR;
});

exit:
if (err != CHIP_NO_ERROR)
{
ChipLogError(Zcl, "ChannelManager::getChannelList status error: %s", err.AsString());
}

return list;
return err;
}

chip::app::Clusters::Channel::Structs::LineupInfo::Type ChannelManager::HandleGetLineup()
CHIP_ERROR ChannelManager::HandleGetLineup(chip::app::AttributeValueEncoder & aEncoder)
{
chip::app::Clusters::Channel::Structs::LineupInfo::Type lineupInfo;
CHIP_ERROR err = CHIP_NO_ERROR;
Expand Down Expand Up @@ -135,6 +167,8 @@ chip::app::Clusters::Channel::Structs::LineupInfo::Type ChannelManager::HandleGe
jfieldID lineupInfoTypeFild = env->GetFieldID(channelLineupClazz, "lineupInfoTypeEnum", "I");
jint jlineupInfoType = (env->GetIntField(channelLineupObject, lineupInfoTypeFild));
lineupInfo.lineupInfoType = static_cast<app::Clusters::Channel::LineupInfoTypeEnum>(jlineupInfoType);

err = aEncoder.Encode(lineupInfo);
}

exit:
Expand All @@ -143,10 +177,10 @@ chip::app::Clusters::Channel::Structs::LineupInfo::Type ChannelManager::HandleGe
ChipLogError(Zcl, "ChannelManager::getChannelLineup status error: %s", err.AsString());
}

return lineupInfo;
return err;
}

chip::app::Clusters::Channel::Structs::ChannelInfo::Type ChannelManager::HandleGetCurrentChannel()
CHIP_ERROR ChannelManager::HandleGetCurrentChannel(chip::app::AttributeValueEncoder & aEncoder)
{
chip::app::Clusters::Channel::Structs::ChannelInfo::Type channelInfo;
CHIP_ERROR err = CHIP_NO_ERROR;
Expand All @@ -173,15 +207,15 @@ chip::app::Clusters::Channel::Structs::ChannelInfo::Type ChannelManager::HandleG
if (jname != NULL)
{
JniUtfString name(env, jname);
channelInfo.callSign = name.charSpan();
channelInfo.name = name.charSpan();
}

jfieldID getJaffiliateCallSignField = env->GetFieldID(channelClass, "affiliateCallSign", "Ljava/lang/String;");
jstring jaffiliateCallSign = static_cast<jstring>(env->GetObjectField(channelInfoObject, getJaffiliateCallSignField));
if (jaffiliateCallSign != NULL)
{
JniUtfString affiliateCallSign(env, jaffiliateCallSign);
channelInfo.callSign = affiliateCallSign.charSpan();
channelInfo.affiliateCallSign = affiliateCallSign.charSpan();
}

jfieldID majorNumField = env->GetFieldID(channelClass, "majorNumber", "I");
Expand All @@ -190,7 +224,9 @@ chip::app::Clusters::Channel::Structs::ChannelInfo::Type ChannelManager::HandleG

jfieldID minorNumField = env->GetFieldID(channelClass, "minorNumber", "I");
jint jminorNum = env->GetIntField(channelInfoObject, minorNumField);
channelInfo.majorNumber = static_cast<uint16_t>(jminorNum);
channelInfo.minorNumber = static_cast<uint16_t>(jminorNum);

err = aEncoder.Encode(channelInfo);
}

exit:
Expand All @@ -199,10 +235,12 @@ chip::app::Clusters::Channel::Structs::ChannelInfo::Type ChannelManager::HandleG
ChipLogError(Zcl, "ChannelManager::HandleGetCurrentChannel status error: %s", err.AsString());
}

return channelInfo;
return err;
}

Commands::ChangeChannelResponse::Type ChannelManager::HandleChangeChannel(const chip::CharSpan & match)
void ChannelManager::HandleChangeChannel(
const chip::CharSpan & match,
chip::app::CommandResponseHelper<chip::app::Clusters::Channel::Commands::ChangeChannelResponse::Type> & responser)
{
std::string name(match.data(), match.size());
JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread();
Expand All @@ -225,11 +263,15 @@ Commands::ChangeChannelResponse::Type ChannelManager::HandleChangeChannel(const
ChipLogError(DeviceLayer, "Java exception in ChannelManager::HandleChangeChannel");
env->ExceptionDescribe();
env->ExceptionClear();
return response;
goto exit;
}

jclass channelClass = env->GetObjectClass(channelObject);

jfieldID getErrorTypeField = env->GetFieldID(channelClass, "errorType", "I");
jint jerrorType = env->GetIntField(channelObject, getErrorTypeField);
response.errorType = static_cast<app::Clusters::Channel::ErrorTypeEnum>(jerrorType);

jfieldID getCallSignField = env->GetFieldID(channelClass, "callSign", "Ljava/lang/String;");
jstring jcallSign = static_cast<jstring>(env->GetObjectField(channelObject, getCallSignField));
if (jcallSign != NULL)
Expand All @@ -243,14 +285,14 @@ Commands::ChangeChannelResponse::Type ChannelManager::HandleChangeChannel(const
if (jname != NULL)
{
JniUtfString junitname(env, jname);
response.channelMatch.callSign = junitname.charSpan();
response.channelMatch.name = junitname.charSpan();
}
jfieldID getJaffiliateCallSignField = env->GetFieldID(channelClass, "affiliateCallSign", "Ljava/lang/String;");
jstring jaffiliateCallSign = static_cast<jstring>(env->GetObjectField(channelObject, getJaffiliateCallSignField));
if (jaffiliateCallSign != NULL)
{
JniUtfString affiliateCallSign(env, jaffiliateCallSign);
response.channelMatch.callSign = affiliateCallSign.charSpan();
response.channelMatch.affiliateCallSign = affiliateCallSign.charSpan();
}

jfieldID majorNumField = env->GetFieldID(channelClass, "majorNumber", "I");
Expand All @@ -259,12 +301,13 @@ Commands::ChangeChannelResponse::Type ChannelManager::HandleChangeChannel(const

jfieldID minorNumField = env->GetFieldID(channelClass, "minorNumber", "I");
jint jminorNum = env->GetIntField(channelObject, minorNumField);
response.channelMatch.majorNumber = static_cast<uint16_t>(jminorNum);
response.channelMatch.minorNumber = static_cast<uint16_t>(jminorNum);

responser.Success(response);
}

exit:

return response;
return;
}

bool ChannelManager::HandleChangeChannelByNumber(const uint16_t & majorNumber, const uint16_t & minorNumber)
Expand Down Expand Up @@ -372,20 +415,3 @@ void ChannelManager::InitializeWithObjects(jobject managerObject)
env->ExceptionClear();
}
}

ChannelManager ChannelManager::sInstance;

/** @brief Channel Cluster Init
*
* This function is called when a specific cluster is initialized. It gives the
* application an opportunity to take care of cluster initialization procedures.
* It is called exactly once for each endpoint where cluster is present.
*
* @param endpoint Ver.: always
*
*/
void emberAfChannelClusterInitCallback(EndpointId endpoint)
{
ChipLogProgress(Zcl, "TV Android App: Channel::SetDefaultDelegate");
chip::app::Clusters::Channel::SetDefaultDelegate(endpoint, &channelManager);
}
19 changes: 7 additions & 12 deletions examples/tv-app/android/java/ChannelManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,20 +23,20 @@
class ChannelManager : public chip::app::Clusters::Channel::Delegate
{
public:
static void NewManager(jint endpoint, jobject manager);
void InitializeWithObjects(jobject managerObject);

std::list<chip::app::Clusters::Channel::Structs::ChannelInfo::Type> HandleGetChannelList() override;
chip::app::Clusters::Channel::Structs::LineupInfo::Type HandleGetLineup() override;
chip::app::Clusters::Channel::Structs::ChannelInfo::Type HandleGetCurrentChannel() override;
virtual CHIP_ERROR HandleGetChannelList(chip::app::AttributeValueEncoder & aEncoder) override;
virtual CHIP_ERROR HandleGetLineup(chip::app::AttributeValueEncoder & aEncoder) override;
virtual CHIP_ERROR HandleGetCurrentChannel(chip::app::AttributeValueEncoder & aEncoder) override;

chip::app::Clusters::Channel::Commands::ChangeChannelResponse::Type HandleChangeChannel(const chip::CharSpan & match) override;
virtual void HandleChangeChannel(
const chip::CharSpan & match,
chip::app::CommandResponseHelper<chip::app::Clusters::Channel::Commands::ChangeChannelResponse::Type> & responser) override;
bool HandleChangeChannelByNumber(const uint16_t & majorNumber, const uint16_t & minorNumber) override;
bool HandleSkipChannel(const uint16_t & count) override;

private:
friend ChannelManager & ChannelMgr();

static ChannelManager sInstance;
jobject mChannelManagerObject = nullptr;
jmethodID mGetChannelListMethod = nullptr;
jmethodID mGetLineupMethod = nullptr;
Expand All @@ -46,8 +46,3 @@ class ChannelManager : public chip::app::Clusters::Channel::Delegate
jmethodID mChangeChannelByNumberMethod = nullptr;
jmethodID mSkipChannelMethod = nullptr;
};

inline class ChannelManager & ChannelMgr()
{
return ChannelManager::sInstance;
}
Loading

0 comments on commit 1410484

Please sign in to comment.