Skip to content

Commit b6e8fd2

Browse files
[Amazon] StopConnect for UDC in Android tv-casting-app
Updated native layer and iOS tv-casting-app to use native layer ConnectionState instead of a pendingPasscode customer check. Changes * Expose native layer ConnectionState to iOS tv-casting-app * Update iOS tv-casting-app to use ConnectionState to determine if we should call stopConnect() * Only call stopConnect() on navigate back from ConnectionExampleView * Updated doc to indicate when a object method will free itself as a side effect Test 1. Manually verified UDC attempt is successful both Android iOS for following 1. Attempt UDC attempt (both commissionee & commissioner generated passcode) 2. Navigate back to discovery page 3. Start new UDC attempt (both commissionee & commissioner generated passcode) 2. Manually verified UDC attempt is successful both Android iOS for following. UDC will finish in the background. 1. Attempt UDC attempt (both commissionee & commissioner generated passcode) 2. Confirm passcode on TV app or casting app depending on who generated passcode 3. Navigate back before commission fnishes. 3. Manual regression test following * UDC attempt happy path (no navigate back) for both commissinee & commissioner generated passcode
1 parent 28acdc2 commit b6e8fd2

File tree

6 files changed

+72
-39
lines changed

6 files changed

+72
-39
lines changed

examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCCastingPlayer.h

+14-2
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,16 @@
2626

2727
@class MCEndpoint;
2828

29+
/**
30+
* @brief Represents CastingPlayer ConnectionState.
31+
* @note Should be kept up to date with matter::casting::core::ConnectionState.
32+
*/
33+
typedef enum {
34+
MC_CASTING_PLAYER_NOT_CONNECTED,
35+
MC_CASTING_PLAYER_CONNECTING,
36+
MC_CASTING_PLAYER_CONNECTED,
37+
} MCCastingPlayerConnectionState;
38+
2939
/**
3040
* @brief MCCastingPlayer represents a Matter commissioner that is able to play media to a physical
3141
* output or to a display screen which is part of the device.
@@ -149,9 +159,11 @@
149159
- (void)disconnect;
150160

151161
/**
152-
* @return true if this CastingPlayer is still pending pass code from user and therefore is not ready
162+
* @brief Get the CastingPlayer's connection state
163+
* @param state The current connection state that will be return.
164+
* @return nil if request submitted successfully, otherwise a NSError object corresponding to the error.
153165
*/
154-
- (bool)isPendingPasscodeFromUser;
166+
- (NSError * _Nullable)getConnectionState:(MCCastingPlayerConnectionState * _Nonnull)state;
155167

156168
- (NSString * _Nonnull)identifier;
157169
- (NSString * _Nonnull)deviceName;

examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCCastingPlayer.mm

+22-7
Original file line numberDiff line numberDiff line change
@@ -190,18 +190,33 @@ - (void)disconnect
190190
});
191191
}
192192

193-
- (bool)isPendingPasscodeFromUser
193+
- (NSError * _Nullable)getConnectionState:(MCCastingPlayerConnectionState * _Nonnull)state;
194194
{
195-
ChipLogProgress(AppServer, "MCCastingPlayer.isPendingPasscodeFromUser() called");
196-
VerifyOrReturnValue([[MCCastingApp getSharedInstance] isRunning], false, ChipLogError(AppServer, "MCCastingPlayer.isPendingPasscodeFromUser() MCCastingApp NOT running"));
195+
ChipLogProgress(AppServer, "MCCastingPlayer.getConnectionState() called");
196+
VerifyOrReturnValue([[MCCastingApp getSharedInstance] isRunning], [MCErrorUtils NSErrorFromChipError:CHIP_ERROR_INCORRECT_STATE], ChipLogError(AppServer, "MCCastingPlayer.getConnectionState() MCCastingApp NOT running"));
197197

198+
__block matter::casting::core::ConnectionState native_state = matter::casting::core::ConnectionState::CASTING_PLAYER_NOT_CONNECTED;
198199
dispatch_queue_t workQueue = [[MCCastingApp getSharedInstance] getWorkQueue];
199-
200-
__block bool isPending = false;
201200
dispatch_sync(workQueue, ^{
202-
isPending = _cppCastingPlayer->IsPendingPasscodeFromUser();
201+
native_state = _cppCastingPlayer->GetConnectionState();
203202
});
204-
return isPending;
203+
204+
switch (native_state) {
205+
case matter::casting::core::ConnectionState::CASTING_PLAYER_NOT_CONNECTED:
206+
*state = MC_CASTING_PLAYER_NOT_CONNECTED;
207+
break;
208+
case matter::casting::core::ConnectionState::CASTING_PLAYER_CONNECTING:
209+
*state = MC_CASTING_PLAYER_CONNECTING;
210+
break;
211+
case matter::casting::core::ConnectionState::CASTING_PLAYER_CONNECTED:
212+
*state = MC_CASTING_PLAYER_CONNECTED;
213+
break;
214+
default:
215+
[NSException raise:@"Unhandled matter::casting::core::ConnectionState" format:@"%d is not handled", native_state];
216+
break;
217+
}
218+
219+
return nil;
205220
}
206221

