ChannelManager.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408
  1. /**
  2. *
  3. * Copyright (c) 2021 Project CHIP Authors
  4. *
  5. * Licensed under the Apache License, Version 2.0 (the "License");
  6. * you may not use this file except in compliance with the License.
  7. * You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. */
  17. #include "ChannelManager.h"
  18. #include "TvApp-JNI.h"
  19. #include <app-common/zap-generated/ids/Clusters.h>
  20. #include <cstdlib>
  21. #include <jni.h>
  22. #include <lib/core/CHIPSafeCasts.h>
  23. #include <lib/support/CHIPJNIError.h>
  24. #include <lib/support/JniReferences.h>
  25. #include <lib/support/JniTypeWrappers.h>
  26. using namespace chip;
  27. using namespace chip::app;
  28. using namespace chip::app::Clusters::Channel;
  29. using namespace chip::Uint8;
  30. /** @brief Channel Cluster Init
  31. *
  32. * This function is called when a specific cluster is initialized. It gives the
  33. * application an opportunity to take care of cluster initialization procedures.
  34. * It is called exactly once for each endpoint where cluster is present.
  35. *
  36. * @param endpoint Ver.: always
  37. *
  38. */
  39. void emberAfChannelClusterInitCallback(EndpointId endpoint)
  40. {
  41. ChipLogProgress(Zcl, "TV Android App: Channel::PostClusterInit");
  42. TvAppJNIMgr().PostClusterInit(chip::app::Clusters::Channel::Id, endpoint);
  43. }
  44. void ChannelManager::NewManager(jint endpoint, jobject manager)
  45. {
  46. ChipLogProgress(Zcl, "TV Android App: Channel::SetDefaultDelegate");
  47. ChannelManager * mgr = new ChannelManager();
  48. mgr->InitializeWithObjects(manager);
  49. chip::app::Clusters::Channel::SetDefaultDelegate(static_cast<EndpointId>(endpoint), mgr);
  50. }
  51. CHIP_ERROR ChannelManager::HandleGetChannelList(AttributeValueEncoder & aEncoder)
  52. {
  53. CHIP_ERROR err = CHIP_NO_ERROR;
  54. JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread();
  55. ChipLogProgress(Zcl, "Received ChannelManager::HandleGetChannelList");
  56. VerifyOrExit(mChannelManagerObject != nullptr, err = CHIP_ERROR_INCORRECT_STATE);
  57. VerifyOrExit(mGetChannelListMethod != nullptr, err = CHIP_ERROR_INCORRECT_STATE);
  58. VerifyOrExit(env != NULL, err = CHIP_JNI_ERROR_NO_ENV);
  59. return aEncoder.EncodeList([this, env](const auto & encoder) -> CHIP_ERROR {
  60. jobjectArray channelInfoList = (jobjectArray) env->CallObjectMethod(mChannelManagerObject, mGetChannelListMethod);
  61. if (env->ExceptionCheck())
  62. {
  63. ChipLogError(Zcl, "Java exception in ChannelManager::HandleGetChannelList");
  64. env->ExceptionDescribe();
  65. env->ExceptionClear();
  66. return CHIP_ERROR_INCORRECT_STATE;
  67. }
  68. jint length = env->GetArrayLength(channelInfoList);
  69. for (jint i = 0; i < length; i++)
  70. {
  71. chip::app::Clusters::Channel::Structs::ChannelInfo::Type channelInfo;
  72. jobject channelObject = env->GetObjectArrayElement(channelInfoList, i);
  73. jclass channelClass = env->GetObjectClass(channelObject);
  74. jfieldID getCallSignField = env->GetFieldID(channelClass, "callSign", "Ljava/lang/String;");
  75. jstring jcallSign = static_cast<jstring>(env->GetObjectField(channelObject, getCallSignField));
  76. JniUtfString callsign(env, jcallSign);
  77. if (jcallSign != nullptr)
  78. {
  79. channelInfo.callSign = Optional<CharSpan>(callsign.charSpan());
  80. }
  81. jfieldID getNameField = env->GetFieldID(channelClass, "name", "Ljava/lang/String;");
  82. jstring jname = static_cast<jstring>(env->GetObjectField(channelObject, getNameField));
  83. JniUtfString name(env, jname);
  84. if (jname != nullptr)
  85. {
  86. channelInfo.name = Optional<CharSpan>(name.charSpan());
  87. }
  88. jfieldID getJaffiliateCallSignField = env->GetFieldID(channelClass, "affiliateCallSign", "Ljava/lang/String;");
  89. jstring jaffiliateCallSign = static_cast<jstring>(env->GetObjectField(channelObject, getJaffiliateCallSignField));
  90. JniUtfString affiliateCallSign(env, jaffiliateCallSign);
  91. if (jaffiliateCallSign != nullptr)
  92. {
  93. channelInfo.affiliateCallSign = Optional<CharSpan>(affiliateCallSign.charSpan());
  94. }
  95. jfieldID majorNumField = env->GetFieldID(channelClass, "majorNumber", "I");
  96. jint jmajorNum = env->GetIntField(channelObject, majorNumField);
  97. channelInfo.majorNumber = static_cast<uint16_t>(jmajorNum);
  98. jfieldID minorNumField = env->GetFieldID(channelClass, "minorNumber", "I");
  99. jint jminorNum = env->GetIntField(channelObject, minorNumField);
  100. channelInfo.minorNumber = static_cast<uint16_t>(jminorNum);
  101. ReturnErrorOnFailure(encoder.Encode(channelInfo));
  102. }
  103. return CHIP_NO_ERROR;
  104. });
  105. exit:
  106. if (err != CHIP_NO_ERROR)
  107. {
  108. ChipLogError(Zcl, "ChannelManager::getChannelList status error: %s", err.AsString());
  109. }
  110. return err;
  111. }
  112. CHIP_ERROR ChannelManager::HandleGetLineup(AttributeValueEncoder & aEncoder)
  113. {
  114. chip::app::Clusters::Channel::Structs::LineupInfo::Type lineupInfo;
  115. CHIP_ERROR err = CHIP_NO_ERROR;
  116. JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread();
  117. ChipLogProgress(Zcl, "Received ChannelManager::HandleGetLineup");
  118. VerifyOrExit(mChannelManagerObject != nullptr, err = CHIP_ERROR_INCORRECT_STATE);
  119. VerifyOrExit(mGetLineupMethod != nullptr, err = CHIP_ERROR_INCORRECT_STATE);
  120. VerifyOrExit(env != NULL, err = CHIP_JNI_ERROR_NO_ENV);
  121. {
  122. jobject channelLineupObject = env->CallObjectMethod(mChannelManagerObject, mGetLineupMethod);
  123. if (channelLineupObject != nullptr)
  124. {
  125. jclass channelLineupClazz = env->GetObjectClass(channelLineupObject);
  126. jfieldID operatorNameFild = env->GetFieldID(channelLineupClazz, "operatorName", "Ljava/lang/String;");
  127. jstring joperatorName = static_cast<jstring>(env->GetObjectField(channelLineupObject, operatorNameFild));
  128. JniUtfString operatorName(env, joperatorName);
  129. if (joperatorName != nullptr)
  130. {
  131. lineupInfo.operatorName = operatorName.charSpan();
  132. }
  133. jfieldID lineupNameFild = env->GetFieldID(channelLineupClazz, "lineupName", "Ljava/lang/String;");
  134. jstring jlineupName = static_cast<jstring>(env->GetObjectField(channelLineupObject, lineupNameFild));
  135. JniUtfString lineupName(env, jlineupName);
  136. if (jlineupName != nullptr)
  137. {
  138. lineupInfo.lineupName = Optional<CharSpan>(lineupName.charSpan());
  139. }
  140. jfieldID postalCodeFild = env->GetFieldID(channelLineupClazz, "postalCode", "Ljava/lang/String;");
  141. jstring jpostalCode = static_cast<jstring>(env->GetObjectField(channelLineupObject, postalCodeFild));
  142. JniUtfString postalCode(env, jpostalCode);
  143. if (jpostalCode != nullptr)
  144. {
  145. lineupInfo.postalCode = Optional<CharSpan>(postalCode.charSpan());
  146. }
  147. jfieldID lineupInfoTypeFild = env->GetFieldID(channelLineupClazz, "lineupInfoType", "I");
  148. jint jlineupInfoType = (env->GetIntField(channelLineupObject, lineupInfoTypeFild));
  149. lineupInfo.lineupInfoType = static_cast<app::Clusters::Channel::LineupInfoTypeEnum>(jlineupInfoType);
  150. err = aEncoder.Encode(lineupInfo);
  151. }
  152. else
  153. {
  154. err = aEncoder.EncodeNull();
  155. }
  156. }
  157. exit:
  158. if (err != CHIP_NO_ERROR)
  159. {
  160. ChipLogError(Zcl, "ChannelManager::getChannelLineup status error: %s", err.AsString());
  161. }
  162. return err;
  163. }
  164. CHIP_ERROR ChannelManager::HandleGetCurrentChannel(AttributeValueEncoder & aEncoder)
  165. {
  166. chip::app::Clusters::Channel::Structs::ChannelInfo::Type channelInfo;
  167. CHIP_ERROR err = CHIP_NO_ERROR;
  168. JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread();
  169. ChipLogProgress(Zcl, "Received ChannelManager::HandleGetCurrentChannel");
  170. VerifyOrExit(mChannelManagerObject != nullptr, err = CHIP_ERROR_INCORRECT_STATE);
  171. VerifyOrExit(mGetCurrentChannelMethod != nullptr, err = CHIP_ERROR_INCORRECT_STATE);
  172. VerifyOrExit(env != NULL, err = CHIP_JNI_ERROR_NO_ENV);
  173. {
  174. jobject channelInfoObject = env->CallObjectMethod(mChannelManagerObject, mGetCurrentChannelMethod);
  175. if (channelInfoObject != nullptr)
  176. {
  177. jclass channelClass = env->GetObjectClass(channelInfoObject);
  178. jfieldID getCallSignField = env->GetFieldID(channelClass, "callSign", "Ljava/lang/String;");
  179. jstring jcallSign = static_cast<jstring>(env->GetObjectField(channelInfoObject, getCallSignField));
  180. JniUtfString callsign(env, jcallSign);
  181. if (jcallSign != nullptr)
  182. {
  183. channelInfo.callSign = Optional<CharSpan>(callsign.charSpan());
  184. }
  185. jfieldID getNameField = env->GetFieldID(channelClass, "name", "Ljava/lang/String;");
  186. jstring jname = static_cast<jstring>(env->GetObjectField(channelInfoObject, getNameField));
  187. JniUtfString name(env, jname);
  188. if (jname != nullptr)
  189. {
  190. channelInfo.name = Optional<CharSpan>(name.charSpan());
  191. }
  192. jfieldID getJaffiliateCallSignField = env->GetFieldID(channelClass, "affiliateCallSign", "Ljava/lang/String;");
  193. jstring jaffiliateCallSign = static_cast<jstring>(env->GetObjectField(channelInfoObject, getJaffiliateCallSignField));
  194. JniUtfString affiliateCallSign(env, jaffiliateCallSign);
  195. if (jaffiliateCallSign != nullptr)
  196. {
  197. channelInfo.affiliateCallSign = Optional<CharSpan>(affiliateCallSign.charSpan());
  198. }
  199. jfieldID majorNumField = env->GetFieldID(channelClass, "majorNumber", "I");
  200. jint jmajorNum = env->GetIntField(channelInfoObject, majorNumField);
  201. channelInfo.majorNumber = static_cast<uint16_t>(jmajorNum);
  202. jfieldID minorNumField = env->GetFieldID(channelClass, "minorNumber", "I");
  203. jint jminorNum = env->GetIntField(channelInfoObject, minorNumField);
  204. channelInfo.minorNumber = static_cast<uint16_t>(jminorNum);
  205. err = aEncoder.Encode(channelInfo);
  206. }
  207. else
  208. {
  209. err = aEncoder.EncodeNull();
  210. return err;
  211. }
  212. }
  213. exit:
  214. if (err != CHIP_NO_ERROR)
  215. {
  216. ChipLogError(Zcl, "ChannelManager::HandleGetCurrentChannel status error: %s", err.AsString());
  217. }
  218. return err;
  219. }
  220. void ChannelManager::HandleChangeChannel(CommandResponseHelper<ChangeChannelResponseType> & helper, const CharSpan & match)
  221. {
  222. std::string name(match.data(), match.size());
  223. JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread();
  224. ChipLogProgress(Zcl, "Received ChannelManager::HandleChangeChannel name %s", name.c_str());
  225. VerifyOrExit(mChannelManagerObject != nullptr, ChipLogError(Zcl, "mChannelManagerObject null"));
  226. VerifyOrExit(mChangeChannelMethod != nullptr, ChipLogError(Zcl, "mChangeChannelMethod null"));
  227. VerifyOrExit(env != NULL, ChipLogError(Zcl, "env null"));
  228. {
  229. UtfString jniname(env, name.c_str());
  230. env->ExceptionClear();
  231. jobject channelObject = env->CallObjectMethod(mChannelManagerObject, mChangeChannelMethod, jniname.jniValue());
  232. if (env->ExceptionCheck())
  233. {
  234. ChipLogError(DeviceLayer, "Java exception in ChannelManager::HandleChangeChannel");
  235. env->ExceptionDescribe();
  236. env->ExceptionClear();
  237. goto exit;
  238. }
  239. jclass channelClass = env->GetObjectClass(channelObject);
  240. ChangeChannelResponseType response;
  241. jfieldID getStatusField = env->GetFieldID(channelClass, "status", "I");
  242. jint jstatus = env->GetIntField(channelObject, getStatusField);
  243. response.status = static_cast<app::Clusters::Channel::ChannelStatusEnum>(jstatus);
  244. jfieldID getNameField = env->GetFieldID(channelClass, "name", "Ljava/lang/String;");
  245. jstring jname = static_cast<jstring>(env->GetObjectField(channelObject, getNameField));
  246. JniUtfString junitname(env, jname);
  247. if (jname != NULL)
  248. {
  249. response.data = MakeOptional(junitname.charSpan());
  250. }
  251. helper.Success(response);
  252. }
  253. exit:
  254. return;
  255. }
  256. bool ChannelManager::HandleChangeChannelByNumber(const uint16_t & majorNumber, const uint16_t & minorNumber)
  257. {
  258. jboolean ret = JNI_FALSE;
  259. JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread();
  260. ChipLogProgress(Zcl, "Received ChannelManager::HandleChangeChannelByNumber majorNumber %d, minorNumber %d", majorNumber,
  261. minorNumber);
  262. VerifyOrExit(mChannelManagerObject != nullptr, ChipLogError(Zcl, "mChannelManagerObject null"));
  263. VerifyOrExit(mChangeChannelByNumberMethod != nullptr, ChipLogError(Zcl, "mChangeChannelByNumberMethod null"));
  264. VerifyOrExit(env != NULL, ChipLogError(Zcl, "env null"));
  265. env->ExceptionClear();
  266. ret = env->CallBooleanMethod(mChannelManagerObject, mChangeChannelByNumberMethod, static_cast<jint>(majorNumber),
  267. static_cast<jint>(minorNumber));
  268. if (env->ExceptionCheck())
  269. {
  270. ChipLogError(DeviceLayer, "Java exception in ChannelManager::changeChannelByNumber");
  271. env->ExceptionDescribe();
  272. env->ExceptionClear();
  273. return false;
  274. }
  275. exit:
  276. return static_cast<bool>(ret);
  277. }
  278. bool ChannelManager::HandleSkipChannel(const uint16_t & count)
  279. {
  280. jboolean ret = JNI_FALSE;
  281. JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread();
  282. ChipLogProgress(Zcl, "Received ChannelManager::HandleSkipChannel count %d", count);
  283. VerifyOrExit(mChannelManagerObject != nullptr, ChipLogError(Zcl, "mChannelManagerObject null"));
  284. VerifyOrExit(mSkipChannelMethod != nullptr, ChipLogError(Zcl, "mSkipChannelMethod null"));
  285. VerifyOrExit(env != NULL, ChipLogError(Zcl, "env null"));
  286. env->ExceptionClear();
  287. ret = env->CallBooleanMethod(mChannelManagerObject, mSkipChannelMethod, static_cast<jint>(count));
  288. if (env->ExceptionCheck())
  289. {
  290. ChipLogError(DeviceLayer, "Java exception in ChannelManager::HandleSkipChannel");
  291. env->ExceptionDescribe();
  292. env->ExceptionClear();
  293. return false;
  294. }
  295. exit:
  296. return static_cast<bool>(ret);
  297. }
  298. void ChannelManager::InitializeWithObjects(jobject managerObject)
  299. {
  300. JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread();
  301. VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Failed to GetEnvForCurrentThread for ChannelManager"));
  302. mChannelManagerObject = env->NewGlobalRef(managerObject);
  303. VerifyOrReturn(mChannelManagerObject != nullptr, ChipLogError(Zcl, "Failed to NewGlobalRef ChannelManager"));
  304. jclass managerClass = env->GetObjectClass(mChannelManagerObject);
  305. VerifyOrReturn(managerClass != nullptr, ChipLogError(Zcl, "Failed to get ChannelManager Java class"));
  306. mGetChannelListMethod = env->GetMethodID(managerClass, "getChannelList", "()[Lcom/tcl/chip/tvapp/ChannelInfo;");
  307. if (mGetChannelListMethod == nullptr)
  308. {
  309. ChipLogError(Zcl, "Failed to access ChannelManager 'getChannelList' method");
  310. env->ExceptionClear();
  311. }
  312. mGetLineupMethod = env->GetMethodID(managerClass, "getLineup", "()Lcom/tcl/chip/tvapp/ChannelLineupInfo;");
  313. if (mGetLineupMethod == nullptr)
  314. {
  315. ChipLogError(Zcl, "Failed to access ChannelManager 'getLineup' method");
  316. env->ExceptionClear();
  317. }
  318. mGetCurrentChannelMethod = env->GetMethodID(managerClass, "getCurrentChannel", "()Lcom/tcl/chip/tvapp/ChannelInfo;");
  319. if (mGetCurrentChannelMethod == nullptr)
  320. {
  321. ChipLogError(Zcl, "Failed to access ChannelManager 'getCurrentChannel' method");
  322. env->ExceptionClear();
  323. }
  324. mChangeChannelMethod = env->GetMethodID(managerClass, "changeChannel", "(Ljava/lang/String;)Lcom/tcl/chip/tvapp/ChannelInfo;");
  325. if (mChangeChannelMethod == nullptr)
  326. {
  327. ChipLogError(Zcl, "Failed to access ChannelManager 'changeChannel' method");
  328. env->ExceptionClear();
  329. }
  330. mChangeChannelByNumberMethod = env->GetMethodID(managerClass, "changeChannelByNumber", "(II)Z");
  331. if (mChangeChannelByNumberMethod == nullptr)
  332. {
  333. ChipLogError(Zcl, "Failed to access ChannelManager 'changeChannelByNumber' method");
  334. env->ExceptionClear();
  335. }
  336. mSkipChannelMethod = env->GetMethodID(managerClass, "skipChannel", "(I)Z");
  337. if (mSkipChannelMethod == nullptr)
  338. {
  339. ChipLogError(Zcl, "Failed to access ChannelManager 'skipChannel' method");
  340. env->ExceptionClear();
  341. }
  342. }