Verizon MMS protocol issue (voice note/video not playing)

Yes it has it.
But all other companies like fig and wonder have figured it out for the Photo compression

They don’t use Google Messages and IIRC the issue only starts when using GM.

Absolutely not true.
It’s an issue with all messaging apps.

Besides Wonder had the problem with their picture MMS.
And Keyphone had the voice note and picture problem

1 Like

The only messaging app that doesn’t have this issue is message plus from Verizon

Maybe someone with a bit more knowledge and experience than me can decompile it and see what’s in it that causes that images should not come in compressed etc.

1 Like

It’s how Verizon sees it.

Even though you know what makes the difference in Message plus, you can’t edit the Google messages app itself. So the fix has to be done on the phone itself.

Basically we need to spoof some identifiers that tells Verizon that it’s not a certified device, and spoof it as if it’s a up to date Verizon certificate device

1 Like

What’s the “it” that Verizon sees?

Forwarded from Claude:

How Verizon’s MMS System Actually Works

When an MMS message arrives at Verizon’s MMSC (Multimedia Messaging Service Centre), the server first determines whether the receiving phone is “MMS capable.”
It extracts the content, puts it on a temporary HTTP server, and sends the phone a WAP SMS with a URL to fetch it. Before delivering, some MMSCs also run a “content adaptation” step — attempting to convert the multimedia content into a format suitable for the receiver. (Wikipedia)

This “content adaptation” is the culprit. Verizon’s MMSC decides how much to transcode/compress based on information the phone sends back when it fetches the MMS — specifically a header called the UAProf (User Agent Profile).

A UAProf is an XML file that describes the capabilities of a mobile handset — vendor, model, screen size, multimedia capabilities, character set support, MMS capabilities, and more. A mobile handset sends an HTTP header containing the URL to its UAProf when it fetches content. The header is usually called X-WAP-Profile.

The carrier’s MMSC receives the UAProf from the terminating device and uses it to determine if transcoding of the MMS message is required, based on the type of network and the attributes of the MMS message. (justia)

So the chain is:

  1. Someone sends you an MMS with a voice note or image
  2. Verizon’s MMSC holds it and sends your phone a notification
  3. Your phone fetches the MMS over HTTP, including an X-WAP-Profile header
    If your phone sends no UAProf URL, or a generic/unrecognized one, Verizon’s MMSC assumes it’s an old, limited device
  4. Verizon aggressively transcodes: images crushed to 20–50 KB, audio converted to QCELP (a 1990s CDMA codec), video split into thumbnail + .qcp
    QCELP (.qcp) is a Qualcomm audio codec originating in 1999, used by CDMA carriers for voice. It is a container format that modern Android phones cannot natively play.
2 Likes

This seems solvable. Probably just spoofing the profile it sends can do the trick

1 Like

You could patch a messaging app or patch the carrier config to use the normal data apn instead of the mms apn

1 Like

Can you elaborate please?

your phone has the ability to send large messages with data, but it uses a special apn for mms messages which some carriers compress. The carrier config app decides which apn to use for which data packet, so you could try to patch it to make mms use normal data apn and see if it helps.

1 Like

So says Gemini

Summary

Looking directly at the quote you provided:

“your phone has the ability to send large messages with data, but it uses a special apn for mms messages which some carriers compress. The carrier config app decides which apn to use for which data packet, so you could try to patch it to make mms use normal data apn and see if it helps.”

This is a very insightful technical theory. Here is a breakdown of what this means, why it makes sense, and how you might approach it.

1. The Theory: APN Separation and Proxies

In Android, the Carrier Config dictates how network traffic is routed based on the APN (Access Point Name).

  • Standard Data (type=default): Routes your regular internet traffic (browsing, apps). Carriers generally don’t touch this data other than basic traffic management.
  • MMS Data (type=mms): Routes traffic specifically to the carrier’s MMSC (Multimedia Messaging Service Center).

Verizon typically routes MMS traffic through a specific internal proxy (often utilizing the VZWAPP or a hidden MMS APN). Because MMS is a legacy protocol with strict size limits (traditionally 300KB to 1.2MB), carriers put aggressive compression gateways on this specific routing path.

The quote suggests that because Android is explicitly telling the modem “send this packet via the MMS APN,” Verizon’s network recognizes it, intercepts it via their legacy MMS proxy, and crushes the file size.

2. How the Proposed Patch Would Work

The idea is to “trick” the phone into sending MMS packets through the standard internet data pipeline rather than the dedicated MMS pipeline.

If your Qin F21 Pro is rooted (which is common for these devices running custom ROMs), you could theoretically bypass this by modifying the APN types:

  • Merging APNs: You would edit the APN settings (often locked by Carrier Config) to append ,mms to your standard data APN (e.g., VZWINTERNET with type default,supl,mms).
  • Deleting the dedicated MMS APN: You would remove the standalone MMS APN so the phone is forced to use the default data connection to reach the MMSC URL (http://mms.vtext.com/servlets/mms).
  • Modifying CarrierConfig: Because modern Android uses the CarrierConfigManager app to hardcode carrier settings, you usually can’t just edit this in the normal Android Settings app. You would need to use a root file explorer to modify the telephony database (/data/user_de/0/com.android.providers.telephony/databases/telephony.db) or build a Magisk module that injects a custom carrier_config_mccmnc.xml overlay to override Verizon’s default APN routing rules.

3. The Caveats: Will it actually work?

While the logic is sound on the device side, there is a major server-side hurdle:

The MMSC Server itself: Even if you route the data over the normal internet APN, the standard messaging app is still trying to HTTP POST the media to Verizon’s MMSC URL. When Verizon’s MMSC receives the file, it might be what applies the aggressive compression before distributing it to the recipient, regardless of which APN the data arrived on.

Why does Verizon Message+ work?
Verizon Message+ doesn’t use standard MMS protocols at all. It uses Verizon’s proprietary Advanced Messaging (a carrier-specific version of RCS/Sync) which sends the media as raw data over an IP connection (via the standard data APN) directly to Verizon’s sync servers, completely bypassing the legacy MMSC that handles standard SMS/MMS.

Conclusion

The forum user’s suggestion is a highly logical workaround for bypassing localized carrier proxies. If you have root access on your F21 Pro, it is absolutely worth testing. You would need to:

  1. Extract your carrier config or access the telephony database.
  2. Ensure the mms type is appended to the main Verizon internet APN.
  3. Remove or disable any secondary APNs dedicated solely to MMS.

If Verizon’s compression is purely proxy-based (happening during the APN routing), this will fix it. If the compression is happening at the MMSC server level upon receipt of the payload, this unfortunately won’t bypass it, and you’d have to rely on an IP-based messaging protocol (like RCS via Google Messages, if it can be forced to activate, or sticking with Message+).

I want to correct myself.

KEYPHONE, did not find ‘the’ solution, they rather implemented that their messaging app should be able to play the QCP audio format. As you can see that audio messages are very unclear and compressed and when saving it to the file manager you can see the file format.

1 Like

:clap: @ars18 :police_car_light: :police_car_light: We need you :index_pointing_at_the_viewer: ! We need your claude prompting skills (and credits :rofl: )!

1 Like

The carrier config app sometimes has the message size limit per carrier in an xml, so you could patch the app to raise the message size limit locally (while still using the apn normally). Could you upload the qin carrierconfig app. I think its in /system_ext/priv-app/MtkCarrierconfig/ (my qin broke yesterday, but I think I remember where it is). Its pretty small and you could decompile it and upload it to claude.

For example, here is where it limits the message size in the verizon xml in the carrier config app in the boost summit flip

MtkCarrierConfig.apk

carrier_config_carrierid_1839_Verizon-Wireless.xml
<?xml version="1.0" encoding="utf-8" standalone="yes"?>

<carrier_config>

<boolean name="carrier_default_wfc_ims_roaming_enabled_bool" value="true" />

<boolean name="aliasEnabled" value="true"/>

<boolean name="allowAttachAudio" value="false"/>

<boolean name="allow_add_call_during_video_call" value="false"/>

<boolean name="allow_adding_apns_bool" value="false"/>

<boolean name="allow_hold_in_ims_call" value="false"/>

<boolean name="allow_merge_wifi_calls_when_vowifi_off_bool" value="false"/>

<boolean name="apn_expand_bool" value="false"/>

<boolean name="broadcast_emergency_call_state_changes_bool" value="true"/>

<boolean name="carrier_allow_turnoff_ims_bool" value="false"/>

<boolean name="carrier_name_override_bool" value="true"/>

<boolean name="carrier_promote_wfc_on_call_fail_bool" value="true"/>

<boolean name="carrier_volte_available_bool" value="true"/>

<boolean name="carrier_volte_provisioned_bool" value="true"/>

<boolean name="carrier_volte_provisioning_required_bool" value="false"/>

<boolean name="carrier_vt_available_bool" value="true"/>

<boolean name="carrier_wfc_ims_available_bool" value="true"/>

<boolean name="disable_voice_barring_notification_bool" value="true"/>

<boolean name="drop_video_call_when_answering_audio_call_bool" value="true"/>

<boolean name="dtmf_type_enabled_bool" value="true"/>

<boolean name="editable_wfc_mode_bool" value="false"/>

<boolean name="editable_wfc_roaming_mode_bool" value="true"/>

<boolean name="enableMMSReadReports" value="false"/>

<boolean name="enableMultipartSMS" value="true"/>

<boolean name="enabledNotifyWapMMSC" value="true"/>

<boolean name="enabledTransID" value="true"/>

<boolean name="is_ims_conference_size_enforced_bool" value="true"/>

<boolean name="mdn_is_additional_voicemail_number_bool" value="true"/>

<boolean name="mmsCloseConnection" value="true"/>

<boolean name="notify_handover_video_from_lte_to_wifi_bool" value="true"/>

<boolean name="notify_handover_video_from_wifi_to_lte_bool" value="true"/>

<boolean name="notify_vt_handover_to_wifi_failure_bool" value="true"/>

<boolean name="operator_selection_expand_bool" value="true"/>

<boolean name="gps.persist_lpp_mode_bool" value="true"/>

<boolean name="prefer_2g_bool" value="false"/>

<boolean name="rtt_supported_bool" value="true"/>

<boolean name="show_apn_setting_cdma_bool" value="true"/>

<boolean name="use_rcs_presence_bool" value="false"/>

<boolean name="sms_requires_destination_number_conversion_bool" value="true"/>

<boolean name="support_3gpp_call_forwarding_while_roaming_bool" value="false"/>

<boolean name="support_downgrade_vt_to_audio_bool" value="false"/>

<boolean name="support_pause_ims_video_calls_bool" value="true"/>

<boolean name="support_swap_after_merge_bool" value="false"/>

<boolean name="treat_downgraded_video_calls_as_video_calls_bool" value="true"/>

<boolean name="video_calls_can_be_hd_audio" value="false"/>

<boolean name="mtk_vt_over_wifi_check_wfc_enable_bool" value="false" />

<boolean name="voicemail_notification_persistent_bool" value="true"/>

<boolean name="wifi_calls_can_be_hd_audio" value="false"/>

<boolean name="world_mode_enabled_bool" value="true"/>

<int name="aliasMaxChars" value="48"/>

<int name="aliasMinChars" value="2"/>

<int name="carrier_default_wfc_ims_mode_int" value="1"/>

<int name="carrier_default_wfc_ims_roaming_mode_int" value="1"/>

<int name="ims_conference_size_limit_int" value="5"/>

<int name="lte_earfcns_rsrp_boost_int" value="6"/>

<int name="maxImageHeight" value="1944"/>

<int name="maxImageWidth" value="2592"/>

<int name="maxMessageSize" value="1258291"/>

<int name="maxSubjectLength" value="80"/>

<int name="recipientLimit" value="20"/>

<int name="smsToMmsTextThreshold" value="7"/>

<int name="volte_replacement_rat_int" value="6"/>

<int name="wfc_spn_format_idx_int" value="1"/>

<string name="carrier_eri_file_name_string">eri_311480.xml</string>

<string name="carrier_name_string">Verizon</string>

<string name="default_vm_number_string">\*86</string>

<string name="emailGatewayNumber">6245</string>

<string name="httpParams">x-up-calling-line-id: 1##LINE1NOCOUNTRYCODE##|X-VzW-MDN: 1##LINE1NOCOUNTRYCODE##</string>

<string name="uaProfTagName">Profile</string>

<string name="sim_country_iso_override_string">us</string>

<string-array name="boosted_lte_earfcns_string_array" num="2">

    <item value="600-1199"/>

    <item value="1950-2399"/>

</string-array>

<string-array name="call_forwarding_blocks_while_roaming_string_array" num="2">

    <item value="\*71"/>

    <item value="\*72"/>

</string-array>

<string-array name="carrier_data_call_permanent_failure_strings" num="11">

    <!--M: \[VzW\] Data Framework

           \[LTE\]\[DR\]\[6.9\] VZ_TC_DATARTRY_53688; VZ_REQ_LTEDATARETRY_7767:

           For LTE Release 11 and earlier UEs, we should retry the same APN once for

           fail cause: 8, 27, 29, 32, 33, 112. -->

    <!--<item value="OPERATOR_BARRED"/>-->

    <!--<item value="MISSING_UNKNOWN_APN"/>-->

    <item value="UNKNOWN_PDP_ADDRESS_TYPE"/>

    <!--<item value="USER_AUTHENTICATION"/>-->

    <item value="ACTIVATION_REJECT_GGSN"/>

    <!--<item value="SERVICE_OPTION_NOT_SUPPORTED"/>-->

    <!--<item value="SERVICE_OPTION_NOT_SUBSCRIBED"/>-->

    <item value="NSAPI_IN_USE"/>

    <item value="ONLY_IPV4_ALLOWED"/>

    <item value="ONLY_IPV6_ALLOWED"/>

    <item value="PROTOCOL_ERRORS"/>

    <item value="RADIO_POWER_OFF"/>

    <item value="TETHERED_CALL_ACTIVE"/>

    <item value="RADIO_NOT_AVAILABLE"/>

    <item value="UNACCEPTABLE_NETWORK_PARAMETER"/>

    <item value="SIGNAL_LOST"/>

</string-array>

<string-array name="carrier_metered_apn_types_strings" num="3">

    <item value="default"/>

    <item value="dun"/>

    <item value="supl"/>

</string-array>

<string-array name="carrier_metered_roaming_apn_types_strings" num="4">

    <item value="default"/>

    <item value="dun"/>

    <item value="mms"/>

    <item value="supl"/>

</string-array>

<string-array name="dial_string_replace_string_array" num="2">

    <item value="\*611:+19085594899"/>

    <item value="\*86:+1MDN"/>

</string-array>

<string-array name="filtered_cnap_names_string_array" num="2">

    <item value="WIRELESS CALLER"/>

    <item value="UNKNOWN NAME"/>

</string-array>

<string-array name="ims_reasoninfo_mapping_string_array" num="10">

    <item value="332|simultaneous call limit has already been reached|1403"/>

    <item value="332|Forbidden: Simultaneous Call Limit Has Already Been Reached|1403"/>

    <item value="338|another device sent all devices busy response|1404"/>

    <item value="501|call completion elsewhere|1014"/>

    <item value="501|call has been pulled by another device|1016"/>

    <item value="510|call has been pulled by another device|1016"/>

    <item value="501|another device sent all devices busy response|1404"/>

    <item value="510|another device sent all devices busy response|1404"/>

    <item value="1014|call has been pulled by another device|1016"/>

    <item value="\*|Call is dropped due to Wi-Fi signal is degraded|1407"/>

</string-array>

<string-array name="read_only_apn_fields_string_array" num="20">

    <item value="name"/>

    <item value="proxy"/>

    <item value="port"/>

    <item value="user"/>

    <item value="password"/>

    <item value="server"/>

    <item value="mmsc"/>

    <item value="mmsproxy"/>

    <item value="mmsport"/>

    <item value="mcc"/>

    <item value="mnc"/>

    <item value="authtype"/>

    <item value="type"/>

    <item value="protocol"/>

    <item value="roaming_protocol"/>

    <item value="bearer"/>

    <item value="bearer_bitmask"/>

    <item value="carrier_enabled"/>

    <item value="mvno_type"/>

    <item value="mvno_match_data"/>

</string-array>

<int-array name="lte_rsrp_thresholds_int_array" num="4">

    <item value="-115"/>

    <item value="-105"/>

    <item value="-95"/>

    <item value="-85"/>

</int-array>

<int-array name="cdma_enhanced_roaming_indicator_for_home_network_int_array" num="11">

    <item value="64"/>

    <item value="65"/>

    <item value="66"/>

    <item value="76"/>

    <item value="77"/>

    <item value="78"/>

    <item value="79"/>

    <item value="80"/>

    <item value="81"/>

    <item value="82"/>

    <item value="83"/>

</int-array>

<string name="5g_icon_display_grace_period_string"

    value="connected_mmwave,any,3;not_restricted_rrc_idle,not_restricted_rrc_con,2"/>

<string name="5g_icon_display_secondary_grace_period_string"

    value="connected_mmwave,not_restricted_rrc_idle,60"/>



<boolean name="mtk_resume_hold_call_after_active_call_end_by_remote" value="true"/>

<boolean name="mtk_disallow_outgoing_calls_during_video_or_voice_call_bool" value="true"/>

<boolean name="ignore_rtt_mode_setting_bool" value="true"/>

<boolean name="mtk_vt_dialpad_support_bool" value="true" />

<boolean name="support_auto_decline_upgrade_request_bool" value="false" />

<boolean name="rtt_supported_for_vt_bool" value="false"/>

<boolean name="rtt_upgrade_supported_bool" value="true"/>

<boolean name="rtt_downgrade_supported_bool" value="false"/>

<boolean name="mtk_rtt_video_switch_supported_bool" value="false"/>

<boolean name="mtk_rtt_auto_accept_request_bool" value="true"/>

<boolean name="mtk_multi_rtt_calls_supported_bool" value="true"/>

<boolean name="mtk_mt_rtt_without_precondition_bool" value="true"/>

<boolean name="allow_hold_call_during_emergency_bool" value="true"/>

</carrier_config>

:man_raising_hand: Proposed solution

Claude’s 2 cents (actually, it probably cost more than that):

Verizon MMS Compression Bug on Qin F21 — Root Cause Analysis

Background

Verizon users on the Qin F21 (and similar small-form-factor Android phones built on MediaTek chipsets) experience two related MMS problems:

  1. Received images are heavily compressed — blurry, often unreadable text in screenshots or documents

  2. Voice notes are unplayable (separate but related issue, addressed in ROM 613)

The forum consensus was that the issue is tied to how the device identifies itself to Verizon’s servers, not to the messaging app in use. The problem affects Google Messages, QKSMS, and every other third-party app. Only Verizon’s own Message+ app is immune, because it uses a proprietary out-of-band authentication mechanism rather than the standard Android MMS stack.

This document traces the problem from the Android framework all the way down to the specific missing lines in the carrier config APK.


How Android MMS Works — The Relevant Path

When a message app (Google Messages, etc.) needs to send or receive an MMS, it does not handle the HTTP transaction itself. Instead it delegates to the Android telephony framework via SmsManager.getCarrierConfigValues() and the platform MMS service. The sequence is:

  1. The messaging app calls SmsManager.getCarrierConfigValues(subId)

  2. This hits SmsController.getCarrierConfigValuesForSubscriber() in the telephony framework

  3. SmsController reads the CarrierConfig bundle for the active SIM — the config that carrier config APKs (like MtkCarrierConfig) supply

  4. A filtered subset of those keys is returned to the messaging app

  5. The messaging app (or the platform MMS service) uses those values to construct the HTTP POST to Verizon’s MMSC (Multimedia Messaging Service Center)

The MMSC is Verizon’s server-side component. It receives inbound MMS, decides what quality/resolution to use when delivering to the recipient, and delivers it. The quality decision is driven by the device identity headers in the HTTP request.


Investigation Step 1 — The Carrier Config APK

The device ships with a MediaTek-customized carrier config APK at /system_ext/priv-app/MtkCarrierconfig/MtkCarrierConfig.apk. This APK contains per-carrier XML files under assets/ that supply carrier-specific settings to Android’s CarrierConfigManager.

The file for Verizon is:

assets/carrier_config_carrierid_1839_Verizon-Wireless.xml

There is also a legacy fallback keyed to Verizon’s MCC/MNC:

assets/carrier_config_mccmnc_311012.xml

The DefaultCarrierConfigService.smali (the APK’s only Java class) shows the config loading priority: it tries carrierid_<specificCarrierId>_*, then carrierid_<carrierId>_*, then carrierid_<mccmncDerivedId>_*, and finally falls back to carrier_config_mccmnc_<mcc><mnc>.xml. All four tiers are merged, with higher-priority tiers winning on conflicts.

MMS-Relevant Keys in the Verizon Config

Scanning the Verizon XML against the full set of MMS-relevant carrier config keys:

Key Value in Verizon XML Purpose
uaProfTagName "Profile" HTTP header name for UAProf
uaProfUrl not present URL placed in the UAProf header
userAgent not present Override for the HTTP User-Agent string
httpParams `x-up-calling-line-id: 1##LINE1NOCOUNTRYCODE## X-VzW-MDN: 1##LINE1NOCOUNTRYCODE##`
maxImageWidth 2592 Max width before sending
maxImageHeight 1944 Max height before sending
maxMessageSize 1258291 (~1.2 MB) Max total MMS size

The httpParams field correctly injects the subscriber’s phone number into every MMSC request. The maxImage* values are generous. But uaProfUrl and userAgent — the two keys that tell Verizon’s MMSC what device it is talking to — are completely absent.

The same absence exists in carrier_config_mccmnc_311012.xml, the fallback config.


Investigation Step 2 — The Telephony Framework

To confirm exactly how these keys travel from the config file to the MMS HTTP request, telephony-common.jar was decompiled with jadx. The jar contains the Android telephony framework classes compiled for this device.

The critical method is SmsController.getMmsConfig(), located at com/android/internal/telephony/SmsController.java:389:

private static Bundle getMmsConfig(BaseBundle config) {
    Bundle filtered = new Bundle();
    // ... boolean and int keys omitted for brevity ...
    filtered.putString("uaProfTagName", config.getString("uaProfTagName"));  // line 415
    filtered.putString("userAgent",     config.getString("userAgent"));       // line 416
    filtered.putString("uaProfUrl",     config.getString("uaProfUrl"));       // line 417
    filtered.putString("httpParams",    config.getString("httpParams"));      // line 418
    filtered.putString("emailGatewayNumber", config.getString("emailGatewayNumber"));
    // ...
    return filtered;
}

This method is called by the public system service method getCarrierConfigValuesForSubscriber() (line 379), which is what SmsManager.getCarrierConfigValues() ultimately invokes. Every messaging app on the device goes through this exact code path.

What this confirms:

  • uaProfUrl is read verbatim from the carrier config bundle and forwarded to every MMS client. Since the Verizon XML doesn’t set it, every app gets back null.

  • userAgent is likewise read and forwarded. Since it is also absent, every app gets back null.

  • When the MMS HTTP client receives null for uaProfUrl, it sends no Profile: header (or an empty one). When it receives null for userAgent, it falls back to constructing a generic User-Agent from android.os.Build.MODEL, which on this device resolves to something containing "Qin F21".


What Verizon’s MMSC Does With This

When Verizon’s MMSC receives an MMS POST it evaluates two HTTP headers to determine device capabilities:

1. The Profile: Header (UAProf)

The Profile: header (whose name comes from uaProfTagName) contains a URL pointing to a UAProf XML — a standardized device capability declaration. It describes things like maximum supported image resolution, accepted MIME types, and screen dimensions.

A certified Verizon device (e.g. Samsung Galaxy S22) sends something like:

Profile: http://wap.samsungmobile.com/uaprof/SM-S901U.xml

Verizon’s MMSC fetches that URL, reads the profile, confirms the device can handle full-resolution content, and delivers the MMS at full quality.

The Qin F21 sends no Profile: header at all because uaProfUrl is null. The MMSC sees an unrecognized device and falls back to its lowest-common-denominator delivery policy: aggressive downscaling.

2. The User-Agent Header

As a secondary identity signal, the MMSC also inspects the HTTP User-Agent string. For the Qin F21, with no userAgent override in carrier config, the MMS stack assembles a string from system properties that includes the literal device model name — something like:

Dalvik/2.1.0 (Linux; U; Android 11; Qin F21 Build/...)

"Qin F21" is not in Verizon’s certified-device database, so even if the MMSC falls back to UA-string-based identification, it still cannot match the device to a known capability profile.

Why Message+ Is Immune

Verizon’s own Message+ app bypasses the standard Android MMS stack entirely. It registers the device with Verizon’s servers using the account credentials from the Verizon app, receiving a session token that the MMSC trusts regardless of what Profile: header is sent. Third-party apps have no access to this registration mechanism and rely entirely on the carrier config values.

Why the maxImage* Values Don’t Help

A common suggestion is to increase maxImageWidth and maxImageHeight. These values control what the sending device does before uploading — they cap the resolution the local device will encode before posting to the MMSC. They have absolutely no effect on what the MMSC does when delivering to the Qin F21. The compression being reported is happening on the delivery path, server-side, based on Verizon’s assessment of the recipient device’s capabilities.


The Fix

The fix requires patching MtkCarrierConfig.apk to add the two missing keys.

Files to Modify

  1. MtkCarrierConfig/assets/carrier_config_carrierid_1839_Verizon-Wireless.xml — primary Verizon config

  2. MtkCarrierConfig/assets/carrier_config_mccmnc_311012.xml — MCCMNC fallback config

Keys to Add

<string name="uaProfUrl">URL_OF_CERTIFIED_DEVICE_UAPROF</string>
<string name="userAgent">UA_STRING_OF_CERTIFIED_DEVICE</string>

Both values should reference the same certified Verizon device, so the MMSC sees a consistent identity across both signals.

Sourcing the Correct Values

The safest way to get confirmed working values is to dump the carrier config from a real Verizon-certified Android device:

adb shell dumpsys carrier_config

Look for the uaProfUrl and userAgent entries in the Verizon block. Any modern Pixel (6, 7, 8) or Samsung Galaxy S-series certified for Verizon will have these set. The UAProf URLs are public — they live on manufacturer servers (e.g. wap.samsungmobile.com, wap.samsungmobile.com, or Google’s static servers for Pixel) and can be fetched in a browser to verify they describe a high-capability device.

Example of what a complete, working Verizon config entry looks like (values are illustrative — use real values sourced from a certified device):

<string name="uaProfUrl">http://wap.samsungmobile.com/uaprof/SM-S901U.xml</string>
<string name="userAgent">Mozilla/5.0 (Linux; Android 12; SM-S901U Build/SP1A.210812.016; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/96.0.4664.45 Mobile Safari/537.36</string>

Rebuilding and Deploying the APK

# Repack with apktool
apktool b MtkCarrierConfig -o MtkCarrierConfig-patched.apk

# Sign with the platform key (required — this is a priv-app)
java -jar signapk.jar platform.x509.pem platform.pk8 \
     MtkCarrierConfig-patched.apk MtkCarrierConfig-signed.apk

# Push to device (requires root)
adb root
adb remount
adb push MtkCarrierConfig-signed.apk \
     /system_ext/priv-app/MtkCarrierconfig/MtkCarrierConfig.apk
adb shell chmod 644 /system_ext/priv-app/MtkCarrierconfig/MtkCarrierConfig.apk
adb reboot

After reboot, verify the config was loaded with:

adb shell dumpsys carrier_config | grep -E "uaProfUrl|userAgent|uaProfTagName"

Both new keys should appear with their values for the Verizon subscription.


Why This Will Work

The Android MMS path from messaging app to MMSC is a direct, transparent chain:

Carrier Config XML
      ↓
CarrierConfigManager (system service)
      ↓
SmsController.getMmsConfig()        ← telephony-common.jar, confirmed
      ↓
SmsManager.getCarrierConfigValues() ← what every messaging app calls
      ↓
MMS HTTP client
      ↓  Profile: <uaProfUrl>
      ↓  User-Agent: <userAgent>
      ↓  x-up-calling-line-id: <phone>
      ↓  X-VzW-MDN: <phone>
Verizon MMSC

Every link in this chain is confirmed. The only broken links are the two missing values in the XML. Once they are present, the MMSC will receive a Profile: header pointing to a known certified device’s UAProf, look up that device’s declared capabilities (full resolution, large JPEG, etc.), and deliver MMS content accordingly.

No changes are needed to any messaging app. The fix is purely in the carrier config layer, which is the correct and intended place for per-carrier MMS tuning in Android’s architecture.


Summary Table

Component File / Location Finding
Carrier Config APK MtkCarrierConfig/assets/carrier_config_carrierid_1839_Verizon-Wireless.xml uaProfUrl and userAgent absent
MCCMNC Fallback MtkCarrierConfig/assets/carrier_config_mccmnc_311012.xml Same two keys absent
Telephony Framework telephony-common.jarSmsController.java:389–424 Confirms both keys forwarded verbatim to all MMS clients; null when absent
Identity Header uaProfTagName = "Profile" Header name is correct; URL to put in it is missing
User-Agent userAgent key No override; device sends “Qin F21” which Verizon doesn’t recognize
Size Limits maxImageWidth/Height, maxMessageSize Already generous; irrelevant to server-side compression on delivery

So, bekitzur tl;dr vechulu - we need a profile header and a user agent from a certified device. Rabbosai?
hint

What’s the big deal? Let’s pull from any smartphone

And this fixes the voice note problem too? Or just the image compression?
Because we need to do it for the M5 emergency