code: public void iceCandidatesReceived(JSONArray candidates) {
          if (isActive()) {
              for (int ii = 0; ii < candidates.length(); ii++) {
                  try {
                      JSONObject eachCandidate = (JSONObject) candidates.get(ii);
                      String mid = eachCandidate.getString("sdpMid");
                      int sdpLineIndex = eachCandidate.getInt("sdpMLineIndex");
                      String sdp = eachCandidate.getString("candidate");
  
                      IceCandidate rtcCandidate = new IceCandidate(mid, sdpLineIndex, sdp);
  
                      try {
                          // Start critical block
                          queuedRemoteCandidatesSemaphore.acquire();
  
                          if (null != queuedRemoteCandidates) {
                              queuedRemoteCandidates.add(rtcCandidate);
                          } else {
                              peerConnection.addIceCandidate(rtcCandidate);
                          }
  
                          // End critical block
                          queuedRemoteCandidatesSemaphore.release();
                      } catch (InterruptedException e) {
                          Log.d(TAG, "Error with remote candidates semaphore");
                      }
  
                  } catch (JSONException e) {
                      Log.d(TAG, "Error processing remote ice candidate data");
                  }
              }
          }
      }
docs: Process ICE candidates suggested by the remote endpoint. This is used internally to the SDK and should not be called directly by your client application.
  
  @param candidates Array of candidates to evaluate