tv-casting-app CDC message CancelPasscode and ErrorCode iOS/Android s… (#35831)

* tv-casting-app CDC message CancelPasscode and ErrorCode iOS/Android sample-app UX updates

* Addressed comments by sharadb-amazon
diff --git a/examples/tv-casting-app/android/App/app/src/main/java/com/matter/casting/ConnectionExampleFragment.java b/examples/tv-casting-app/android/App/app/src/main/java/com/matter/casting/ConnectionExampleFragment.java
index 5db9a35..fc3ba6c 100644
--- a/examples/tv-casting-app/android/App/app/src/main/java/com/matter/casting/ConnectionExampleFragment.java
+++ b/examples/tv-casting-app/android/App/app/src/main/java/com/matter/casting/ConnectionExampleFragment.java
@@ -54,7 +54,9 @@
   private final CastingPlayer targetCastingPlayer;
   private final boolean useCommissionerGeneratedPasscode;
   private TextView connectionFragmentStatusTextView;
+  private TextView commissionerDeclarationErrorTextView;
   private Button connectionFragmentNextButton;
+  private AlertDialog passcodeDialog;
 
   public ConnectionExampleFragment(
       CastingPlayer targetCastingPlayer, boolean useCommissionerGeneratedPasscode) {
@@ -100,6 +102,8 @@
     Log.i(TAG, "onViewCreated()");
 
     connectionFragmentStatusTextView = getView().findViewById(R.id.connectionFragmentStatusText);
+    commissionerDeclarationErrorTextView =
+        getView().findViewById(R.id.commissionerDeclarationErrorTextView);
     if (useCommissionerGeneratedPasscode) {
       connectionFragmentStatusTextView.setText(
           "Verifying or establishing connection with Casting Player with device name: "
@@ -190,32 +194,52 @@
                       },
                       null);
 
-              // CommissionerDeclaration is only needed for the CastingPlayer/Commissioner-Generated
-              // passcode commissioning flow.
-              if (useCommissionerGeneratedPasscode) {
-                connectionCallbacks.onCommissionerDeclaration =
-                    new MatterCallback<CommissionerDeclaration>() {
-                      @Override
-                      public void handle(CommissionerDeclaration cd) {
-                        Log.i(TAG, "CastingPlayer CommissionerDeclaration message received: ");
-                        cd.logDetail();
+              // The CommissionerDeclaration callback is optional and only needed for the
+              // CastingPlayer/Commissioner-Generated
+              // passcode commissioning flow. However, if we want to know when the
+              // CastingPlayer/Commissioner user
+              // has cancelled the connection attempt when using the Client/Commissionee generated
+              // passcode flow, then we
+              // need to implement this callback.
+              connectionCallbacks.onCommissionerDeclaration =
+                  new MatterCallback<CommissionerDeclaration>() {
+                    @Override
+                    public void handle(CommissionerDeclaration cd) {
+                      Log.i(TAG, "CastingPlayer CommissionerDeclaration message received: ");
+                      cd.logDetail();
 
-                        getActivity()
-                            .runOnUiThread(
-                                () -> {
+                      getActivity()
+                          .runOnUiThread(
+                              () -> {
+                                connectionFragmentStatusTextView.setText(
+                                    "CommissionerDeclaration message received from Casting Player: \n\n");
+                                if (cd.getCommissionerPasscode()) {
+
+                                  displayPasscodeInputDialog(getActivity());
+
                                   connectionFragmentStatusTextView.setText(
-                                      "CommissionerDeclaration message received from Casting Player: \n\n");
-                                  if (cd.getCommissionerPasscode()) {
-
-                                    displayPasscodeInputDialog(getActivity());
-
+                                      "CommissionerDeclaration message received from Casting Player: A passcode is now displayed for the user by the Casting Player. \n\n");
+                                }
+                                if (cd.getCancelPasscode()) {
+                                  if (useCommissionerGeneratedPasscode) {
                                     connectionFragmentStatusTextView.setText(
-                                        "CommissionerDeclaration message received from Casting Player: A passcode is now displayed for the user by the Casting Player. \n\n");
+                                        "CastingPlayer/Commissioner-Generated passcode connection attempt cancelled by the CastingPlayer/Commissioner user. \n\nRoute back to exit. \n\n");
+                                  } else {
+                                    connectionFragmentStatusTextView.setText(
+                                        "Connection attempt cancelled by the CastingPlayer/Commissioner user. \n\nRoute back to exit. \n\n");
                                   }
-                                });
-                      }
-                    };
-              }
+                                  if (passcodeDialog != null && passcodeDialog.isShowing()) {
+                                    passcodeDialog.dismiss();
+                                  }
+                                }
+                                if (cd.getErrorCode() != CommissionerDeclaration.CdError.noError) {
+                                  commissionerDeclarationErrorTextView.setText(
+                                      "CommissionerDeclaration error from CastingPlayer: "
+                                          + cd.getErrorCode().getDescription());
+                                }
+                              });
+                    }
+                  };
 
               MatterError err =
                   targetCastingPlayer.verifyOrEstablishConnection(
@@ -331,7 +355,7 @@
                 TAG,
                 "displayPasscodeInputDialog() user cancelled the CastingPlayer/Commissioner-Generated Passcode input dialog. Calling stopConnecting()");
             connectionFragmentStatusTextView.setText(
-                "Connection attempt with Casting Player cancelled by the user, route back to exit. \n\n");
+                "Connection attempt with Casting Player cancelled by the Casting Client/Commissionee user. \n\nRoute back to exit. \n\n");
             MatterError err = targetCastingPlayer.stopConnecting();
             if (err.hasError()) {
               MatterError finalErr = err;
@@ -348,9 +372,9 @@
         });
 
     builder.setView(dialogView);
