ChannelManager.cpp 17 KB

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