i m trying to build a feature for parental control app which works like oneway camera live stream view of child device to parent device, i have this code but there seems to be some error as it dont get connected now, intially it got connected randomly two times, the offer answer and candidates are being sent but now view of child camera onparent device

here's child app code:
package com.example.smartparentalcontrolkids;

import android.Manifest;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.provider.Settings;
import android.util.Log;
import androidx.activity.EdgeToEdge;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;

import com.google.firebase.firestore.*;

import org.webrtc.*;

import java.util.*;

public class ChildCameraActivity extends AppCompatActivity {
    private SurfaceViewRenderer mSurfaceView;
    private PeerConnectionFactory peerConnectionFactory;
    private PeerConnection peerConnection;
    private VideoTrack localVideoTrack;
    private VideoCapturer videoCapturer;
    private SurfaceTextureHelper surfaceTextureHelper;
    private EglBase eglBase;
    private FirebaseFirestore firestore;
    private String childId;
    private final String TAG = "ChildCameraStream";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        EdgeToEdge.enable(this);
        setContentView(R.layout.activity_child_camera);

        mSurfaceView = findViewById(R.id.surface_view);
        firestore = FirebaseFirestore.getInstance();
        childId = Settings.Secure.getString(getContentResolver(), Settings.Secure.ANDROID_ID);

        eglBase = EglBase.create();
        mSurfaceView.init(eglBase.getEglBaseContext(), null);

        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED
                || ActivityCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(this, new String[] {
                    Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO }, 100);
        } else {
            listenForCameraRequest();
        }

    }

    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        if (requestCode == 100
                && grantResults.length == 2
                && grantResults[0] == PackageManager.PERMISSION_GRANTED
                && grantResults[1] == PackageManager.PERMISSION_GRANTED) {
            listenForCameraRequest();
        } else {
            finish();
        }
    }

    private void listenForCameraRequest() {
        firestore.collection("camera_stream_requests").document(childId)
                .addSnapshotListener((snapshot, error) -> {
                    if (error != null || snapshot == null || !snapshot.exists()) return;
                    Boolean start = snapshot.getBoolean("start");
                    if (Boolean.TRUE.equals(start)) {
                        startStreaming();
                    }
                });
    }

    private void startStreaming() {
        initializePeerConnectionFactory();
        initializeVideoCapturer();
        createPeerConnection();
        createAndSendOffer();
    }

    private void initializePeerConnectionFactory() {
        PeerConnectionFactory.initialize(PeerConnectionFactory.InitializationOptions.builder(this).createInitializationOptions());
        peerConnectionFactory = PeerConnectionFactory.builder()
                .setVideoEncoderFactory(new DefaultVideoEncoderFactory(eglBase.getEglBaseContext(), true, true))
                .setVideoDecoderFactory(new DefaultVideoDecoderFactory(eglBase.getEglBaseContext()))
                .createPeerConnectionFactory();
    }

    private void initializeVideoCapturer() {
        videoCapturer = createCameraCapturer();
        surfaceTextureHelper = SurfaceTextureHelper.create("CaptureThread", eglBase.getEglBaseContext());
        VideoSource videoSource = peerConnectionFactory.createVideoSource(false);
        videoCapturer.initialize(surfaceTextureHelper, getApplicationContext(), videoSource.getCapturerObserver());
        try {
            videoCapturer.startCapture(1280, 720, 30);
        } catch (Exception e) {
            Log.e(TAG, "Failed to start capture", e);
        }
        localVideoTrack = peerConnectionFactory.createVideoTrack("ARDAMSv0", videoSource);
        localVideoTrack.addSink(mSurfaceView);
    }

    private VideoCapturer createCameraCapturer() {
        Camera2Enumerator enumerator = new Camera2Enumerator(this);
        for (String deviceName : enumerator.getDeviceNames()) {
            if (enumerator.isBackFacing(deviceName)) {
                VideoCapturer capturer = enumerator.createCapturer(deviceName, null);
                if (capturer != null) return capturer;
            }
        }
        throw new RuntimeException("No back facing camera found!");
    }

    private void createPeerConnection() {
        List<PeerConnection.IceServer> iceServers = Arrays.asList(
                PeerConnection.IceServer.builder("stun:stun.l.google.com:19302").createIceServer()
        );

        PeerConnection.RTCConfiguration rtcConfig = new PeerConnection.RTCConfiguration(iceServers);
        peerConnection = peerConnectionFactory.createPeerConnection(rtcConfig, new PeerConnection.Observer() {
            @Override public void onIceCandidate(IceCandidate candidate) {
                Map<String, Object> cand = new HashMap<>();
                cand.put("candidate", candidate.sdp);
                cand.put("sdpMid", candidate.sdpMid);
                cand.put("sdpMLineIndex", candidate.sdpMLineIndex);
                firestore.collection("camera_signals").document(childId)
                        .collection("ice_candidates").document("latest_offer").set(cand);
            }
            @Override public void onIceCandidatesRemoved(IceCandidate[] iceCandidates) {}
            @Override public void onAddStream(MediaStream stream) {}
            @Override public void onDataChannel(DataChannel dc) {}
            @Override public void onIceConnectionChange(PeerConnection.IceConnectionState state) {}
            @Override public void onIceConnectionReceivingChange(boolean b) {}
            @Override public void onIceGatheringChange(PeerConnection.IceGatheringState state) {}
            @Override public void onRemoveStream(MediaStream stream) {}
            @Override public void onRenegotiationNeeded() {}
            @Override public void onSignalingChange(PeerConnection.SignalingState state) {}
            @Override public void onTrack(RtpTransceiver transceiver) {}
        });

        // Modern WebRTC: addTrack instead of deprecated addStream
        peerConnection.addTrack(localVideoTrack);

        // Listen for answer
        firestore.collection("camera_signals")
                .document(childId)
                .collection("answer")
                .document("latest_answer") // ✅ fixed doc ID
                .addSnapshotListener((docSnap, e) -> {
                    if (e != null || docSnap == null || !docSnap.exists()) return;
                    String sdp = docSnap.getString("sdp");
                    if (sdp != null) {
                        SessionDescription answer = new SessionDescription(SessionDescription.Type.ANSWER, sdp);
                        peerConnection.setRemoteDescription(new SimpleSdpObserver(), answer);
                    }
                });


        // Listen for ICE candidates from parent
        firestore.collection("camera_signals").document(childId)
                .collection("parent_ice_candidates").document("latest_offer").addSnapshotListener((snap, e) -> {
                    if (e != null || snap == null || !snap.exists()) return;

                        IceCandidate candidate = new IceCandidate(
                                snap.getString("sdpMid"),
                                Objects.requireNonNull(snap.getLong("sdpMLineIndex")).intValue(),
                                snap.getString("candidate")
                        );
                        peerConnection.addIceCandidate(candidate);

                });
    }

    private void createAndSendOffer() {
        peerConnection.createOffer(new SdpObserver() {
            @Override public void onCreateSuccess(SessionDescription sessionDescription) {
                peerConnection.setLocalDescription(new SimpleSdpObserver(), sessionDescription);
                Map<String, Object> offer = new HashMap<>();
                offer.put("sdp", sessionDescription.description);

                firestore.collection("camera_signals")
                        .document(childId)
                        .collection("offer")
                        .document("latest_offer") // ✅ fixed doc ID
                        .set(offer);

            }
            @Override public void onSetSuccess() {}
            @Override public void onCreateFailure(String s) {}
            @Override public void onSetFailure(String s) {}
        }, new MediaConstraints());
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (peerConnection != null) peerConnection.close();
        if (videoCapturer != null) {
            try {
                videoCapturer.stopCapture();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            videoCapturer.dispose();
        }
        if (surfaceTextureHelper != null) surfaceTextureHelper.dispose();
        mSurfaceView.release();
        eglBase.release();
        firestore.collection("camera_stream_requests").document(childId).delete();
    }

    private static class SimpleSdpObserver implements SdpObserver {
        @Override public void onCreateSuccess(SessionDescription s) {}
        @Override public void onSetSuccess() {}
        @Override public void onCreateFailure(String s) {}
        @Override public void onSetFailure(String s) {}
    }
}

