/* * * 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 "AppPlatformShellCommands-JNI.h" #include "AppImpl.h" #include "TvApp-JNI.h" #include #include #include #include #include #include #include #if CHIP_DEVICE_CONFIG_APP_PLATFORM_ENABLED #include #endif // CHIP_DEVICE_CONFIG_APP_PLATFORM_ENABLED using namespace chip; char response[1024]; using namespace ::chip::Controller; #if CHIP_DEVICE_CONFIG_APP_PLATFORM_ENABLED using namespace chip::AppPlatform; using namespace chip::Access; #endif // CHIP_DEVICE_CONFIG_APP_PLATFORM_ENABLED using namespace chip::app::Clusters; #if CHIP_DEVICE_CONFIG_APP_PLATFORM_ENABLED static CHIP_ERROR pairApp(bool printHeader, size_t index) { if (printHeader) { char str[64]; sprintf(str, "udc-commission %ld\r\n", static_cast(index)); strcat(response, str); } DeviceCommissioner * commissioner = GetDeviceCommissioner(); UDCClientState * state = commissioner->GetUserDirectedCommissioningServer()->GetUDCClients().GetUDCClientState(index); if (state == nullptr) { char str[64]; sprintf(str, "udc client[%ld] null \r\n", static_cast(index)); strcat(response, str); } else { ContentApp * app = ContentAppPlatform::GetInstance().LoadContentAppByClient(state->GetVendorId(), state->GetProductId()); if (app == nullptr) { char str[64]; sprintf(str, "no app found for vendor id=%d \r\n", state->GetVendorId()); strcat(response, str); return CHIP_ERROR_BAD_REQUEST; } if (app->GetAccountLoginDelegate() == nullptr) { char str[64]; sprintf(str, "no AccountLogin cluster for app with vendor id=%d \r\n", state->GetVendorId()); strcat(response, str); return CHIP_ERROR_BAD_REQUEST; } char rotatingIdString[chip::Dnssd::kMaxRotatingIdLen * 2 + 1] = ""; Encoding::BytesToUppercaseHexString(state->GetRotatingId(), state->GetRotatingIdLength(), rotatingIdString, sizeof(rotatingIdString)); CharSpan rotatingIdSpan = CharSpan(rotatingIdString, strlen(rotatingIdString)); static const size_t kSetupPinSize = 12; char setupPin[kSetupPinSize]; app->GetAccountLoginDelegate()->GetSetupPin(setupPin, kSetupPinSize, rotatingIdSpan); std::string pinString(setupPin); char * eptr; uint32_t pincode = (uint32_t) strtol(pinString.c_str(), &eptr, 10); if (pincode == 0) { char str[64]; sprintf(str, "udc no pin returned for vendor id=%d rotating ID=%s \r\n", state->GetVendorId(), rotatingIdString); strcat(response, str); return CHIP_ERROR_BAD_REQUEST; } return CommissionerPairUDC(pincode, index); } return CHIP_NO_ERROR; } void DumpAccessControlEntry(const Access::AccessControl::Entry & entry) { CHIP_ERROR err; { FabricIndex fabricIndex; SuccessOrExit(err = entry.GetFabricIndex(fabricIndex)); char str[64]; sprintf(str, "fabricIndex: %u\n", fabricIndex); strcat(response, str); } { Privilege privilege; SuccessOrExit(err = entry.GetPrivilege(privilege)); char str[64]; sprintf(str, "privilege: %d\n", to_underlying(privilege)); strcat(response, str); } { AuthMode authMode; SuccessOrExit(err = entry.GetAuthMode(authMode)); char str[64]; sprintf(str, "authMode: %d\n", to_underlying(authMode)); strcat(response, str); } { size_t count; SuccessOrExit(err = entry.GetSubjectCount(count)); if (count) { char str[64]; sprintf(str, "subjects: %u\n", static_cast(count)); strcat(response, str); for (size_t i = 0; i < count; ++i) { NodeId subject; SuccessOrExit(err = entry.GetSubject(i, subject)); char buffer[64]; sprintf(buffer, " %u: 0x" ChipLogFormatX64, static_cast(i), ChipLogValueX64(subject)); strcat(response, buffer); } } } { size_t count; SuccessOrExit(err = entry.GetTargetCount(count)); if (count) { char str[64]; sprintf(str, "\ntargets: %u\n", static_cast(count)); strcat(response, str); for (size_t i = 0; i < count; ++i) { Access::AccessControl::Entry::Target target; SuccessOrExit(err = entry.GetTarget(i, target)); char buffer[64]; if (target.flags & Access::AccessControl::Entry::Target::kCluster) { sprintf(buffer, " %u: cluster: 0x" ChipLogFormatMEI, static_cast(i), ChipLogValueMEI(target.cluster)); strcat(buffer, "\n"); strcat(response, buffer); } if (target.flags & Access::AccessControl::Entry::Target::kEndpoint) { sprintf(buffer, " %u: endpoint: %u", static_cast(i), target.endpoint); strcat(buffer, "\n"); strcat(response, buffer); } if (target.flags & Access::AccessControl::Entry::Target::kDeviceType) { sprintf(buffer, " %u: deviceType: 0x" ChipLogFormatMEI, static_cast(i), ChipLogValueMEI(target.deviceType)); strcat(buffer, "\n"); strcat(response, buffer); } } } } strcat(response, "----- END ENTRY -----\n"); exit: if (err != CHIP_NO_ERROR) { ChipLogError(DeviceLayer, "DumpAccessControlEntry: dump failed %" CHIP_ERROR_FORMAT, err.Format()); strcpy(response, "Error occurred"); } } char * AppPlatformHandler(int argc, char ** argv) { CHIP_ERROR err; if (argc == 0 || strcmp(argv[0], "help") == 0) { strcpy(response, "check usage instructions on the UI"); } else if (strcmp(argv[0], "add-admin-vendor") == 0) { if (argc < 2) { strcpy(response, "check usage instructions on the UI"); } char * eptr; uint16_t vid = (uint16_t) strtol(argv[1], &eptr, 10); ContentAppFactoryImpl * factory = GetContentAppFactoryImpl(); factory->AddAdminVendorId(vid); ChipLogProgress(DeviceLayer, "added admin-vendor"); strcpy(response, "added admin-vendor"); return response; } else if (strcmp(argv[0], "add") == 0) { if (argc < 2) { strcpy(response, "check usage instructions on the UI"); } char * eptr; uint16_t vid = (uint16_t) strtol(argv[1], &eptr, 10); uint16_t pid = 0; if (argc >= 3) { pid = (uint16_t) strtol(argv[2], &eptr, 10); } ContentAppPlatform::GetInstance().LoadContentAppByClient(vid, pid); ChipLogProgress(DeviceLayer, "added app"); strcpy(response, "added app"); return response; } else if (strcmp(argv[0], "print-app-access") == 0) { Access::AccessControl::EntryIterator iterator; SuccessOrExit(err = Access::GetAccessControl().Entries(GetDeviceCommissioner()->GetFabricIndex(), iterator)); // clear entry strcpy(response, ""); Access::AccessControl::Entry entry; while (iterator.Next(entry) == CHIP_NO_ERROR) { DumpAccessControlEntry(entry); } return response; } else if (strcmp(argv[0], "print-apps") == 0) { ContentAppFactoryImpl * factory = GetContentAppFactoryImpl(); factory->LogInstalledApps(); ChipLogProgress(DeviceLayer, "logged installed apps"); strcpy(response, "logged installed apps"); return response; } else if (strcmp(argv[0], "remove-app-access") == 0) { Access::GetAccessControl().DeleteAllEntriesForFabric(GetDeviceCommissioner()->GetFabricIndex()); strcpy(response, "removed app access"); return response; } else if (strcmp(argv[0], "remove") == 0) { if (argc < 2) { strcpy(response, "check usage instructions on the UI"); } char * eptr; uint16_t endpoint = (uint16_t) strtol(argv[1], &eptr, 10); ContentApp * app = ContentAppPlatform::GetInstance().GetContentApp(endpoint); if (app == nullptr) { ChipLogProgress(DeviceLayer, "app not found"); strcpy(response, "app not found"); return response; } ContentAppPlatform::GetInstance().RemoveContentApp(app); ChipLogProgress(DeviceLayer, "removed app"); strcpy(response, "removed app"); return response; } else if (strcmp(argv[0], "setpin") == 0) { if (argc < 3) { strcpy(response, "check usage instructions on the UI"); } char * eptr; uint16_t endpoint = (uint16_t) strtol(argv[1], &eptr, 10); char * pincode = argv[2]; ContentApp * app = ContentAppPlatform::GetInstance().GetContentApp(endpoint); if (app == nullptr) { ChipLogProgress(DeviceLayer, "app not found"); strcpy(response, "app not found"); return response; } if (app->GetAccountLoginDelegate() == nullptr) { ChipLogProgress(DeviceLayer, "no AccountLogin cluster for app with endpoint id=%d ", endpoint); strcpy(response, "no AccountLogin cluster for app with endpoint"); return response; } app->GetAccountLoginDelegate()->SetSetupPin(pincode); ChipLogProgress(DeviceLayer, "set pin success"); strcpy(response, "set pin success"); return response; } else if (strcmp(argv[0], "commission") == 0) { if (argc < 2) { strcpy(response, "check usage instructions on the UI"); } char * eptr; size_t index = (size_t) strtol(argv[1], &eptr, 10); SuccessOrExit(err = pairApp(true, index)); return response; } else { strcpy(response, "invalid argument"); return response; } return response; exit: ChipLogError(DeviceLayer, "Error: %" CHIP_ERROR_FORMAT, err.Format()); strcpy(response, "Error occurred"); return response; } #endif // CHIP_DEVICE_CONFIG_APP_PLATFORM_ENABLED #define JNI_METHOD(RETURN, METHOD_NAME) \ extern "C" JNIEXPORT RETURN JNICALL Java_com_matter_tv_server_tvapp_AppPlatformShellCommands_##METHOD_NAME JNI_METHOD(jstring, OnExecuteCommand)(JNIEnv * env, jobject, jobjectArray stringArray) { int argc = env->GetArrayLength(stringArray); char ** argv = new char *[(uint) argc]; // Fill in argv for (int i = 0; i < argc; i++) { jstring string = (jstring) (env->GetObjectArrayElement(stringArray, i)); argv[i] = (char *) env->GetStringUTFChars(string, 0); } // Store response to show it to the users char * buf = AppPlatformHandler(argc, argv); // Release UTF Chars for (int i = 0; i < argc; i++) { ChipLogProgress(DeviceLayer, " Value=%s ", argv[i]); jstring string = (jstring) (env->GetObjectArrayElement(stringArray, i)); env->ReleaseStringUTFChars(string, argv[i]); } return env->NewStringUTF(buf); }