Skip to content

Commit

Permalink
Enable content launcher test for tv app (#12961)
Browse files Browse the repository at this point in the history
* Enable test and connect the logic

* Zap generate files

* Enabled List of Strings in java template

* Run zap regen tool

* Added delegate methods for attributes, updated linux and android tv app

* Updated code per comments

* Run zap regen

* Restyle fix
  • Loading branch information
lazarkov authored Dec 16, 2021
1 parent 00ec330 commit 5988375
Show file tree
Hide file tree
Showing 55 changed files with 4,351 additions and 549 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14460,7 +14460,7 @@
],
"attributes": [
{
"name": "accepts header list",
"name": "accept header list",
"code": 0,
"mfgCode": null,
"side": "server",
Expand Down
3 changes: 3 additions & 0 deletions examples/all-clusters-app/linux/include/tv-callbacks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@
*******************************************************************************
******************************************************************************/

#include <list>
#include <string>

bool lowPowerClusterSleep()
{
return true;
Expand Down
1 change: 1 addition & 0 deletions examples/chip-tool/templates/tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ function getTests()
'TV_MediaPlaybackCluster',
'TV_TvChannelCluster',
'TV_LowPowerCluster',
'TV_ContentLauncherCluster',
'TV_MediaInputCluster',
];

Expand Down
2 changes: 1 addition & 1 deletion examples/thermostat/thermostat-common/thermostat.zap
Original file line number Diff line number Diff line change
Expand Up @@ -13120,7 +13120,7 @@
],
"attributes": [
{
"name": "accepts header list",
"name": "accept header list",
"code": 0,
"mfgCode": null,
"side": "server",
Expand Down
329 changes: 127 additions & 202 deletions examples/tv-app/android/java/ContentLauncherManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,206 +45,9 @@ using namespace chip;

ContentLauncherManager ContentLauncherManager::sInstance;

namespace {

class ContentLauncherAttrAccess : public app::AttributeAccessInterface
{
public:
ContentLauncherAttrAccess() : app::AttributeAccessInterface(Optional<EndpointId>::Missing(), app::Clusters::ContentLauncher::Id)
{}

CHIP_ERROR Read(const app::ConcreteReadAttributePath & aPath, app::AttributeValueEncoder & aEncoder) override
{
if (aPath.mAttributeId == app::Clusters::ContentLauncher::Attributes::AcceptsHeaderList::Id)
{
return ContentLauncherMgr().GetAcceptsHeader(aEncoder);
}
else if (aPath.mAttributeId == app::Clusters::ContentLauncher::Attributes::SupportedStreamingProtocols::Id)
{
return ContentLauncherMgr().GetSupportedStreamingTypes(aEncoder);
}

return CHIP_NO_ERROR;
}
};

ContentLauncherAttrAccess gContentLauncherAttrAccess;

} // anonymous namespace

/** @brief Content Launch 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 emberAfContentLauncherClusterInitCallback(EndpointId endpoint)
{
static bool attrAccessRegistered = false;
if (!attrAccessRegistered)
{
registerAttributeAccessOverride(&gContentLauncherAttrAccess);
attrAccessRegistered = true;
}
}

ContentLaunchResponse contentLauncherClusterLaunchContent(chip::EndpointId endpointId,
std::list<ContentLaunchParamater> parameterList, bool autoplay,
const chip::CharSpan & data)
{
return ContentLauncherMgr().LaunchContent(endpointId, parameterList, autoplay, data);
}

ContentLaunchResponse contentLauncherClusterLaunchUrl(const chip::CharSpan & contentUrl, const chip::CharSpan & displayString,
ContentLaunchBrandingInformation & brandingInformation)
{
return ContentLauncherMgr().LaunchUrl(contentUrl, displayString, brandingInformation);
}

void ContentLauncherManager::InitializeWithObjects(jobject managerObject)
{
JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread();
VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Failed to GetEnvForCurrentThread for ContentLauncherManager"));

mContentLauncherManagerObject = env->NewGlobalRef(managerObject);
VerifyOrReturn(mContentLauncherManagerObject != nullptr, ChipLogError(Zcl, "Failed to NewGlobalRef ContentLauncherManager"));

jclass ContentLauncherClass = env->GetObjectClass(managerObject);
VerifyOrReturn(ContentLauncherClass != nullptr, ChipLogError(Zcl, "Failed to get ContentLauncherManager Java class"));

mGetAcceptsHeaderMethod = env->GetMethodID(ContentLauncherClass, "getAcceptsHeader", "()[Ljava/lang/String;");
if (mGetAcceptsHeaderMethod == nullptr)
{
ChipLogError(Zcl, "Failed to access MediaInputManager 'getInputList' method");
env->ExceptionClear();
}

mGetSupportedStreamingTypesMethod = env->GetMethodID(ContentLauncherClass, "getSupportedStreamingTypes", "()[I");
if (mGetSupportedStreamingTypesMethod == nullptr)
{
ChipLogError(Zcl, "Failed to access MediaInputManager 'getSupportedStreamingTypes' method");
env->ExceptionClear();
}

mLaunchContentMethod = env->GetMethodID(
ContentLauncherClass, "launchContent",
"([Lcom/tcl/chip/tvapp/ContentLaunchSearchParameter;ZLjava/lang/String;)Lcom/tcl/chip/tvapp/ContentLaunchResponse;");
if (mLaunchContentMethod == nullptr)
{
ChipLogError(Zcl, "Failed to access MediaInputManager 'launchContent' method");
env->ExceptionClear();
}

mLaunchUrlMethod = env->GetMethodID(ContentLauncherClass, "launchUrl",
"(Ljava/lang/String;Ljava/lang/String;Lcom/tcl/chip/tvapp/"
"ContentLaunchBrandingInformation;)Lcom/tcl/chip/tvapp/ContentLaunchResponse;");
if (mLaunchUrlMethod == nullptr)
{
ChipLogError(AppServer, "Failed to access 'launchUrl' method");
env->ExceptionClear();
}
}

CHIP_ERROR ContentLauncherManager::GetAcceptsHeader(chip::app::AttributeValueEncoder & aEncoder)
{
CHIP_ERROR err = CHIP_NO_ERROR;
JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread();

ChipLogProgress(Zcl, "Received ContentLauncherManager::GetAcceptsHeader");
VerifyOrExit(mContentLauncherManagerObject != nullptr, err = CHIP_ERROR_INCORRECT_STATE);
VerifyOrExit(mGetAcceptsHeaderMethod != 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 headersArray = (jobjectArray) env->CallObjectMethod(mContentLauncherManagerObject, mGetAcceptsHeaderMethod);
if (env->ExceptionCheck())
{
ChipLogError(Zcl, "Java exception in ContentLauncherManager::GetAcceptsHeader");
env->ExceptionDescribe();
env->ExceptionClear();
return CHIP_ERROR_INCORRECT_STATE;
}

jint size = env->GetArrayLength(headersArray);
for (int i = 0; i < size; i++)
{
jstring acceptsheader = (jstring) env->GetObjectArrayElement(headersArray, i);
if (acceptsheader != nullptr)
{
JniUtfString header(env, acceptsheader);

chip::ByteSpan bHeader((const uint8_t *) (header.c_str()), (size_t)(header.size()));
ReturnErrorOnFailure(encoder.Encode(bHeader));

// Todo: should be chanSpan?
// ReturnErrorOnFailure(encoder.Encode(header.charSpan()));
}
}

return CHIP_NO_ERROR;
});

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

return err;
}

CHIP_ERROR ContentLauncherManager::GetSupportedStreamingTypes(chip::app::AttributeValueEncoder & aEncoder)
{
CHIP_ERROR err = CHIP_NO_ERROR;
JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread();

ChipLogProgress(Zcl, "Received ContentLauncherManager::GetSupportedStreamingTypes");
VerifyOrExit(mContentLauncherManagerObject != nullptr, err = CHIP_ERROR_INCORRECT_STATE);
VerifyOrExit(mGetSupportedStreamingTypesMethod != 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 {
jintArray typesArray = (jintArray) env->CallObjectMethod(mContentLauncherManagerObject, mGetSupportedStreamingTypesMethod);
if (env->ExceptionCheck())
{
ChipLogError(Zcl, "Java exception in ContentLauncherManager::GetSupportedStreamingTypes");
env->ExceptionDescribe();
env->ExceptionClear();
return CHIP_ERROR_INCORRECT_STATE;
}

jboolean isCopy = JNI_FALSE;
jint * ptypes = env->GetIntArrayElements(typesArray, &isCopy);
jint size = env->GetArrayLength(typesArray);

CHIP_ERROR err = CHIP_NO_ERROR;
for (int i = 0; i < size; i++)
{
err = encoder.Encode(static_cast<uint8_t>(ptypes[i]));
if (err != CHIP_NO_ERROR)
{
break;
}
}
env->ReleaseIntArrayElements(typesArray, ptypes, 0);
return err;
});

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

return err;
}

ContentLaunchResponse ContentLauncherManager::LaunchContent(chip::EndpointId endpointId,
std::list<ContentLaunchParamater> parameterList, bool autoplay,
const chip::CharSpan & data)
ContentLaunchResponse ContentLauncherManager::HandleLaunchContent(chip::EndpointId endpointId,
const std::list<ContentLaunchParamater> & parameterList,
bool autoplay, const chip::CharSpan & data)
{
ContentLaunchResponse response;
CHIP_ERROR err = CHIP_NO_ERROR;
Expand Down Expand Up @@ -297,8 +100,9 @@ ContentLaunchResponse ContentLauncherManager::LaunchContent(chip::EndpointId end
return response;
}

ContentLaunchResponse ContentLauncherManager::LaunchUrl(const chip::CharSpan & contentUrl, const chip::CharSpan & displayString,
ContentLaunchBrandingInformation & brandingInformation)
ContentLaunchResponse
ContentLauncherManager::HandleLaunchUrl(const chip::CharSpan & contentUrl, const chip::CharSpan & displayString,
const std::list<ContentLaunchBrandingInformation> & brandingInformation)
{
ContentLaunchResponse response;
CHIP_ERROR err = CHIP_NO_ERROR;
Expand Down Expand Up @@ -351,3 +155,124 @@ ContentLaunchResponse ContentLauncherManager::LaunchUrl(const chip::CharSpan & c

return response;
}

std::list<std::string> ContentLauncherManager::HandleGetAcceptHeaderList()
{
CHIP_ERROR err = CHIP_NO_ERROR;
JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread();
std::list<std::string> acceptedHeadersList;

ChipLogProgress(Zcl, "Received ContentLauncherManager::GetAcceptHeader");
VerifyOrExit(mContentLauncherManagerObject != nullptr, err = CHIP_ERROR_INCORRECT_STATE);
VerifyOrExit(mGetAcceptHeaderMethod != nullptr, err = CHIP_ERROR_INCORRECT_STATE);
VerifyOrExit(env != NULL, err = CHIP_JNI_ERROR_NO_ENV);

{
jobjectArray acceptedHeadersArray =
(jobjectArray) env->CallObjectMethod(mContentLauncherManagerObject, mGetAcceptHeaderMethod);
if (env->ExceptionCheck())
{
ChipLogError(Zcl, "Java exception in ContentLauncherManager::GetAcceptHeader");
env->ExceptionDescribe();
env->ExceptionClear();
err = CHIP_ERROR_INCORRECT_STATE;
goto exit;
}

jint size = env->GetArrayLength(acceptedHeadersArray);
for (int i = 0; i < size; i++)
{

jstring jAcceptedHeader = (jstring) env->GetObjectArrayElement(acceptedHeadersArray, i);
const char * convertedValue = (env)->GetStringUTFChars(jAcceptedHeader, JNI_FALSE);
std::string acceptedHeader = std::string(convertedValue, strlen(convertedValue));
acceptedHeadersList.push_front(acceptedHeader);
}
}

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

return acceptedHeadersList;
}

uint32_t ContentLauncherManager::HandleGetSupportedStreamingProtocols()
{
CHIP_ERROR err = CHIP_NO_ERROR;
JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread();
uint32_t supportedStreamingProtocols = 0;

ChipLogProgress(Zcl, "Received ContentLauncherManager::GetSupportedStreamingProtocols");
VerifyOrExit(mContentLauncherManagerObject != nullptr, err = CHIP_ERROR_INCORRECT_STATE);
VerifyOrExit(mGetSupportedStreamingProtocolsMethod != nullptr, err = CHIP_ERROR_INCORRECT_STATE);
VerifyOrExit(env != NULL, err = CHIP_JNI_ERROR_NO_ENV);

{
jint jSupportedStreamingProtocols =
env->CallIntMethod(mContentLauncherManagerObject, mGetSupportedStreamingProtocolsMethod);
supportedStreamingProtocols = (uint32_t) jSupportedStreamingProtocols;
if (env->ExceptionCheck())
{
ChipLogError(Zcl, "Java exception in ContentLauncherManager::GetAcceptHeader");
env->ExceptionDescribe();
env->ExceptionClear();
err = CHIP_ERROR_INCORRECT_STATE;
goto exit;
}
}

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

return supportedStreamingProtocols;
}

void ContentLauncherManager::InitializeWithObjects(jobject managerObject)
{
JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread();
VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Failed to GetEnvForCurrentThread for ContentLauncherManager"));

mContentLauncherManagerObject = env->NewGlobalRef(managerObject);
VerifyOrReturn(mContentLauncherManagerObject != nullptr, ChipLogError(Zcl, "Failed to NewGlobalRef ContentLauncherManager"));

jclass ContentLauncherClass = env->GetObjectClass(managerObject);
VerifyOrReturn(ContentLauncherClass != nullptr, ChipLogError(Zcl, "Failed to get ContentLauncherManager Java class"));

mGetAcceptHeaderMethod = env->GetMethodID(ContentLauncherClass, "getAcceptHeader", "()[Ljava/lang/String;");
if (mGetAcceptHeaderMethod == nullptr)
{
ChipLogError(Zcl, "Failed to access MediaInputManager 'getInputList' method");
env->ExceptionClear();
}

mGetSupportedStreamingProtocolsMethod = env->GetMethodID(ContentLauncherClass, "getSupportedStreamingProtocols", "()[I");
if (mGetSupportedStreamingProtocolsMethod == nullptr)
{
ChipLogError(Zcl, "Failed to access MediaInputManager 'getSupportedStreamingProtocols' method");
env->ExceptionClear();
}

mLaunchContentMethod = env->GetMethodID(
ContentLauncherClass, "launchContent",
"([Lcom/tcl/chip/tvapp/ContentLaunchSearchParameter;ZLjava/lang/String;)Lcom/tcl/chip/tvapp/ContentLaunchResponse;");
if (mLaunchContentMethod == nullptr)
{
ChipLogError(Zcl, "Failed to access MediaInputManager 'launchContent' method");
env->ExceptionClear();
}

mLaunchUrlMethod = env->GetMethodID(ContentLauncherClass, "launchUrl",
"(Ljava/lang/String;Ljava/lang/String;Lcom/tcl/chip/tvapp/"
"ContentLaunchBrandingInformation;)Lcom/tcl/chip/tvapp/ContentLaunchResponse;");
if (mLaunchUrlMethod == nullptr)
{
ChipLogError(AppServer, "Failed to access 'launchUrl' method");
env->ExceptionClear();
}
}
Loading

0 comments on commit 5988375

Please sign in to comment.