Skip to content

Commit 4424836

Browse files
sharadb-amazonpull[bot]
authored andcommitted
tv-casting-app: Handle uncaught exceptions before JNI crashes app and make iOS discoverCommissioners API callback based (#24896)
* iOS tv-casting-app: Making discovery API callback based * tv-casting-app: Handled uncaught exceptions and null pointer issues * Changing catch-all to catch Throwable instead of just Exception
1 parent e3b8e77 commit 4424836

File tree

16 files changed

+235
-56
lines changed

16 files changed

+235
-56
lines changed

examples/tv-casting-app/android/App/app/src/main/java/com/chip/casting/app/CertTestFragment.java

+38-17
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,12 @@ public void onClick(View v) {
8181
private void runCertTests(Activity activity) {
8282
CertTestMatterSuccessFailureCallback successFailureCallback =
8383
new CertTestMatterSuccessFailureCallback(activity);
84-
CertTestMatterSuccessFailureCallbackInteger successFailureCallbackInteger =
85-
new CertTestMatterSuccessFailureCallbackInteger(successFailureCallback);
84+
CertTestMatterSuccessCallback successCallback =
85+
new CertTestMatterSuccessCallback(successFailureCallback);
86+
CertTestMatterFailureCallback failureCallback =
87+
new CertTestMatterFailureCallback(successFailureCallback);
88+
CertTestMatterSuccessCallbackInteger successCallbackInteger =
89+
new CertTestMatterSuccessCallbackInteger(successFailureCallback);
8690
CertTestMatterCallbackHandler callback =
8791
new CertTestMatterCallbackHandler(successFailureCallback);
8892

@@ -269,39 +273,39 @@ private void runCertTests(Activity activity) {
269273
successFailureCallback,
270274
() -> {
271275
tvCastingApp.applicationBasic_readApplicationVersion(
272-
kContentApp, successFailureCallback, successFailureCallback);
276+
kContentApp, successCallback, failureCallback);
273277
});
274278

275279
runAndWait(
276280
"applicationBasic_readVendorName",
277281
successFailureCallback,
278282
() -> {
279283
tvCastingApp.applicationBasic_readVendorName(
280-
kContentApp, successFailureCallback, successFailureCallback);
284+
kContentApp, successCallback, failureCallback);
281285
});
282286

283287
runAndWait(
284288
"applicationBasic_readApplicationName",
285289
successFailureCallback,
286290
() -> {
287291
tvCastingApp.applicationBasic_readApplicationName(
288-
kContentApp, successFailureCallback, successFailureCallback);
292+
kContentApp, successCallback, failureCallback);
289293
});
290294

291295
runAndWait(
292296
"applicationBasic_readVendorID",
293297
successFailureCallback,
294298
() -> {
295299
tvCastingApp.applicationBasic_readVendorID(
296-
kContentApp, successFailureCallbackInteger, successFailureCallbackInteger);
300+
kContentApp, successCallbackInteger, failureCallback);
297301
});
298302

299303
runAndWait(
300304
"applicationBasic_readProductID",
301305
successFailureCallback,
302306
() -> {
303307
tvCastingApp.applicationBasic_readProductID(
304-
kContentApp, successFailureCallbackInteger, successFailureCallbackInteger);
308+
kContentApp, successCallbackInteger, failureCallback);
305309
});
306310

307311
runAndWait(
@@ -320,7 +324,7 @@ public void handle(MediaPlaybackTypes.PlaybackStateEnum response) {
320324
activity, MatterError.NO_ERROR, "mediaPlayback_subscribeToCurrentState");
321325
}
322326
},
323-
successFailureCallback,
327+
failureCallback,
324328
0,
325329
20,
326330
new SubscriptionEstablishedCallback() {
@@ -415,8 +419,7 @@ public void handle(MatterError error) {
415419
}
416420
}
417421

