Skip to content

Commit

Permalink
tv-casting-app fixed memory issues around stopDiscovery function
Browse files Browse the repository at this point in the history
  • Loading branch information
pgregorr-amazon committed Aug 2, 2024
1 parent 1e9082f commit 79faacc
Show file tree
Hide file tree
Showing 10 changed files with 198 additions and 50 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
import androidx.fragment.app.Fragment;
import com.R;
import com.matter.casting.core.CastingPlayer;
import com.matter.casting.core.CastingPlayerDiscovery;
import com.matter.casting.core.MatterCastingPlayerDiscovery;
import com.matter.casting.support.CommissionerDeclaration;
import com.matter.casting.support.ConnectionCallbacks;
import com.matter.casting.support.IdentificationDeclarationOptions;
Expand All @@ -56,6 +58,10 @@ public class ConnectionExampleFragment extends Fragment {
private TextView connectionFragmentStatusTextView;
private Button connectionFragmentNextButton;

// Get a singleton instance of the MatterCastingPlayerDiscovery. Which can be used to call stopDiscovery() during connection.
static final CastingPlayerDiscovery matterCastingPlayerDiscovery =
MatterCastingPlayerDiscovery.getInstance();

public ConnectionExampleFragment(
CastingPlayer targetCastingPlayer, boolean useCommissionerGeneratedPasscode) {
Log.i(
Expand Down Expand Up @@ -123,6 +129,13 @@ public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
callback.handleConnectionComplete(targetCastingPlayer, useCommissionerGeneratedPasscode);
});

Button stopDiscoveryButton = getView().findViewById(R.id.stopDiscoveryButton);
stopDiscoveryButton.setOnClickListener(
v -> {
Log.i(TAG, "onViewCreated() stopDiscoveryButton button clicked. Calling stopDiscovery()");
stopDiscovery();
});

Executors.newSingleThreadExecutor()
.submit(
() -> {
Expand Down Expand Up @@ -160,13 +173,17 @@ public void handle(Void v) {
Log.i(
TAG,
"Successfully connected to CastingPlayer with deviceId: "
+ targetCastingPlayer.getDeviceId());
+ targetCastingPlayer.getDeviceId()
+ ", useCommissionerGeneratedPasscode: "
+ useCommissionerGeneratedPasscode);
getActivity()
.runOnUiThread(
() -> {
connectionFragmentStatusTextView.setText(
"Successfully connected to Casting Player with device name: "
+ targetCastingPlayer.getDeviceName()
+ "\n\nUsed CastingPlayer Passcode: "
+ useCommissionerGeneratedPasscode
+ "\n\n");
connectionFragmentNextButton.setEnabled(true);
});
Expand Down Expand Up @@ -351,6 +368,19 @@ public void onClick(DialogInterface dialog, int which) {
.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
}

private void stopDiscovery() {
Log.i(TAG, "ConnectionExampleFragment stopDiscovery() called, calling MatterCastingPlayerDiscovery.stopDiscovery()");

MatterError err = matterCastingPlayerDiscovery.stopDiscovery();
if (err.hasError()) {
Log.e(
TAG,
"ConnectionExampleFragment stopDiscovery() MatterCastingPlayerDiscovery.stopDiscovery() called, err Stop: " + err);
} else {
Log.d(TAG, "ConnectionExampleFragment stopDiscovery() MatterCastingPlayerDiscovery.stopDiscovery() success");
}
}

/** Interface for notifying the host. */
public interface Callback {
/** Notifies listener to trigger transition on completion of connection */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ public class DiscoveryExampleFragment extends Fragment {
public void onAdded(CastingPlayer castingPlayer) {
Log.i(
TAG,
"onAdded() Discovered CastingPlayer deviceId: " + castingPlayer.getDeviceId());
"DiscoveryExampleFragment onAdded() Discovered CastingPlayer deviceId: " + castingPlayer.getDeviceId());
// Display CastingPlayer info on the screen
new Handler(Looper.getMainLooper())
.post(
Expand All @@ -80,7 +80,7 @@ public void onAdded(CastingPlayer castingPlayer) {
public void onChanged(CastingPlayer castingPlayer) {
Log.i(
TAG,
"onChanged() Discovered changes to CastingPlayer with deviceId: "
"DiscoveryExampleFragment onChanged() Discovered changes to CastingPlayer with deviceId: "
+ castingPlayer.getDeviceId());
// Update the CastingPlayer on the screen
new Handler(Looper.getMainLooper())
Expand All @@ -107,7 +107,7 @@ public void onChanged(CastingPlayer castingPlayer) {
public void onRemoved(CastingPlayer castingPlayer) {
Log.i(
TAG,
"onRemoved() Removed CastingPlayer with deviceId: "
"DiscoveryExampleFragment onRemoved() Removed CastingPlayer with deviceId: "
+ castingPlayer.getDeviceId());
// Remove CastingPlayer from the screen
new Handler(Looper.getMainLooper())
Expand Down Expand Up @@ -215,7 +215,9 @@ public void onResume() {
@Override
public void onPause() {
super.onPause();
Log.i(TAG, "onPause() called");
Log.i(TAG, "DiscoveryExampleFragment onPause() called, calling stopDiscovery()");
// Stop discovery when leaving the fragment, for example, while displaying the ConnectionExampleFragment.
stopDiscovery();
}

/** Interface for notifying the host. */
Expand Down Expand Up @@ -261,7 +263,7 @@ private boolean startDiscovery() {
}

private void stopDiscovery() {
Log.i(TAG, "stopDiscovery() called");
Log.i(TAG, "DiscoveryExampleFragment stopDiscovery() called");
matterDiscoveryErrorMessageTextView.setText(
getString(R.string.matter_discovery_error_message_initial));

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
Expand All @@ -11,7 +12,6 @@
android:textStyle="bold"
android:textSize="18sp"
android:padding="16dp"
android:textColor="@android:color/white"
android:gravity="center"
android:text="@string/matter_connection_input_dialog_title" />

Expand All @@ -24,7 +24,6 @@
android:paddingEnd="16dp"
android:paddingTop="8dp"
android:paddingBottom="8dp"
android:textColor="@android:color/white"
android:text="@string/matter_connection_input_dialog_instructions" />

<EditText
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,36 @@
tools:context=".matter.casting.ConnectionExampleFragment"
android:padding="10sp">

<TextView
android:id="@+id/connectionFragmentStatusText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="24sp"/>

<Button
android:enabled="false"
android:id="@+id/connectionFragmentNextButton"
android:layout_below="@id/connectionFragmentStatusText"
<LinearLayout
android:id="@+id/connectionFragmentLinearLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/matter_connection_next_button_text" />
android:orientation="vertical"
tools:layout_editor_absoluteX="1dp"
tools:layout_editor_absoluteY="1dp"
android:padding="10sp">

<TextView
android:id="@+id/connectionFragmentStatusText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="24sp"/>

<Button
android:enabled="false"
android:id="@+id/connectionFragmentNextButton"
android:layout_below="@id/connectionFragmentStatusText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/matter_connection_next_button_text" />

<Button
android:enabled="true"
android:id="@+id/stopDiscoveryButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/matter_stop_discovery_button_text" />

</LinearLayout>

</RelativeLayout>
40 changes: 25 additions & 15 deletions examples/tv-casting-app/tv-casting-common/core/CastingPlayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
*/

#include "CastingPlayer.h"
#include "Endpoint.h"
#include "CastingPlayerDiscovery.h"

#include "support/CastingStore.h"

Expand All @@ -27,13 +27,14 @@ namespace matter {
namespace casting {
namespace core {

CastingPlayer * CastingPlayer::mTargetCastingPlayer = nullptr;
memory::Weak<CastingPlayer> CastingPlayer::mTargetCastingPlayer;

void CastingPlayer::VerifyOrEstablishConnection(ConnectionCallbacks connectionCallbacks, uint16_t commissioningWindowTimeoutSec,
IdentificationDeclarationOptions idOptions)
{
ChipLogProgress(AppServer, "CastingPlayer::VerifyOrEstablishConnection() called");

CastingPlayerDiscovery * castingPlayerDiscovery = CastingPlayerDiscovery::GetInstance();
std::vector<core::CastingPlayer>::iterator it;
std::vector<core::CastingPlayer> cachedCastingPlayers = support::CastingStore::GetInstance()->ReadAll();

Expand All @@ -53,8 +54,9 @@ void CastingPlayer::VerifyOrEstablishConnection(ConnectionCallbacks connectionCa
mConnectionState = CASTING_PLAYER_CONNECTING;
mOnCompleted = connectionCallbacks.mOnConnectionComplete;
mCommissioningWindowTimeoutSec = commissioningWindowTimeoutSec;
mTargetCastingPlayer = this;
mTargetCastingPlayer = weak_from_this();
mIdOptions = idOptions;
castingPlayerDiscovery->ClearDisconnectedCastingPlayersInternal();

// Register the handler for Commissioner's CommissionerDeclaration messages. The CommissionerDeclaration messages provide
// information indicating the Commissioner's pre-commissioning state.
Expand Down Expand Up @@ -120,7 +122,7 @@ void CastingPlayer::VerifyOrEstablishConnection(ConnectionCallbacks connectionCa
nullptr,
[](void * context, chip::Messaging::ExchangeManager & exchangeMgr, const chip::SessionHandle & sessionHandle) {
ChipLogProgress(AppServer,
"CastingPlayer::VerifyOrEstablishConnection() Connection to CastingPlayer successful");
"CastingPlayer::VerifyOrEstablishConnection() FindOrEstablishSession Connection to CastingPlayer successful");
CastingPlayer::GetTargetCastingPlayer()->mConnectionState = CASTING_PLAYER_CONNECTED;

// this async call will Load all the endpoints with their respective attributes into the TargetCastingPlayer
Expand All @@ -129,7 +131,7 @@ void CastingPlayer::VerifyOrEstablishConnection(ConnectionCallbacks connectionCa
support::EndpointListLoader::GetInstance()->Load();
},
[](void * context, const chip::ScopedNodeId & peerId, CHIP_ERROR error) {
ChipLogError(AppServer, "CastingPlayer::VerifyOrEstablishConnection() Connection to CastingPlayer failed");
ChipLogError(AppServer, "CastingPlayer::VerifyOrEstablishConnection() FindOrEstablishSession Connection to CastingPlayer failed");
CastingPlayer::GetTargetCastingPlayer()->mConnectionState = CASTING_PLAYER_NOT_CONNECTED;
CHIP_ERROR e = support::CastingStore::GetInstance()->Delete(*CastingPlayer::GetTargetCastingPlayer());
if (e != CHIP_NO_ERROR)
Expand All @@ -139,7 +141,7 @@ void CastingPlayer::VerifyOrEstablishConnection(ConnectionCallbacks connectionCa

VerifyOrReturn(CastingPlayer::GetTargetCastingPlayer()->mOnCompleted);
CastingPlayer::GetTargetCastingPlayer()->mOnCompleted(error, nullptr);
mTargetCastingPlayer = nullptr;
mTargetCastingPlayer.reset();
});
return; // FindOrEstablishSession called. Return early.
}
Expand Down Expand Up @@ -195,8 +197,8 @@ CHIP_ERROR CastingPlayer::ContinueConnecting()
"CastingPlayer::ContinueConnecting() mIdOptions.mCommissionerPasscode == false, ContinueConnecting() should "
"only be called when the CastingPlayer/Commissioner-Generated passcode commissioning flow is in progress."););

CHIP_ERROR err = CHIP_NO_ERROR;
mTargetCastingPlayer = this;
CHIP_ERROR err = CHIP_NO_ERROR;
mTargetCastingPlayer = weak_from_this();

ChipLogProgress(AppServer, "CastingPlayer::ContinueConnecting() calling OpenBasicCommissioningWindow()");
SuccessOrExit(err = chip::Server::GetInstance().GetCommissioningWindowManager().OpenBasicCommissioningWindow(
Expand Down Expand Up @@ -235,7 +237,8 @@ CHIP_ERROR CastingPlayer::StopConnecting()
mIdOptions.mCancelPasscode = true;
mConnectionState = CASTING_PLAYER_NOT_CONNECTED;
mCommissioningWindowTimeoutSec = kCommissioningWindowTimeoutSec;
mTargetCastingPlayer = nullptr;
mTargetCastingPlayer.reset();
CastingPlayerDiscovery::GetInstance()->ClearCastingPlayersInternal();

// If a CastingPlayer::ContinueConnecting() error occurs, StopConnecting() can be called while sUdcInProgress == true.
// sUdcInProgress should be set to false before sending the CancelPasscode IdentificationDeclaration message to the
Expand Down Expand Up @@ -273,18 +276,21 @@ void CastingPlayer::resetState(CHIP_ERROR err)
support::ChipDeviceEventHandler::SetUdcStatus(false);
mConnectionState = CASTING_PLAYER_NOT_CONNECTED;
mCommissioningWindowTimeoutSec = kCommissioningWindowTimeoutSec;
mTargetCastingPlayer = nullptr;
mTargetCastingPlayer.reset();
if (mOnCompleted)
{
mOnCompleted(err, nullptr);
mOnCompleted = nullptr;
}
CastingPlayerDiscovery::GetInstance()->ClearCastingPlayersInternal();
}

void CastingPlayer::Disconnect()
{
ChipLogProgress(AppServer, "CastingPlayer::Disconnect()");
mConnectionState = CASTING_PLAYER_NOT_CONNECTED;
mTargetCastingPlayer = nullptr;
mTargetCastingPlayer.reset();
CastingPlayerDiscovery::GetInstance()->ClearCastingPlayersInternal();
}

void CastingPlayer::RegisterEndpoint(const memory::Strong<Endpoint> endpoint)
Expand Down Expand Up @@ -320,6 +326,7 @@ CHIP_ERROR CastingPlayer::SendUserDirectedCommissioningRequest()
ReturnErrorOnFailure(chip::Server::GetInstance().SendUserDirectedCommissioningRequest(
chip::Transport::PeerAddress::UDP(*ipAddressToUse, mAttributes.port, mAttributes.interfaceId), id));

ChipLogProgress(AppServer, "CastingPlayer::SendUserDirectedCommissioningRequest() complete");
return CHIP_NO_ERROR;
}

Expand Down Expand Up @@ -478,23 +485,26 @@ ConnectionContext::ConnectionContext(void * clientContext, core::CastingPlayer *

mOnConnectedCallback = new chip::Callback::Callback<chip::OnDeviceConnected>(
[](void * context, chip::Messaging::ExchangeManager & exchangeMgr, const chip::SessionHandle & sessionHandle) {
ChipLogProgress(AppServer, "Device Connection success callback called");
ChipLogProgress(AppServer, "CastingPlayer::ConnectionContext() Device Connection success callback called");
ConnectionContext * connectionContext = static_cast<ConnectionContext *>(context);
VerifyOrReturn(connectionContext != nullptr && connectionContext->mTargetCastingPlayer != nullptr,
ChipLogError(AppServer, "Invalid ConnectionContext received in DeviceConnection success callback"));
ChipLogError(AppServer, "CastingPlayer::ConnectionContext() Invalid ConnectionContext received in DeviceConnection success callback"));

ChipLogProgress(AppServer, "CastingPlayer::ConnectionContext() calling mConnectionState = core::CASTING_PLAYER_CONNECTED");
connectionContext->mTargetCastingPlayer->mConnectionState = core::CASTING_PLAYER_CONNECTED;
ChipLogProgress(AppServer, "CastingPlayer::ConnectionContext() calling mOnDeviceConnectedFn");
connectionContext->mOnDeviceConnectedFn(connectionContext->mClientContext, exchangeMgr, sessionHandle);
ChipLogProgress(AppServer, "CastingPlayer::ConnectionContext() calling delete connectionContext");
delete connectionContext;
},
this);

mOnConnectionFailureCallback = new chip::Callback::Callback<chip::OnDeviceConnectionFailure>(
[](void * context, const chip::ScopedNodeId & peerId, CHIP_ERROR error) {
ChipLogError(AppServer, "Device Connection failure callback called with %" CHIP_ERROR_FORMAT, error.Format());
ChipLogError(AppServer, "CastingPlayer::ConnectionContext() Device Connection failure callback called with %" CHIP_ERROR_FORMAT, error.Format());
ConnectionContext * connectionContext = static_cast<ConnectionContext *>(context);
VerifyOrReturn(connectionContext != nullptr && connectionContext->mTargetCastingPlayer != nullptr,
ChipLogError(AppServer, "Invalid ConnectionContext received in DeviceConnection failure callback"));
ChipLogError(AppServer, "CastingPlayer::ConnectionContext() Invalid ConnectionContext received in DeviceConnection failure callback"));
connectionContext->mTargetCastingPlayer->mConnectionState = CASTING_PLAYER_NOT_CONNECTED;
connectionContext->mOnDeviceConnectionFailureFn(connectionContext->mClientContext, peerId, error);
delete connectionContext;
Expand Down
Loading

0 comments on commit 79faacc

Please sign in to comment.