Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Take connection operations off the UI thread (#122) (#25580)
Browse files Browse the repository at this point in the history
Clicking connect in the tv-casting-app freezes the UI for a few seconds
because it tries to attempt the connection on the UI thread. This puts
it in an async thread so that the UI is not blocked while its trying to
establish that connection.

Tested by attempting the connection and verifying it wasn't paused and
still showed the right messages and connected successfully.
cliffamzn authored and pull[bot] committed Aug 28, 2023
1 parent 2d6060f commit 5823841
Showing 1 changed file with 112 additions and 82 deletions.
Original file line number Diff line number Diff line change
@@ -17,6 +17,7 @@
import com.chip.casting.TvCastingApp;
import com.chip.casting.VideoPlayer;
import com.chip.casting.util.GlobalCastingConstants;
import java.util.concurrent.Executors;

/** A {@link Fragment} to get the TV Casting App commissioned / connected. */
public class ConnectionFragment extends Fragment {
@@ -28,6 +29,9 @@ public class ConnectionFragment extends Fragment {
private boolean openCommissioningWindowSuccess;
private boolean sendUdcSuccess;

private TextView commissioningWindowStatusView;
private TextView onboardingPayloadView;

public ConnectionFragment(TvCastingApp tvCastingApp, DiscoveredNodeData selectedCommissioner) {
this.tvCastingApp = tvCastingApp;
this.selectedCommissioner = selectedCommissioner;
@@ -52,97 +56,123 @@ public void onCreate(Bundle savedInstanceState) {
@Override
public View onCreateView(
LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
Callback callback = (ConnectionFragment.Callback) this.getActivity();

SuccessCallback<VideoPlayer> onConnectionSuccess =
new SuccessCallback<VideoPlayer>() {
@Override
public void handle(VideoPlayer videoPlayer) {
Log.d(TAG, "handle() called on OnConnectionSuccess with " + videoPlayer);
callback.handleCommissioningComplete();
}
};

FailureCallback onConnectionFailure =
new FailureCallback() {
@Override
public void handle(MatterError matterError) {
Log.d(TAG, "handle() called on OnConnectionFailure with " + matterError);
}
};

SuccessCallback<ContentApp> onNewOrUpdatedEndpoints =
new SuccessCallback<ContentApp>() {
@Override
public void handle(ContentApp contentApp) {
Log.d(TAG, "handle() called on OnNewOrUpdatedEndpoint with " + contentApp);
}
};

if (selectedCommissioner != null && selectedCommissioner.isPreCommissioned()) {
VideoPlayer videoPlayer = selectedCommissioner.toConnectableVideoPlayer();
Log.d(TAG, "Calling verifyOrEstablishConnectionSuccess with VideoPlayer: " + videoPlayer);
tvCastingApp.verifyOrEstablishConnection(
videoPlayer, onConnectionSuccess, onConnectionFailure, onNewOrUpdatedEndpoints);
} else {
Log.d(TAG, "Running commissioning");
this.openCommissioningWindowSuccess =
tvCastingApp.openBasicCommissioningWindow(
GlobalCastingConstants.CommissioningWindowDurationSecs,
new MatterCallbackHandler() {
@Override
public void handle(MatterError error) {
Log.d(TAG, "handle() called on CommissioningComplete event with " + error);
}
},
onConnectionSuccess,
onConnectionFailure,
onNewOrUpdatedEndpoints);

if (this.openCommissioningWindowSuccess) {
if (selectedCommissioner != null && selectedCommissioner.getNumIPs() > 0) {
String ipAddress = selectedCommissioner.getIpAddresses().get(0).getHostAddress();
Log.d(
TAG,
"ConnectionFragment calling tvCastingApp.sendUserDirectedCommissioningRequest with IP: "
+ ipAddress
+ " port: "
+ selectedCommissioner.getPort());

this.sendUdcSuccess = tvCastingApp.sendCommissioningRequest(selectedCommissioner);
}
}
}

return inflater.inflate(R.layout.fragment_connection, container, false);
}

@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
String commissioningWindowStatus = "";
if (selectedCommissioner != null && selectedCommissioner.isPreCommissioned()) {
commissioningWindowStatus = "Establishing connection with selected Video Player";
} else {
commissioningWindowStatus = "Failed to open commissioning window";
if (this.openCommissioningWindowSuccess) {
commissioningWindowStatus = "Commissioning window has been opened. Commission manually.";
if (this.sendUdcSuccess) {
commissioningWindowStatus =
"Commissioning window has been opened. Commissioning requested from "
+ selectedCommissioner.getDeviceName();
}
TextView onboardingPayloadView = getView().findViewById(R.id.onboardingPayload);
onboardingPayloadView.setText(
"Onboarding PIN: "
+ GlobalCastingConstants.SetupPasscode
+ "\nDiscriminator: "
+ GlobalCastingConstants.Discriminator);
onboardingPayloadView = getView().findViewById(R.id.onboardingPayload);
commissioningWindowStatusView = getView().findViewById(R.id.commissioningWindowStatus);

String commissioningWindowStatus =
(selectedCommissioner != null && selectedCommissioner.isPreCommissioned())
? "Establishing CASE session with video player..."
: "Requesting to be commissioned by the video player...";
commissioningWindowStatusView.setText(commissioningWindowStatus);

Executors.newSingleThreadExecutor()
.submit(
() -> {
Callback callback = (ConnectionFragment.Callback) this.getActivity();

SuccessCallback<VideoPlayer> onConnectionSuccess =
new SuccessCallback<VideoPlayer>() {
@Override
public void handle(VideoPlayer videoPlayer) {
Log.d(TAG, "handle() called on OnConnectionSuccess with " + videoPlayer);
callback.handleCommissioningComplete();
}
};

FailureCallback onConnectionFailure =
new FailureCallback() {
@Override
public void handle(MatterError matterError) {
Log.d(TAG, "handle() called on OnConnectionFailure with " + matterError);
}
};

SuccessCallback<ContentApp> onNewOrUpdatedEndpoints =
new SuccessCallback<ContentApp>() {
@Override
public void handle(ContentApp contentApp) {
Log.d(TAG, "handle() called on OnNewOrUpdatedEndpoint with " + contentApp);
}
};

if (selectedCommissioner != null && selectedCommissioner.isPreCommissioned()) {
VideoPlayer videoPlayer = selectedCommissioner.toConnectableVideoPlayer();
Log.d(
TAG,
"Calling verifyOrEstablishConnectionSuccess with VideoPlayer: " + videoPlayer);
tvCastingApp.verifyOrEstablishConnection(
videoPlayer, onConnectionSuccess, onConnectionFailure, onNewOrUpdatedEndpoints);
} else {
beginCommissioning(
onConnectionSuccess, onConnectionFailure, onNewOrUpdatedEndpoints);
}
});
}

private void beginCommissioning(
SuccessCallback<VideoPlayer> onConnectionSuccess,
FailureCallback onConnectionFailure,
SuccessCallback<ContentApp> onNewOrUpdatedEndpoints) {
Log.d(TAG, "Running commissioning");
this.openCommissioningWindowSuccess =
tvCastingApp.openBasicCommissioningWindow(
GlobalCastingConstants.CommissioningWindowDurationSecs,
new MatterCallbackHandler() {
@Override
public void handle(MatterError error) {
Log.d(TAG, "handle() called on CommissioningComplete event with " + error);
}
},
onConnectionSuccess,
onConnectionFailure,
onNewOrUpdatedEndpoints);

if (this.openCommissioningWindowSuccess) {
if (selectedCommissioner != null && selectedCommissioner.getNumIPs() > 0) {
String ipAddress = selectedCommissioner.getIpAddresses().get(0).getHostAddress();
Log.d(
TAG,
"ConnectionFragment calling tvCastingApp.sendUserDirectedCommissioningRequest with IP: "
+ ipAddress
+ " port: "
+ selectedCommissioner.getPort());

this.sendUdcSuccess = tvCastingApp.sendCommissioningRequest(selectedCommissioner);
updateUiOnConnectionSuccess();
}
} else {
getActivity()
.runOnUiThread(
() -> {
commissioningWindowStatusView.setText("Failed to open commissioning window");
});
}
}

TextView commissioningWindowStatusView = getView().findViewById(R.id.commissioningWindowStatus);
commissioningWindowStatusView.setText(commissioningWindowStatus);
private void updateUiOnConnectionSuccess() {
getActivity()
.runOnUiThread(
() -> {
String finalCommissioningWindowStatus =
"Commissioning window has been opened. Commission manually.";
if (this.sendUdcSuccess) {
finalCommissioningWindowStatus =
"Commissioning window has been opened. Commissioning requested from "
+ selectedCommissioner.getDeviceName();
}
onboardingPayloadView.setText(
"Onboarding PIN: "
+ GlobalCastingConstants.SetupPasscode
+ "\nDiscriminator: "
+ GlobalCastingConstants.Discriminator);
commissioningWindowStatusView.setText(finalCommissioningWindowStatus);
});
}

/** Interface for notifying the host. */

0 comments on commit 5823841

Please sign in to comment.