Skip to content

Human operator#54

Merged
Android-PowerUser merged 14 commits intomainfrom
human-operator
Mar 3, 2026
Merged

Human operator#54
Android-PowerUser merged 14 commits intomainfrom
human-operator

Conversation

@Android-PowerUser
Copy link
Owner

No description provided.

@Android-PowerUser Android-PowerUser merged commit b56f067 into main Mar 3, 2026
5 checks passed
Copy link

@amazon-q-developer amazon-q-developer bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review Summary

This PR introduces a human operator feature for remote screen control via WebRTC. While the implementation is functional, there are 5 critical issues that must be fixed before merge:

Critical Issues Found:

  1. Memory Leak - Deprecated Handler constructor in MainActivity causing potential memory leaks
  2. Crash Risk - Null pointer exceptions in WebRTCClient when dataChannel is null during tap events
  3. Crash Risk - Multiple forced unwraps (!!) in WebRTCSender that will crash if objects become null
  4. Crash Risk - Unhandled JSON parsing exceptions when processing tap coordinates
  5. Crash Risk - Unsafe type casts and null handling in screen capture initialization

Security Concerns:

The AndroidManifest declares sensitive permissions (QUERY_ALL_PACKAGES, INJECT_EVENTS) that may require Play Store justification or could be rejected. Ensure these are absolutely necessary for core functionality.

Recommendation:

Do not merge until the crash risks are resolved. The memory leak and null safety issues will cause production crashes and poor user experience. Please address the code suggestions provided in the line-by-line comments.


You can now have the agent implement changes and create commits directly on your pull request's source branch. Simply comment with /q followed by your request in natural language to ask the agent to make changes.


⚠️ This PR contains more than 30 files. Amazon Q is better at reviewing smaller PRs, and may miss issues in larger changesets.

Comment on lines +158 to +163
private fun sendDataChannelMessage(message: String) {
val buffer = DataChannel.Buffer(java.nio.ByteBuffer.wrap(message.toByteArray()), false)
if (dataChannel?.send(buffer) != true) {
Log.w(TAG, "Failed to send DataChannel message: ${message.take(50)}")
}
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛑 Crash Risk: Null pointer exception when dataChannel is null. The sendDataChannelMessage method attempts to send data when dataChannel may be null, but only logs a warning. This means tap events will silently fail when the data channel isn't open, causing the UI to be unresponsive. Add proper null checks or wait for the data channel to open before allowing user interaction.

Comment on lines +138 to +143
val json = com.google.gson.JsonParser.parseString(message).asJsonObject
if (json.has("type") && json.get("type").asString == "tap") {
val x = json.get("x").asFloat
val y = json.get("y").asFloat
listener.onTapReceived(x, y)
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛑 Crash Risk: Unhandled JSON parsing exception can crash the app. If the JSON is malformed or missing required fields (x, y), asFloat will throw an exception that's caught but leaves the connection in an inconsistent state. Validate JSON fields exist before accessing them.

Suggested change
val json = com.google.gson.JsonParser.parseString(message).asJsonObject
if (json.has("type") && json.get("type").asString == "tap") {
val x = json.get("x").asFloat
val y = json.get("y").asFloat
listener.onTapReceived(x, y)
}
val json = com.google.gson.JsonParser.parseString(message).asJsonObject
if (json.has("type") && json.get("type").asString == "tap") {
if (json.has("x") && json.has("y")) {
val x = json.get("x").asFloat
val y = json.get("y").asFloat
listener.onTapReceived(x, y)
} else {
Log.w(TAG, "Tap message missing x or y coordinates")
}
}

Comment on lines +201 to +206
android.os.Handler(mainLooper).postDelayed({
val answer = rtcClient.getLocalDescription()
if (answer != null) {
signalingClient?.sendAnswer(answer.description)
}
}, 1000)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛑 Security Vulnerability: Deprecated Handler constructor causes memory leak and potential crashes. The android.os.Handler(mainLooper) constructor is deprecated and can lead to memory leaks when the activity is destroyed but the handler continues to exist. Use Handler(Looper.getMainLooper()) with proper lifecycle management or coroutines.

Suggested change
android.os.Handler(mainLooper).postDelayed({
val answer = rtcClient.getLocalDescription()
if (answer != null) {
signalingClient?.sendAnswer(answer.description)
}
}, 1000)
override fun onSDPOffer(sdp: String) {
rtcClient.setRemoteOffer(sdp)
// Send answer after a short delay
Handler(Looper.getMainLooper()).postDelayed({
val answer = rtcClient.getLocalDescription()
if (answer != null) {
signalingClient?.sendAnswer(answer.description)
}
}, 1000)
}

Comment on lines +66 to +78
val factory = peerConnectionFactory ?: return
videoSource = factory.createVideoSource(videoCapturer!!.isScreencast)

// Initialize capturer
(videoCapturer as ScreenCapturerAndroid).initialize(
SurfaceTextureHelper.create("CaptureThread", eglBase.eglBaseContext),
context,
videoSource!!.capturerObserver
)
(videoCapturer as ScreenCapturerAndroid).startCapture(720, 1280, 30) // Adjust resolution/fps as needed

videoTrack = factory.createVideoTrack("ARDAMSv0", videoSource)
videoTrack?.setEnabled(true)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛑 Crash Risk: Multiple forced unwraps and unsafe casts can crash the app. Replace !! operators and unsafe casts with safe alternatives to prevent NullPointerException and ClassCastException. The current implementation will crash if videoCapturer is null or not a ScreenCapturerAndroid instance.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant