Работающие звонки
This commit is contained in:
@@ -16,6 +16,7 @@
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <time.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <android/log.h>
|
||||
@@ -125,6 +126,12 @@ struct AdditionalTsState {
|
||||
uint64_t base_timestamp = 0;
|
||||
};
|
||||
|
||||
struct SenderTsOffsetState {
|
||||
bool initialized = false;
|
||||
bool enabled = false;
|
||||
uint64_t offset = 0;
|
||||
};
|
||||
|
||||
static inline uint16_t load16_be(const uint8_t* p) {
|
||||
return (uint16_t)(((uint16_t)p[0] << 8) | (uint16_t)p[1]);
|
||||
}
|
||||
@@ -334,6 +341,25 @@ static inline void fill_nonce_from_ts32(uint32_t ts, uint8_t nonce[24]) {
|
||||
nonce[7] = (uint8_t)(ts);
|
||||
}
|
||||
|
||||
static inline void fill_nonce_from_ts64(uint64_t ts, uint8_t nonce[24]) {
|
||||
nonce[0] = (uint8_t)(ts >> 56);
|
||||
nonce[1] = (uint8_t)(ts >> 48);
|
||||
nonce[2] = (uint8_t)(ts >> 40);
|
||||
nonce[3] = (uint8_t)(ts >> 32);
|
||||
nonce[4] = (uint8_t)(ts >> 24);
|
||||
nonce[5] = (uint8_t)(ts >> 16);
|
||||
nonce[6] = (uint8_t)(ts >> 8);
|
||||
nonce[7] = (uint8_t)(ts);
|
||||
}
|
||||
|
||||
static inline uint64_t monotonic_48k_ticks() {
|
||||
struct timespec ts {};
|
||||
if (clock_gettime(CLOCK_MONOTONIC, &ts) != 0) return 0;
|
||||
const uint64_t sec = (uint64_t)ts.tv_sec;
|
||||
const uint64_t nsec = (uint64_t)ts.tv_nsec;
|
||||
return sec * 48000ULL + (nsec * 48000ULL) / 1000000000ULL;
|
||||
}
|
||||
|
||||
static inline uint32_t opus_base_frame_samples(uint8_t config) {
|
||||
// RFC 6716 TOC config mapping at 48 kHz.
|
||||
if (config <= 11) {
|
||||
@@ -550,6 +576,7 @@ public:
|
||||
bool nonce_from_generated_ts = false;
|
||||
bool nonce_from_additional_data = false;
|
||||
bool additional_was_rtp_header = false;
|
||||
bool additional_used_mono_offset = false;
|
||||
uint32_t generated_ts_used = 0;
|
||||
|
||||
// Build nonce from RTP timestamp in additional_data (preferred).
|
||||
@@ -579,23 +606,36 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
if (nonce_from_rtp_header && header_size <= frame.size()) {
|
||||
// Keep RTP header clear, encrypt payload only.
|
||||
if (header_size > 0) {
|
||||
memcpy(encrypted_frame.data(), frame.data(), header_size);
|
||||
// Some Android sender pipelines expose stream-relative ad8 timestamps
|
||||
// (0, 960, 1920, ...), while desktop receiver expects an absolute base.
|
||||
// For interop, add a monotonic 48k offset once when first ad8 is tiny.
|
||||
if (nonce_from_additional_data &&
|
||||
additional_data.size() == 8 &&
|
||||
!additional_was_rtp_header &&
|
||||
additional_data.data() != nullptr) {
|
||||
const uint64_t ad_ts64 = load64_be(additional_data.data());
|
||||
if (!sender_ts_offset_.initialized) {
|
||||
sender_ts_offset_.initialized = true;
|
||||
// Keep pure raw-abs mode by default; desktop is the source of truth.
|
||||
sender_ts_offset_.enabled = false;
|
||||
sender_ts_offset_.offset = 0ULL;
|
||||
diag_event("ENC ad8-base init ssrc=%u ad_ts=%llu use_mono=%d mono_off=%llu\n",
|
||||
ssrc,
|
||||
(unsigned long long)ad_ts64,
|
||||
sender_ts_offset_.enabled ? 1 : 0,
|
||||
(unsigned long long)sender_ts_offset_.offset);
|
||||
}
|
||||
if (sender_ts_offset_.enabled) {
|
||||
const uint64_t ts_adj = ad_ts64 + sender_ts_offset_.offset;
|
||||
fill_nonce_from_ts64(ts_adj, nonce);
|
||||
additional_used_mono_offset = true;
|
||||
}
|
||||
const size_t payload_size = frame.size() - header_size;
|
||||
rosetta_xchacha20_xor(
|
||||
encrypted_frame.data() + header_size,
|
||||
frame.data() + header_size,
|
||||
payload_size,
|
||||
nonce,
|
||||
key_);
|
||||
} else {
|
||||
// Legacy path: frame is payload-only.
|
||||
rosetta_xchacha20_xor(encrypted_frame.data(),
|
||||
frame.data(), frame.size(), nonce, key_);
|
||||
}
|
||||
|
||||
// Desktop createEncodedStreams encrypts full encoded chunk.
|
||||
// To stay wire-compatible, do not preserve any leading RTP-like bytes.
|
||||
rosetta_xchacha20_xor(encrypted_frame.data(),
|
||||
frame.data(), frame.size(), nonce, key_);
|
||||
*bytes_written = frame.size();
|
||||
|
||||
if (nonce_from_generated_ts) {
|
||||
@@ -628,7 +668,9 @@ public:
|
||||
: (nonce_from_additional_data
|
||||
? (additional_was_rtp_header
|
||||
? "ad-rtp"
|
||||
: (additional_used_relative_ts ? "raw-rel" : "raw-abs"))
|
||||
: (additional_used_mono_offset
|
||||
? "raw-abs+mono"
|
||||
: (additional_used_relative_ts ? "raw-rel" : "raw-abs")))
|
||||
: "raw-abs"));
|
||||
LOGI("ENC frame#%d mt=%s ssrc=%u sz=%zu ad=%zu hdr=%zu mode=%s nonce_ts=%u gen_ts=%u next_step=%u rtp_ok=%d rtp_seq=%u rtp_ts=%u rtp_ssrc=%u opus_ok=%d key_fp=%08x in_h=%08x out_h=%08x ad8=%02x%02x%02x%02x%02x%02x%02x%02x",
|
||||
n, media_type_name(media_type), ssrc, frame.size(), additional_data.size(), header_size, mode,
|
||||
@@ -663,6 +705,7 @@ private:
|
||||
mutable std::atomic<int> diag_count_{0};
|
||||
mutable RtpProbeState rtp_probe_;
|
||||
mutable GeneratedTsState generated_ts_;
|
||||
mutable SenderTsOffsetState sender_ts_offset_;
|
||||
uint32_t key_fingerprint_ = 0;
|
||||
uint8_t key_[32];
|
||||
};
|
||||
@@ -746,20 +789,8 @@ public:
|
||||
|
||||
bool used_generated_resync = false;
|
||||
|
||||
if (nonce_from_rtp_header && header_size <= encrypted_frame.size()) {
|
||||
if (header_size > 0) {
|
||||
memcpy(frame.data(), encrypted_frame.data(), header_size);
|
||||
}
|
||||
const size_t payload_size = encrypted_frame.size() - header_size;
|
||||
rosetta_xchacha20_xor(
|
||||
frame.data() + header_size,
|
||||
encrypted_frame.data() + header_size,
|
||||
payload_size,
|
||||
nonce,
|
||||
key_);
|
||||
} else {
|
||||
rosetta_xchacha20_xor(frame.data(), encrypted_frame.data(), encrypted_frame.size(), nonce, key_);
|
||||
}
|
||||
// Desktop createEncodedStreams decrypts full encoded chunk.
|
||||
rosetta_xchacha20_xor(frame.data(), encrypted_frame.data(), encrypted_frame.size(), nonce, key_);
|
||||
|
||||
if (nonce_from_additional_data) {
|
||||
bool plausible = is_plausible_decrypted_audio_frame(frame.data(), encrypted_frame.size());
|
||||
|
||||
@@ -6,7 +6,6 @@ import android.util.Log
|
||||
import com.rosetta.messenger.data.MessageRepository
|
||||
import java.security.MessageDigest
|
||||
import java.security.SecureRandom
|
||||
import java.util.IdentityHashMap
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
@@ -137,8 +136,8 @@ object CallManager {
|
||||
|
||||
// E2EE (XChaCha20 — compatible with Desktop)
|
||||
private var sharedKeyBytes: ByteArray? = null
|
||||
private val senderEncryptors = IdentityHashMap<RtpSender, XChaCha20E2EE.Encryptor>()
|
||||
private val receiverDecryptors = IdentityHashMap<RtpReceiver, XChaCha20E2EE.Decryptor>()
|
||||
private val senderEncryptors = LinkedHashMap<String, XChaCha20E2EE.Encryptor>()
|
||||
private val receiverDecryptors = LinkedHashMap<String, XChaCha20E2EE.Decryptor>()
|
||||
private var pendingAudioSenderForE2ee: RtpSender? = null
|
||||
private var lastRemoteOfferFingerprint: String = ""
|
||||
private var lastLocalOfferFingerprint: String = ""
|
||||
@@ -1063,11 +1062,22 @@ object CallManager {
|
||||
breadcrumb("STATE[$marker] ${buildStateSnapshot()}")
|
||||
}
|
||||
|
||||
private fun senderMapKey(sender: RtpSender): String {
|
||||
val id = runCatching { sender.id() }.getOrNull().orEmpty()
|
||||
return if (id.isNotBlank()) "sid:$id" else "sender@${System.identityHashCode(sender)}"
|
||||
}
|
||||
|
||||
private fun receiverMapKey(receiver: RtpReceiver): String {
|
||||
val id = runCatching { receiver.id() }.getOrNull().orEmpty()
|
||||
return if (id.isNotBlank()) "rid:$id" else "recv@${System.identityHashCode(receiver)}"
|
||||
}
|
||||
|
||||
private fun attachSenderE2EE(sender: RtpSender?) {
|
||||
if (!e2eeAvailable) return
|
||||
val key = sharedKeyBytes ?: return
|
||||
if (sender == null) return
|
||||
val existing = senderEncryptors[sender]
|
||||
val mapKey = senderMapKey(sender)
|
||||
val existing = senderEncryptors[mapKey]
|
||||
if (existing != null) {
|
||||
runCatching { sender.setFrameEncryptor(existing) }
|
||||
return
|
||||
@@ -1086,7 +1096,7 @@ object CallManager {
|
||||
breadcrumb("4. calling sender.setFrameEncryptor…")
|
||||
sender.setFrameEncryptor(enc)
|
||||
breadcrumb("5. setFrameEncryptor OK!")
|
||||
senderEncryptors[sender] = enc
|
||||
senderEncryptors[mapKey] = enc
|
||||
pendingAudioSenderForE2ee = null
|
||||
} catch (e: Throwable) {
|
||||
saveCrashReport("attachSenderE2EE failed", e)
|
||||
@@ -1104,7 +1114,8 @@ object CallManager {
|
||||
if (!e2eeAvailable) return
|
||||
val key = sharedKeyBytes ?: return
|
||||
if (receiver == null) return
|
||||
val existing = receiverDecryptors[receiver]
|
||||
val mapKey = receiverMapKey(receiver)
|
||||
val existing = receiverDecryptors[mapKey]
|
||||
if (existing != null) {
|
||||
runCatching { receiver.setFrameDecryptor(existing) }
|
||||
return
|
||||
@@ -1123,7 +1134,7 @@ object CallManager {
|
||||
breadcrumb("9. calling receiver.setFrameDecryptor…")
|
||||
receiver.setFrameDecryptor(dec)
|
||||
breadcrumb("10. setFrameDecryptor OK!")
|
||||
receiverDecryptors[receiver] = dec
|
||||
receiverDecryptors[mapKey] = dec
|
||||
} catch (e: Throwable) {
|
||||
saveCrashReport("attachReceiverE2EE failed", e)
|
||||
Log.e(TAG, "E2EE: receiver decryptor failed", e)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.rosetta.messenger.ui.crashlogs
|
||||
|
||||
import android.widget.Toast
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.*
|
||||
@@ -8,13 +9,16 @@ import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.ArrowBack
|
||||
import androidx.compose.material.icons.filled.BugReport
|
||||
import androidx.compose.material.icons.filled.ContentCopy
|
||||
import androidx.compose.material.icons.filled.Delete
|
||||
import androidx.compose.material.icons.filled.Share
|
||||
import androidx.compose.material3.*
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.platform.LocalClipboardManager
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.text.AnnotatedString
|
||||
import androidx.compose.ui.text.font.FontFamily
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.unit.dp
|
||||
@@ -263,6 +267,8 @@ private fun CrashDetailScreen(
|
||||
onDelete: () -> Unit
|
||||
) {
|
||||
var showDeleteDialog by remember { mutableStateOf(false) }
|
||||
val clipboardManager = LocalClipboardManager.current
|
||||
val context = LocalContext.current
|
||||
|
||||
Scaffold(
|
||||
topBar = {
|
||||
@@ -274,6 +280,14 @@ private fun CrashDetailScreen(
|
||||
}
|
||||
},
|
||||
actions = {
|
||||
IconButton(
|
||||
onClick = {
|
||||
clipboardManager.setText(AnnotatedString(crashReport.content))
|
||||
Toast.makeText(context, "Full log copied", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
) {
|
||||
Icon(Icons.Default.ContentCopy, contentDescription = "Copy Full Log")
|
||||
}
|
||||
IconButton(onClick = { /* TODO: Share */ }) {
|
||||
Icon(Icons.Default.Share, contentDescription = "Share")
|
||||
}
|
||||
|
||||
@@ -9,7 +9,8 @@ Stock `io.github.webrtc-sdk:android:125.6422.07` can call audio frame encryptor
|
||||
`additional_data` (`ad=0`), so nonce derivation based on timestamp is unavailable.
|
||||
|
||||
Desktop uses frame timestamp for nonce. This patch aligns Android with that approach by passing
|
||||
an 8-byte big-endian timestamp payload in `additional_data`:
|
||||
an 8-byte big-endian timestamp payload in `additional_data` (absolute RTP timestamp,
|
||||
including sender start offset):
|
||||
|
||||
- bytes `0..3` = `0`
|
||||
- bytes `4..7` = RTP timestamp (big-endian)
|
||||
@@ -18,10 +19,14 @@ an 8-byte big-endian timestamp payload in `additional_data`:
|
||||
|
||||
- `build_custom_webrtc.sh` — reproducible build script
|
||||
- `patches/0001-audio-e2ee-pass-rtp-timestamp-as-additional-data.patch` — WebRTC patch
|
||||
- `patches/0002-android-build-on-mac-host.patch` — allows Android target build on macOS host
|
||||
- `patches/0003-macos-host-java-ijar.patch` — enables host tools (`ijar`/`jdk`) on macOS
|
||||
- `patches/0004-macos-linker-missing-L-dirs.patch` — skips invalid host `-L...` paths for lld
|
||||
- `patches/0005-macos-server-utils-socket.patch` — handles macOS socket errno in Android Java compile helper
|
||||
|
||||
## Build
|
||||
|
||||
Recommended on Linux (macOS can work but is less predictable for long WebRTC builds).
|
||||
Recommended on Linux (macOS is supported via additional patches in this folder).
|
||||
|
||||
Bootstrap `depot_tools` first:
|
||||
|
||||
@@ -47,6 +52,7 @@ Optional env vars:
|
||||
- `SYNC_JOBS` — `gclient sync` jobs (default: `1`, safer for googlesource limits)
|
||||
- `SYNC_RETRIES` — sync retry attempts (default: `8`)
|
||||
- `SYNC_RETRY_BASE_SEC` — base retry delay in seconds (default: `20`)
|
||||
- `MAC_ANDROID_NDK_ROOT` — local Android NDK path on macOS (default: `~/Library/Android/sdk/ndk/27.1.12297006`)
|
||||
|
||||
## Troubleshooting (HTTP 429 / RESOURCE_EXHAUSTED)
|
||||
|
||||
|
||||
@@ -9,7 +9,13 @@ set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
ROSETTA_ANDROID_DIR="$(cd "${SCRIPT_DIR}/../.." && pwd)"
|
||||
PATCH_FILE="${SCRIPT_DIR}/patches/0001-audio-e2ee-pass-rtp-timestamp-as-additional-data.patch"
|
||||
PATCH_FILES=(
|
||||
"${SCRIPT_DIR}/patches/0001-audio-e2ee-pass-rtp-timestamp-as-additional-data.patch"
|
||||
"${SCRIPT_DIR}/patches/0002-android-build-on-mac-host.patch"
|
||||
"${SCRIPT_DIR}/patches/0003-macos-host-java-ijar.patch"
|
||||
"${SCRIPT_DIR}/patches/0004-macos-linker-missing-L-dirs.patch"
|
||||
"${SCRIPT_DIR}/patches/0005-macos-server-utils-socket.patch"
|
||||
)
|
||||
|
||||
# Default target: WebRTC M125 family used by app dependency 125.6422.07.
|
||||
WEBRTC_BRANCH="${WEBRTC_BRANCH:-branch-heads/6422}"
|
||||
@@ -132,21 +138,63 @@ sync_with_retry
|
||||
|
||||
echo "[webrtc-custom] applying Rosetta patch..."
|
||||
git reset --hard
|
||||
git apply --check "${PATCH_FILE}"
|
||||
git apply "${PATCH_FILE}"
|
||||
for patch in "${PATCH_FILES[@]}"; do
|
||||
echo "[webrtc-custom] apply $(basename "${patch}")"
|
||||
git apply --check "${patch}"
|
||||
git apply "${patch}"
|
||||
done
|
||||
|
||||
# macOS host tweaks:
|
||||
# - point third_party/jdk/current to local JDK
|
||||
# - use locally installed Android NDK (darwin toolchain)
|
||||
if [[ "$(uname -s)" == "Darwin" ]]; then
|
||||
if [[ -z "${JAVA_HOME:-}" ]]; then
|
||||
JAVA_HOME="$(/usr/libexec/java_home 2>/dev/null || true)"
|
||||
fi
|
||||
if [[ -z "${JAVA_HOME:-}" || ! -d "${JAVA_HOME}" ]]; then
|
||||
echo "[webrtc-custom] ERROR: JAVA_HOME not found on macOS"
|
||||
exit 1
|
||||
fi
|
||||
JAVA_HOME_CANDIDATE="${JAVA_HOME}"
|
||||
if [[ ! -f "${JAVA_HOME_CANDIDATE}/conf/logging.properties" ]] && [[ -d "${JAVA_HOME_CANDIDATE}/libexec/openjdk.jdk/Contents/Home" ]]; then
|
||||
JAVA_HOME_CANDIDATE="${JAVA_HOME_CANDIDATE}/libexec/openjdk.jdk/Contents/Home"
|
||||
fi
|
||||
if [[ ! -f "${JAVA_HOME_CANDIDATE}/conf/logging.properties" ]]; then
|
||||
echo "[webrtc-custom] ERROR: invalid JAVA_HOME (conf/logging.properties not found): ${JAVA_HOME}"
|
||||
exit 1
|
||||
fi
|
||||
JAVA_HOME="${JAVA_HOME_CANDIDATE}"
|
||||
ln -sfn "${JAVA_HOME}" "${WEBRTC_SRC}/third_party/jdk/current"
|
||||
echo "[webrtc-custom] macOS JDK linked: ${WEBRTC_SRC}/third_party/jdk/current -> ${JAVA_HOME}"
|
||||
fi
|
||||
|
||||
mkdir -p "$(dirname "${OUT_AAR}")"
|
||||
|
||||
echo "[webrtc-custom] building AAR (this can take a while)..."
|
||||
GN_ARGS=(
|
||||
is_debug=false
|
||||
is_component_build=false
|
||||
rtc_include_tests=false
|
||||
rtc_build_examples=false
|
||||
)
|
||||
|
||||
if [[ "$(uname -s)" == "Darwin" ]]; then
|
||||
MAC_ANDROID_NDK_ROOT="${MAC_ANDROID_NDK_ROOT:-$HOME/Library/Android/sdk/ndk/27.1.12297006}"
|
||||
if [[ ! -d "${MAC_ANDROID_NDK_ROOT}" ]]; then
|
||||
echo "[webrtc-custom] ERROR: Android NDK not found at ${MAC_ANDROID_NDK_ROOT}"
|
||||
echo "[webrtc-custom] Set MAC_ANDROID_NDK_ROOT to your local NDK path."
|
||||
exit 1
|
||||
fi
|
||||
GN_ARGS+=("android_ndk_root=\"${MAC_ANDROID_NDK_ROOT}\"")
|
||||
GN_ARGS+=("android_ndk_version=\"27.1.12297006\"")
|
||||
echo "[webrtc-custom] macOS Android NDK: ${MAC_ANDROID_NDK_ROOT}"
|
||||
fi
|
||||
|
||||
python3 tools_webrtc/android/build_aar.py \
|
||||
--build-dir out_rosetta_aar \
|
||||
--output "${OUT_AAR}" \
|
||||
--arch "${ARCHS[@]}" \
|
||||
--extra-gn-args \
|
||||
is_debug=false \
|
||||
is_component_build=false \
|
||||
rtc_include_tests=false \
|
||||
rtc_build_examples=false
|
||||
--extra-gn-args "${GN_ARGS[@]}"
|
||||
|
||||
echo "[webrtc-custom] done"
|
||||
echo "[webrtc-custom] AAR: ${OUT_AAR}"
|
||||
|
||||
@@ -25,22 +25,24 @@ index 17cf859ed8..b9d9ab14c8 100644
|
||||
decrypted_audio_payload);
|
||||
|
||||
diff --git a/audio/channel_send.cc b/audio/channel_send.cc
|
||||
index 4a2700177b..93283c2e78 100644
|
||||
index 4a2700177b..7ebb501704 100644
|
||||
--- a/audio/channel_send.cc
|
||||
+++ b/audio/channel_send.cc
|
||||
@@ -320,10 +320,21 @@ int32_t ChannelSend::SendRtpAudio(AudioFrameType frameType,
|
||||
@@ -320,10 +320,23 @@ int32_t ChannelSend::SendRtpAudio(AudioFrameType frameType,
|
||||
|
||||
// Encrypt the audio payload into the buffer.
|
||||
size_t bytes_written = 0;
|
||||
+ const uint32_t additional_data_timestamp =
|
||||
+ rtp_timestamp_without_offset + rtp_rtcp_->StartTimestamp();
|
||||
+ const uint8_t additional_data_bytes[8] = {
|
||||
+ 0,
|
||||
+ 0,
|
||||
+ 0,
|
||||
+ 0,
|
||||
+ static_cast<uint8_t>((rtp_timestamp_without_offset >> 24) & 0xff),
|
||||
+ static_cast<uint8_t>((rtp_timestamp_without_offset >> 16) & 0xff),
|
||||
+ static_cast<uint8_t>((rtp_timestamp_without_offset >> 8) & 0xff),
|
||||
+ static_cast<uint8_t>(rtp_timestamp_without_offset & 0xff),
|
||||
+ static_cast<uint8_t>((additional_data_timestamp >> 24) & 0xff),
|
||||
+ static_cast<uint8_t>((additional_data_timestamp >> 16) & 0xff),
|
||||
+ static_cast<uint8_t>((additional_data_timestamp >> 8) & 0xff),
|
||||
+ static_cast<uint8_t>(additional_data_timestamp & 0xff),
|
||||
+ };
|
||||
+
|
||||
int encrypt_status = frame_encryptor_->Encrypt(
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
diff --git a/build/config/BUILDCONFIG.gn b/build/config/BUILDCONFIG.gn
|
||||
index 26fad5adf..7a614f334 100644
|
||||
--- a/build/config/BUILDCONFIG.gn
|
||||
+++ b/build/config/BUILDCONFIG.gn
|
||||
@@ -239,7 +239,8 @@ if (host_toolchain == "") {
|
||||
_default_toolchain = ""
|
||||
|
||||
if (target_os == "android") {
|
||||
- assert(host_os == "linux", "Android builds are only supported on Linux.")
|
||||
+ assert(host_os == "linux" || host_os == "mac",
|
||||
+ "Android builds are only supported on Linux/macOS.")
|
||||
_default_toolchain = "//build/toolchain/android:android_clang_$target_cpu"
|
||||
} else if (target_os == "chromeos" || target_os == "linux") {
|
||||
# See comments in build/toolchain/cros/BUILD.gn about board compiles.
|
||||
diff --git a/build/config/android/config.gni b/build/config/android/config.gni
|
||||
index 427739d70..6a5ab0594 100644
|
||||
--- a/build/config/android/config.gni
|
||||
+++ b/build/config/android/config.gni
|
||||
@@ -327,7 +327,7 @@ if (is_android || is_chromeos) {
|
||||
|
||||
# Defines the name the Android build gives to the current host CPU
|
||||
# architecture, which is different than the names GN uses.
|
||||
- if (host_cpu == "x64") {
|
||||
+ if (host_cpu == "x64" || host_cpu == "arm64") {
|
||||
android_host_arch = "x86_64"
|
||||
} else if (host_cpu == "x86") {
|
||||
android_host_arch = "x86"
|
||||
34
tools/webrtc-custom/patches/0003-macos-host-java-ijar.patch
Normal file
34
tools/webrtc-custom/patches/0003-macos-host-java-ijar.patch
Normal file
@@ -0,0 +1,34 @@
|
||||
diff --git a/third_party/ijar/BUILD.gn b/third_party/ijar/BUILD.gn
|
||||
index 8dc9fe21cf8..49c50e6636f 100644
|
||||
--- a/third_party/ijar/BUILD.gn
|
||||
+++ b/third_party/ijar/BUILD.gn
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
# A tool that removes all non-interface-specific parts from a .jar file.
|
||||
|
||||
-if (is_linux || is_chromeos) {
|
||||
+if (is_linux || is_chromeos || is_mac) {
|
||||
config("ijar_compiler_flags") {
|
||||
if (is_clang) {
|
||||
cflags = [
|
||||
diff --git a/third_party/jdk/BUILD.gn b/third_party/jdk/BUILD.gn
|
||||
index e003eef94d7..ec49922942b 100644
|
||||
--- a/third_party/jdk/BUILD.gn
|
||||
+++ b/third_party/jdk/BUILD.gn
|
||||
@@ -3,10 +3,12 @@
|
||||
# found in the LICENSE file.
|
||||
|
||||
config("jdk") {
|
||||
- include_dirs = [
|
||||
- "current/include",
|
||||
- "current/include/linux",
|
||||
- ]
|
||||
+ include_dirs = [ "current/include" ]
|
||||
+ if (host_os == "mac") {
|
||||
+ include_dirs += [ "current/include/darwin" ]
|
||||
+ } else {
|
||||
+ include_dirs += [ "current/include/linux" ]
|
||||
+ }
|
||||
}
|
||||
|
||||
group("java_data") {
|
||||
@@ -0,0 +1,102 @@
|
||||
diff --git a/build/toolchain/apple/linker_driver.py b/build/toolchain/apple/linker_driver.py
|
||||
index 0632230cf..798442534 100755
|
||||
--- a/build/toolchain/apple/linker_driver.py
|
||||
+++ b/build/toolchain/apple/linker_driver.py
|
||||
@@ -7,6 +7,7 @@
|
||||
import os
|
||||
import os.path
|
||||
import re
|
||||
+import shlex
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
@@ -113,6 +114,53 @@ class LinkerDriver(object):
|
||||
# The temporary directory for intermediate LTO object files. If it
|
||||
# exists, it will clean itself up on script exit.
|
||||
self._object_path_lto = None
|
||||
+ self._temp_rsp_files = []
|
||||
+
|
||||
+ def _sanitize_rsp_arg(self, arg):
|
||||
+ if not arg.startswith('@'):
|
||||
+ return arg
|
||||
+ rsp_path = arg[1:]
|
||||
+ if not os.path.isfile(rsp_path):
|
||||
+ return arg
|
||||
+
|
||||
+ try:
|
||||
+ with open(rsp_path, 'r', encoding='utf-8') as f:
|
||||
+ rsp_content = f.read()
|
||||
+ except OSError:
|
||||
+ return arg
|
||||
+
|
||||
+ tokens = shlex.split(rsp_content, posix=True)
|
||||
+ sanitized = []
|
||||
+ changed = False
|
||||
+ i = 0
|
||||
+ while i < len(tokens):
|
||||
+ tok = tokens[i]
|
||||
+ if tok == '-L' and i + 1 < len(tokens):
|
||||
+ lib_dir = tokens[i + 1]
|
||||
+ if not os.path.isdir(lib_dir):
|
||||
+ changed = True
|
||||
+ i += 2
|
||||
+ continue
|
||||
+ elif tok.startswith('-L') and len(tok) > 2:
|
||||
+ lib_dir = tok[2:]
|
||||
+ if not os.path.isdir(lib_dir):
|
||||
+ changed = True
|
||||
+ i += 1
|
||||
+ continue
|
||||
+ sanitized.append(tok)
|
||||
+ i += 1
|
||||
+
|
||||
+ if not changed:
|
||||
+ return arg
|
||||
+
|
||||
+ fd, temp_path = tempfile.mkstemp(prefix='linker_driver_', suffix='.rsp')
|
||||
+ os.close(fd)
|
||||
+ with open(temp_path, 'w', encoding='utf-8') as f:
|
||||
+ for tok in sanitized:
|
||||
+ f.write(tok)
|
||||
+ f.write('\n')
|
||||
+ self._temp_rsp_files.append(temp_path)
|
||||
+ return '@' + temp_path
|
||||
|
||||
def run(self):
|
||||
"""Runs the linker driver, separating out the main compiler driver's
|
||||
@@ -135,11 +183,25 @@ class LinkerDriver(object):
|
||||
assert driver_action[0] not in linker_driver_actions
|
||||
linker_driver_actions[driver_action[0]] = driver_action[1]
|
||||
else:
|
||||
+ if arg.startswith('@'):
|
||||
+ arg = self._sanitize_rsp_arg(arg)
|
||||
# TODO(crbug.com/1446796): On Apple, the linker command line
|
||||
# produced by rustc for LTO includes these arguments, but the
|
||||
# Apple linker doesn't accept them.
|
||||
# Upstream bug: https://github.com/rust-lang/rust/issues/60059
|
||||
BAD_RUSTC_ARGS = '-Wl,-plugin-opt=O[0-9],-plugin-opt=mcpu=.*'
|
||||
+ if arg == '-Wl,-fatal_warnings':
|
||||
+ # Some host link steps on Apple Silicon produce benign
|
||||
+ # warnings from injected search paths (e.g. /usr/local/lib
|
||||
+ # missing). Don't fail the whole build on those warnings.
|
||||
+ continue
|
||||
+ if arg.startswith('-L') and len(arg) > 2:
|
||||
+ # Some environments inject non-existent library search
|
||||
+ # paths (e.g. /usr/local/lib on Apple Silicon). lld treats
|
||||
+ # them as hard errors, so skip missing -L entries.
|
||||
+ lib_dir = arg[2:]
|
||||
+ if not os.path.isdir(lib_dir):
|
||||
+ continue
|
||||
if not re.match(BAD_RUSTC_ARGS, arg):
|
||||
compiler_driver_args.append(arg)
|
||||
|
||||
@@ -185,6 +247,9 @@ class LinkerDriver(object):
|
||||
|
||||
# Re-report the original failure.
|
||||
raise
|
||||
+ finally:
|
||||
+ for path in self._temp_rsp_files:
|
||||
+ _remove_path(path)
|
||||
|
||||
def _get_linker_output(self):
|
||||
"""Returns the value of the output argument to the linker."""
|
||||
@@ -0,0 +1,15 @@
|
||||
diff --git a/build/android/gyp/util/server_utils.py b/build/android/gyp/util/server_utils.py
|
||||
index 6d5ed79d3..c05b57529 100644
|
||||
--- a/build/android/gyp/util/server_utils.py
|
||||
+++ b/build/android/gyp/util/server_utils.py
|
||||
@@ -36,7 +36,9 @@ def MaybeRunCommand(name, argv, stamp_file, force):
|
||||
except socket.error as e:
|
||||
# [Errno 111] Connection refused. Either the server has not been started
|
||||
# or the server is not currently accepting new connections.
|
||||
- if e.errno == 111:
|
||||
+ # [Errno 2] Abstract Unix sockets are unsupported on macOS, so treat
|
||||
+ # this the same way (build server unavailable).
|
||||
+ if e.errno in (111, 2):
|
||||
if force:
|
||||
raise RuntimeError(
|
||||
'\n\nBuild server is not running and '
|
||||
Reference in New Issue
Block a user