-    AlertDialog alertDialog = builder.create();
-    alertDialog.show();
-    alertDialog
+    passcodeDialog = builder.create(); // Store the dialog instance in the passcodeDialog variable
+    passcodeDialog.show();
+    passcodeDialog
         .getWindow()
         .setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
   }
diff --git a/examples/tv-casting-app/android/App/app/src/main/jni/com/matter/casting/support/CommissionerDeclaration.java b/examples/tv-casting-app/android/App/app/src/main/jni/com/matter/casting/support/CommissionerDeclaration.java
index 82213a3..401c948 100644
--- a/examples/tv-casting-app/android/App/app/src/main/jni/com/matter/casting/support/CommissionerDeclaration.java
+++ b/examples/tv-casting-app/android/App/app/src/main/jni/com/matter/casting/support/CommissionerDeclaration.java
@@ -22,39 +22,62 @@
 public class CommissionerDeclaration {
   static final String TAG = CommissionerDeclaration.class.getSimpleName();
 
-  /** The allowed values for the ErrorCode field are the following */
+  /**
+   * The allowed values for the ErrorCode field are the following. Indicates errors incurred during
+   * commissioning.
+   */
   public enum CdError {
-    kNoError(0),
-    kCommissionableDiscoveryFailed(1),
-    kPaseConnectionFailed(2),
-    kPaseAuthFailed(3),
-    kDacValidationFailed(4),
-    kAlreadyOnFabric(5),
-    kOperationalDiscoveryFailed(6),
-    kCaseConnectionFailed(7),
-    kCaseAuthFailed(8),
-    kConfigurationFailed(9),
-    kBindingConfigurationFailed(10),
-    kCommissionerPasscodeNotSupported(11),
-    kInvalidIdentificationDeclarationParams(12),
-    kAppInstallConsentPending(13),
-    kAppInstalling(14),
-    kAppInstallFailed(15),
-    kAppInstalledRetryNeeded(16),
-    kCommissionerPasscodeDisabled(17),
-    kUnexpectedCommissionerPasscodeReady(18);
+    noError(0, "No error"),
+    commissionableDiscoveryFailed(1, "Commissionable Node discovery failed"),
+    paseConnectionFailed(2, "PASE connection failed"),
+    paseAuthFailed(3, "PASE authentication failed (bad Passcode)"),
+    dacValidationFailed(4, "DAC validation failed"),
+    alreadyOnFabric(5, "Already on fabric"),
+    operationalDiscoveryFailed(6, "Operational Node discovery failed"),
+    caseConnectionFailed(7, "CASE connection failed"),
+    caseAuthFailed(8, "CASE authentication failed"),
+    configurationFailed(9, "Configuration failed"),
+    bindingConfigurationFailed(10, "Binding Configuration failed"),
+    commissionerPasscodeNotSupported(11, "Commissioner Passcode not supported"),
+    invalidIdentificationDeclarationParams(12, "Invalid UDC Identification Declaration parameters"),
+    appInstallConsentPending(13, "App Install Consent Pending"),
+    appInstalling(14, "App Installing"),
+    appInstallFailed(15, "App Install Failed"),
+    appInstalledRetryNeeded(16, "App Installed, Retry Needed"),
+    commissionerPasscodeDisabled(17, "Commissioner Passcode disabled"),
+    unexpectedCommissionerPasscodeReady(18, "Unexpected Commissioner Passcode ready");
+
     private final int value;
+    private final String description;
+
+    private CdError(int value, String description) {
+      this.value = value;
+      this.description = description;
+    }
+
+    private static String getDefaultDescription(int value) {
+      for (CdError error : CdError.values()) {
+        if (error.value == value) {
+          return error.name();
+        }
+      }
+      return "Unknown Error";
+    }
 
     CdError(int value) {
-      this.value = value;
+      this(value, getDefaultDescription(value));
     }
 
     public int getValue() {
       return value;
     }
+
+    public String getDescription() {
+      return description;
+    }
   }
   /** Feature: All - Indicates errors incurred during commissioning. */
-  private CdError errorCode = CdError.kNoError;
+  private CdError errorCode = CdError.noError;
   /**
    * Feature: Coordinate PIN Dialogs - When NoPasscode field set to true, and the Commissioner
    * determines that a Passcode code will be needed for commissioning.
@@ -81,6 +104,11 @@
    * also displays a QR code.
    */
   private boolean qRCodeDisplayed = false;
+  /**
+   * Feature: Commissioner-Generated Passcode - Flag to indicate when the CastingplAYER/Commissioner
+   * user has decided to exit the commissioning process.
+   */
+  private boolean cancelPasscode = false;
 
   public CommissionerDeclaration(
       int errorCode,
@@ -88,13 +116,15 @@
       boolean noAppsFound,
       boolean passcodeDialogDisplayed,
       boolean commissionerPasscode,
-      boolean qRCodeDisplayed) {
+      boolean qRCodeDisplayed,
+      boolean cancelPasscode) {
     this.errorCode = CdError.values()[errorCode];
     this.needsPasscode = needsPasscode;
     this.noAppsFound = noAppsFound;
     this.passcodeDialogDisplayed = passcodeDialogDisplayed;
     this.commissionerPasscode = commissionerPasscode;
     this.qRCodeDisplayed = qRCodeDisplayed;
+    this.cancelPasscode = cancelPasscode;
   }
 
   public void setErrorCode(CdError errorCode) {
@@ -145,6 +175,10 @@
     return this.qRCodeDisplayed;
   }
 
+  public boolean getCancelPasscode() {
+    return this.cancelPasscode;
+  }
+
   @Override
   public String toString() {
     return "CommissionerDeclaration::errorCode:               "
@@ -163,7 +197,10 @@
         + commissionerPasscode
         + "\n"
         + "CommissionerDeclaration::qRCodeDisplayed:         "
-        + qRCodeDisplayed;
+        + qRCodeDisplayed
+        + "\n"
+        + "CommissionerDeclaration::cancelPasscode:          "
+        + cancelPasscode;
   }
 
   public void logDetail() {
diff --git a/examples/tv-casting-app/android/App/app/src/main/jni/cpp/support/Converters-JNI.cpp b/examples/tv-casting-app/android/App/app/src/main/jni/cpp/support/Converters-JNI.cpp
index 69f70c4..5b002f3 100644
--- a/examples/tv-casting-app/android/App/app/src/main/jni/cpp/support/Converters-JNI.cpp
+++ b/examples/tv-casting-app/android/App/app/src/main/jni/cpp/support/Converters-JNI.cpp
@@ -528,7 +528,7 @@
                                                                          jCommissionerDeclarationClass);
     VerifyOrReturnValue(err == CHIP_NO_ERROR, nullptr);
 
-    jmethodID jCommissionerDeclarationConstructor = env->GetMethodID(jCommissionerDeclarationClass, "<init>", "(IZZZZZ)V");
+    jmethodID jCommissionerDeclarationConstructor = env->GetMethodID(jCommissionerDeclarationClass, "<init>", "(IZZZZZZ)V");
     if (jCommissionerDeclarationConstructor == nullptr)
     {
         ChipLogError(AppServer,
@@ -539,7 +539,8 @@
 
     return env->NewObject(jCommissionerDeclarationClass, jCommissionerDeclarationConstructor,
                           static_cast<jint>(cppCd.GetErrorCode()), cppCd.GetNeedsPasscode(), cppCd.GetNoAppsFound(),
-                          cppCd.GetPasscodeDialogDisplayed(), cppCd.GetCommissionerPasscode(), cppCd.GetQRCodeDisplayed());
+                          cppCd.GetPasscodeDialogDisplayed(), cppCd.GetCommissionerPasscode(), cppCd.GetQRCodeDisplayed(),
+                          cppCd.GetCancelPasscode());
 }
 
 }; // namespace support