207222
- (instancetype _Nonnull)initWithCppCastingPlayer:(matter::casting::memory::Strong<matter::casting::core::CastingPlayer>)cppCastingPlayer

examples/tv-casting-app/darwin/TvCasting/TvCasting/MCConnectionExampleViewModel.swift

+12-29
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,13 @@ class MCConnectionExampleViewModel: ObservableObject {
4545
func cancelConnectionAttempt(selectedCastingPlayer: MCCastingPlayer?) {
4646
DispatchQueue.main.async {
4747
// Only stop connection if we are pending passcode confirmation
48-
if selectedCastingPlayer?.isPendingPasscodeFromUser() == true {
48+
var connectionState = MC_CASTING_PLAYER_NOT_CONNECTED;
49+
let err = selectedCastingPlayer?.getConnectionState(&connectionState)
50+
if err != nil {
51+
self.Log.error("MCConnectionExampleViewModel cancelConnect() MCCastingPlayer.getConnectionState() failed due to: \(err)")
52+
}
53+
54+
if connectionState == MC_CASTING_PLAYER_CONNECTING {
4955
self.Log.info("MCConnectionExampleViewModel cancelConnect(). User navigating back from ConnectionView")
5056
let err = selectedCastingPlayer?.stopConnecting()
5157
if err == nil {
@@ -125,17 +131,9 @@ class MCConnectionExampleViewModel: ObservableObject {
125131
dataSource.update(newCommissionableData)
126132
self.Log.info("MCConnectionExampleViewModel connect() commissionerDeclarationCallback, Updated MCAppParametersDataSource instance with new MCCommissionableData.")
127133
} else {
128-
self.Log.error("MCConnectionExampleViewModel connect() commissionerDeclarationCallback, InitializationExample.getAppParametersDataSource() failed, calling stopConnecting()")
129-
self.connectionStatus = "Failed to update the MCAppParametersDataSource with the user entered passcode: \n\nRoute back and try again."
134+
self.Log.error("MCConnectionExampleViewModel connect() commissionerDeclarationCallback, InitializationExample.getAppParametersDataSource() failed")
135+
self.connectionStatus = "Failed to update the MCAppParametersDataSource with the user entered passcode: \n\nRoute back to disconnect and try again."
130136
self.connectionSuccess = false
131-
// Since we failed to update the passcode, Attempt to cancel the connection attempt with
132-
// the CastingPlayer/Commissioner.
133-
let err = selectedCastingPlayer?.stopConnecting()
134-
if err == nil {
135-
self.Log.info("MCConnectionExampleViewModel connect() commissionerDeclarationCallback, InitializationExample.getAppParametersDataSource() failed, then stopConnecting() succeeded")
136-
} else {
137-
self.Log.error("MCConnectionExampleViewModel connect() commissionerDeclarationCallback, InitializationExample.getAppParametersDataSource() failed, then stopConnecting() failed due to: \(err)")
138-
}
139137
return
140138
}
141139

@@ -144,28 +142,13 @@ class MCConnectionExampleViewModel: ObservableObject {
144142
if errContinue == nil {
145143
self.connectionStatus = "Continuing to connect with user entered passcode: \(userEnteredPasscode)"
146144
} else {
147-
self.connectionStatus = "Continue Connecting to Casting Player failed with: \(String(describing: errContinue)) \n\nRoute back and try again."
145+
self.connectionStatus = "Continue Connecting to Casting Player failed with: \(String(describing: errContinue)) \n\nRoute back to disconnect and try again."
148146
self.Log.error("MCConnectionExampleViewModel connect() commissionerDeclarationCallback, MCCastingPlayer.continueConnecting() failed due to: \(errContinue)")
149-
// Since continueConnecting() failed, Attempt to cancel the connection attempt with
150-
// the CastingPlayer/Commissioner.
151-
let err = selectedCastingPlayer?.stopConnecting()
152-
if err == nil {
153-
self.Log.info("MCConnectionExampleViewModel connect() commissionerDeclarationCallback, MCCastingPlayer.continueConnecting() failed, then stopConnecting() succeeded")
154-
} else {
155-
self.Log.error("MCConnectionExampleViewModel connect() commissionerDeclarationCallback, MCCastingPlayer.continueConnecting() failed, then stopConnecting() failed due to: \(err)")
156-
}
157147
}
158148
}, cancelConnecting: {
159-
self.Log.info("MCConnectionExampleViewModel connect() commissionerDeclarationCallback, Connection attempt cancelled by the user, calling MCCastingPlayer.stopConnecting()")
160-
let err = selectedCastingPlayer?.stopConnecting()
149+
self.Log.info("MCConnectionExampleViewModel connect() commissionerDeclarationCallback, Connection attempt cancelled by the user")
161150
self.connectionSuccess = false
162-
if err == nil {
163-
self.connectionStatus = "User cancelled the connection attempt with CastingPlayer. \n\nRoute back to exit."
164-
self.Log.info("MCConnectionExampleViewModel connect() commissionerDeclarationCallback, User cancelled the connection attempt with MCCastingPlayer, MCCastingPlayer.stopConnecting() succeeded.")
165-
} else {
166-
self.connectionStatus = "Cancel connection failed due to: \(String(describing: err)) \n\nRoute back to exit."
167-
self.Log.error("MCConnectionExampleViewModel connect() commissionerDeclarationCallback, MCCastingPlayer.stopConnecting() failed due to: \(err)")
168-
}
151+
self.connectionStatus = "User cancelled the connection attempt with CastingPlayer. \n\nRoute back to disconnect & exit."
169152
})
170153
}
171154
}

examples/tv-casting-app/tv-casting-common/core/CastingPlayer.h

+11-1
Original file line numberDiff line numberDiff line change
@@ -218,11 +218,15 @@ class CastingPlayer : public std::enable_shared_from_this<CastingPlayer>
218218
* otherwise. StopConnecting() can only be called by the client during the CastingPlayer/Commissioner-Generated passcode
219219
* commissioning flow. Calling StopConnecting() during the Client/Commissionee-Generated commissioning flow will return a
220220
* CHIP_ERROR_INCORRECT_STATE error.
221+
*
222+
* @note This method will free the calling object as a side effect.
221223
*/
222224
CHIP_ERROR StopConnecting();
223225

224226
/**
225227
* @brief Sets the internal connection state of this CastingPlayer to "disconnected"
228+
*
229+
* @note This method will free the calling object as a side effect.
226230
*/
227231
void Disconnect();
228232

@@ -286,7 +290,11 @@ class CastingPlayer : public std::enable_shared_from_this<CastingPlayer>
286290
/**
287291
* @brief Return the current state of the CastingPlayer
288292
*/
289-
ConnectionState GetConnectionState() const { return mConnectionState; }
293+
ConnectionState GetConnectionState() const
294+
{
295+
ChipLogError(AppServer, "CastingPlayer::GetConnectionState() state: %d", mConnectionState);
296+
return mConnectionState;
297+
}
290298

291299
private:
292300
std::vector<memory::Strong<Endpoint>> mEndpoints;
@@ -326,6 +334,8 @@ class CastingPlayer : public std::enable_shared_from_this<CastingPlayer>
326334
/**
327335
* @brief resets this CastingPlayer's state and calls mOnCompleted with the CHIP_ERROR. Also, after calling mOnCompleted, it
328336
* clears mOnCompleted by setting it to a nullptr.
337+
*
338+
* @note This method will free the calling object as a side effect.
329339
*/
330340
void resetState(CHIP_ERROR err);
331341

examples/tv-casting-app/tv-casting-common/core/CastingPlayerDiscovery.h

+1
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ class CastingPlayerDiscovery
108108
static CastingPlayerDiscovery * GetInstance();
109109
~CastingPlayerDiscovery()
110110
{
111+
ChipLogError(AppServer, "CastingPlayerDiscovery destructor() called");
111112
mCastingPlayers.clear();
112113
mCastingPlayersInternal.clear();
113114
}

examples/tv-casting-app/tv-casting-common/support/ChipDeviceEventHandler.cpp

+12
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,18 @@ void ChipDeviceEventHandler::Handle(const chip::DeviceLayer::ChipDeviceEvent * e
3737
{
3838
ChipLogProgress(AppServer, "ChipDeviceEventHandler::Handle() called");
3939

40+
// Make sure we have not disconnected from the TargetCastingPlayer when handling incoming messages.
41+
// Sometimes the tv-app will still send messages after we clean up the TargetCastingPlayer.
42+
// Exmaple: Call stopConnecting() after immediately after calling continueConnectiong()
43+
//
44+
// A proper fix would be to either not let user navigate back when running post commission or update commissioner, commissionee
45+
// communication protocal to better handle asynchronous disconnects
46+
if (CastingPlayer::GetTargetCastingPlayer() == nullptr)
47+
{
48+
ChipLogError(AppServer, "ChipDeviceEventHandler::Handler() TargetCastingPlayer is null for event: %u", event->Type);
49+
return;
50+
}
51+
4052
bool runPostCommissioning = false;
4153
chip::NodeId targetNodeId = 0;
4254
chip::FabricIndex targetFabricIndex = 0;

0 commit comments

Comments
 (0)