418-
class CertTestMatterSuccessFailureCallback extends FailureCallback
419-
implements SuccessCallback<String> {
422+
class CertTestMatterSuccessFailureCallback {
420423
private Activity activity;
421424
private String testMethod;
422425
private CountDownLatch cdl;
@@ -433,7 +436,6 @@ public void setCountDownLatch(CountDownLatch cdl) {
433436
this.cdl = cdl;
434437
}
435438

436-
@Override
437439
public void handle(MatterError error) {
438440
try {
439441
cdl.countDown();
@@ -446,7 +448,6 @@ public void handle(MatterError error) {
446448
}
447449
}
448450

449-
@Override
450451
public void handle(String response) {
451452
try {
452453
cdl.countDown();
@@ -460,18 +461,38 @@ public void handle(String response) {
460461
}
461462
}
462463

463-
class CertTestMatterSuccessFailureCallbackInteger extends FailureCallback
464-
implements SuccessCallback<Integer> {
464+
class CertTestMatterSuccessCallback extends SuccessCallback<String> {
465+
private CertTestMatterSuccessFailureCallback delegate;
466+
467+
CertTestMatterSuccessCallback(CertTestMatterSuccessFailureCallback delegate) {
468+
this.delegate = delegate;
469+
}
470+
471+
@Override
472+
public void handle(String response) {
473+
delegate.handle(response);
474+
}
475+
}
465476

477+
class CertTestMatterFailureCallback extends FailureCallback {
466478
private CertTestMatterSuccessFailureCallback delegate;
467479

468-
CertTestMatterSuccessFailureCallbackInteger(CertTestMatterSuccessFailureCallback delegate) {
480+
CertTestMatterFailureCallback(CertTestMatterSuccessFailureCallback delegate) {
469481
this.delegate = delegate;
470482
}
471483

472484
@Override
473-
public void handle(MatterError error) {
474-
delegate.handle(error);
485+
public void handle(MatterError err) {
486+
delegate.handle(err);
487+
}
488+
}
489+
490+
class CertTestMatterSuccessCallbackInteger extends SuccessCallback<Integer> {
491+
492+
private CertTestMatterSuccessFailureCallback delegate;
493+
494+
CertTestMatterSuccessCallbackInteger(CertTestMatterSuccessFailureCallback delegate) {
495+
this.delegate = delegate;
475496
}
476497

477498
@Override

examples/tv-casting-app/android/App/app/src/main/java/com/chip/casting/app/MediaPlaybackFragment.java

+29-19
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import android.widget.TextView;
99
import androidx.annotation.Nullable;
1010
import androidx.fragment.app.Fragment;
11+
import androidx.fragment.app.FragmentActivity;
1112
import com.chip.casting.ContentApp;
1213
import com.chip.casting.FailureCallback;
1314
import com.chip.casting.MatterError;
@@ -63,13 +64,16 @@ public void onClick(View v) {
6364
TextView currentStateValue = getView().findViewById(R.id.currentStateValue);
6465

6566
SuccessCallback<MediaPlaybackTypes.PlaybackStateEnum> successCallback =
66-
playbackStateEnum -> {
67-
Log.d(
68-
TAG,
69-
"handle() called on SuccessCallback<MediaPlaybackResponseTypes.PlaybackStateEnum> with "
70-
+ playbackStateEnum);
71-
getActivity()
72-
.runOnUiThread(
67+
new SuccessCallback<MediaPlaybackTypes.PlaybackStateEnum>() {
68+
@Override
69+
public void handle(MediaPlaybackTypes.PlaybackStateEnum playbackStateEnum) {
70+
Log.d(
71+
TAG,
72+
"handle() called on SuccessCallback<MediaPlaybackResponseTypes.PlaybackStateEnum> with "
73+
+ playbackStateEnum);
74+
FragmentActivity fragmentActivity = getActivity();
75+
if (fragmentActivity != null) {
76+
fragmentActivity.runOnUiThread(
7377
new Runnable() {
7478
@Override
7579
public void run() {
@@ -78,6 +82,8 @@ public void run() {
7882
}
7983
}
8084
});
85+
}
86+
}
8187
};
8288

8389
FailureCallback failureCallback =
@@ -97,18 +103,22 @@ public void run() {
97103
};
98104

99105
SubscriptionEstablishedCallback subscriptionEstablishedCallback =
100-
(SubscriptionEstablishedCallback)
101-
() -> {
102-
Log.d(TAG, "handle() called on SubscriptionEstablishedCallback");
103-
getActivity()
104-
.runOnUiThread(
105-
new Runnable() {
106-
@Override
107-
public void run() {
108-
subscriptionStatus.setText("Subscription established!");
109-
}
110-
});
111-
};
106+
new SubscriptionEstablishedCallback() {
107+
@Override
108+
public void handle() {
109+
Log.d(TAG, "handle() called on SubscriptionEstablishedCallback");
110+
FragmentActivity fragmentActivity = getActivity();
111+
if (fragmentActivity != null) {
112+
fragmentActivity.runOnUiThread(
113+
new Runnable() {
114+
@Override
115+
public void run() {
116+
subscriptionStatus.setText("Subscription established!");
117+
}
118+
});
119+
}
120+
}
121+
};
112122

113123
boolean retVal =
114124
tvCastingApp.mediaPlayback_subscribeToCurrentState(

examples/tv-casting-app/android/App/app/src/main/jni/com/chip/casting/FailureCallback.java

+10-2
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,18 @@
1717
*/
1818
package com.chip.casting;
1919

20+
import android.util.Log;
21+
2022
public abstract class FailureCallback {
23+
private static final String TAG = FailureCallback.class.getSimpleName();
24+
2125
public abstract void handle(MatterError err);
2226

23-
public final void handle(int errorCode, String errorMessage) {
24-
handle(new MatterError(errorCode, errorMessage));
27+
private final void handleInternal(int errorCode, String errorMessage) {
28+
try {
29+
handle(new MatterError(errorCode, errorMessage));
30+
} catch (Throwable t) {
31+
Log.e(TAG, "FailureCallback::Caught an unhandled Throwable from the client: " + t);
32+
}
2533
}
2634
}

examples/tv-casting-app/android/App/app/src/main/jni/com/chip/casting/MatterCallbackHandler.java

+10-2
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,18 @@
1717
*/
1818
package com.chip.casting;
1919

20+
import android.util.Log;
21+
2022
public abstract class MatterCallbackHandler {
23+
private static final String TAG = MatterCallbackHandler.class.getSimpleName();
24+
2125
public abstract void handle(MatterError err);
2226

23-
public final void handle(int errorCode, String errorMessage) {
24-
handle(new MatterError(errorCode, errorMessage));
27+
private final void handleInternal(int errorCode, String errorMessage) {
28+
try {
29+
handle(new MatterError(errorCode, errorMessage));
30+
} catch (Throwable t) {
31+
Log.e(TAG, "MatterCallbackHandler::Caught an unhandled Throwable from the client: " + t);
32+
}
2533
}
2634
}

examples/tv-casting-app/android/App/app/src/main/jni/com/chip/casting/SubscriptionEstablishedCallback.java

+16-2
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,20 @@
1717
*/
1818
package com.chip.casting;
1919

20-
public interface SubscriptionEstablishedCallback {
21-
void handle();
20+
import android.util.Log;
21+
22+
public abstract class SubscriptionEstablishedCallback {
23+
private static final String TAG = SubscriptionEstablishedCallback.class.getSimpleName();
24+
25+
public abstract void handle();
26+
27+
private void handleInternal() {
28+
try {
29+
handle();
30+
} catch (Throwable t) {
31+
Log.e(
32+
TAG,
33+
"SubscriptionEstablishedCallback::Caught an unhandled Throwable from the client: " + t);
34+
}
35+
}
2236
}

examples/tv-casting-app/android/App/app/src/main/jni/com/chip/casting/SuccessCallback.java

+14-2
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,18 @@
1717
*/
1818
package com.chip.casting;
1919

20-
public interface SuccessCallback<R> {
21-
void handle(R response);
20+
import android.util.Log;
21+
22+
public abstract class SuccessCallback<R> {
23+
private static final String TAG = SuccessCallback.class.getSimpleName();
24+
25+
public abstract void handle(R response);
26+
27+
public void handleInternal(R response) {
28+
try {
29+
handle(response);
30+
} catch (Throwable t) {
31+
Log.e(TAG, "SuccessCallback::Caught an unhandled Throwable from the client: " + t);
32+
}
33+
}
2234
}

examples/tv-casting-app/android/App/app/src/main/jni/cpp/ConversionUtils.cpp

+3
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ CHIP_ERROR convertJAppParametersToCppAppParams(jobject appParameters, AppParams
6161
CHIP_ERROR convertJContentAppToTargetEndpointInfo(jobject contentApp, TargetEndpointInfo & outTargetEndpointInfo)
6262
{
6363
ChipLogProgress(AppServer, "convertJContentAppToTargetEndpointInfo called");
64+
VerifyOrReturnError(contentApp != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
6465
JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
6566

6667
jclass jContentAppClass;
@@ -124,6 +125,7 @@ CHIP_ERROR convertTargetEndpointInfoToJContentApp(TargetEndpointInfo * targetEnd
124125
CHIP_ERROR convertJVideoPlayerToTargetVideoPlayerInfo(jobject videoPlayer, TargetVideoPlayerInfo & outTargetVideoPlayerInfo)
125126
{
126127
ChipLogProgress(AppServer, "convertJVideoPlayerToTargetVideoPlayerInfo called");
128+
VerifyOrReturnError(videoPlayer != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
127129
JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
128130

129131
jclass jVideoPlayerClass;
@@ -241,6 +243,7 @@ CHIP_ERROR convertJDiscoveredNodeDataToCppDiscoveredNodeData(jobject jDiscovered
241243
chip::Dnssd::DiscoveredNodeData & outCppDiscoveredNodeData)
242244
{
243245
ChipLogProgress(AppServer, "convertJDiscoveredNodeDataToCppDiscoveredNodeData called");
246+
VerifyOrReturnError(jDiscoveredNodeData != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
244247

245248
JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
246249

examples/tv-casting-app/android/App/app/src/main/jni/cpp/MatterCallbackHandler-JNI.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,10 @@ CHIP_ERROR CallbackBaseJNI::SetUp(JNIEnv * env, jobject inHandler)
3131
mClazz = env->GetObjectClass(mObject);
3232
VerifyOrExit(mClazz != nullptr, ChipLogError(AppServer, "Failed to get handler Java class"));
3333

34-
mMethod = env->GetMethodID(mClazz, "handle", mMethodSignature);
34+
mMethod = env->GetMethodID(mClazz, "handleInternal", mMethodSignature);
3535
if (mMethod == nullptr)
3636
{
37-
ChipLogError(AppServer, "Failed to access 'handle' method with signature %s", mMethodSignature);
37+
ChipLogError(AppServer, "Failed to access 'handleInternal' method with signature %s", mMethodSignature);
3838
env->ExceptionClear();
3939
}
4040

examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge.xcodeproj/project.pbxproj

+4
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
3CCB8742286A593700771BAD /* ConversionUtils.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 3CCB873C286A593700771BAD /* ConversionUtils.hpp */; };
2727
3CCB8743286A593700771BAD /* CastingServerBridge.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3CCB873D286A593700771BAD /* CastingServerBridge.mm */; };
2828
3CCB8744286A593700771BAD /* ConversionUtils.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3CCB873E286A593700771BAD /* ConversionUtils.mm */; };
29+
3CD6D01A298CDA2100D7569A /* CommissionerDiscoveryDelegateImpl.h in Headers */ = {isa = PBXBuildFile; fileRef = 3CD6D019298CDA2100D7569A /* CommissionerDiscoveryDelegateImpl.h */; };
2930
3CE868F42946D76200FCB92B /* CommissionableDataProviderImpl.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3CE868F32946D76200FCB92B /* CommissionableDataProviderImpl.mm */; };
3031
3CF8532728E37F1000F07B9F /* MatterError.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3CF8532628E37F1000F07B9F /* MatterError.mm */; };
3132
/* End PBXBuildFile section */
@@ -60,6 +61,7 @@
6061
3CCB873C286A593700771BAD /* ConversionUtils.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = ConversionUtils.hpp; sourceTree = "<group>"; };
6162
3CCB873D286A593700771BAD /* CastingServerBridge.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = CastingServerBridge.mm; sourceTree = "<group>"; };
6263
3CCB873E286A593700771BAD /* ConversionUtils.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ConversionUtils.mm; sourceTree = "<group>"; };
64+
3CD6D019298CDA2100D7569A /* CommissionerDiscoveryDelegateImpl.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CommissionerDiscoveryDelegateImpl.h; sourceTree = "<group>"; };
6365
3CE868F32946D76200FCB92B /* CommissionableDataProviderImpl.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = CommissionableDataProviderImpl.mm; sourceTree = "<group>"; };
6466
3CF8532528E37ED800F07B9F /* MatterError.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MatterError.h; sourceTree = "<group>"; };
6567
3CF8532628E37F1000F07B9F /* MatterError.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = MatterError.mm; sourceTree = "<group>"; };
@@ -128,6 +130,7 @@
128130
3C26AC8F2927008900BA6881 /* DeviceAttestationCredentialsProviderImpl.mm */,
129131
3C0D9CDF2920A30C00D3332B /* CommissionableDataProviderImpl.hpp */,
130132
3CE868F32946D76200FCB92B /* CommissionableDataProviderImpl.mm */,
133+
3CD6D019298CDA2100D7569A /* CommissionerDiscoveryDelegateImpl.h */,
131134
);
132135
path = MatterTvCastingBridge;
133136
sourceTree = "<group>";
@@ -139,6 +142,7 @@
139142
isa = PBXHeadersBuildPhase;
140143
buildActionMask = 2147483647;
141144
files = (
145+
3CD6D01A298CDA2100D7569A /* CommissionerDiscoveryDelegateImpl.h in Headers */,
142146
3C26AC8C2926FE0C00BA6881 /* DeviceAttestationCredentialsProviderImpl.hpp in Headers */,
143147
3CCB8740286A593700771BAD /* CastingServerBridge.h in Headers */,
144148
3CCB8742286A593700771BAD /* ConversionUtils.hpp in Headers */,

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

+2-1
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,8 @@
4545
@param discoveryRequestSentHandler Handler to call after the Commissioner discovery request has been sent
4646
*/
4747
- (void)discoverCommissioners:(dispatch_queue_t _Nonnull)clientQueue
48-
discoveryRequestSentHandler:(nullable void (^)(bool))discoveryRequestSentHandler;
48+
discoveryRequestSentHandler:(nullable void (^)(bool))discoveryRequestSentHandler
49+
discoveredCommissionerHandler:(nullable void (^)(DiscoveredNodeData * _Nonnull))discoveredCommissionerHandler;
4950

5051
/*!
5152
@brief Retrieve a discovered commissioner TV

0 commit comments

Comments
 (0)