diff --git a/examples/tv-casting-app/android/App/app/src/main/res/layout/fragment_matter_connection_example.xml b/examples/tv-casting-app/android/App/app/src/main/res/layout/fragment_matter_connection_example.xml
index 9c2cf86..1e68622 100644
--- a/examples/tv-casting-app/android/App/app/src/main/res/layout/fragment_matter_connection_example.xml
+++ b/examples/tv-casting-app/android/App/app/src/main/res/layout/fragment_matter_connection_example.xml
@@ -28,6 +28,16 @@
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:text="@string/matter_connection_next_button_text" />
+        
+        <TextView
+            android:id="@+id/commissionerDeclarationErrorTextView"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:textSize="18sp"
+            android:textColor="@android:color/holo_red_dark"
+            android:layout_gravity="center_horizontal"
+            android:layout_marginTop="20dp"
+            android:text=""/>
 
     </LinearLayout>
 
diff --git a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCCommissionerDeclaration.h b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCCommissionerDeclaration.h
index 85bc465..f81d032 100644
--- a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCCommissionerDeclaration.h
+++ b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCCommissionerDeclaration.h
@@ -25,27 +25,29 @@
  */
 @interface MCCommissionerDeclaration : NSObject
 
-/** The allowed values for the ErrorCode field are the following */
+/** The allowed values for the ErrorCode field are the following. Indicates errors incurred
+ * during commissioning.
+ */
 typedef NS_ENUM(NSInteger, CdError) {
-    kNoError = 0,
-    kCommissionableDiscoveryFailed = 1,
-    kPaseConnectionFailed = 2,
-    kPaseAuthFailed = 3,
-    kDacValidationFailed = 4,
-    kAlreadyOnFabric = 5,
-    kOperationalDiscoveryFailed = 6,
-    kCaseConnectionFailed = 7,
-    kCaseAuthFailed = 8,
-    kConfigurationFailed = 9,
-    kBindingConfigurationFailed = 10,
-    kCommissionerPasscodeNotSupported = 11,
-    kInvalidIdentificationDeclarationParams = 12,
-    kAppInstallConsentPending = 13,
-    kAppInstalling = 14,
-    kAppInstallFailed = 15,
-    kAppInstalledRetryNeeded = 16,
-    kCommissionerPasscodeDisabled = 17,
-    kUnexpectedCommissionerPasscodeReady = 18
+    noError = 0,
+    commissionableDiscoveryFailed = 1,
+    paseConnectionFailed = 2,
+    paseAuthFailed = 3,
+    dacValidationFailed = 4,
+    alreadyOnFabric = 5,
+    operationalDiscoveryFailed = 6,
+    caseConnectionFailed = 7,
+    caseAuthFailed = 8,
+    configurationFailed = 9,
+    bindingConfigurationFailed = 10,
+    commissionerPasscodeNotSupported = 11,
+    invalidIdentificationDeclarationParams = 12,
+    appInstallConsentPending = 13,
+    appInstalling = 14,
+    appInstallFailed = 15,
+    appInstalledRetryNeeded = 16,
+    commissionerPasscodeDisabled = 17,
+    unexpectedCommissionerPasscodeReady = 18
 };
 
 /** Feature: All - Indicates errors incurred during commissioning. */