and here's parent app code:
package com.example.smartparentalcontrol;

import android.os.Bundle;
import android.util.Log;

import androidx.appcompat.app.AppCompatActivity;

import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.firestore.*;

import org.webrtc.*;

import java.util.*;

public class ViewCameraActivity extends AppCompatActivity {
    private static final String TAG = "ParentCameraView";

    private SurfaceViewRenderer surfaceView;
    private EglBase eglBase;
    private PeerConnectionFactory peerConnectionFactory;
    private PeerConnection peerConnection;
    private VideoTrack remoteVideoTrack;
    private String childId, parentId;
    private FirebaseFirestore firestore;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_view_camera);
        surfaceView = findViewById(R.id.surface_view);

        childId = getIntent().getStringExtra("childId");
        parentId = FirebaseAuth.getInstance().getCurrentUser().getUid();
        firestore = FirebaseFirestore.getInstance();

        eglBase = EglBase.create();
        surfaceView.init(eglBase.getEglBaseContext(), null);

        sendCameraRequest();

        initializePeerConnectionFactory();
        createPeerConnection();

        listenForOffer();
        listenForIceCandidates();

        findViewById(R.id.backButton).setOnClickListener(v -> finish());
    }

    private void sendCameraRequest() {
        Map<String, Object> request = new HashMap<>();
        request.put("start", true);
        firestore.collection("camera_stream_requests").document(childId).set(request);
    }

    private void initializePeerConnectionFactory() {
        PeerConnectionFactory.initialize(PeerConnectionFactory.InitializationOptions.builder(this)
                .createInitializationOptions());
        peerConnectionFactory = PeerConnectionFactory.builder()
                .setVideoEncoderFactory(new DefaultVideoEncoderFactory(eglBase.getEglBaseContext(), true, true))
                .setVideoDecoderFactory(new DefaultVideoDecoderFactory(eglBase.getEglBaseContext()))
                .createPeerConnectionFactory();
    }

    private void createPeerConnection() {
        List<PeerConnection.IceServer> iceServers = Arrays.asList(
                PeerConnection.IceServer.builder("stun:stun.l.google.com:19302").createIceServer()
        );
        PeerConnection.RTCConfiguration rtcConfig = new PeerConnection.RTCConfiguration(iceServers);

        peerConnection = peerConnectionFactory.createPeerConnection(rtcConfig, new PeerConnection.Observer() {
            @Override public void onIceCandidate(IceCandidate candidate) {
                Map<String, Object> cand = new HashMap<>();
                cand.put("candidate", candidate.sdp);
                cand.put("sdpMid", candidate.sdpMid);
                cand.put("sdpMLineIndex", candidate.sdpMLineIndex);
                firestore.collection("camera_signals").document(childId)
                        .collection("parent_ice_candidates").document("latest_offer").set(cand);
            }

            @Override
            public void onIceCandidatesRemoved(IceCandidate[] iceCandidates) {

            }

            @Override
            public void onAddStream(MediaStream mediaStream) {

            }

            @Override
            public void onTrack(RtpTransceiver transceiver) {
                MediaStreamTrack track = transceiver.getReceiver().track();
                if (track instanceof VideoTrack) {
                    remoteVideoTrack = (VideoTrack) track;
                    remoteVideoTrack.addSink(surfaceView);
                }

            }
            @Override public void onDataChannel(DataChannel dc) {}
            @Override public void onIceConnectionChange(PeerConnection.IceConnectionState state) {}
            @Override public void onIceConnectionReceivingChange(boolean b) {}
            @Override public void onIceGatheringChange(PeerConnection.IceGatheringState state) {}
            @Override public void onRemoveStream(MediaStream stream) {}
            @Override public void onRenegotiationNeeded() {}
            @Override public void onSignalingChange(PeerConnection.SignalingState state) {}

        });
        peerConnection.addTransceiver(MediaStreamTrack.MediaType.MEDIA_TYPE_VIDEO);
    }

    private void listenForOffer() {
        firestore.collection("camera_signals")
                .document(childId)
                .collection("offer")
                .document("latest_offer") // ✅ fixed doc ID
                .addSnapshotListener((docSnap, e) -> {
                    if (e != null || docSnap == null || !docSnap.exists()) return;
                    String sdp = docSnap.getString("sdp");
                    if (sdp != null) {
                        SessionDescription offer = new SessionDescription(SessionDescription.Type.OFFER, sdp);
                        peerConnection.setRemoteDescription(new SimpleSdpObserver(), offer);
                        createAndSendAnswer();
                    }
                });

    }

    private void createAndSendAnswer() {
        peerConnection.createAnswer(new SdpObserver() {
            @Override public void onCreateSuccess(SessionDescription sessionDescription) {
                peerConnection.setLocalDescription(new SimpleSdpObserver(), sessionDescription);
                Map<String, Object> answer = new HashMap<>();
                answer.put("sdp", sessionDescription.description);

                firestore.collection("camera_signals")
                        .document(childId)
                        .collection("answer")
                        .document("latest_answer") // ✅ fixed doc ID
                        .set(answer);

            }
            @Override public void onSetSuccess() {}
            @Override public void onCreateFailure(String s) {}
            @Override public void onSetFailure(String s) {}
        }, new MediaConstraints());
    }

    private void listenForIceCandidates() {
        firestore.collection("camera_signals").document(childId)
                .collection("ice_candidates").document("latest_offer").addSnapshotListener((snap, e) -> {
                    if (e != null || snap == null || !snap.exists()) return;

                    IceCandidate candidate = new IceCandidate(
                            snap.getString("sdpMid"),
                                Objects.requireNonNull(snap.getLong("sdpMLineIndex")).intValue(),
                            snap.getString("candidate")
                        );
                        peerConnection.addIceCandidate(candidate);

                });
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (peerConnection != null) peerConnection.close();
        if (surfaceView != null) surfaceView.release();
        // Remove camera request to stop streaming
        firestore.collection("camera_stream_requests").document(childId).delete();
    }

    // Utility SdpObserver
    private static class SimpleSdpObserver implements SdpObserver {
        @Override public void onCreateSuccess(SessionDescription s) {}
        @Override public void onSetSuccess() {}
        @Override public void onCreateFailure(String s) {}
        @Override public void onSetFailure(String s) {}
    }
}