diff --git a/examples/tv-casting-app/android/App/app/src/main/jni/com/chip/casting/NsdResolveListener.java b/examples/tv-casting-app/android/App/app/src/main/jni/com/chip/casting/NsdResolveListener.java index 253dbee0968874..638425675dc99b 100644 --- a/examples/tv-casting-app/android/App/app/src/main/jni/com/chip/casting/NsdResolveListener.java +++ b/examples/tv-casting-app/android/App/app/src/main/jni/com/chip/casting/NsdResolveListener.java @@ -143,13 +143,13 @@ private boolean isPassingDeviceTypeFilter(DiscoveredNodeData discoveredNodeData) private void addCommissioningInfo(DiscoveredNodeData discoveredNodeData) { if (preCommissionedVideoPlayers != null) { + long currentUnixTimeMS = System.currentTimeMillis(); for (VideoPlayer videoPlayer : preCommissionedVideoPlayers) { if (videoPlayer.isSameAs(discoveredNodeData)) { Log.d( TAG, "Matching Video Player with the following information found for DiscoveredNodeData" + videoPlayer); - long currentUnixTimeMS = System.currentTimeMillis(); Log.d(TAG, "Updating discovery timestamp for VideoPlayer to " + currentUnixTimeMS); videoPlayer.setLastDiscoveredMs(currentUnixTimeMS); discoveredNodeData.setConnectableVideoPlayer(videoPlayer); diff --git a/examples/tv-casting-app/android/App/app/src/main/jni/com/chip/casting/TvCastingApp.java b/examples/tv-casting-app/android/App/app/src/main/jni/com/chip/casting/TvCastingApp.java index a0749585d0c6df..5eb1c0241438be 100644 --- a/examples/tv-casting-app/android/App/app/src/main/jni/com/chip/casting/TvCastingApp.java +++ b/examples/tv-casting-app/android/App/app/src/main/jni/com/chip/casting/TvCastingApp.java @@ -44,7 +44,7 @@ public class TvCastingApp { Arrays.asList(35L); // Video player = 35; // delay before which we assume undiscovered cached players may be in STR mode - private static final long CHIP_DEVICE_CONFIG_STR_DISCOVERY_DELAY_SEC = 5; + private static final long CHIP_DEVICE_CONFIG_STR_DISCOVERY_DELAY_SEC = 3; private static TvCastingApp sInstance; private Context applicationContext; diff --git a/examples/tv-casting-app/android/App/app/src/main/jni/com/chip/casting/VideoPlayer.java b/examples/tv-casting-app/android/App/app/src/main/jni/com/chip/casting/VideoPlayer.java index fab9b027a78cc4..9c93b264eeb33a 100644 --- a/examples/tv-casting-app/android/App/app/src/main/jni/com/chip/casting/VideoPlayer.java +++ b/examples/tv-casting-app/android/App/app/src/main/jni/com/chip/casting/VideoPlayer.java @@ -17,6 +17,7 @@ */ package com.chip.casting; +import android.util.Log; import java.net.InetAddress; import java.util.HashSet; import java.util.List; @@ -63,9 +64,11 @@ public VideoPlayer( String MACAddress, boolean isAsleep, boolean isConnected) { + Log.d(TAG, "VideoPlayer() called with MACAddress = " + MACAddress); + this.nodeId = nodeId; this.fabricIndex = fabricIndex; - this.deviceName = deviceName; + this.deviceName = deviceName != null ? new String(deviceName) : null; this.vendorId = vendorId; this.productId = productId; this.deviceType = deviceType; @@ -73,10 +76,10 @@ public VideoPlayer( this.isConnected = isConnected; this.numIPs = numIPs; this.ipAddresses = ipAddresses; - this.hostName = hostName; - this.MACAddress = MACAddress; + this.hostName = hostName != null ? new String(hostName) : null; + this.MACAddress = MACAddress != null ? new String(MACAddress) : null; this.lastDiscoveredMs = lastDiscoveredMs; - this.instanceName = instanceName; + this.instanceName = instanceName != null ? new String(instanceName) : null; this.port = port; this.isAsleep = isAsleep; this.isInitialized = true; diff --git a/examples/tv-casting-app/android/App/app/src/main/jni/cpp/ConversionUtils.cpp b/examples/tv-casting-app/android/App/app/src/main/jni/cpp/ConversionUtils.cpp index 8c1dbdaeb36147..5fa7d715a80d44 100644 --- a/examples/tv-casting-app/android/App/app/src/main/jni/cpp/ConversionUtils.cpp +++ b/examples/tv-casting-app/android/App/app/src/main/jni/cpp/ConversionUtils.cpp @@ -162,7 +162,7 @@ CHIP_ERROR convertJVideoPlayerToTargetVideoPlayerInfo(jobject videoPlayer, Targe jfieldID getInstanceNameField = env->GetFieldID(jVideoPlayerClass, "instanceName", "Ljava/lang/String;"); jstring jInstanceName = static_cast(env->GetObjectField(videoPlayer, getInstanceNameField)); const char * instanceName = {}; - if(jInstanceName != nullptr) + if (jInstanceName != nullptr) { instanceName = env->GetStringUTFChars(jInstanceName, 0); } @@ -170,19 +170,19 @@ CHIP_ERROR convertJVideoPlayerToTargetVideoPlayerInfo(jobject videoPlayer, Targe jfieldID jLastDiscoveredMs = env->GetFieldID(jVideoPlayerClass, "lastDiscoveredMs", "J"); long lastDiscoveredMs = static_cast(env->GetLongField(videoPlayer, jLastDiscoveredMs)); - jfieldID getMACAddressField = env->GetFieldID(jVideoPlayerClass, "MACAddress", "Ljava/lang/String;"); - jstring jMACAddress = static_cast(env->GetObjectField(videoPlayer, getMACAddressField)); - const char * MACAddress = jMACAddress == nullptr ? nullptr : env->GetStringUTFChars(jMACAddress, 0); - jfieldID jIsAsleep = env->GetFieldID(jVideoPlayerClass, "isAsleep", "Z"); bool isAsleep = static_cast(env->GetBooleanField(videoPlayer, jIsAsleep)); outTargetVideoPlayerInfo.Initialize(nodeId, fabricIndex, nullptr, nullptr, vendorId, productId, deviceType, deviceName, hostName, 0, nullptr, port, instanceName, chip::System::Clock::Timestamp(lastDiscoveredMs)); + jfieldID getMACAddressField = env->GetFieldID(jVideoPlayerClass, "MACAddress", "Ljava/lang/String;"); + jstring jMACAddress = static_cast(env->GetObjectField(videoPlayer, getMACAddressField)); + const char * MACAddress = jMACAddress == nullptr ? nullptr : env->GetStringUTFChars(jMACAddress, 0); if (MACAddress != nullptr) { - chip::CharSpan MACAddressSpan(MACAddress, strlen(MACAddress) - 1); + ChipLogProgress(AppServer, "convertJVideoPlayerToTargetVideoPlayerInfo MACAddress: %s", MACAddress); + chip::CharSpan MACAddressSpan(MACAddress, 2 * chip::DeviceLayer::ConfigurationManager::kPrimaryMACAddressLength); outTargetVideoPlayerInfo.SetMACAddress(MACAddressSpan); } @@ -252,15 +252,17 @@ CHIP_ERROR convertTargetVideoPlayerInfoToJVideoPlayer(TargetVideoPlayerInfo * ta jstring instanceName = targetVideoPlayerInfo->GetInstanceName() == nullptr ? nullptr : env->NewStringUTF(targetVideoPlayerInfo->GetInstanceName()); + ChipLogProgress(AppServer, "convertTargetVideoPlayerInfoToJVideoPlayer created jstring instanceName"); jstring MACAddress = nullptr; if (targetVideoPlayerInfo->GetMACAddress() != nullptr && targetVideoPlayerInfo->GetMACAddress()->data() != nullptr) { - char MACAddressWithNil[2 * chip::DeviceLayer::ConfigurationManager::kMaxMACAddressLength + 1]; - strncpy(MACAddressWithNil, targetVideoPlayerInfo->GetMACAddress()->data(), - targetVideoPlayerInfo->GetMACAddress()->size()); + char MACAddressWithNil[2 * chip::DeviceLayer::ConfigurationManager::kPrimaryMACAddressLength + 1]; + memcpy(MACAddressWithNil, targetVideoPlayerInfo->GetMACAddress()->data(), + targetVideoPlayerInfo->GetMACAddress()->size()); MACAddressWithNil[targetVideoPlayerInfo->GetMACAddress()->size()] = '\0'; - MACAddress = env->NewStringUTF(MACAddressWithNil); + ChipLogProgress(AppServer, "convertTargetVideoPlayerInfoToJVideoPlayer MACAddressWithNil: %s", MACAddressWithNil); + MACAddress = env->NewStringUTF(MACAddressWithNil); } jobject jIPAddressList = nullptr; diff --git a/examples/tv-casting-app/tv-casting-common/BUILD.gn b/examples/tv-casting-app/tv-casting-common/BUILD.gn index a04b0ca383c8df..cacd33a369d24c 100644 --- a/examples/tv-casting-app/tv-casting-common/BUILD.gn +++ b/examples/tv-casting-app/tv-casting-common/BUILD.gn @@ -47,6 +47,7 @@ chip_data_model("tv-casting-common") { "${chip_root}/zzz_generated/chip-tool/zap-generated/cluster/logging/DataModelLogger.cpp", "commands/clusters/ModelCommand.cpp", "commands/common/CHIPCommand.cpp", + "include/AndroidSystemTimeSupport.h", "include/AppParams.h", "include/ApplicationBasic.h", "include/ApplicationLauncher.h", @@ -67,6 +68,7 @@ chip_data_model("tv-casting-common") { "include/TargetNavigator.h", "include/TargetVideoPlayerInfo.h", "include/WakeOnLan.h", + "src/AndroidSystemTimeSupport.cpp", "src/AppParams.cpp", "src/ApplicationLauncher.cpp", "src/CastingServer.cpp", diff --git a/examples/tv-casting-app/tv-casting-common/include/AndroidSystemTimeSupport.h b/examples/tv-casting-app/tv-casting-common/include/AndroidSystemTimeSupport.h new file mode 100644 index 00000000000000..1e864951ad7cef --- /dev/null +++ b/examples/tv-casting-app/tv-casting-common/include/AndroidSystemTimeSupport.h @@ -0,0 +1,35 @@ +/* + * + * Copyright (c) 2023 Project CHIP Authors + * All rights reserved. + * + * 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 + +#include +#include + +#include +#include +#include +#include + +class AndroidClockImpl +{ +public: + static CHIP_ERROR GetClock_RealTime(chip::System::Clock::Microseconds64 & aCurTime); + + static CHIP_ERROR GetClock_RealTimeMS(chip::System::Clock::Milliseconds64 & aCurTime); +}; diff --git a/examples/tv-casting-app/tv-casting-common/include/CHIPProjectAppConfig.h b/examples/tv-casting-app/tv-casting-common/include/CHIPProjectAppConfig.h index cfa3f4cd160e13..642666d5102c85 100644 --- a/examples/tv-casting-app/tv-casting-common/include/CHIPProjectAppConfig.h +++ b/examples/tv-casting-app/tv-casting-common/include/CHIPProjectAppConfig.h @@ -69,13 +69,13 @@ #define CHIP_DEVICE_CONFIG_DYNAMIC_ENDPOINT_COUNT 4 // cached players that were seen before this window (in hours) will not be surfaced as "discovered" -#define CHIP_DEVICE_CONFIG_STR_CACHE_LAST_DISCOVERED_HOURS 7 * 24 +//#define CHIP_DEVICE_CONFIG_STR_CACHE_LAST_DISCOVERED_HOURS 7 * 24 // time (in sec) assumed to be required for player to wake up after sending WoL magic packet #define CHIP_DEVICE_CONFIG_STR_WAKE_UP_DELAY_SEC 10 // delay (in sec) before which we assume undiscovered cached players may be in STR mode -#define CHIP_DEVICE_CONFIG_STR_DISCOVERY_DELAY_SEC 5 +#define CHIP_DEVICE_CONFIG_STR_DISCOVERY_DELAY_SEC 3 // Include the CHIPProjectConfig from config/standalone // Add this at the end so that we can hit our #defines first diff --git a/examples/tv-casting-app/tv-casting-common/include/TargetVideoPlayerInfo.h b/examples/tv-casting-app/tv-casting-common/include/TargetVideoPlayerInfo.h index cfcd2c6a5c45ca..732ab21d1960d5 100644 --- a/examples/tv-casting-app/tv-casting-common/include/TargetVideoPlayerInfo.h +++ b/examples/tv-casting-app/tv-casting-common/include/TargetVideoPlayerInfo.h @@ -18,6 +18,7 @@ #pragma once +#include "AndroidSystemTimeSupport.h" #include "TargetEndpointInfo.h" #include "app/clusters/bindings/BindingManager.h" #include @@ -89,13 +90,37 @@ class TargetVideoPlayerInfo uint16_t GetPort() const { return mPort; } const char * GetInstanceName() const { return mInstanceName; } - chip::CharSpan * GetMACAddress() { return &mMACAddress; } + chip::CharSpan * GetMACAddress() + { + if (mMACAddress.data() != nullptr && mMACAddress.size() > 0) + { + ChipLogProgress(AppServer, "TargetVideoPlayerInfo.GetMACAddress: %.*s", static_cast(mMACAddress.size()), + mMACAddress.data()); + } + else + { + ChipLogProgress(AppServer, "TargetVideoPlayerInfo.GetMACAddress returning ref to empty CharSpan"); + } + + return &mMACAddress; + } + void SetIsAsleep(bool isAsleep) { mIsAsleep = isAsleep; } bool IsAsleep() { return mIsAsleep; } void SetMACAddress(chip::CharSpan MACAddress) { - memcpy(mMACAddressBuf, MACAddress.data(), MACAddress.size()); - mMACAddress = chip::CharSpan(mMACAddressBuf, MACAddress.size()); + if (MACAddress.data() != nullptr && MACAddress.size() > 0) + { + ChipLogProgress(AppServer, "TargetVideoPlayerInfo.SetMACAddress: %.*s", static_cast(MACAddress.size()), + MACAddress.data()); + } + else + { + ChipLogProgress(AppServer, "TargetVideoPlayerInfo.SetMACAddress to empty CharSpan"); + } + + memcpy(mMACAddressBuf, MACAddress.data(), sizeof(mMACAddressBuf)); + mMACAddress = chip::CharSpan(mMACAddressBuf, sizeof(mMACAddressBuf)); } chip::System::Clock::Timestamp GetLastDiscovered() { return mLastDiscovered; } void SetLastDiscovered(chip::System::Clock::Timestamp lastDiscovered) { mLastDiscovered = lastDiscovered; } @@ -105,7 +130,12 @@ class TargetVideoPlayerInfo // it was recently discoverable if its mLastDiscovered.count is within // CHIP_DEVICE_CONFIG_STR_CACHE_LAST_DISCOVERED_HOURS of current time chip::System::Clock::Timestamp currentUnixTimeMS = chip::System::Clock::kZero; - chip::System::SystemClock().GetClock_RealTimeMS(currentUnixTimeMS); +#ifdef __ANDROID__ + VerifyOrReturnValue(AndroidClockImpl::GetClock_RealTimeMS(currentUnixTimeMS) == CHIP_NO_ERROR, true); +#else + VerifyOrReturnValue(chip::System::SystemClock().GetClock_RealTimeMS(currentUnixTimeMS) == CHIP_NO_ERROR, true); +#endif + ChipLogProgress(AppServer, "WasRecentlyDiscoverable currentUnixTimeMS: %lu mLastDiscovered: %lu", static_cast(currentUnixTimeMS.count()), static_cast(mLastDiscovered.count())); return mLastDiscovered.count() > @@ -209,7 +239,7 @@ class TargetVideoPlayerInfo char mInstanceName[chip::Dnssd::Commission::kInstanceNameMaxLength + 1]; uint16_t mPort; chip::CharSpan mMACAddress; - char mMACAddressBuf[2 * chip::DeviceLayer::ConfigurationManager::kMaxMACAddressLength]; + char mMACAddressBuf[2 * chip::DeviceLayer::ConfigurationManager::kPrimaryMACAddressLength]; chip::System::Clock::Timestamp mLastDiscovered; bool mIsAsleep = false; bool mInitialized = false; diff --git a/examples/tv-casting-app/tv-casting-common/src/AndroidSystemTimeSupport.cpp b/examples/tv-casting-app/tv-casting-common/src/AndroidSystemTimeSupport.cpp new file mode 100644 index 00000000000000..dd1c422007837b --- /dev/null +++ b/examples/tv-casting-app/tv-casting-common/src/AndroidSystemTimeSupport.cpp @@ -0,0 +1,50 @@ +/* + * + * Copyright (c) 2023 Project CHIP Authors + * All rights reserved. + * + * 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 "AndroidSystemTimeSupport.h" + +CHIP_ERROR AndroidClockImpl::GetClock_RealTime(chip::System::Clock::Microseconds64 & aCurTime) +{ + ChipLogProgress(AppServer, "AndroidClockImpl::GetClock_RealTime called"); + struct timeval tv; + if (gettimeofday(&tv, nullptr) != 0) + { + return CHIP_ERROR_POSIX(errno); + } + if (tv.tv_sec < CHIP_SYSTEM_CONFIG_VALID_REAL_TIME_THRESHOLD) + { + return CHIP_ERROR_REAL_TIME_NOT_SYNCED; + } + if (tv.tv_usec < 0) + { + return CHIP_ERROR_REAL_TIME_NOT_SYNCED; + } + static_assert(CHIP_SYSTEM_CONFIG_VALID_REAL_TIME_THRESHOLD >= 0, "We might be letting through negative tv_sec values!"); + aCurTime = chip::System::Clock::Microseconds64((static_cast(tv.tv_sec) * UINT64_C(1000000)) + + static_cast(tv.tv_usec)); + return CHIP_NO_ERROR; +} + +CHIP_ERROR AndroidClockImpl::GetClock_RealTimeMS(chip::System::Clock::Milliseconds64 & aCurTime) +{ + ChipLogProgress(AppServer, "AndroidClockImpl::GetClock_RealTimeMS called"); + chip::System::Clock::Microseconds64 curTimeUs; + auto err = GetClock_RealTime(curTimeUs); + aCurTime = std::chrono::duration_cast(curTimeUs); + return err; +} diff --git a/examples/tv-casting-app/tv-casting-common/src/CastingServer.cpp b/examples/tv-casting-app/tv-casting-common/src/CastingServer.cpp index 56e1b5f7ea26f2..a5878fdb130cbe 100644 --- a/examples/tv-casting-app/tv-casting-common/src/CastingServer.cpp +++ b/examples/tv-casting-app/tv-casting-common/src/CastingServer.cpp @@ -655,7 +655,11 @@ void CastingServer::DeviceEventCallback(const DeviceLayer::ChipDeviceEvent * eve { // add discovery timestamp chip::System::Clock::Timestamp currentUnixTimeMS = chip::System::Clock::kZero; +#ifdef __ANDROID__ + AndroidClockImpl::GetClock_RealTimeMS(currentUnixTimeMS); +#else chip::System::SystemClock().GetClock_RealTimeMS(currentUnixTimeMS); +#endif ChipLogProgress(AppServer, "Updating discovery timestamp for VideoPlayer to %lu", static_cast(currentUnixTimeMS.count())); CastingServer::GetInstance()->mActiveTargetVideoPlayerInfo.SetLastDiscovered(currentUnixTimeMS); diff --git a/examples/tv-casting-app/tv-casting-common/src/PersistenceManager.cpp b/examples/tv-casting-app/tv-casting-common/src/PersistenceManager.cpp index 4ee718963159c4..9feacd503f6a9a 100644 --- a/examples/tv-casting-app/tv-casting-common/src/PersistenceManager.cpp +++ b/examples/tv-casting-app/tv-casting-common/src/PersistenceManager.cpp @@ -267,11 +267,11 @@ CHIP_ERROR PersistenceManager::ReadAllVideoPlayers(TargetVideoPlayerInfo outVide char hostName[chip::Dnssd::kHostNameMaxLength + 1] = {}; size_t numIPs = 0; Inet::IPAddress ipAddress[chip::Dnssd::CommonResolutionData::kMaxIPAddresses]; - uint64_t lastDiscoveredMs = 0; - char MACAddressBuf[2 * chip::DeviceLayer::ConfigurationManager::kMaxMACAddressLength] = {}; - uint32_t MACAddressLength = 0; - char instanceName[chip::Dnssd::Commission::kInstanceNameMaxLength + 1] = {}; - uint16_t port = 0; + uint64_t lastDiscoveredMs = 0; + char MACAddressBuf[2 * chip::DeviceLayer::ConfigurationManager::kPrimaryMACAddressLength] = {}; + uint32_t MACAddressLength = 0; + char instanceName[chip::Dnssd::Commission::kInstanceNameMaxLength + 1] = {}; + uint16_t port = 0; CHIP_ERROR err; while ((err = reader.Next()) == CHIP_NO_ERROR) @@ -349,7 +349,7 @@ CHIP_ERROR PersistenceManager::ReadAllVideoPlayers(TargetVideoPlayerInfo outVide { MACAddressLength = reader.GetLength(); ReturnErrorOnFailure(reader.GetBytes(reinterpret_cast(MACAddressBuf), - 2 * chip::DeviceLayer::ConfigurationManager::kMaxMACAddressLength)); + 2 * chip::DeviceLayer::ConfigurationManager::kPrimaryMACAddressLength)); continue; }