@@ -76,13 +78,24 @@
  * also displays a QR code.
  */
 @property (nonatomic, readonly) BOOL qRCodeDisplayed;
+/**
+ * Feature: Commissioner-Generated Passcode - Flag to indicate when the CastingplAYER/Commissioner
+ * user has decided to exit the commissioning process.
+ */
+@property (nonatomic, readonly) BOOL cancelPasscode;
 
 - (instancetype)initWithOptions:(NSInteger)errorCode
                   needsPasscode:(BOOL)needsPasscode
                     noAppsFound:(BOOL)noAppsFound
         passcodeDialogDisplayed:(BOOL)passcodeDialogDisplayed
            commissionerPasscode:(BOOL)commissionerPasscode
-                qRCodeDisplayed:(BOOL)qRCodeDisplayed;
+                qRCodeDisplayed:(BOOL)qRCodeDisplayed
+                 cancelPasscode:(BOOL)cancelPasscode;
+
+/**
+ * Function to return the error code as a string.
+ */
+- (NSString *)getErrorCodeString;
 
 - (NSString *)description;
 - (void)logDetail;
diff --git a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCCommissionerDeclaration.mm b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCCommissionerDeclaration.mm
index 1663f16..c9388ac 100644
--- a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCCommissionerDeclaration.mm
+++ b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCCommissionerDeclaration.mm
@@ -36,6 +36,7 @@
         _passcodeDialogDisplayed = cppCommissionerDeclaration->GetPasscodeDialogDisplayed();
         _commissionerPasscode = cppCommissionerDeclaration->GetCommissionerPasscode();
         _qRCodeDisplayed = cppCommissionerDeclaration->GetQRCodeDisplayed();
+        _cancelPasscode = cppCommissionerDeclaration->GetCancelPasscode();
     }
     return self;
 }
@@ -46,6 +47,7 @@
         passcodeDialogDisplayed:(BOOL)passcodeDialogDisplayed
            commissionerPasscode:(BOOL)commissionerPasscode
                 qRCodeDisplayed:(BOOL)qRCodeDisplayed
+                 cancelPasscode:(BOOL)cancelPasscode
 {
     self = [super init];
     if (self) {
@@ -55,62 +57,69 @@
         _passcodeDialogDisplayed = passcodeDialogDisplayed;
         _commissionerPasscode = commissionerPasscode;
         _qRCodeDisplayed = qRCodeDisplayed;
+        _cancelPasscode = cancelPasscode;
     }
     return self;
 }
 
 - (NSString *)description
 {
-    return [NSString stringWithFormat:@"MCCommissionerDeclaration::errorCode:               %@\nMCCommissionerDeclaration::needsPasscode:           %d\nMCCommissionerDeclaration::noAppsFound:             %d\nMCCommissionerDeclaration::passcodeDialogDisplayed: %d\nMCCommissionerDeclaration::commissionerPasscode:    %d\nMCCommissionerDeclaration::qRCodeDisplayed:         %d",
+    return [NSString stringWithFormat:@"MCCommissionerDeclaration::errorCode:               %@\nMCCommissionerDeclaration::needsPasscode:           %d\nMCCommissionerDeclaration::noAppsFound:             %d\nMCCommissionerDeclaration::passcodeDialogDisplayed: %d\nMCCommissionerDeclaration::commissionerPasscode:    %d\nMCCommissionerDeclaration::qRCodeDisplayed:         %d\nMCCommissionerDeclaration::cancelPasscode:          %d",
                      [self stringForErrorCode:self.errorCode],
                      self.needsPasscode,
                      self.noAppsFound,
                      self.passcodeDialogDisplayed,
                      self.commissionerPasscode,
-                     self.qRCodeDisplayed];
+                     self.qRCodeDisplayed,
+                     self.cancelPasscode];
+}
+
+- (NSString *)getErrorCodeString
+{
+    return [self stringForErrorCode:self.errorCode];
 }
 
 - (NSString *)stringForErrorCode:(CdError)errorCode
 {
     switch (errorCode) {
-    case kNoError:
-        return @"kNoError";
-    case kCommissionableDiscoveryFailed:
-        return @"kCommissionableDiscoveryFailed";
-    case kPaseConnectionFailed:
-        return @"kPaseConnectionFailed";
-    case kPaseAuthFailed:
-        return @"kPaseAuthFailed";
-    case kDacValidationFailed:
-        return @"kDacValidationFailed";
-    case kAlreadyOnFabric:
-        return @"kAlreadyOnFabric";
-    case kOperationalDiscoveryFailed:
-        return @"kOperationalDiscoveryFailed";
-    case kCaseConnectionFailed:
-        return @"kCaseConnectionFailed";
-    case kCaseAuthFailed:
-        return @"kCaseAuthFailed";
-    case kConfigurationFailed:
-        return @"kConfigurationFailed";
-    case kBindingConfigurationFailed:
-        return @"kBindingConfigurationFailed";
-    case kCommissionerPasscodeNotSupported:
-        return @"kCommissionerPasscodeNotSupported";
-    case kInvalidIdentificationDeclarationParams:
-        return @"kInvalidIdentificationDeclarationParams";
-    case kAppInstallConsentPending:
-        return @"kAppInstallConsentPending";
-    case kAppInstalling:
-        return @"kAppInstalling";
-    case kAppInstallFailed:
-        return @"kAppInstallFailed";
-    case kAppInstalledRetryNeeded:
-        return @"kAppInstalledRetryNeeded";
-    case kCommissionerPasscodeDisabled:
-        return @"kCommissionerPasscodeDisabled";
-    case kUnexpectedCommissionerPasscodeReady:
-        return @"kUnexpectedCommissionerPasscodeReady";
+    case noError:
+        return @"noError";
+    case commissionableDiscoveryFailed:
+        return @"commissionableDiscoveryFailed";
+    case paseConnectionFailed:
+        return @"paseConnectionFailed";
+    case paseAuthFailed:
+        return @"paseAuthFailed";
+    case dacValidationFailed:
+        return @"dacValidationFailed";
+    case alreadyOnFabric:
+        return @"alreadyOnFabric";
+    case operationalDiscoveryFailed:
+        return @"operationalDiscoveryFailed";
+    case caseConnectionFailed:
+        return @"caseConnectionFailed";
+    case caseAuthFailed:
+        return @"caseAuthFailed";
+    case configurationFailed:
+        return @"configurationFailed";
+    case bindingConfigurationFailed:
+        return @"bindingConfigurationFailed";
+    case commissionerPasscodeNotSupported:
+        return @"commissionerPasscodeNotSupported";
+    case invalidIdentificationDeclarationParams:
+        return @"invalidIdentificationDeclarationParams";
+    case appInstallConsentPending:
+        return @"appInstallConsentPending";
+    case appInstalling:
+        return @"appInstalling";
+    case appInstallFailed:
+        return @"appInstallFailed";
+    case appInstalledRetryNeeded:
+        return @"appInstalledRetryNeeded";
+    case commissionerPasscodeDisabled:
+        return @"commissionerPasscodeDisabled";
+    case unexpectedCommissionerPasscodeReady:
+        return @"unexpectedCommissionerPasscodeReady";
     default:
         return @"Unknown Error";
     }
diff --git a/examples/tv-casting-app/darwin/TvCasting/TvCasting/MCConnectionExampleView.swift b/examples/tv-casting-app/darwin/TvCasting/TvCasting/MCConnectionExampleView.swift
index 36ac837..5760fae 100644
--- a/examples/tv-casting-app/darwin/TvCasting/TvCasting/MCConnectionExampleView.swift
+++ b/examples/tv-casting-app/darwin/TvCasting/TvCasting/MCConnectionExampleView.swift
@@ -65,6 +65,13 @@
                         .padding()
                 }
             }
+            Spacer()  // Push the error code to the bottom
+            if let errorCode = viewModel.errorCodeDescription {
+
+                Text("\(errorCode)")
+                    .foregroundColor(.red)
+                    .padding()
+            }
         }
         .navigationTitle("Connecting...")
         .frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity, alignment: .top)
diff --git a/examples/tv-casting-app/darwin/TvCasting/TvCasting/MCConnectionExampleViewModel.swift b/examples/tv-casting-app/darwin/TvCasting/TvCasting/MCConnectionExampleViewModel.swift
index 895b4a5..815c79f 100644
--- a/examples/tv-casting-app/darwin/TvCasting/TvCasting/MCConnectionExampleViewModel.swift
+++ b/examples/tv-casting-app/darwin/TvCasting/TvCasting/MCConnectionExampleViewModel.swift
@@ -22,6 +22,8 @@
 class MCConnectionExampleViewModel: ObservableObject {
     let Log = Logger(subsystem: "com.matter.casting",
                      category: "MCConnectionExampleViewModel")
+
+    var passcodeAlertController: UIAlertController?
     
     // VendorId of the MCEndpoint on the MCCastingPlayer that the MCCastingApp desires to interact with after connection
     let kDesiredEndpointVendorId: UInt16 = 65521;
@@ -38,6 +40,8 @@
 
     @Published var connectionStatus: String?;
 
+    @Published var errorCodeDescription: String?
+
     func connect(selectedCastingPlayer: MCCastingPlayer?, useCommissionerGeneratedPasscode: Bool) {
         self.Log.info("MCConnectionExampleViewModel.connect() useCommissionerGeneratedPasscode: \(String(describing: useCommissionerGeneratedPasscode))")
 
@@ -63,6 +67,22 @@
         let commissionerDeclarationCallback: (MCCommissionerDeclaration) -> Void = { commissionerDeclarationMessage in
             DispatchQueue.main.async {
                 self.Log.info("MCConnectionExampleViewModel connect() commissionerDeclarationCallback, recived a message form the MCCastingPlayer:\n\(commissionerDeclarationMessage)")
+
+                // Display CommissionerDeclaration error code if `errorCode` is not `kNoError`
+                if commissionerDeclarationMessage.errorCode != CdError.noError {
+                    self.errorCodeDescription = "CommissionerDeclaration error from CastingPlayer: \(commissionerDeclarationMessage.getErrorCodeString())"
+                    self.Log.error("MCConnectionExampleViewModel connect() Casting Player/Commissioner Error: \(self.errorCodeDescription ?? "Unknown Error")")
+                }
+
+                // Check if the passcode dialog should be cancelled
+                if commissionerDeclarationMessage.cancelPasscode {
+                    self.Log.info("MCConnectionExampleViewModel connect() commissionerDeclarationCallback. Cancel passcode received. Dismissing the PasscodeInputDialog.")
+                    self.passcodeAlertController?.dismiss(animated: true, completion: nil)
+                    self.connectionStatus = "Connection attempt cancelled by the CastingPlayer/Commissioner user. \n\nRoute back to exit."
+                    return
+                }
+
+                // Continue with passcode dialog if needed
                 if commissionerDeclarationMessage.commissionerPasscode {
                     self.Log.info("MCConnectionExampleViewModel connect() commissionerDeclarationCallback, calling getTopMostViewController()")
                     if let topViewController = self.getTopMostViewController() {
@@ -151,7 +171,7 @@
             targetAppInfo = MCTargetAppInfo(vendorId: kDesiredEndpointVendorId)
             connectionCallbacks = MCConnectionCallbacks(
                 callbacks: connectionCompleteCallback,
-                commissionerDeclarationCallback: nil
+                commissionerDeclarationCallback: commissionerDeclarationCallback
             )
         }
 
@@ -171,6 +191,7 @@
 
         // Create the alert controller
         let alertController = UIAlertController(title: "Enter Passcode", message: nil, preferredStyle: .alert)
+        self.passcodeAlertController = alertController
 
         // Add the text field with the default passcode
         alertController.addTextField { textField in