diff --git a/Patches/LineageOS-17.1/android_external_freetype/360951.patch b/Patches/LineageOS-17.1/android_external_freetype/360951.patch new file mode 100644 index 00000000..027187d3 --- /dev/null +++ b/Patches/LineageOS-17.1/android_external_freetype/360951.patch @@ -0,0 +1,50 @@ +From cd6630c7a6387077cec3b6113313d3852bb5c2b2 Mon Sep 17 00:00:00 2001 +From: Werner Lemberg +Date: Sat, 19 Mar 2022 06:40:17 +0100 +Subject: [PATCH] DO NOT MERGE - Cherry-pick two upstream changes + +This cherry picks following two changes: + +0c2bdb01a2e1d24a3e592377a6d0822856e10df2 +22a0cccb4d9d002f33c1ba7a4b36812c7d4f46b5 + +Bug: 271680254 +Test: N/A +(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:4ffa271ab538f57b65a65d434a2df9d3f8cd2f4a) +(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:b0f8930701bf19229075cc930ad15813ff5fb07b) +Merged-In: I42469df8e8b07221d64e3f8574c4f30110dbda7e +Change-Id: I42469df8e8b07221d64e3f8574c4f30110dbda7e +--- + src/base/ftobjs.c | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +diff --git a/src/base/ftobjs.c b/src/base/ftobjs.c +index e301f8f11..70ba6e749 100644 +--- a/src/base/ftobjs.c ++++ b/src/base/ftobjs.c +@@ -2389,6 +2389,15 @@ + #endif + + ++ /* only use lower 31 bits together with sign bit */ ++ if ( face_index > 0 ) ++ face_index &= 0x7FFFFFFFL; ++ else ++ { ++ face_index &= 0x7FFFFFFFL; ++ face_index = -face_index; ++ } ++ + #ifdef FT_DEBUG_LEVEL_TRACE + FT_TRACE3(( "FT_Open_Face: " )); + if ( face_index < 0 ) +@@ -3244,6 +3253,9 @@ + if ( !face ) + return FT_THROW( Invalid_Face_Handle ); + ++ if ( !face->size ) ++ return FT_THROW( Invalid_Size_Handle ); ++ + if ( !req || req->width < 0 || req->height < 0 || + req->type >= FT_SIZE_REQUEST_TYPE_MAX ) + return FT_THROW( Invalid_Argument ); diff --git a/Patches/LineageOS-17.1/android_frameworks_base/360952-backport.patch b/Patches/LineageOS-17.1/android_frameworks_base/360952-backport.patch new file mode 100644 index 00000000..d5626a2d --- /dev/null +++ b/Patches/LineageOS-17.1/android_frameworks_base/360952-backport.patch @@ -0,0 +1,243 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: "Nate(Qiang) Jiang" +Date: Wed, 26 Oct 2022 21:52:34 +0000 +Subject: [PATCH] Passpoint Add more check to limit the config size + +Bug: 245299920 +Test: atest con.android.server.wifi +(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:e1a80210f3f0391c989a2a86fd4aef739bf2574c) +Merged-In: I97522ce3607547c10025caa107cd1a40455a9c5d +Change-Id: I97522ce3607547c10025caa107cd1a40455a9c5d +--- + .../wifi/hotspot2/PasspointConfiguration.java | 59 +++++++++++++- + .../net/wifi/hotspot2/pps/Credential.java | 10 ++- + .../android/net/wifi/hotspot2/pps/HomeSp.java | 79 ++++++++++++++++++- + .../hotspot2/PasspointConfigurationTest.java | 2 +- + 4 files changed, 146 insertions(+), 4 deletions(-) + +diff --git a/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java b/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java +index 9095b5d927a2..eff56acf4dfb 100644 +--- a/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java ++++ b/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java +@@ -52,8 +52,42 @@ public final class PasspointConfiguration implements Parcelable { + + /** + * Maximum bytes for URL string. ++ * @hide ++ */ ++ public static final int MAX_URL_BYTES = 2048; ++ ++ /** ++ * Maximum size for match entry, just to limit the size of the Passpoint config. ++ * @hide ++ */ ++ public static final int MAX_NUMBER_OF_ENTRIES = 16; ++ ++ /** ++ * Maximum size for OI entry. ++ * The spec allows a string of up to 255 characters, with comma delimited numbers like ++ * 001122,334455. So with minimum OI size of 7, the maximum amount of OIs is 36. ++ * @hide ++ */ ++ public static final int MAX_NUMBER_OF_OI = 36; ++ ++ ++ /** ++ * Maximum bytes for a string entry like FQDN and friendly name. ++ * @hide ++ */ ++ public static final int MAX_STRING_LENGTH = 255; ++ ++ /** ++ * HESSID is 48 bit. ++ * @hide ++ */ ++ public static final long MAX_HESSID_VALUE = ((long) 1 << 48) - 1; ++ ++ /** ++ * Organization Identifiers is 3 or 5 Octets. 24 or 36 bit. ++ * @hide + */ +- private static final int MAX_URL_BYTES = 1023; ++ public static final long MAX_OI_VALUE = ((long) 1 << 40) - 1; + + /** + * Integer value used for indicating null value in the Parcel. +@@ -572,7 +606,30 @@ public final class PasspointConfiguration implements Parcelable { + return false; + } + ++ if (mAaaServerTrustedNames != null) { ++ if (mAaaServerTrustedNames.length > MAX_NUMBER_OF_ENTRIES) { ++ Log.d(TAG, "Too many AaaServerTrustedNames"); ++ return false; ++ } ++ for (String fqdn : mAaaServerTrustedNames) { ++ if (fqdn.getBytes(StandardCharsets.UTF_8).length > MAX_STRING_LENGTH) { ++ Log.d(TAG, "AaaServerTrustedNames is too long"); ++ return false; ++ } ++ } ++ } ++ if (mSubscriptionType != null) { ++ if (mSubscriptionType.getBytes(StandardCharsets.UTF_8).length > MAX_STRING_LENGTH) { ++ Log.d(TAG, "SubscriptionType is too long"); ++ return false; ++ } ++ } ++ + if (mTrustRootCertList != null) { ++ if (mTrustRootCertList.size() > MAX_NUMBER_OF_ENTRIES) { ++ Log.d(TAG, "Too many TrustRootCert"); ++ return false; ++ } + for (Map.Entry entry : mTrustRootCertList.entrySet()) { + String url = entry.getKey(); + byte[] certFingerprint = entry.getValue(); +diff --git a/wifi/java/android/net/wifi/hotspot2/pps/Credential.java b/wifi/java/android/net/wifi/hotspot2/pps/Credential.java +index 9409c03c614d..6d12ccef29ae 100644 +--- a/wifi/java/android/net/wifi/hotspot2/pps/Credential.java ++++ b/wifi/java/android/net/wifi/hotspot2/pps/Credential.java +@@ -16,6 +16,8 @@ + + package android.net.wifi.hotspot2.pps; + ++import static android.net.wifi.hotspot2.PasspointConfiguration.MAX_STRING_LENGTH; ++ + import android.net.wifi.EAPConstants; + import android.net.wifi.ParcelUtil; + import android.os.Parcel; +@@ -413,7 +415,13 @@ public final class Credential implements Parcelable { + + mPassword.getBytes(StandardCharsets.UTF_8).length); + return false; + } +- ++ if (mSoftTokenApp != null) { ++ if (mSoftTokenApp.getBytes(StandardCharsets.UTF_8).length > MAX_STRING_LENGTH) { ++ Log.d(TAG, "app name exceeding maximum length: " ++ + mSoftTokenApp.getBytes(StandardCharsets.UTF_8).length); ++ return false; ++ } ++ } + // Only supports EAP-TTLS for user credential. + if (mEapType != EAPConstants.EAP_TTLS) { + Log.d(TAG, "Invalid EAP Type for user credential: " + mEapType); +diff --git a/wifi/java/android/net/wifi/hotspot2/pps/HomeSp.java b/wifi/java/android/net/wifi/hotspot2/pps/HomeSp.java +index 49a76c33d209..cdb9ec5cec3c 100644 +--- a/wifi/java/android/net/wifi/hotspot2/pps/HomeSp.java ++++ b/wifi/java/android/net/wifi/hotspot2/pps/HomeSp.java +@@ -16,6 +16,13 @@ + + package android.net.wifi.hotspot2.pps; + ++import static android.net.wifi.hotspot2.PasspointConfiguration.MAX_HESSID_VALUE; ++import static android.net.wifi.hotspot2.PasspointConfiguration.MAX_NUMBER_OF_ENTRIES; ++import static android.net.wifi.hotspot2.PasspointConfiguration.MAX_NUMBER_OF_OI; ++import static android.net.wifi.hotspot2.PasspointConfiguration.MAX_OI_VALUE; ++import static android.net.wifi.hotspot2.PasspointConfiguration.MAX_STRING_LENGTH; ++import static android.net.wifi.hotspot2.PasspointConfiguration.MAX_URL_BYTES; ++ + import android.os.Parcelable; + import android.os.Parcel; + import android.text.TextUtils; +@@ -328,16 +335,86 @@ public final class HomeSp implements Parcelable { + Log.d(TAG, "Missing FQDN"); + return false; + } ++ if (mFqdn.getBytes(StandardCharsets.UTF_8).length > MAX_STRING_LENGTH) { ++ Log.d(TAG, "FQDN is too long"); ++ return false; ++ } + if (TextUtils.isEmpty(mFriendlyName)) { + Log.d(TAG, "Missing friendly name"); + return false; + } ++ if (mFriendlyName.getBytes(StandardCharsets.UTF_8).length > MAX_STRING_LENGTH) { ++ Log.d(TAG, "Friendly name is too long"); ++ return false; ++ } + // Verify SSIDs specified in the NetworkID + if (mHomeNetworkIds != null) { ++ if (mHomeNetworkIds.size() > MAX_NUMBER_OF_ENTRIES) { ++ Log.d(TAG, "too many SSID in HomeNetworkIDs"); ++ return false; ++ } + for (Map.Entry entry : mHomeNetworkIds.entrySet()) { + if (entry.getKey() == null || + entry.getKey().getBytes(StandardCharsets.UTF_8).length > MAX_SSID_BYTES) { +- Log.d(TAG, "Invalid SSID in HomeNetworkIDs"); ++ Log.d(TAG, "SSID is too long in HomeNetworkIDs"); ++ return false; ++ } ++ if (entry.getValue() != null ++ && (entry.getValue() > MAX_HESSID_VALUE || entry.getValue() < 0)) { ++ Log.d(TAG, "HESSID is out of range"); ++ return false; ++ } ++ } ++ } ++ if (mIconUrl != null && mIconUrl.getBytes(StandardCharsets.UTF_8).length > MAX_URL_BYTES) { ++ Log.d(TAG, "Icon URL is too long"); ++ return false; ++ } ++ if (mMatchAllOis != null) { ++ if (mMatchAllOis.length > MAX_NUMBER_OF_OI) { ++ Log.d(TAG, "too many match all Organization Identifiers in the profile"); ++ return false; ++ } ++ for (long oi : mMatchAllOis) { ++ if (oi > MAX_OI_VALUE || oi < 0) { ++ Log.d(TAG, "Organization Identifiers is out of range"); ++ return false; ++ } ++ } ++ } ++ if (mMatchAnyOis != null) { ++ if (mMatchAnyOis.length > MAX_NUMBER_OF_OI) { ++ Log.d(TAG, "too many match any Organization Identifiers in the profile"); ++ return false; ++ } ++ for (long oi : mMatchAnyOis) { ++ if (oi > MAX_OI_VALUE || oi < 0) { ++ Log.d(TAG, "Organization Identifiers is out of range"); ++ return false; ++ } ++ } ++ } ++ if (mRoamingConsortiumOis != null) { ++ if (mRoamingConsortiumOis.length > MAX_NUMBER_OF_OI) { ++ Log.d(TAG, "too many Roaming Consortium Organization Identifiers in the " ++ + "profile"); ++ return false; ++ } ++ for (long oi : mRoamingConsortiumOis) { ++ if (oi > MAX_OI_VALUE || oi < 0) { ++ Log.d(TAG, "Organization Identifiers is out of range"); ++ return false; ++ } ++ } ++ } ++ if (mOtherHomePartners != null) { ++ if (mOtherHomePartners.length > MAX_NUMBER_OF_ENTRIES) { ++ Log.d(TAG, "too many other home partners in the profile"); ++ return false; ++ } ++ for (String fqdn : mOtherHomePartners) { ++ if (fqdn.length() > MAX_STRING_LENGTH) { ++ Log.d(TAG, "FQDN is too long in OtherHomePartners"); + return false; + } + } +diff --git a/wifi/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java b/wifi/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java +index fc03e7eb6176..6b4f7b0cc51e 100644 +--- a/wifi/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java ++++ b/wifi/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java +@@ -43,7 +43,7 @@ import java.util.Map; + */ + @SmallTest + public class PasspointConfigurationTest { +- private static final int MAX_URL_BYTES = 1023; ++ private static final int MAX_URL_BYTES = 2048; + private static final int CERTIFICATE_FINGERPRINT_BYTES = 32; + + /** diff --git a/Patches/LineageOS-17.1/android_frameworks_base/360953-backport.patch b/Patches/LineageOS-17.1/android_frameworks_base/360953-backport.patch new file mode 100644 index 00000000..9941be55 --- /dev/null +++ b/Patches/LineageOS-17.1/android_frameworks_base/360953-backport.patch @@ -0,0 +1,145 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Lucas Lin +Date: Fri, 3 Mar 2023 08:13:50 +0000 +Subject: [PATCH] Sanitize VPN label to prevent HTML injection + +This commit will try to sanitize the content of VpnDialog. This +commit creates a function which will try to sanitize the VPN +label, if the sanitized VPN label is different from the original +one, which means the VPN label might contain HTML tag or the VPN +label violates the words restriction(may contain some wording +which will mislead the user). For this kind of case, show the +package name instead of the VPN label to prevent misleading the +user. + +The malicious VPN app might be able to add a large number of line +breaks with HTML in order to hide the system-displayed text from +the user in the connection request dialog. Thus, sanitizing the +content of the dialog is needed. + +Bug: 204554636 +Test: N/A +(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:2178216b98bf9865edee198f45192f0b883624ab) +Merged-In: I8eb890fd2e5797d8d6ab5b12f9c628bc9616081d +Change-Id: I8eb890fd2e5797d8d6ab5b12f9c628bc9616081d +--- + packages/VpnDialogs/res/values/strings.xml | 28 ++++++++++ + .../com/android/vpndialogs/ConfirmDialog.java | 53 +++++++++++++++++-- + 2 files changed, 76 insertions(+), 5 deletions(-) + +diff --git a/packages/VpnDialogs/res/values/strings.xml b/packages/VpnDialogs/res/values/strings.xml +index 443a9bc33b90..b4166f0bedfd 100644 +--- a/packages/VpnDialogs/res/values/strings.xml ++++ b/packages/VpnDialogs/res/values/strings.xml +@@ -89,4 +89,32 @@ + without any consequences. [CHAR LIMIT=20] --> + Dismiss + ++ ++ ++ %1$s… ( ++ %2$s) ++ ++ ++ ++ ++ %1$s ( ++ %2$s) ++ + +diff --git a/packages/VpnDialogs/src/com/android/vpndialogs/ConfirmDialog.java b/packages/VpnDialogs/src/com/android/vpndialogs/ConfirmDialog.java +index 48adb9ba3f63..f74cc2f93916 100644 +--- a/packages/VpnDialogs/src/com/android/vpndialogs/ConfirmDialog.java ++++ b/packages/VpnDialogs/src/com/android/vpndialogs/ConfirmDialog.java +@@ -43,10 +43,52 @@ public class ConfirmDialog extends AlertActivity + implements DialogInterface.OnClickListener, ImageGetter { + private static final String TAG = "VpnConfirm"; + ++ // Usually the label represents the app name, 150 code points might be enough to display the app ++ // name, and 150 code points won't cover the warning message from VpnDialog. ++ static final int MAX_VPN_LABEL_LENGTH = 150; ++ + private String mPackage; + + private IConnectivityManager mService; + ++ private View mView; ++ ++ /** ++ * This function will use the string resource to combine the VPN label and the package name. ++ * ++ * If the VPN label violates the length restriction, the first 30 code points of VPN label and ++ * the package name will be returned. Or return the VPN label and the package name directly if ++ * the VPN label doesn't violate the length restriction. ++ * ++ * The result will be something like, ++ * - ThisIsAVeryLongVpnAppNameWhich... (com.vpn.app) ++ * if the VPN label violates the length restriction. ++ * or ++ * - VpnLabelWith<br>HtmlTag (com.vpn.app) ++ * if the VPN label doesn't violate the length restriction. ++ * ++ */ ++ private String getSimplifiedLabel(String vpnLabel, String packageName) { ++ if (vpnLabel.codePointCount(0, vpnLabel.length()) > 30) { ++ return getString(R.string.sanitized_vpn_label_with_ellipsis, ++ vpnLabel.substring(0, vpnLabel.offsetByCodePoints(0, 30)), ++ packageName); ++ } ++ ++ return getString(R.string.sanitized_vpn_label, vpnLabel, packageName); ++ } ++ ++ protected String getSanitizedVpnLabel(String vpnLabel, String packageName) { ++ final String sanitizedVpnLabel = Html.escapeHtml(vpnLabel); ++ final boolean exceedMaxVpnLabelLength = sanitizedVpnLabel.codePointCount(0, ++ sanitizedVpnLabel.length()) > MAX_VPN_LABEL_LENGTH; ++ if (exceedMaxVpnLabelLength || !vpnLabel.equals(sanitizedVpnLabel)) { ++ return getSimplifiedLabel(sanitizedVpnLabel, packageName); ++ } ++ ++ return sanitizedVpnLabel; ++ } ++ + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); +@@ -69,15 +111,16 @@ public class ConfirmDialog extends AlertActivity + finish(); + return; + } +- View view = View.inflate(this, R.layout.confirm, null); +- ((TextView) view.findViewById(R.id.warning)).setText( +- Html.fromHtml(getString(R.string.warning, getVpnLabel()), +- this, null /* tagHandler */)); ++ mView = View.inflate(this, R.layout.confirm, null); ++ ((TextView) mView.findViewById(R.id.warning)).setText( ++ Html.fromHtml(getString(R.string.warning, getSanitizedVpnLabel( ++ getVpnLabel().toString(), mPackage)), ++ this /* imageGetter */, null /* tagHandler */)); + mAlertParams.mTitle = getText(R.string.prompt); + mAlertParams.mPositiveButtonText = getText(android.R.string.ok); + mAlertParams.mPositiveButtonListener = this; + mAlertParams.mNegativeButtonText = getText(android.R.string.cancel); +- mAlertParams.mView = view; ++ mAlertParams.mView = mView; + setupAlert(); + + getWindow().setCloseOnTouchOutside(false); diff --git a/Patches/LineageOS-17.1/android_frameworks_base/360954.patch b/Patches/LineageOS-17.1/android_frameworks_base/360954.patch new file mode 100644 index 00000000..ce50c48d --- /dev/null +++ b/Patches/LineageOS-17.1/android_frameworks_base/360954.patch @@ -0,0 +1,84 @@ +From 40c4c5abce61b881309acc19be8f483f419ca9a7 Mon Sep 17 00:00:00 2001 +From: Michael Groover +Date: Fri, 31 Mar 2023 21:31:22 +0000 +Subject: [PATCH] Limit the number of supported v1 and v2 signers + +The v1 and v2 APK Signature Schemes support multiple signers; this +was intended to allow multiple entities to sign an APK. Previously, +the platform had no limits placed on the number of signers supported +in an APK, but this commit sets a hard limit of 10 supported signers +for these signature schemes to ensure a large number of signers +does not place undue burden on the platform. + +Bug: 266580022 +Test: Manually verified the platform only allowed an APK with the + maximum number of supported signers. +(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:6f6ee8a55f37c2b8c0df041b2bd53ec928764597) +Merged-In: I6aa86b615b203cdc69d58a593ccf8f18474ca091 +Change-Id: I6aa86b615b203cdc69d58a593ccf8f18474ca091 +--- + .../util/apk/ApkSignatureSchemeV2Verifier.java | 10 ++++++++++ + core/java/android/util/jar/StrictJarVerifier.java | 11 +++++++++++ + 2 files changed, 21 insertions(+) + +diff --git a/core/java/android/util/apk/ApkSignatureSchemeV2Verifier.java b/core/java/android/util/apk/ApkSignatureSchemeV2Verifier.java +index 346fe293d7aee..f0c20bec7d7b6 100644 +--- a/core/java/android/util/apk/ApkSignatureSchemeV2Verifier.java ++++ b/core/java/android/util/apk/ApkSignatureSchemeV2Verifier.java +@@ -75,6 +75,11 @@ public class ApkSignatureSchemeV2Verifier { + + private static final int APK_SIGNATURE_SCHEME_V2_BLOCK_ID = 0x7109871a; + ++ /** ++ * The maximum number of signers supported by the v2 APK signature scheme. ++ */ ++ private static final int MAX_V2_SIGNERS = 10; ++ + /** + * Returns {@code true} if the provided APK contains an APK Signature Scheme V2 signature. + * +@@ -183,6 +188,11 @@ private static VerifiedSigner verify( + } + while (signers.hasRemaining()) { + signerCount++; ++ if (signerCount > MAX_V2_SIGNERS) { ++ throw new SecurityException( ++ "APK Signature Scheme v2 only supports a maximum of " + MAX_V2_SIGNERS ++ + " signers"); ++ } + try { + ByteBuffer signer = getLengthPrefixedSlice(signers); + X509Certificate[] certs = verifySigner(signer, contentDigests, certFactory); +diff --git a/core/java/android/util/jar/StrictJarVerifier.java b/core/java/android/util/jar/StrictJarVerifier.java +index 45254908c5c96..a6aca330d323e 100644 +--- a/core/java/android/util/jar/StrictJarVerifier.java ++++ b/core/java/android/util/jar/StrictJarVerifier.java +@@ -78,6 +78,11 @@ class StrictJarVerifier { + "SHA1", + }; + ++ /** ++ * The maximum number of signers supported by the JAR signature scheme. ++ */ ++ private static final int MAX_JAR_SIGNERS = 10; ++ + private final String jarName; + private final StrictJarManifest manifest; + private final HashMap metaEntries; +@@ -293,10 +298,16 @@ synchronized boolean readCertificates() { + return false; + } + ++ int signerCount = 0; + Iterator it = metaEntries.keySet().iterator(); + while (it.hasNext()) { + String key = it.next(); + if (key.endsWith(".DSA") || key.endsWith(".RSA") || key.endsWith(".EC")) { ++ if (++signerCount > MAX_JAR_SIGNERS) { ++ throw new SecurityException( ++ "APK Signature Scheme v1 only supports a maximum of " + MAX_JAR_SIGNERS ++ + " signers"); ++ } + verifyCertificate(key); + it.remove(); + } diff --git a/Patches/LineageOS-17.1/android_frameworks_base/360955.patch b/Patches/LineageOS-17.1/android_frameworks_base/360955.patch new file mode 100644 index 00000000..5235951f --- /dev/null +++ b/Patches/LineageOS-17.1/android_frameworks_base/360955.patch @@ -0,0 +1,1034 @@ +From d82d12e9a1b41102034236f4c607cfeb4d14cd10 Mon Sep 17 00:00:00 2001 +From: Bill Yi +Date: Tue, 4 Apr 2023 10:14:08 -0700 +Subject: [PATCH] Import translations. DO NOT MERGE ANYWHERE + +BUG:204554636 + +Auto-generated-cl: translation import +(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:2fe87df11e447755351c1934bcbae5f2f870950d) +Merged-In: I1720c67e4361d9019b12fa5a510cd34918dfedb4 +Change-Id: I1720c67e4361d9019b12fa5a510cd34918dfedb4 +--- + packages/VpnDialogs/res/values-af/strings.xml | 2 ++ + packages/VpnDialogs/res/values-am/strings.xml | 2 ++ + packages/VpnDialogs/res/values-ar/strings.xml | 2 ++ + packages/VpnDialogs/res/values-as/strings.xml | 2 ++ + packages/VpnDialogs/res/values-az/strings.xml | 2 ++ + packages/VpnDialogs/res/values-b+sr+Latn/strings.xml | 2 ++ + packages/VpnDialogs/res/values-be/strings.xml | 2 ++ + packages/VpnDialogs/res/values-bg/strings.xml | 2 ++ + packages/VpnDialogs/res/values-bn/strings.xml | 2 ++ + packages/VpnDialogs/res/values-bs/strings.xml | 2 ++ + packages/VpnDialogs/res/values-ca/strings.xml | 2 ++ + packages/VpnDialogs/res/values-cs/strings.xml | 2 ++ + packages/VpnDialogs/res/values-da/strings.xml | 2 ++ + packages/VpnDialogs/res/values-de/strings.xml | 2 ++ + packages/VpnDialogs/res/values-el/strings.xml | 2 ++ + packages/VpnDialogs/res/values-en-rAU/strings.xml | 2 ++ + packages/VpnDialogs/res/values-en-rCA/strings.xml | 2 ++ + packages/VpnDialogs/res/values-en-rGB/strings.xml | 2 ++ + packages/VpnDialogs/res/values-en-rIN/strings.xml | 2 ++ + packages/VpnDialogs/res/values-en-rXC/strings.xml | 2 ++ + packages/VpnDialogs/res/values-es-rUS/strings.xml | 2 ++ + packages/VpnDialogs/res/values-es/strings.xml | 2 ++ + packages/VpnDialogs/res/values-et/strings.xml | 2 ++ + packages/VpnDialogs/res/values-eu/strings.xml | 2 ++ + packages/VpnDialogs/res/values-fa/strings.xml | 2 ++ + packages/VpnDialogs/res/values-fi/strings.xml | 2 ++ + packages/VpnDialogs/res/values-fr-rCA/strings.xml | 2 ++ + packages/VpnDialogs/res/values-fr/strings.xml | 2 ++ + packages/VpnDialogs/res/values-gl/strings.xml | 2 ++ + packages/VpnDialogs/res/values-gu/strings.xml | 2 ++ + packages/VpnDialogs/res/values-hi/strings.xml | 2 ++ + packages/VpnDialogs/res/values-hr/strings.xml | 2 ++ + packages/VpnDialogs/res/values-hu/strings.xml | 2 ++ + packages/VpnDialogs/res/values-hy/strings.xml | 2 ++ + packages/VpnDialogs/res/values-in/strings.xml | 2 ++ + packages/VpnDialogs/res/values-is/strings.xml | 2 ++ + packages/VpnDialogs/res/values-it/strings.xml | 2 ++ + packages/VpnDialogs/res/values-iw/strings.xml | 2 ++ + packages/VpnDialogs/res/values-ja/strings.xml | 2 ++ + packages/VpnDialogs/res/values-ka/strings.xml | 2 ++ + packages/VpnDialogs/res/values-kk/strings.xml | 2 ++ + packages/VpnDialogs/res/values-km/strings.xml | 2 ++ + packages/VpnDialogs/res/values-kn/strings.xml | 2 ++ + packages/VpnDialogs/res/values-ko/strings.xml | 2 ++ + packages/VpnDialogs/res/values-ky/strings.xml | 2 ++ + packages/VpnDialogs/res/values-lo/strings.xml | 2 ++ + packages/VpnDialogs/res/values-lt/strings.xml | 2 ++ + packages/VpnDialogs/res/values-lv/strings.xml | 2 ++ + packages/VpnDialogs/res/values-mk/strings.xml | 2 ++ + packages/VpnDialogs/res/values-ml/strings.xml | 2 ++ + packages/VpnDialogs/res/values-mn/strings.xml | 2 ++ + packages/VpnDialogs/res/values-mr/strings.xml | 2 ++ + packages/VpnDialogs/res/values-ms/strings.xml | 2 ++ + packages/VpnDialogs/res/values-my/strings.xml | 2 ++ + packages/VpnDialogs/res/values-nb/strings.xml | 2 ++ + packages/VpnDialogs/res/values-ne/strings.xml | 2 ++ + packages/VpnDialogs/res/values-nl/strings.xml | 2 ++ + packages/VpnDialogs/res/values-or/strings.xml | 2 ++ + packages/VpnDialogs/res/values-pa/strings.xml | 2 ++ + packages/VpnDialogs/res/values-pl/strings.xml | 2 ++ + packages/VpnDialogs/res/values-pt-rBR/strings.xml | 2 ++ + packages/VpnDialogs/res/values-pt-rPT/strings.xml | 2 ++ + packages/VpnDialogs/res/values-pt/strings.xml | 2 ++ + packages/VpnDialogs/res/values-ro/strings.xml | 2 ++ + packages/VpnDialogs/res/values-ru/strings.xml | 2 ++ + packages/VpnDialogs/res/values-si/strings.xml | 2 ++ + packages/VpnDialogs/res/values-sk/strings.xml | 2 ++ + packages/VpnDialogs/res/values-sl/strings.xml | 2 ++ + packages/VpnDialogs/res/values-sq/strings.xml | 2 ++ + packages/VpnDialogs/res/values-sr/strings.xml | 2 ++ + packages/VpnDialogs/res/values-sv/strings.xml | 2 ++ + packages/VpnDialogs/res/values-sw/strings.xml | 2 ++ + packages/VpnDialogs/res/values-ta/strings.xml | 2 ++ + packages/VpnDialogs/res/values-te/strings.xml | 2 ++ + packages/VpnDialogs/res/values-th/strings.xml | 2 ++ + packages/VpnDialogs/res/values-tl/strings.xml | 2 ++ + packages/VpnDialogs/res/values-tr/strings.xml | 2 ++ + packages/VpnDialogs/res/values-uk/strings.xml | 2 ++ + packages/VpnDialogs/res/values-ur/strings.xml | 2 ++ + packages/VpnDialogs/res/values-uz/strings.xml | 2 ++ + packages/VpnDialogs/res/values-vi/strings.xml | 2 ++ + packages/VpnDialogs/res/values-zh-rCN/strings.xml | 2 ++ + packages/VpnDialogs/res/values-zh-rHK/strings.xml | 2 ++ + packages/VpnDialogs/res/values-zh-rTW/strings.xml | 2 ++ + packages/VpnDialogs/res/values-zu/strings.xml | 2 ++ + 85 files changed, 170 insertions(+) + +diff --git a/packages/VpnDialogs/res/values-af/strings.xml b/packages/VpnDialogs/res/values-af/strings.xml +index ac82b0e0009a1..b2718fd83e4fc 100644 +--- a/packages/VpnDialogs/res/values-af/strings.xml ++++ b/packages/VpnDialogs/res/values-af/strings.xml +@@ -33,4 +33,6 @@ + "Ontkoppel" + "Maak program oop" + "Maak toe" ++ "%1$s … ( %2$s)" ++ "%1$s ( %2$s)" + +diff --git a/packages/VpnDialogs/res/values-am/strings.xml b/packages/VpnDialogs/res/values-am/strings.xml +index ad9773b248a4e..91821fba203b2 100644 +--- a/packages/VpnDialogs/res/values-am/strings.xml ++++ b/packages/VpnDialogs/res/values-am/strings.xml +@@ -33,4 +33,6 @@ + "ግንኙነት አቋርጥ" + "መተግበሪያን ክፈት" + "አሰናብት" ++ "%1$s… ( %2$s)" ++ "%1$s ( %2$s)" + +diff --git a/packages/VpnDialogs/res/values-ar/strings.xml b/packages/VpnDialogs/res/values-ar/strings.xml +index 808cde906d2ff..20057c66750c4 100644 +--- a/packages/VpnDialogs/res/values-ar/strings.xml ++++ b/packages/VpnDialogs/res/values-ar/strings.xml +@@ -33,4 +33,6 @@ + "قطع الاتصال" + "فتح التطبيق" + "تجاهل" ++ "%1$s… ( %2$s)" ++ "%1$s ( %2$s)" + +diff --git a/packages/VpnDialogs/res/values-as/strings.xml b/packages/VpnDialogs/res/values-as/strings.xml +index 45d8458f4d45c..9d05505b1fa8d 100644 +--- a/packages/VpnDialogs/res/values-as/strings.xml ++++ b/packages/VpnDialogs/res/values-as/strings.xml +@@ -33,4 +33,6 @@ + "সংযোগ বিচ্ছিন্ন কৰক" + "এপ্ খোলক" + "অগ্ৰাহ্য কৰক" ++ "%1$s… ( %2$s)" ++ "%1$s ( %2$s)" + +diff --git a/packages/VpnDialogs/res/values-az/strings.xml b/packages/VpnDialogs/res/values-az/strings.xml +index 2bdf23ee2aa09..47cdeee180ed8 100644 +--- a/packages/VpnDialogs/res/values-az/strings.xml ++++ b/packages/VpnDialogs/res/values-az/strings.xml +@@ -33,4 +33,6 @@ + "Əlaqəni kəs" + "Tətbiqi açın" + "İmtina edin" ++ "%1$s… ( %2$s)" ++ "%1$s ( %2$s)" + +diff --git a/packages/VpnDialogs/res/values-b+sr+Latn/strings.xml b/packages/VpnDialogs/res/values-b+sr+Latn/strings.xml +index f40e40670bf39..ea8e60d36ba5d 100644 +--- a/packages/VpnDialogs/res/values-b+sr+Latn/strings.xml ++++ b/packages/VpnDialogs/res/values-b+sr+Latn/strings.xml +@@ -33,4 +33,6 @@ + "Prekini vezu" + "Otvori aplikaciju" + "Odbaci" ++ "%1$s… ( %2$s)" ++ "%1$s ( %2$s)" + +diff --git a/packages/VpnDialogs/res/values-be/strings.xml b/packages/VpnDialogs/res/values-be/strings.xml +index 0903c8ece36b3..914a1638b14a2 100644 +--- a/packages/VpnDialogs/res/values-be/strings.xml ++++ b/packages/VpnDialogs/res/values-be/strings.xml +@@ -33,4 +33,6 @@ + "Адключыцца" + "Адкрыць праграму" + "Адхіліць" ++ "%1$s… ( %2$s)" ++ "%1$s ( %2$s)" + +diff --git a/packages/VpnDialogs/res/values-bg/strings.xml b/packages/VpnDialogs/res/values-bg/strings.xml +index 9ac853d2016fd..e1aa242496de2 100644 +--- a/packages/VpnDialogs/res/values-bg/strings.xml ++++ b/packages/VpnDialogs/res/values-bg/strings.xml +@@ -33,4 +33,6 @@ + "Изключване" + "Към приложението" + "Отхвърляне" ++ "%1$s… (%2$s)" ++ "%1$s (%2$s)" + +diff --git a/packages/VpnDialogs/res/values-bn/strings.xml b/packages/VpnDialogs/res/values-bn/strings.xml +index 5e11fd9934b64..1b0fc48a9139f 100644 +--- a/packages/VpnDialogs/res/values-bn/strings.xml ++++ b/packages/VpnDialogs/res/values-bn/strings.xml +@@ -33,4 +33,6 @@ + "সংযোগ বিচ্ছিন্ন করুন" + "অ্যাপটি খুলুন" + "খারিজ করুন" ++ "%1$s… ( %2$s)" ++ "%1$s ( %2$s)" + +diff --git a/packages/VpnDialogs/res/values-bs/strings.xml b/packages/VpnDialogs/res/values-bs/strings.xml +index 56812d59e1068..c8537ca6de177 100644 +--- a/packages/VpnDialogs/res/values-bs/strings.xml ++++ b/packages/VpnDialogs/res/values-bs/strings.xml +@@ -33,4 +33,6 @@ + "Prekini vezu" + "Otvori aplikaciju" + "Odbaci" ++ "%1$s… ( %2$s)" ++ "%1$s ( %2$s)" + +diff --git a/packages/VpnDialogs/res/values-ca/strings.xml b/packages/VpnDialogs/res/values-ca/strings.xml +index 97738c316f4bd..1702e553f6e3b 100644 +--- a/packages/VpnDialogs/res/values-ca/strings.xml ++++ b/packages/VpnDialogs/res/values-ca/strings.xml +@@ -33,4 +33,6 @@ + "Desconnecta" + "Obre l\'aplicació" + "Ignora" ++ "%1$s… ( %2$s)" ++ "%1$s ( %2$s)" + +diff --git a/packages/VpnDialogs/res/values-cs/strings.xml b/packages/VpnDialogs/res/values-cs/strings.xml +index 5cc809c7cb027..909cd2982b278 100644 +--- a/packages/VpnDialogs/res/values-cs/strings.xml ++++ b/packages/VpnDialogs/res/values-cs/strings.xml +@@ -33,4 +33,6 @@ + "Odpojit" + "Do aplikace" + "Zavřít" ++ "%1$s… ( %2$s)" ++ "%1$s (%2$s)" + +diff --git a/packages/VpnDialogs/res/values-da/strings.xml b/packages/VpnDialogs/res/values-da/strings.xml +index 7641158af3da6..f8985bd263f3b 100644 +--- a/packages/VpnDialogs/res/values-da/strings.xml ++++ b/packages/VpnDialogs/res/values-da/strings.xml +@@ -33,4 +33,6 @@ + "Fjern tilknytning" + "Åbn app" + "Luk" ++ "%1$s… ( %2$s)" ++ "%1$s ( %2$s)" + +diff --git a/packages/VpnDialogs/res/values-de/strings.xml b/packages/VpnDialogs/res/values-de/strings.xml +index 0f1e009804394..d757363157679 100644 +--- a/packages/VpnDialogs/res/values-de/strings.xml ++++ b/packages/VpnDialogs/res/values-de/strings.xml +@@ -33,4 +33,6 @@ + "Verbindung trennen" + "App öffnen" + "Schließen" ++ "%1$s… (%2$s)" ++ "%1$s (%2$s)" + +diff --git a/packages/VpnDialogs/res/values-el/strings.xml b/packages/VpnDialogs/res/values-el/strings.xml +index 78bcc43ff6099..13df0dda440d7 100644 +--- a/packages/VpnDialogs/res/values-el/strings.xml ++++ b/packages/VpnDialogs/res/values-el/strings.xml +@@ -33,4 +33,6 @@ + "Αποσύνδεση" + "Άνοιγμα εφαρμογής" + "Παράβλεψη" ++ "%1$s… ( %2$s)" ++ "%1$s ( %2$s)" + +diff --git a/packages/VpnDialogs/res/values-en-rAU/strings.xml b/packages/VpnDialogs/res/values-en-rAU/strings.xml +index 6ed50a7668ae4..0fb49a1ad7e72 100644 +--- a/packages/VpnDialogs/res/values-en-rAU/strings.xml ++++ b/packages/VpnDialogs/res/values-en-rAU/strings.xml +@@ -33,4 +33,6 @@ + "Disconnect" + "Open app" + "Dismiss" ++ "%1$s… ( %2$s)" ++ "%1$s ( %2$s)" + +diff --git a/packages/VpnDialogs/res/values-en-rCA/strings.xml b/packages/VpnDialogs/res/values-en-rCA/strings.xml +index 6ed50a7668ae4..0fb49a1ad7e72 100644 +--- a/packages/VpnDialogs/res/values-en-rCA/strings.xml ++++ b/packages/VpnDialogs/res/values-en-rCA/strings.xml +@@ -33,4 +33,6 @@ + "Disconnect" + "Open app" + "Dismiss" ++ "%1$s… ( %2$s)" ++ "%1$s ( %2$s)" + +diff --git a/packages/VpnDialogs/res/values-en-rGB/strings.xml b/packages/VpnDialogs/res/values-en-rGB/strings.xml +index 6ed50a7668ae4..0fb49a1ad7e72 100644 +--- a/packages/VpnDialogs/res/values-en-rGB/strings.xml ++++ b/packages/VpnDialogs/res/values-en-rGB/strings.xml +@@ -33,4 +33,6 @@ + "Disconnect" + "Open app" + "Dismiss" ++ "%1$s… ( %2$s)" ++ "%1$s ( %2$s)" + +diff --git a/packages/VpnDialogs/res/values-en-rIN/strings.xml b/packages/VpnDialogs/res/values-en-rIN/strings.xml +index 6ed50a7668ae4..0fb49a1ad7e72 100644 +--- a/packages/VpnDialogs/res/values-en-rIN/strings.xml ++++ b/packages/VpnDialogs/res/values-en-rIN/strings.xml +@@ -33,4 +33,6 @@ + "Disconnect" + "Open app" + "Dismiss" ++ "%1$s… ( %2$s)" ++ "%1$s ( %2$s)" + +diff --git a/packages/VpnDialogs/res/values-en-rXC/strings.xml b/packages/VpnDialogs/res/values-en-rXC/strings.xml +index 9d010e63518f9..2fb8403a69203 100644 +--- a/packages/VpnDialogs/res/values-en-rXC/strings.xml ++++ b/packages/VpnDialogs/res/values-en-rXC/strings.xml +@@ -33,4 +33,6 @@ + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‎‏‎‏‏‏‏‎‏‏‎‎‏‎‎‏‏‎‎‏‎‏‏‏‏‏‏‏‏‏‏‎‏‏‎‎‎‎‏‏‎‏‏‎‏‎‏‏‎‏‎‏‏‏‏‎‎‎‎Disconnect‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‏‏‏‎‎‏‎‏‏‏‏‎‏‏‎‏‎‏‎‎‏‎‎‎‏‎‏‏‎‏‎‎‏‏‎‏‎‎‏‎‎‏‎‏‏‏‏‏‏‏‏‎‎‎‏‎‏‏‎Open app‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‎‏‏‏‏‏‎‎‎‏‎‏‏‏‎‏‎‎‏‏‎‎‎‎‎‎‏‎‏‏‏‏‎‏‎‎‎‎‎‎‏‎‎‎‎‎‎‎‏‏‎‎‏‏‏‎‏‏‎Dismiss‎‏‎‎‏‎" ++ "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‎‎‏‎‏‎‏‎‏‏‏‏‏‏‎‎‏‎‏‏‎‏‎‏‏‎‎‏‎‏‏‎‏‏‏‏‏‎‎‏‎‎‏‏‎‏‏‎‏‎‏‏‎‎‏‏‎‏‏‎‎‏‎‎‏‏‎%1$s‎‏‎‎‏‏‏‎… ( ‎‏‎‎‏‏‎%2$s‎‏‎‎‏‏‏‎)‎‏‎‎‏‎" ++ "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‏‎‎‎‎‎‏‏‎‏‏‏‏‎‏‎‏‏‎‎‎‎‎‎‏‎‎‏‎‏‏‎‎‏‏‎‏‎‎‏‎‎‏‎‏‏‏‎‏‎‏‏‎‎‏‏‏‎‎‎‏‎‎‏‏‎%1$s‎‏‎‎‏‏‏‎ ( ‎‏‎‎‏‏‎%2$s‎‏‎‎‏‏‏‎)‎‏‎‎‏‎" + +diff --git a/packages/VpnDialogs/res/values-es-rUS/strings.xml b/packages/VpnDialogs/res/values-es-rUS/strings.xml +index 21cfc042e707f..4917d6158bba9 100644 +--- a/packages/VpnDialogs/res/values-es-rUS/strings.xml ++++ b/packages/VpnDialogs/res/values-es-rUS/strings.xml +@@ -33,4 +33,6 @@ + "Desconectar" + "Abrir app" + "Descartar" ++ "%1$s… ( %2$s)" ++ "%1$s ( %2$s)" + +diff --git a/packages/VpnDialogs/res/values-es/strings.xml b/packages/VpnDialogs/res/values-es/strings.xml +index 372147f2479a0..6efb545a97eda 100644 +--- a/packages/VpnDialogs/res/values-es/strings.xml ++++ b/packages/VpnDialogs/res/values-es/strings.xml +@@ -33,4 +33,6 @@ + "Desconectar" + "Abrir aplicación" + "Cerrar" ++ "%1$s… ( %2$s)" ++ "%1$s ( %2$s)" + +diff --git a/packages/VpnDialogs/res/values-et/strings.xml b/packages/VpnDialogs/res/values-et/strings.xml +index c328cd725396e..b15c130f0d702 100644 +--- a/packages/VpnDialogs/res/values-et/strings.xml ++++ b/packages/VpnDialogs/res/values-et/strings.xml +@@ -33,4 +33,6 @@ + "Katkesta ühendus" + "Ava rakendus" + "Loobu" ++ "%1$s… ( %2$s)" ++ "%1$s ( %2$s)" + +diff --git a/packages/VpnDialogs/res/values-eu/strings.xml b/packages/VpnDialogs/res/values-eu/strings.xml +index a3b7716e91d33..a07237366c292 100644 +--- a/packages/VpnDialogs/res/values-eu/strings.xml ++++ b/packages/VpnDialogs/res/values-eu/strings.xml +@@ -33,4 +33,6 @@ + "Deskonektatu" + "Ireki aplikazioa" + "Baztertu" ++ "%1$s… (%2$s)" ++ "%1$s (%2$s)" + +diff --git a/packages/VpnDialogs/res/values-fa/strings.xml b/packages/VpnDialogs/res/values-fa/strings.xml +index 56f847c158279..30e7493141c68 100644 +--- a/packages/VpnDialogs/res/values-fa/strings.xml ++++ b/packages/VpnDialogs/res/values-fa/strings.xml +@@ -33,4 +33,6 @@ + "قطع اتصال" + "باز کردن برنامه" + "رد کردن" ++ "%1$s… ( %2$s)" ++ "%1$s ( %2$s)" + +diff --git a/packages/VpnDialogs/res/values-fi/strings.xml b/packages/VpnDialogs/res/values-fi/strings.xml +index 91c918af09c3f..40d4a9feb4a10 100644 +--- a/packages/VpnDialogs/res/values-fi/strings.xml ++++ b/packages/VpnDialogs/res/values-fi/strings.xml +@@ -33,4 +33,6 @@ + "Katkaise yhteys" + "Avaa sovellus" + "Hylkää" ++ "%1$s… (%2$s)" ++ "%1$s (%2$s)" + +diff --git a/packages/VpnDialogs/res/values-fr-rCA/strings.xml b/packages/VpnDialogs/res/values-fr-rCA/strings.xml +index aa86c7ca8a7f1..2bcf6b2ed382e 100644 +--- a/packages/VpnDialogs/res/values-fr-rCA/strings.xml ++++ b/packages/VpnDialogs/res/values-fr-rCA/strings.xml +@@ -33,4 +33,6 @@ + "Déconnecter" + "Ouvrir l\'application" + "Ignorer" ++ "%1$s… ( %2$s)" ++ "%1$s ( %2$s)" + +diff --git a/packages/VpnDialogs/res/values-fr/strings.xml b/packages/VpnDialogs/res/values-fr/strings.xml +index 71801197ddf26..820c8f98c8065 100644 +--- a/packages/VpnDialogs/res/values-fr/strings.xml ++++ b/packages/VpnDialogs/res/values-fr/strings.xml +@@ -33,4 +33,6 @@ + "Déconnecter" + "Ouvrir l\'application" + "Ignorer" ++ "%1$s… (%2$s)" ++ "%1$s (%2$s)" + +diff --git a/packages/VpnDialogs/res/values-gl/strings.xml b/packages/VpnDialogs/res/values-gl/strings.xml +index 8a66d081a71be..765e7f7336e23 100644 +--- a/packages/VpnDialogs/res/values-gl/strings.xml ++++ b/packages/VpnDialogs/res/values-gl/strings.xml +@@ -33,4 +33,6 @@ + "Desconectar" + "Abrir aplicación" + "Ignorar" ++ "%1$s… (%2$s)" ++ "%1$s (%2$s)" + +diff --git a/packages/VpnDialogs/res/values-gu/strings.xml b/packages/VpnDialogs/res/values-gu/strings.xml +index 961711c57c3de..6faeb8758d0b4 100644 +--- a/packages/VpnDialogs/res/values-gu/strings.xml ++++ b/packages/VpnDialogs/res/values-gu/strings.xml +@@ -33,4 +33,6 @@ + "ડિસ્કનેક્ટ કરો" + "ઍપ ખોલો" + "છોડી દો" ++ "%1$s… ( %2$s)" ++ "%1$s ( %2$s)" + +diff --git a/packages/VpnDialogs/res/values-hi/strings.xml b/packages/VpnDialogs/res/values-hi/strings.xml +index eed0858787d9e..80914cf5ee15d 100644 +--- a/packages/VpnDialogs/res/values-hi/strings.xml ++++ b/packages/VpnDialogs/res/values-hi/strings.xml +@@ -33,4 +33,6 @@ + "डिसकनेक्ट करें" + "ऐप खोलें" + "खारिज करें" ++ "%1$s… ( %2$s)" ++ "%1$s ( %2$s)" + +diff --git a/packages/VpnDialogs/res/values-hr/strings.xml b/packages/VpnDialogs/res/values-hr/strings.xml +index aa9e436f56e72..7d68f0ab4f44b 100644 +--- a/packages/VpnDialogs/res/values-hr/strings.xml ++++ b/packages/VpnDialogs/res/values-hr/strings.xml +@@ -33,4 +33,6 @@ + "Prekini vezu" + "Otvori aplikaciju" + "Odbaci" ++ "%1$s… (%2$s)" ++ "%1$s (%2$s)" + +diff --git a/packages/VpnDialogs/res/values-hu/strings.xml b/packages/VpnDialogs/res/values-hu/strings.xml +index 703aa792f3c33..97d3946418b45 100644 +--- a/packages/VpnDialogs/res/values-hu/strings.xml ++++ b/packages/VpnDialogs/res/values-hu/strings.xml +@@ -33,4 +33,6 @@ + "Kapcsolat bontása" + "Alkalmazás indítása" + "Bezárás" ++ "%1$s… ( %2$s)" ++ "%1$s ( %2$s)" + +diff --git a/packages/VpnDialogs/res/values-hy/strings.xml b/packages/VpnDialogs/res/values-hy/strings.xml +index c296c85472830..84eace72bb3c5 100644 +--- a/packages/VpnDialogs/res/values-hy/strings.xml ++++ b/packages/VpnDialogs/res/values-hy/strings.xml +@@ -33,4 +33,6 @@ + "Անջատել" + "Բացել հավելվածը" + "Փակել" ++ "%1$s… ( %2$s)" ++ "%1$s ( %2$s)" + +diff --git a/packages/VpnDialogs/res/values-in/strings.xml b/packages/VpnDialogs/res/values-in/strings.xml +index 18ef372a8cda0..1782b696805bd 100644 +--- a/packages/VpnDialogs/res/values-in/strings.xml ++++ b/packages/VpnDialogs/res/values-in/strings.xml +@@ -33,4 +33,6 @@ + "Putuskan sambungan" + "Buka aplikasi" + "Tutup" ++ "%1$s… ( %2$s)" ++ "%1$s ( %2$s)" + +diff --git a/packages/VpnDialogs/res/values-is/strings.xml b/packages/VpnDialogs/res/values-is/strings.xml +index 70fb40fc467ca..af87d13e7aaf6 100644 +--- a/packages/VpnDialogs/res/values-is/strings.xml ++++ b/packages/VpnDialogs/res/values-is/strings.xml +@@ -33,4 +33,6 @@ + "Aftengja" + "Opna forrit" + "Hunsa" ++ "%1$s… ( %2$s)" ++ "%1$s ( %2$s)" + +diff --git a/packages/VpnDialogs/res/values-it/strings.xml b/packages/VpnDialogs/res/values-it/strings.xml +index 2602493faf002..5689acbea102a 100644 +--- a/packages/VpnDialogs/res/values-it/strings.xml ++++ b/packages/VpnDialogs/res/values-it/strings.xml +@@ -33,4 +33,6 @@ + "Disconnetti" + "Apri app" + "Ignora" ++ "%1$s… (%2$s)" ++ "%1$s (%2$s)" + +diff --git a/packages/VpnDialogs/res/values-iw/strings.xml b/packages/VpnDialogs/res/values-iw/strings.xml +index ebabd4e71aef5..12cfc323e9655 100644 +--- a/packages/VpnDialogs/res/values-iw/strings.xml ++++ b/packages/VpnDialogs/res/values-iw/strings.xml +@@ -33,4 +33,6 @@ + "נתק" + "לאפליקציה" + "סגירה" ++ "%1$s… ( %2$s)" ++ "%1$s ( %2$s)" + +diff --git a/packages/VpnDialogs/res/values-ja/strings.xml b/packages/VpnDialogs/res/values-ja/strings.xml +index 8480692e9dd36..32898a3a1ce22 100644 +--- a/packages/VpnDialogs/res/values-ja/strings.xml ++++ b/packages/VpnDialogs/res/values-ja/strings.xml +@@ -33,4 +33,6 @@ + "切断" + "アプリを開く" + "閉じる" ++ "%1$s…(%2$s)" ++ "%1$s%2$s)" + +diff --git a/packages/VpnDialogs/res/values-ka/strings.xml b/packages/VpnDialogs/res/values-ka/strings.xml +index e5a07532c32e3..0cc59d21a1da4 100644 +--- a/packages/VpnDialogs/res/values-ka/strings.xml ++++ b/packages/VpnDialogs/res/values-ka/strings.xml +@@ -33,4 +33,6 @@ + "კავშირის გაწყვეტა" + "გახსენით აპი" + "დახურვა" ++ "%1$s… ( %2$s)" ++ "%1$s ( %2$s)" + +diff --git a/packages/VpnDialogs/res/values-kk/strings.xml b/packages/VpnDialogs/res/values-kk/strings.xml +index 79f79c34e1b40..d702f3f4a4246 100644 +--- a/packages/VpnDialogs/res/values-kk/strings.xml ++++ b/packages/VpnDialogs/res/values-kk/strings.xml +@@ -33,4 +33,6 @@ + "Ажырату" + "Қолданбаны ашу" + "Жабу" ++ "%1$s… ( %2$s)" ++ "%1$s ( %2$s)" + +diff --git a/packages/VpnDialogs/res/values-km/strings.xml b/packages/VpnDialogs/res/values-km/strings.xml +index 06f34dbf27331..60627104f3f4b 100644 +--- a/packages/VpnDialogs/res/values-km/strings.xml ++++ b/packages/VpnDialogs/res/values-km/strings.xml +@@ -33,4 +33,6 @@ + "ផ្ដាច់" + "បើកកម្មវិធី" + "បដិសេធ" ++ "%1$s… ( %2$s)" ++ "%1$s ( %2$s)" + +diff --git a/packages/VpnDialogs/res/values-kn/strings.xml b/packages/VpnDialogs/res/values-kn/strings.xml +index 040cd6c5aeda2..254d64de3bdf9 100644 +--- a/packages/VpnDialogs/res/values-kn/strings.xml ++++ b/packages/VpnDialogs/res/values-kn/strings.xml +@@ -33,4 +33,6 @@ + "ಸಂಪರ್ಕ ಕಡಿತಗೊಳಿಸು" + "ಅಪ್ಲಿಕೇಶನ್ ತೆರೆಯಿರಿ" + "ವಜಾಗೊಳಿಸಿ" ++ "%1$s… ( %2$s)" ++ "%1$s ( %2$s)" + +diff --git a/packages/VpnDialogs/res/values-ko/strings.xml b/packages/VpnDialogs/res/values-ko/strings.xml +index 6ad497680ae79..d2281938176ac 100644 +--- a/packages/VpnDialogs/res/values-ko/strings.xml ++++ b/packages/VpnDialogs/res/values-ko/strings.xml +@@ -33,4 +33,6 @@ + "연결 끊기" + "앱 열기" + "닫기" ++ "%1$s…(%2$s)" ++ "%1$s(%2$s)" + +diff --git a/packages/VpnDialogs/res/values-ky/strings.xml b/packages/VpnDialogs/res/values-ky/strings.xml +index 4e2f698bb1e53..4521766745712 100644 +--- a/packages/VpnDialogs/res/values-ky/strings.xml ++++ b/packages/VpnDialogs/res/values-ky/strings.xml +@@ -33,4 +33,6 @@ + "Ажыратуу" + "Колдонмону ачуу" + "Четке кагуу" ++ "%1$s… ( %2$s)" ++ "%1$s ( %2$s)" + +diff --git a/packages/VpnDialogs/res/values-lo/strings.xml b/packages/VpnDialogs/res/values-lo/strings.xml +index c591308480c16..1b851e127abd4 100644 +--- a/packages/VpnDialogs/res/values-lo/strings.xml ++++ b/packages/VpnDialogs/res/values-lo/strings.xml +@@ -33,4 +33,6 @@ + "ຕັດການເຊື່ອມຕໍ່" + "ເປີດແອັບ" + "ປິດໄວ້" ++ "%1$s… ( %2$s)" ++ "%1$s ( %2$s)" + +diff --git a/packages/VpnDialogs/res/values-lt/strings.xml b/packages/VpnDialogs/res/values-lt/strings.xml +index 8846310730ce5..e8e20a8d218d9 100644 +--- a/packages/VpnDialogs/res/values-lt/strings.xml ++++ b/packages/VpnDialogs/res/values-lt/strings.xml +@@ -33,4 +33,6 @@ + "Atsijungti" + "Atidaryti programą" + "Atsisakyti" ++ "%1$s… (%2$s)" ++ "%1$s (%2$s)" + +diff --git a/packages/VpnDialogs/res/values-lv/strings.xml b/packages/VpnDialogs/res/values-lv/strings.xml +index 07625b6173c68..af19f4dce065b 100644 +--- a/packages/VpnDialogs/res/values-lv/strings.xml ++++ b/packages/VpnDialogs/res/values-lv/strings.xml +@@ -33,4 +33,6 @@ + "Pārtraukt savienojumu" + "Atvērt lietotni" + "Nerādīt" ++ "%1$s… ( %2$s)" ++ "%1$s ( %2$s)" + +diff --git a/packages/VpnDialogs/res/values-mk/strings.xml b/packages/VpnDialogs/res/values-mk/strings.xml +index b5a64f2130666..4db7e4a502418 100644 +--- a/packages/VpnDialogs/res/values-mk/strings.xml ++++ b/packages/VpnDialogs/res/values-mk/strings.xml +@@ -33,4 +33,6 @@ + "Исклучи" + "Отвори ја апликацијата" + "Отфрли" ++ "%1$s… ( %2$s)" ++ "%1$s ( %2$s)" + +diff --git a/packages/VpnDialogs/res/values-ml/strings.xml b/packages/VpnDialogs/res/values-ml/strings.xml +index 680d0ef539b7a..9d3bba43f84ce 100644 +--- a/packages/VpnDialogs/res/values-ml/strings.xml ++++ b/packages/VpnDialogs/res/values-ml/strings.xml +@@ -33,4 +33,6 @@ + "വിച്ഛേദിക്കുക" + "ആപ്പ് തുറക്കുക" + "നിരസിക്കുക" ++ "%1$s… ( %2$s)" ++ "%1$s ( %2$s)" + +diff --git a/packages/VpnDialogs/res/values-mn/strings.xml b/packages/VpnDialogs/res/values-mn/strings.xml +index 9aa104aff5ab6..15f56b155053a 100644 +--- a/packages/VpnDialogs/res/values-mn/strings.xml ++++ b/packages/VpnDialogs/res/values-mn/strings.xml +@@ -33,4 +33,6 @@ + "Салгах" + "Апп нээх" + "Хаах" ++ "%1$s… ( %2$s)" ++ "%1$s ( %2$s)" + +diff --git a/packages/VpnDialogs/res/values-mr/strings.xml b/packages/VpnDialogs/res/values-mr/strings.xml +index 41d74290815da..99c7f44c9d5f0 100644 +--- a/packages/VpnDialogs/res/values-mr/strings.xml ++++ b/packages/VpnDialogs/res/values-mr/strings.xml +@@ -33,4 +33,6 @@ + "‍डिस्कनेक्ट करा" + "अ‍ॅप उघडा" + "डिसमिस करा" ++ "%1$s… ( %2$s)" ++ "%1$s ( %2$s)" + +diff --git a/packages/VpnDialogs/res/values-ms/strings.xml b/packages/VpnDialogs/res/values-ms/strings.xml +index b489f2edabc0a..a7de3f1663036 100644 +--- a/packages/VpnDialogs/res/values-ms/strings.xml ++++ b/packages/VpnDialogs/res/values-ms/strings.xml +@@ -33,4 +33,6 @@ + "Putuskan sambungan" + "Buka apl" + "Ketepikan" ++ "%1$s… ( %2$s)" ++ "%1$s ( %2$s)" + +diff --git a/packages/VpnDialogs/res/values-my/strings.xml b/packages/VpnDialogs/res/values-my/strings.xml +index 9d60ff42a7cdd..52675b6092ac7 100644 +--- a/packages/VpnDialogs/res/values-my/strings.xml ++++ b/packages/VpnDialogs/res/values-my/strings.xml +@@ -33,4 +33,6 @@ + "ချိတ်ဆက်ခြင်းရပ်ရန်" + "အက်ပ်ကို ဖွင့်ရန်" + "ပယ်ရန်" ++ "%1$s… ( %2$s)" ++ "%1$s ( %2$s)" + +diff --git a/packages/VpnDialogs/res/values-nb/strings.xml b/packages/VpnDialogs/res/values-nb/strings.xml +index be572d4408f87..bad15e913938c 100644 +--- a/packages/VpnDialogs/res/values-nb/strings.xml ++++ b/packages/VpnDialogs/res/values-nb/strings.xml +@@ -33,4 +33,6 @@ + "Koble fra" + "Åpne appen" + "Lukk" ++ "%1$s… ( %2$s)" ++ "%1$s ( %2$s)" + +diff --git a/packages/VpnDialogs/res/values-ne/strings.xml b/packages/VpnDialogs/res/values-ne/strings.xml +index b716c35cfad42..ac21dd1713d16 100644 +--- a/packages/VpnDialogs/res/values-ne/strings.xml ++++ b/packages/VpnDialogs/res/values-ne/strings.xml +@@ -33,4 +33,6 @@ + "विच्छेदन गर्नुहोस्" + "अनुप्रयोग खोल्नुहोस्" + "खारेज गर्नुहोस्" ++ "%1$s… ( %2$s)" ++ "%1$s ( %2$s)" + +diff --git a/packages/VpnDialogs/res/values-nl/strings.xml b/packages/VpnDialogs/res/values-nl/strings.xml +index 8073b09e203ce..ab77d5e9f2187 100644 +--- a/packages/VpnDialogs/res/values-nl/strings.xml ++++ b/packages/VpnDialogs/res/values-nl/strings.xml +@@ -33,4 +33,6 @@ + "Verbinding verbreken" + "App openen" + "Sluiten" ++ "%1$s… (%2$s)" ++ "%1$s (%2$s)" + +diff --git a/packages/VpnDialogs/res/values-or/strings.xml b/packages/VpnDialogs/res/values-or/strings.xml +index f1122ebd43865..40ad247433deb 100644 +--- a/packages/VpnDialogs/res/values-or/strings.xml ++++ b/packages/VpnDialogs/res/values-or/strings.xml +@@ -33,4 +33,6 @@ + "ବିଚ୍ଛିନ୍ନ କରନ୍ତୁ" + "ଆପ୍‌ ଖୋଲନ୍ତୁ" + "ଖାରଜ କରନ୍ତୁ" ++ "%1$s… ( %2$s)" ++ "%1$s ( %2$s)" + +diff --git a/packages/VpnDialogs/res/values-pa/strings.xml b/packages/VpnDialogs/res/values-pa/strings.xml +index 1815f4fb0d253..a3b6e04061c1a 100644 +--- a/packages/VpnDialogs/res/values-pa/strings.xml ++++ b/packages/VpnDialogs/res/values-pa/strings.xml +@@ -33,4 +33,6 @@ + "ਡਿਸਕਨੈਕਟ ਕਰੋ" + "ਐਪ ਖੋਲ੍ਹੋ" + "ਖਾਰਜ ਕਰੋ" ++ "%1$s… ( %2$s)" ++ "%1$s ( %2$s)" + +diff --git a/packages/VpnDialogs/res/values-pl/strings.xml b/packages/VpnDialogs/res/values-pl/strings.xml +index d5201d7fbdf54..3af093ae9841d 100644 +--- a/packages/VpnDialogs/res/values-pl/strings.xml ++++ b/packages/VpnDialogs/res/values-pl/strings.xml +@@ -33,4 +33,6 @@ + "Rozłącz" + "Otwórz aplikację" + "Zamknij" ++ "%1$s… (%2$s)" ++ "%1$s (%2$s)" + +diff --git a/packages/VpnDialogs/res/values-pt-rBR/strings.xml b/packages/VpnDialogs/res/values-pt-rBR/strings.xml +index 75c140617cf58..8c1ae840aa15f 100644 +--- a/packages/VpnDialogs/res/values-pt-rBR/strings.xml ++++ b/packages/VpnDialogs/res/values-pt-rBR/strings.xml +@@ -33,4 +33,6 @@ + "Desconectar" + "Abrir app" + "Dispensar" ++ "%1$s… (%2$s)" ++ "%1$s (%2$s)" + +diff --git a/packages/VpnDialogs/res/values-pt-rPT/strings.xml b/packages/VpnDialogs/res/values-pt-rPT/strings.xml +index 01beddbab4e4d..34980dc309169 100644 +--- a/packages/VpnDialogs/res/values-pt-rPT/strings.xml ++++ b/packages/VpnDialogs/res/values-pt-rPT/strings.xml +@@ -33,4 +33,6 @@ + "Desligar" + "Abrir aplicação" + "Ignorar" ++ "%1$s… ( %2$s)" ++ "%1$s ( %2$s)" + +diff --git a/packages/VpnDialogs/res/values-pt/strings.xml b/packages/VpnDialogs/res/values-pt/strings.xml +index 75c140617cf58..8c1ae840aa15f 100644 +--- a/packages/VpnDialogs/res/values-pt/strings.xml ++++ b/packages/VpnDialogs/res/values-pt/strings.xml +@@ -33,4 +33,6 @@ + "Desconectar" + "Abrir app" + "Dispensar" ++ "%1$s… (%2$s)" ++ "%1$s (%2$s)" + +diff --git a/packages/VpnDialogs/res/values-ro/strings.xml b/packages/VpnDialogs/res/values-ro/strings.xml +index 4e60df2eca8e8..11137cce96b53 100644 +--- a/packages/VpnDialogs/res/values-ro/strings.xml ++++ b/packages/VpnDialogs/res/values-ro/strings.xml +@@ -33,4 +33,6 @@ + "Deconectați" + "Deschideți aplicația" + "Închideți" ++ "%1$s… (%2$s)" ++ "%1$s (%2$s)" + +diff --git a/packages/VpnDialogs/res/values-ru/strings.xml b/packages/VpnDialogs/res/values-ru/strings.xml +index f8fcfb83aa9a6..84a71d25cc160 100644 +--- a/packages/VpnDialogs/res/values-ru/strings.xml ++++ b/packages/VpnDialogs/res/values-ru/strings.xml +@@ -33,4 +33,6 @@ + "Разъединить" + "Открыть приложение" + "Закрыть" ++ "%1$s… (%2$s)" ++ "%1$s (%2$s)" + +diff --git a/packages/VpnDialogs/res/values-si/strings.xml b/packages/VpnDialogs/res/values-si/strings.xml +index bb97a5d86c5fa..e1dbf97748397 100644 +--- a/packages/VpnDialogs/res/values-si/strings.xml ++++ b/packages/VpnDialogs/res/values-si/strings.xml +@@ -33,4 +33,6 @@ + "විසන්ධි කරන්න" + "යෙදුම විවෘත කරන්න" + "ඉවතලන්න" ++ "%1$s… ( %2$s)" ++ "%1$s ( %2$s)" + +diff --git a/packages/VpnDialogs/res/values-sk/strings.xml b/packages/VpnDialogs/res/values-sk/strings.xml +index a08117adfac1e..ded28aeba8a51 100644 +--- a/packages/VpnDialogs/res/values-sk/strings.xml ++++ b/packages/VpnDialogs/res/values-sk/strings.xml +@@ -33,4 +33,6 @@ + "Odpojiť" + "Otvoriť aplikáciu" + "Zavrieť" ++ "%1$s… ( %2$s" ++ "%1$s ( %2$s)" + +diff --git a/packages/VpnDialogs/res/values-sl/strings.xml b/packages/VpnDialogs/res/values-sl/strings.xml +index d5014fa343945..62bdd03cbe67e 100644 +--- a/packages/VpnDialogs/res/values-sl/strings.xml ++++ b/packages/VpnDialogs/res/values-sl/strings.xml +@@ -33,4 +33,6 @@ + "Prekini povezavo" + "Odpri aplikacijo" + "Opusti" ++ "%1$s … (%2$s)" ++ "%1$s (%2$s)" + +diff --git a/packages/VpnDialogs/res/values-sq/strings.xml b/packages/VpnDialogs/res/values-sq/strings.xml +index 4a96e7b92212d..50ad7cf02c8e6 100644 +--- a/packages/VpnDialogs/res/values-sq/strings.xml ++++ b/packages/VpnDialogs/res/values-sq/strings.xml +@@ -33,4 +33,6 @@ + "Shkëputu" + "Hap aplikacionin" + "Largoje" ++ "%1$s… ( %2$s)" ++ "%1$s ( %2$s)" + +diff --git a/packages/VpnDialogs/res/values-sr/strings.xml b/packages/VpnDialogs/res/values-sr/strings.xml +index 8ce8060e333dd..3bc65413b7289 100644 +--- a/packages/VpnDialogs/res/values-sr/strings.xml ++++ b/packages/VpnDialogs/res/values-sr/strings.xml +@@ -33,4 +33,6 @@ + "Прекини везу" + "Отвори апликацију" + "Одбаци" ++ "%1$s… ( %2$s)" ++ "%1$s ( %2$s)" + +diff --git a/packages/VpnDialogs/res/values-sv/strings.xml b/packages/VpnDialogs/res/values-sv/strings.xml +index 16b6a31d7d1ad..fee6f971824d3 100644 +--- a/packages/VpnDialogs/res/values-sv/strings.xml ++++ b/packages/VpnDialogs/res/values-sv/strings.xml +@@ -33,4 +33,6 @@ + "Koppla från" + "Öppna appen" + "Ignorera" ++ "%1$s… (%2$s)" ++ "%1$s (%2$s)" + +diff --git a/packages/VpnDialogs/res/values-sw/strings.xml b/packages/VpnDialogs/res/values-sw/strings.xml +index ea2688438b7ac..3e696f20fabe8 100644 +--- a/packages/VpnDialogs/res/values-sw/strings.xml ++++ b/packages/VpnDialogs/res/values-sw/strings.xml +@@ -33,4 +33,6 @@ + "Tenganisha" + "Fungua programu" + "Ondoa" ++ "%1$s… ( %2$s)" ++ "%1$s ( %2$s)" + +diff --git a/packages/VpnDialogs/res/values-ta/strings.xml b/packages/VpnDialogs/res/values-ta/strings.xml +index 3b4cc571d8609..8cdffc8579ebd 100644 +--- a/packages/VpnDialogs/res/values-ta/strings.xml ++++ b/packages/VpnDialogs/res/values-ta/strings.xml +@@ -33,4 +33,6 @@ + "தொடர்பைத் துண்டி" + "பயன்பாட்டைத் திற" + "நிராகரி" ++ "%1$s… ( %2$s)" ++ "%1$s ( %2$s)" + +diff --git a/packages/VpnDialogs/res/values-te/strings.xml b/packages/VpnDialogs/res/values-te/strings.xml +index 864c926bc615c..416f2e399240e 100644 +--- a/packages/VpnDialogs/res/values-te/strings.xml ++++ b/packages/VpnDialogs/res/values-te/strings.xml +@@ -33,4 +33,6 @@ + "డిస్‌కనెక్ట్ చేయి" + "యాప్‌ని తెరవండి" + "తీసివేయండి" ++ "%1$s… ( %2$s)" ++ "%1$s ( %2$s)" + +diff --git a/packages/VpnDialogs/res/values-th/strings.xml b/packages/VpnDialogs/res/values-th/strings.xml +index 333ff5fefacc8..14e2b7fcb8c9e 100644 +--- a/packages/VpnDialogs/res/values-th/strings.xml ++++ b/packages/VpnDialogs/res/values-th/strings.xml +@@ -33,4 +33,6 @@ + "ยกเลิกการเชื่อมต่อ" + "เปิดแอป" + "ปิด" ++ "%1$s… ( %2$s)" ++ "%1$s ( %2$s)" + +diff --git a/packages/VpnDialogs/res/values-tl/strings.xml b/packages/VpnDialogs/res/values-tl/strings.xml +index 9c01c32d0d0d4..b79e262ffce9e 100644 +--- a/packages/VpnDialogs/res/values-tl/strings.xml ++++ b/packages/VpnDialogs/res/values-tl/strings.xml +@@ -33,4 +33,6 @@ + "Idiskonekta" + "Buksan ang app" + "I-dismiss" ++ "%1$s… ( %2$s)" ++ "%1$s ( %2$s)" + +diff --git a/packages/VpnDialogs/res/values-tr/strings.xml b/packages/VpnDialogs/res/values-tr/strings.xml +index 8665a47e66334..309d116d77150 100644 +--- a/packages/VpnDialogs/res/values-tr/strings.xml ++++ b/packages/VpnDialogs/res/values-tr/strings.xml +@@ -33,4 +33,6 @@ + "Bağlantıyı kes" + "Uygulamayı aç" + "Kapat" ++ "%1$s… ( %2$s)" ++ "%1$s ( %2$s)" + +diff --git a/packages/VpnDialogs/res/values-uk/strings.xml b/packages/VpnDialogs/res/values-uk/strings.xml +index 8f91abf990b33..fe726049974ae 100644 +--- a/packages/VpnDialogs/res/values-uk/strings.xml ++++ b/packages/VpnDialogs/res/values-uk/strings.xml +@@ -33,4 +33,6 @@ + "Від’єднати" + "Відкрити додаток" + "Закрити" ++ "%1$s… ( %2$s)" ++ "%1$s ( %2$s)" + +diff --git a/packages/VpnDialogs/res/values-ur/strings.xml b/packages/VpnDialogs/res/values-ur/strings.xml +index db0c2971a64cd..d2ee5a8d0aa97 100644 +--- a/packages/VpnDialogs/res/values-ur/strings.xml ++++ b/packages/VpnDialogs/res/values-ur/strings.xml +@@ -33,4 +33,6 @@ + "منقطع کریں" + "ایپ کھولیں" + "برخاست کریں" ++ "%1$s… ( %2$s)" ++ "%1$s ( %2$s)" + +diff --git a/packages/VpnDialogs/res/values-uz/strings.xml b/packages/VpnDialogs/res/values-uz/strings.xml +index 5a348a0610d3d..854417691e30c 100644 +--- a/packages/VpnDialogs/res/values-uz/strings.xml ++++ b/packages/VpnDialogs/res/values-uz/strings.xml +@@ -33,4 +33,6 @@ + "Aloqani uzish" + "Ilovani ochish" + "Yopish" ++ "%1$s… ( %2$s)" ++ "%1$s ( %2$s)" + +diff --git a/packages/VpnDialogs/res/values-vi/strings.xml b/packages/VpnDialogs/res/values-vi/strings.xml +index 097c9aeee0134..d74151a819e14 100644 +--- a/packages/VpnDialogs/res/values-vi/strings.xml ++++ b/packages/VpnDialogs/res/values-vi/strings.xml +@@ -33,4 +33,6 @@ + "Ngắt kết nối" + "Mở ứng dụng" + "Loại bỏ" ++ "%1$s… (%2$s)" ++ "%1$s (%2$s)" + +diff --git a/packages/VpnDialogs/res/values-zh-rCN/strings.xml b/packages/VpnDialogs/res/values-zh-rCN/strings.xml +index 7e528bdfb04a3..92e10fd9fe16d 100644 +--- a/packages/VpnDialogs/res/values-zh-rCN/strings.xml ++++ b/packages/VpnDialogs/res/values-zh-rCN/strings.xml +@@ -33,4 +33,6 @@ + "断开连接" + "打开应用" + "关闭" ++ "%1$s…(%2$s)" ++ "%1$s (%2$s)" + +diff --git a/packages/VpnDialogs/res/values-zh-rHK/strings.xml b/packages/VpnDialogs/res/values-zh-rHK/strings.xml +index 49605b08cdeed..a67e30d104087 100644 +--- a/packages/VpnDialogs/res/values-zh-rHK/strings.xml ++++ b/packages/VpnDialogs/res/values-zh-rHK/strings.xml +@@ -33,4 +33,6 @@ + "中斷連線" + "開啟應用程式" + "關閉" ++ "%1$s… ( %2$s)" ++ "%1$s ( %2$s)" + +diff --git a/packages/VpnDialogs/res/values-zh-rTW/strings.xml b/packages/VpnDialogs/res/values-zh-rTW/strings.xml +index edd8e61d55556..234635091f118 100644 +--- a/packages/VpnDialogs/res/values-zh-rTW/strings.xml ++++ b/packages/VpnDialogs/res/values-zh-rTW/strings.xml +@@ -33,4 +33,6 @@ + "中斷連線" + "開啟應用程式" + "關閉" ++ "%1$s… (%2$s)" ++ "%1$s (%2$s)" + +diff --git a/packages/VpnDialogs/res/values-zu/strings.xml b/packages/VpnDialogs/res/values-zu/strings.xml +index 4ab1225e6fc6b..6c7d0471efac7 100644 +--- a/packages/VpnDialogs/res/values-zu/strings.xml ++++ b/packages/VpnDialogs/res/values-zu/strings.xml +@@ -33,4 +33,6 @@ + "Ayixhumekile kwi-inthanethi" + "Vula uhlelo lokusebenza" + "Cashisa" ++ "%1$s… ( %2$s)" ++ "%1$s ( %2$s)" + diff --git a/Patches/LineageOS-17.1/android_frameworks_base/360956.patch b/Patches/LineageOS-17.1/android_frameworks_base/360956.patch new file mode 100644 index 00000000..dce1167b --- /dev/null +++ b/Patches/LineageOS-17.1/android_frameworks_base/360956.patch @@ -0,0 +1,85 @@ +From fcbc4bc0d51ae2f9180ddea578d0a0defb742662 Mon Sep 17 00:00:00 2001 +From: "Nate(Qiang) Jiang" +Date: Thu, 13 Apr 2023 21:20:37 +0000 +Subject: [PATCH] DO NOT MERGE: Add size check on PPS#policy + +Bug: 275340417 +Test: atest android.net.wifi +(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:d1afd2c47d086e0365bf6814a9f47555c294769f) +Merged-In: I6e6128b7ed5327da8dbc9186a82bef0f2e4197bb +Change-Id: I6e6128b7ed5327da8dbc9186a82bef0f2e4197bb +--- + .../android/net/wifi/hotspot2/pps/Policy.java | 28 ++++++++++++++++--- + 1 file changed, 24 insertions(+), 4 deletions(-) + +diff --git a/wifi/java/android/net/wifi/hotspot2/pps/Policy.java b/wifi/java/android/net/wifi/hotspot2/pps/Policy.java +index b0a2cc397c53b..4bdacebda0606 100644 +--- a/wifi/java/android/net/wifi/hotspot2/pps/Policy.java ++++ b/wifi/java/android/net/wifi/hotspot2/pps/Policy.java +@@ -16,6 +16,9 @@ + + package android.net.wifi.hotspot2.pps; + ++import static android.net.wifi.hotspot2.PasspointConfiguration.MAX_NUMBER_OF_ENTRIES; ++import static android.net.wifi.hotspot2.PasspointConfiguration.MAX_STRING_LENGTH; ++ + import android.os.Parcel; + import android.os.Parcelable; + import android.text.TextUtils; +@@ -269,11 +272,19 @@ public String toString() { + */ + public boolean validate() { + if (TextUtils.isEmpty(mFqdn)) { +- Log.d(TAG, "Missing FQDN"); ++ Log.e(TAG, "Missing FQDN"); ++ return false; ++ } ++ if (mFqdn.getBytes(StandardCharsets.UTF_8).length > MAX_STRING_LENGTH) { ++ Log.e(TAG, "FQDN is too long"); + return false; + } + if (TextUtils.isEmpty(mCountries)) { +- Log.d(TAG, "Missing countries"); ++ Log.e(TAG, "Missing countries"); ++ return false; ++ } ++ if (mCountries.getBytes(StandardCharsets.UTF_8).length > MAX_STRING_LENGTH) { ++ Log.e(TAG, "country is too long"); + return false; + } + return true; +@@ -449,7 +460,7 @@ public boolean validate() { + } + for (String ssid : mExcludedSsidList) { + if (ssid.getBytes(StandardCharsets.UTF_8).length > MAX_SSID_BYTES) { +- Log.d(TAG, "Invalid SSID: " + ssid); ++ Log.e(TAG, "Invalid SSID: " + ssid); + return false; + } + } +@@ -457,15 +468,24 @@ public boolean validate() { + // Validate required protocol to port map. + if (mRequiredProtoPortMap != null) { + for (Map.Entry entry : mRequiredProtoPortMap.entrySet()) { ++ int protocol = entry.getKey(); ++ if (protocol < 0 || protocol > 255) { ++ Log.e(TAG, "Invalid IP protocol: " + protocol); ++ return false; ++ } + String portNumber = entry.getValue(); + if (portNumber.getBytes(StandardCharsets.UTF_8).length > MAX_PORT_STRING_BYTES) { +- Log.d(TAG, "PortNumber string bytes exceeded the max: " + portNumber); ++ Log.e(TAG, "PortNumber string bytes exceeded the max: " + portNumber); + return false; + } + } + } + // Validate preferred roaming partner list. + if (mPreferredRoamingPartnerList != null) { ++ if (mPreferredRoamingPartnerList.size() > MAX_NUMBER_OF_ENTRIES) { ++ Log.e(TAG, "Number of the Preferred Roaming Partner exceed the limit"); ++ return false; ++ } + for (RoamingPartner partner : mPreferredRoamingPartnerList) { + if (!partner.validate()) { + return false; diff --git a/Patches/LineageOS-17.1/android_frameworks_base/360957.patch b/Patches/LineageOS-17.1/android_frameworks_base/360957.patch new file mode 100644 index 00000000..0d56aaea --- /dev/null +++ b/Patches/LineageOS-17.1/android_frameworks_base/360957.patch @@ -0,0 +1,42 @@ +From cd13551b9bc759701bbaa50fc0b2c77f0de6e122 Mon Sep 17 00:00:00 2001 +From: "Nate(Qiang) Jiang" +Date: Wed, 12 Apr 2023 18:32:50 +0000 +Subject: [PATCH] DO NOT MERGE: Limit the ServiceFriendlyNames + +Bug: 274445194 +Test: atest android.net.wifi +(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:6b1746ab6f0ff4020c78381833554f20344c2e2a) +Merged-In: Id4e16007531ba1ce3e3f9fa3d3111b5af57751be +Change-Id: Id4e16007531ba1ce3e3f9fa3d3111b5af57751be +--- + .../wifi/hotspot2/PasspointConfiguration.java | 17 +++++++++++++++++ + 1 file changed, 17 insertions(+) + +diff --git a/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java b/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java +index 09f91d688f7ba..a6509e3e9fe10 100644 +--- a/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java ++++ b/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java +@@ -842,6 +842,23 @@ private boolean validateForCommonR1andR2() { + } + } + } ++ if (mServiceFriendlyNames != null) { ++ if (mServiceFriendlyNames.size() > MAX_NUMBER_OF_ENTRIES) { ++ Log.e(TAG, "ServiceFriendlyNames exceed the max!"); ++ return false; ++ } ++ for (Map.Entry names : mServiceFriendlyNames.entrySet()) { ++ if (names.getKey() == null || names.getValue() == null) { ++ Log.e(TAG, "Service friendly name entry should not be null"); ++ return false; ++ } ++ if (names.getKey().length() > MAX_STRING_LENGTH ++ || names.getValue().length() > MAX_STRING_LENGTH) { ++ Log.e(TAG, "Service friendly name is to long"); ++ return false; ++ } ++ } ++ } + return true; + } + diff --git a/Patches/LineageOS-17.1/android_frameworks_base/360958-backport.patch b/Patches/LineageOS-17.1/android_frameworks_base/360958-backport.patch new file mode 100644 index 00000000..d6135b1d --- /dev/null +++ b/Patches/LineageOS-17.1/android_frameworks_base/360958-backport.patch @@ -0,0 +1,38 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Winson Chung +Date: Wed, 8 Feb 2023 01:04:46 +0000 +Subject: [PATCH] Only allow NEW_TASK flag when adjusting pending intents + +Bug: 243794108 +Test: atest CtsSecurityBulletinHostTestCases:android.security.cts.CVE_2023_20918 +(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:c62d2e1021a030f4f0ae5fcfc8fe8e0875fa669f) +Merged-In: I5d329beecef1902c36704e93d0bc5cb60d0e2f5b +Change-Id: I5d329beecef1902c36704e93d0bc5cb60d0e2f5b +--- + core/java/android/app/ActivityOptions.java | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java +index 36ab62aedc09..c8f54fd275ee 100644 +--- a/core/java/android/app/ActivityOptions.java ++++ b/core/java/android/app/ActivityOptions.java +@@ -20,6 +20,8 @@ import static android.Manifest.permission.CONTROL_REMOTE_APP_TRANSITION_ANIMATIO + import static android.app.ActivityTaskManager.SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT; + import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED; + import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; ++import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; ++import static android.content.Intent.FLAG_RECEIVER_FOREGROUND; + import static android.view.Display.INVALID_DISPLAY; + + import android.annotation.Nullable; +@@ -1262,7 +1264,9 @@ public class ActivityOptions extends ComponentOptions { + * @hide + */ + public int getPendingIntentLaunchFlags() { +- return mPendingIntentLaunchFlags; ++ // b/243794108: Ignore all flags except the new task flag, to be reconsidered in b/254490217 ++ return mPendingIntentLaunchFlags & ++ (FLAG_ACTIVITY_NEW_TASK | FLAG_RECEIVER_FOREGROUND); + } + + /** diff --git a/Patches/LineageOS-17.1/android_frameworks_base/360959.patch b/Patches/LineageOS-17.1/android_frameworks_base/360959.patch new file mode 100644 index 00000000..9b2cc966 --- /dev/null +++ b/Patches/LineageOS-17.1/android_frameworks_base/360959.patch @@ -0,0 +1,39 @@ +From 9a334720003494e411ab0f0cfd66b3cc4cc104fb Mon Sep 17 00:00:00 2001 +From: Aaron Liu +Date: Tue, 28 Mar 2023 13:15:04 -0700 +Subject: [PATCH] DO NOT MERGE Dismiss keyguard when simpin auth'd and... + +security method is none. This is mostly to fix the case where we auth +sim pin in the set up wizard and it goes straight to keyguard instead of +the setup wizard activity. + +This works with the prevent bypass keyguard flag because the device +should be noe secure in this case. + +Fixes: 222446076 +Test: turn locked sim on, which opens the sim pin screen. Auth the +screen and observe that keyguard is not shown. +(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:48fa9bef3451e4a358c941af5b230f99881c5cb6) +Cherry-picking this CL as a security fix + +Bug: 222446076 +(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:09f004722284ef6b9790ddf9338a1708b3f0833c) +Merged-In: If4360dd6ae2e5f79b43eaf1a29687ac9cc4b6101 +Change-Id: If4360dd6ae2e5f79b43eaf1a29687ac9cc4b6101 +--- + .../src/com/android/keyguard/KeyguardSecurityContainer.java | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java +index b2020d9fe2d53..1cef61a2e18a1 100644 +--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java ++++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java +@@ -739,7 +739,7 @@ boolean showNextSecurityScreenOrFinish(boolean authenticated, int targetUserId, + case SimPuk: + // Shortcut for SIM PIN/PUK to go to directly to user's security screen or home + SecurityMode securityMode = mSecurityModel.getSecurityMode(targetUserId); +- if (securityMode == SecurityMode.None && mLockPatternUtils.isLockScreenDisabled( ++ if (securityMode == SecurityMode.None || mLockPatternUtils.isLockScreenDisabled( + KeyguardUpdateMonitor.getCurrentUser())) { + finish = true; + eventSubtype = BOUNCER_DISMISS_SIM; diff --git a/Patches/LineageOS-17.1/android_frameworks_base/360960.patch b/Patches/LineageOS-17.1/android_frameworks_base/360960.patch new file mode 100644 index 00000000..c81443c7 --- /dev/null +++ b/Patches/LineageOS-17.1/android_frameworks_base/360960.patch @@ -0,0 +1,30 @@ +From 67b68368ef609a22b83b48d355cbef2e01480a88 Mon Sep 17 00:00:00 2001 +From: Ioana Alexandru +Date: Fri, 28 Apr 2023 14:11:04 +0000 +Subject: [PATCH] DO NOT MERGE Increase notification channel limit. + +This was previously reduced because it can cause an out of memory error or be abused to trigger a permanent denial of service, but it breaks some messages apps in Android 11, as they are creating too many channels. Rolling it back until the apps are fixed to reduce user impact. + +Bug: 279447569 +Bug: 261723753 +Test: N/A, this was previously 50k +(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:5664378a7cac48184ec0702a41aaed0677d41136) +Merged-In: Id8da382f812d4abb8db723c40a61366a7402da4f +Change-Id: Id8da382f812d4abb8db723c40a61366a7402da4f +--- + .../java/com/android/server/notification/PreferencesHelper.java | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/services/core/java/com/android/server/notification/PreferencesHelper.java b/services/core/java/com/android/server/notification/PreferencesHelper.java +index 8f969dc83a09c..282816079a262 100644 +--- a/services/core/java/com/android/server/notification/PreferencesHelper.java ++++ b/services/core/java/com/android/server/notification/PreferencesHelper.java +@@ -92,7 +92,7 @@ public class PreferencesHelper implements RankingConfig { + private static final String NON_BLOCKABLE_CHANNEL_DELIM = ":"; + + @VisibleForTesting +- static final int NOTIFICATION_CHANNEL_COUNT_LIMIT = 5000; ++ static final int NOTIFICATION_CHANNEL_COUNT_LIMIT = 50000; + @VisibleForTesting + static final int NOTIFICATION_CHANNEL_GROUP_COUNT_LIMIT = 6000; + diff --git a/Patches/LineageOS-17.1/android_frameworks_base/360961-backport.patch b/Patches/LineageOS-17.1/android_frameworks_base/360961-backport.patch new file mode 100644 index 00000000..bb2e2d2c --- /dev/null +++ b/Patches/LineageOS-17.1/android_frameworks_base/360961-backport.patch @@ -0,0 +1,102 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Ioana Alexandru +Date: Fri, 21 Apr 2023 15:39:22 +0000 +Subject: [PATCH] Verify URI permissions for EXTRA_REMOTE_INPUT_HISTORY_ITEMS. + +Also added the person URIs in the test, since they weren't being +checked. + +Test: atest NotificationManagerServiceTest & tested with POC from bug +Bug: 276729064 +(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:e0d8602a0200ba92283463bd54cefcf97394bfa8) +(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:63f8ce3efd9a564ae83f1de38791a6d67c5a8ddb) +Merged-In: I848545f7aee202495c515f47a32871a2cb6ae707 +Change-Id: I848545f7aee202495c515f47a32871a2cb6ae707 +--- + core/java/android/app/Notification.java | 11 +++++++ + .../NotificationManagerServiceTest.java | 32 +++++++++++++++++++ + 2 files changed, 43 insertions(+) + +diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java +index 3e75c52bf893..9fe3583df601 100644 +--- a/core/java/android/app/Notification.java ++++ b/core/java/android/app/Notification.java +@@ -2454,6 +2454,17 @@ public class Notification implements Parcelable + if (extras.containsKey(EXTRA_BACKGROUND_IMAGE_URI)) { + visitor.accept(Uri.parse(extras.getString(EXTRA_BACKGROUND_IMAGE_URI))); + } ++ ++ final RemoteInputHistoryItem[] history = (RemoteInputHistoryItem[]) ++ extras.getParcelableArray(Notification.EXTRA_REMOTE_INPUT_HISTORY_ITEMS); ++ if (history != null) { ++ for (int i = 0; i < history.length; i++) { ++ RemoteInputHistoryItem item = history[i]; ++ if (item.getUri() != null) { ++ visitor.accept(item.getUri()); ++ } ++ } ++ } + } + + if (MessagingStyle.class.equals(getNotificationStyle()) && extras != null) { +diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java +index 6c1620751866..b2ce41f5b373 100755 +--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java ++++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java +@@ -93,6 +93,7 @@ import android.app.NotificationManager; + import android.app.PendingIntent; + import android.app.Person; + import android.app.RemoteInput; ++import android.app.RemoteInputHistoryItem; + import android.app.admin.DevicePolicyManagerInternal; + import android.app.usage.UsageStatsManagerInternal; + import android.companion.ICompanionDeviceManager; +@@ -3414,10 +3415,36 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { + public void testVisitUris() throws Exception { + final Uri audioContents = Uri.parse("content://com.example/audio"); + final Uri backgroundImage = Uri.parse("content://com.example/background"); ++ final Icon personIcon1 = Icon.createWithContentUri("content://media/person1"); ++ final Icon personIcon2 = Icon.createWithContentUri("content://media/person2"); ++ final Icon personIcon3 = Icon.createWithContentUri("content://media/person3"); ++ final Person person1 = new Person.Builder() ++ .setName("Messaging Person") ++ .setIcon(personIcon1) ++ .build(); ++ final Person person2 = new Person.Builder() ++ .setName("People List Person 1") ++ .setIcon(personIcon2) ++ .build(); ++ final Person person3 = new Person.Builder() ++ .setName("People List Person 2") ++ .setIcon(personIcon3) ++ .build(); ++ final Uri historyUri1 = Uri.parse("content://com.example/history1"); ++ final Uri historyUri2 = Uri.parse("content://com.example/history2"); ++ final RemoteInputHistoryItem historyItem1 = new RemoteInputHistoryItem(null, historyUri1, ++ "a"); ++ final RemoteInputHistoryItem historyItem2 = new RemoteInputHistoryItem(null, historyUri2, ++ "b"); + + Bundle extras = new Bundle(); + extras.putParcelable(Notification.EXTRA_AUDIO_CONTENTS_URI, audioContents); + extras.putString(Notification.EXTRA_BACKGROUND_IMAGE_URI, backgroundImage.toString()); ++ extras.putParcelable(Notification.EXTRA_MESSAGING_PERSON, person1); ++ extras.putParcelableArrayList(Notification.EXTRA_PEOPLE_LIST, ++ new ArrayList<>(Arrays.asList(person2, person3))); ++ extras.putParcelableArray(Notification.EXTRA_REMOTE_INPUT_HISTORY_ITEMS, ++ new RemoteInputHistoryItem[]{historyItem1, historyItem2}); + + Notification n = new Notification.Builder(mContext, "a") + .setContentTitle("notification with uris") +@@ -3429,6 +3456,11 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { + n.visitUris(visitor); + verify(visitor, times(1)).accept(eq(audioContents)); + verify(visitor, times(1)).accept(eq(backgroundImage)); ++ verify(visitor, times(1)).accept(eq(personIcon1.getUri())); ++ verify(visitor, times(1)).accept(eq(personIcon2.getUri())); ++ verify(visitor, times(1)).accept(eq(personIcon3.getUri())); ++ verify(visitor, times(1)).accept(eq(historyUri1)); ++ verify(visitor, times(1)).accept(eq(historyUri2)); + } + + @Test diff --git a/Patches/LineageOS-17.1/android_frameworks_base/360962-backport.patch b/Patches/LineageOS-17.1/android_frameworks_base/360962-backport.patch new file mode 100644 index 00000000..c32dac1e --- /dev/null +++ b/Patches/LineageOS-17.1/android_frameworks_base/360962-backport.patch @@ -0,0 +1,99 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Andr=C3=A1s=20Kurucz?= +Date: Fri, 21 Apr 2023 09:45:07 +0000 +Subject: [PATCH] Truncate ShortcutInfo Id + +Creating Conversation with a ShortcutId longer than 65_535 (max unsigned short), we did not save the conversation settings into the notification_policy.xml due to a restriction in FastDataOutput. +This put us to a state where the user changing the importance or turning off the notifications for the given conversation had no effect on notification behavior. + +Fixes: 273729476 +Test: atest ShortcutManagerTest2 +Test: Create a test app which creates a Conversation with a long shortcutId. Go to the Conversation Settings and turn off Notifications. Post a new Notification to this Conversation and see if it is displayed. +(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:f31df6234091b5b1de258a01dd4b2d8e5415ee2e) +Merged-In: I2617de6f9e8a7dbfd8fbeff589a7d592f00d87c5 +Change-Id: I2617de6f9e8a7dbfd8fbeff589a7d592f00d87c5 +--- + .../java/android/content/pm/ShortcutInfo.java | 20 ++++++++++++++++--- + .../server/pm/ShortcutManagerTest2.java | 10 ++++++++++ + 2 files changed, 27 insertions(+), 3 deletions(-) + +diff --git a/core/java/android/content/pm/ShortcutInfo.java b/core/java/android/content/pm/ShortcutInfo.java +index 58aacc2c36c7..4bd28aefc0a9 100644 +--- a/core/java/android/content/pm/ShortcutInfo.java ++++ b/core/java/android/content/pm/ShortcutInfo.java +@@ -236,6 +236,12 @@ public final class ShortcutInfo implements Parcelable { + */ + public static final int DISABLED_REASON_OTHER_RESTORE_ISSUE = 103; + ++ /** ++ * The maximum length of Shortcut ID. IDs will be truncated at this limit. ++ * @hide ++ */ ++ public static final int MAX_ID_LENGTH = 1000; ++ + /** @hide */ + @IntDef(prefix = { "DISABLED_REASON_" }, value = { + DISABLED_REASON_NOT_DISABLED, +@@ -408,8 +414,7 @@ public final class ShortcutInfo implements Parcelable { + + private ShortcutInfo(Builder b) { + mUserId = b.mContext.getUserId(); +- +- mId = Preconditions.checkStringNotEmpty(b.mId, "Shortcut ID must be provided"); ++ mId = getSafeId(Preconditions.checkStringNotEmpty(b.mId, "Shortcut ID must be provided")); + + // Note we can't do other null checks here because SM.updateShortcuts() takes partial + // information. +@@ -511,6 +516,14 @@ public final class ShortcutInfo implements Parcelable { + return ret; + } + ++ @NonNull ++ private static String getSafeId(@NonNull String id) { ++ if (id.length() > MAX_ID_LENGTH) { ++ return id.substring(0, MAX_ID_LENGTH); ++ } ++ return id; ++ } ++ + /** + * Throws if any of the mandatory fields is not set. + * +@@ -2009,7 +2022,8 @@ public final class ShortcutInfo implements Parcelable { + final ClassLoader cl = getClass().getClassLoader(); + + mUserId = source.readInt(); +- mId = source.readString(); ++ mId = getSafeId(Preconditions.checkStringNotEmpty(source.readString8(), ++ "Shortcut ID must be provided")); + mPackageName = source.readString(); + mActivity = source.readParcelable(cl); + mFlags = source.readInt(); +diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java +index fd3678dae0c4..18970322d854 100644 +--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java ++++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java +@@ -53,6 +53,7 @@ import java.io.File; + import java.io.FileWriter; + import java.io.IOException; + import java.io.Writer; ++import java.util.Collections; + import java.util.Locale; + + /** +@@ -223,6 +224,15 @@ public class ShortcutManagerTest2 extends BaseShortcutManagerTest { + }); + } + ++ public void testShortcutIdTruncated() { ++ ShortcutInfo si = new ShortcutInfo.Builder(getTestContext(), ++ String.join("", Collections.nCopies(Short.MAX_VALUE, "s"))).build(); ++ ++ assertTrue( ++ "id must be truncated to MAX_ID_LENGTH", ++ si.getId().length() <= ShortcutInfo.MAX_ID_LENGTH); ++ } ++ + public void testShortcutInfoParcel() { + setCaller(CALLING_PACKAGE_1, USER_10); + ShortcutInfo si = parceled(new ShortcutInfo.Builder(mClientContext) diff --git a/Patches/LineageOS-17.1/android_frameworks_base/360963.patch b/Patches/LineageOS-17.1/android_frameworks_base/360963.patch new file mode 100644 index 00000000..51ffe5b2 --- /dev/null +++ b/Patches/LineageOS-17.1/android_frameworks_base/360963.patch @@ -0,0 +1,127 @@ +From c7abcb66259f6ffc57f4b378d14b1999576ada03 Mon Sep 17 00:00:00 2001 +From: Ioana Alexandru +Date: Thu, 27 Apr 2023 12:36:05 +0000 +Subject: [PATCH] Visit URIs in landscape/portrait custom remote views. + +Bug: 277740848 +Test: atest RemoteViewsTest NotificationManagerServiceTest & tested with POC from bug +(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:e8acb2f660bdb03616989852f9dbbf1726f8237e) +(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:43e1ae4e0d408604b9e3c18ac0e9bf87529b92a8) +Merged-In: I7d3d35df0ec38945019f71755bed8797b7af4517 +Change-Id: I7d3d35df0ec38945019f71755bed8797b7af4517 +--- + core/java/android/widget/RemoteViews.java | 6 ++ + .../src/android/widget/RemoteViewsTest.java | 64 +++++++++++++++++++ + 2 files changed, 70 insertions(+) + +diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java +index a9b2c4df255f1..ec36b9ed578c6 100644 +--- a/core/java/android/widget/RemoteViews.java ++++ b/core/java/android/widget/RemoteViews.java +@@ -562,6 +562,12 @@ public void visitUris(@NonNull Consumer visitor) { + mActions.get(i).visitUris(visitor); + } + } ++ if (mLandscape != null) { ++ mLandscape.visitUris(visitor); ++ } ++ if (mPortrait != null) { ++ mPortrait.visitUris(visitor); ++ } + } + + private static void visitIconUri(Icon icon, @NonNull Consumer visitor) { +diff --git a/core/tests/coretests/src/android/widget/RemoteViewsTest.java b/core/tests/coretests/src/android/widget/RemoteViewsTest.java +index 8cb7e1b95245e..46f2c0928fc3d 100644 +--- a/core/tests/coretests/src/android/widget/RemoteViewsTest.java ++++ b/core/tests/coretests/src/android/widget/RemoteViewsTest.java +@@ -20,6 +20,10 @@ + import static org.junit.Assert.assertEquals; + import static org.junit.Assert.assertSame; + import static org.junit.Assert.assertTrue; ++import static org.mockito.ArgumentMatchers.eq; ++import static org.mockito.Mockito.spy; ++import static org.mockito.Mockito.times; ++import static org.mockito.Mockito.verify; + + import android.app.ActivityOptions; + import android.app.PendingIntent; +@@ -29,6 +33,8 @@ + import android.graphics.Bitmap; + import android.graphics.drawable.BitmapDrawable; + import android.graphics.drawable.Drawable; ++import android.graphics.drawable.Icon; ++import android.net.Uri; + import android.os.AsyncTask; + import android.os.Binder; + import android.os.Parcel; +@@ -50,6 +56,7 @@ + import java.util.ArrayList; + import java.util.Arrays; + import java.util.concurrent.CountDownLatch; ++import java.util.function.Consumer; + + /** + * Tests for RemoteViews. +@@ -499,4 +506,61 @@ public ActivityOptions createSharedElementActivityOptions( + return null; + } + } ++ ++ @Test ++ public void visitUris() { ++ RemoteViews views = new RemoteViews(mPackage, R.layout.remote_views_test); ++ ++ final Uri imageUri = Uri.parse("content://media/image"); ++ final Icon icon1 = Icon.createWithContentUri("content://media/icon1"); ++ final Icon icon2 = Icon.createWithContentUri("content://media/icon2"); ++ final Icon icon3 = Icon.createWithContentUri("content://media/icon3"); ++ final Icon icon4 = Icon.createWithContentUri("content://media/icon4"); ++ views.setImageViewUri(R.id.image, imageUri); ++ views.setTextViewCompoundDrawables(R.id.text, icon1, icon2, icon3, icon4); ++ ++ Consumer visitor = (Consumer) spy(Consumer.class); ++ views.visitUris(visitor); ++ verify(visitor, times(1)).accept(eq(imageUri)); ++ verify(visitor, times(1)).accept(eq(icon1.getUri())); ++ verify(visitor, times(1)).accept(eq(icon2.getUri())); ++ verify(visitor, times(1)).accept(eq(icon3.getUri())); ++ verify(visitor, times(1)).accept(eq(icon4.getUri())); ++ } ++ ++ @Test ++ public void visitUris_separateOrientation() { ++ final RemoteViews landscape = new RemoteViews(mPackage, R.layout.remote_views_test); ++ final Uri imageUriL = Uri.parse("content://landscape/image"); ++ final Icon icon1L = Icon.createWithContentUri("content://landscape/icon1"); ++ final Icon icon2L = Icon.createWithContentUri("content://landscape/icon2"); ++ final Icon icon3L = Icon.createWithContentUri("content://landscape/icon3"); ++ final Icon icon4L = Icon.createWithContentUri("content://landscape/icon4"); ++ landscape.setImageViewUri(R.id.image, imageUriL); ++ landscape.setTextViewCompoundDrawables(R.id.text, icon1L, icon2L, icon3L, icon4L); ++ ++ final RemoteViews portrait = new RemoteViews(mPackage, 33); ++ final Uri imageUriP = Uri.parse("content://portrait/image"); ++ final Icon icon1P = Icon.createWithContentUri("content://portrait/icon1"); ++ final Icon icon2P = Icon.createWithContentUri("content://portrait/icon2"); ++ final Icon icon3P = Icon.createWithContentUri("content://portrait/icon3"); ++ final Icon icon4P = Icon.createWithContentUri("content://portrait/icon4"); ++ portrait.setImageViewUri(R.id.image, imageUriP); ++ portrait.setTextViewCompoundDrawables(R.id.text, icon1P, icon2P, icon3P, icon4P); ++ ++ RemoteViews views = new RemoteViews(landscape, portrait); ++ ++ Consumer visitor = (Consumer) spy(Consumer.class); ++ views.visitUris(visitor); ++ verify(visitor, times(1)).accept(eq(imageUriL)); ++ verify(visitor, times(1)).accept(eq(icon1L.getUri())); ++ verify(visitor, times(1)).accept(eq(icon2L.getUri())); ++ verify(visitor, times(1)).accept(eq(icon3L.getUri())); ++ verify(visitor, times(1)).accept(eq(icon4L.getUri())); ++ verify(visitor, times(1)).accept(eq(imageUriP)); ++ verify(visitor, times(1)).accept(eq(icon1P.getUri())); ++ verify(visitor, times(1)).accept(eq(icon2P.getUri())); ++ verify(visitor, times(1)).accept(eq(icon3P.getUri())); ++ verify(visitor, times(1)).accept(eq(icon4P.getUri())); ++ } + } diff --git a/Patches/LineageOS-17.1/android_frameworks_opt_net_wifi/360964-backport.patch b/Patches/LineageOS-17.1/android_frameworks_opt_net_wifi/360964-backport.patch new file mode 100644 index 00000000..49bac3c8 --- /dev/null +++ b/Patches/LineageOS-17.1/android_frameworks_opt_net_wifi/360964-backport.patch @@ -0,0 +1,103 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: "Nate(Qiang) Jiang" +Date: Thu, 13 Apr 2023 19:25:51 +0000 +Subject: [PATCH] DO NOT MERGE: Add pre-share key check for wapi + +Bug: 275339978 +Test: atest com.androi.server.wifi +(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:07d112fb45449e06233b71e877e835084c76f220) +Merged-In: Ibd3ee52c5993a541abb7b373e4052091d13e9c4f +Change-Id: Ibd3ee52c5993a541abb7b373e4052091d13e9c4f +--- + .../server/wifi/WifiConfigurationUtil.java | 4 ++ + .../wifi/WifiConfigurationUtilTest.java | 41 +++++++++++++++++++ + 2 files changed, 45 insertions(+) + +diff --git a/service/java/com/android/server/wifi/WifiConfigurationUtil.java b/service/java/com/android/server/wifi/WifiConfigurationUtil.java +index b8992a011..2bb7b0dd2 100644 +--- a/service/java/com/android/server/wifi/WifiConfigurationUtil.java ++++ b/service/java/com/android/server/wifi/WifiConfigurationUtil.java +@@ -701,6 +701,10 @@ public class WifiConfigurationUtil { + && !validatePassword(config.preSharedKey, isAdd, false)) { + return false; + } ++ if (config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.WAPI_PSK) ++ && !validatePassword(config.preSharedKey, isAdd, false)) { ++ return false; ++ } + if (config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.OWE)) { + // PMF mandatory for OWE networks + if (!config.requirePMF) { +diff --git a/tests/wifitests/src/com/android/server/wifi/WifiConfigurationUtilTest.java b/tests/wifitests/src/com/android/server/wifi/WifiConfigurationUtilTest.java +index 7173dae5b..aaa3f2605 100644 +--- a/tests/wifitests/src/com/android/server/wifi/WifiConfigurationUtilTest.java ++++ b/tests/wifitests/src/com/android/server/wifi/WifiConfigurationUtilTest.java +@@ -352,6 +352,18 @@ public class WifiConfigurationUtilTest { + assertFalse(WifiConfigurationUtil.validate(config, WifiConfigurationUtil.VALIDATE_FOR_ADD)); + } + ++ @Test ++ public void testValidateNegativeCases_BadAsciiPskLengthWapi() { ++ WifiConfiguration config = WifiConfigurationTestUtil.createWapiPskNetwork(); ++ assertTrue(WifiConfigurationUtil.validate(config, WifiConfigurationUtil.VALIDATE_FOR_ADD)); ++ ++ config.preSharedKey = "\"abcdffeeretretyetreteteteabe34tetrertertrsraaaaaaaaaaa345eqwrweewq" ++ + "weqe\""; ++ assertFalse(WifiConfigurationUtil.validate(config, WifiConfigurationUtil.VALIDATE_FOR_ADD)); ++ config.preSharedKey = "\"454\""; ++ assertFalse(WifiConfigurationUtil.validate(config, WifiConfigurationUtil.VALIDATE_FOR_ADD)); ++ } ++ + /** + * Verify that the validate method fails to validate WifiConfiguration with bad sae length. + */ +@@ -380,6 +392,15 @@ public class WifiConfigurationUtilTest { + assertFalse(WifiConfigurationUtil.validate(config, WifiConfigurationUtil.VALIDATE_FOR_ADD)); + } + ++ @Test ++ public void testValidateNegativeCases_MalformedAsciiPskStringWapi() { ++ WifiConfiguration config = WifiConfigurationTestUtil.createWapiPskNetwork(); ++ assertTrue(WifiConfigurationUtil.validate(config, WifiConfigurationUtil.VALIDATE_FOR_ADD)); ++ ++ config.preSharedKey = "\"abcdfefeeretrety"; ++ assertFalse(WifiConfigurationUtil.validate(config, WifiConfigurationUtil.VALIDATE_FOR_ADD)); ++ } ++ + /** + * Verify that the validate method fails to validate WifiConfiguration with malformed sae + * string. +@@ -407,6 +428,17 @@ public class WifiConfigurationUtilTest { + assertFalse(WifiConfigurationUtil.validate(config, WifiConfigurationUtil.VALIDATE_FOR_ADD)); + } + ++ @Test ++ public void testValidateNegativeCases_BadHexPskLengthWapi() { ++ WifiConfiguration config = WifiConfigurationTestUtil.createWapiPskNetwork(); ++ assertTrue(WifiConfigurationUtil.validate(config, WifiConfigurationUtil.VALIDATE_FOR_ADD)); ++ ++ config.preSharedKey = "abcd123456788990013453445345465465476546"; ++ assertFalse(WifiConfigurationUtil.validate(config, WifiConfigurationUtil.VALIDATE_FOR_ADD)); ++ config.preSharedKey = ""; ++ assertFalse(WifiConfigurationUtil.validate(config, WifiConfigurationUtil.VALIDATE_FOR_ADD)); ++ } ++ + /** + * Verify that the validate method fails to validate WifiConfiguration with malformed psk + * string. +@@ -420,6 +452,15 @@ public class WifiConfigurationUtilTest { + assertFalse(WifiConfigurationUtil.validate(config, WifiConfigurationUtil.VALIDATE_FOR_ADD)); + } + ++ @Test ++ public void testValidateNegativeCases_MalformedHexPskStringWapi() { ++ WifiConfiguration config = WifiConfigurationTestUtil.createWapiPskNetwork(); ++ assertTrue(WifiConfigurationUtil.validate(config, WifiConfigurationUtil.VALIDATE_FOR_ADD)); ++ ++ config.preSharedKey = "adbdfgretrtyrtyrty"; ++ assertFalse(WifiConfigurationUtil.validate(config, WifiConfigurationUtil.VALIDATE_FOR_ADD)); ++ } ++ + /** + * Verify that the validate method fails to validate WifiConfiguration with malformed sae + * string. diff --git a/Patches/LineageOS-17.1/android_system_bt/360969.patch b/Patches/LineageOS-17.1/android_system_bt/360969.patch new file mode 100644 index 00000000..8e3d4c55 --- /dev/null +++ b/Patches/LineageOS-17.1/android_system_bt/360969.patch @@ -0,0 +1,45 @@ +From 785e4f3712e63acb5cb0b0d028609fcc268b9b78 Mon Sep 17 00:00:00 2001 +From: tyiu +Date: Tue, 28 Mar 2023 18:40:51 +0000 +Subject: [PATCH] Fix gatt_end_operation buffer overflow + +Added boundary check for gatt_end_operation to prevent writing out of +boundary. + +Since response of the GATT server is handled in +gatt_client_handle_server_rsp() and gatt_process_read_rsp(), the maximum +lenth that can be passed into the handlers is bounded by +GATT_MAX_MTU_SIZE, which is set to 517, which is greater than +GATT_MAX_ATTR_LEN which is set to 512. The fact that there is no spec +that gaurentees MTU response to be less than or equal to 512 bytes can +cause a buffer overflow when performing memcpy without length check. + +Bug: 261068592 +Test: No test since not affecting behavior +Tag: #security +Ignore-AOSP-First: security +(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:dd7298e982e4bbf0138a490562679c9a4a755200) +Merged-In: I49e2797cd9300ee4cd69f2c7fa5f0073db78b873 +Change-Id: I49e2797cd9300ee4cd69f2c7fa5f0073db78b873 +--- + stack/gatt/gatt_utils.cc | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/stack/gatt/gatt_utils.cc b/stack/gatt/gatt_utils.cc +index 2bd42400013..013011778b0 100644 +--- a/stack/gatt/gatt_utils.cc ++++ b/stack/gatt/gatt_utils.cc +@@ -1198,6 +1198,13 @@ void gatt_end_operation(tGATT_CLCB* p_clcb, tGATT_STATUS status, void* p_data) { + cb_data.att_value.handle = p_clcb->s_handle; + cb_data.att_value.len = p_clcb->counter; + ++ if (cb_data.att_value.len > GATT_MAX_ATTR_LEN) { ++ LOG(WARNING) << __func__ ++ << StringPrintf(" Large cb_data.att_value, size=%d", ++ cb_data.att_value.len); ++ cb_data.att_value.len = GATT_MAX_ATTR_LEN; ++ } ++ + if (p_data && p_clcb->counter) + memcpy(cb_data.att_value.value, p_data, cb_data.att_value.len); + } diff --git a/Patches/LineageOS-17.1/android_system_nfc/360972.patch b/Patches/LineageOS-17.1/android_system_nfc/360972.patch new file mode 100644 index 00000000..ba7eb8d5 --- /dev/null +++ b/Patches/LineageOS-17.1/android_system_nfc/360972.patch @@ -0,0 +1,34 @@ +From ce05a2670c9ceb76b6ff5715d25331f2c59ddab6 Mon Sep 17 00:00:00 2001 +From: Alisher Alikhodjaev +Date: Tue, 2 May 2023 14:20:57 -0700 +Subject: [PATCH] OOBW in rw_i93_send_to_upper() + +Bug: 271849189 +Test: tag r/w +(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:dc9d09e1698725712628d394bf9be4c9003579e8) +Merged-In: I1d55954e56a3f995f8dd48bf484fe9fce02b2ed1 +Change-Id: I1d55954e56a3f995f8dd48bf484fe9fce02b2ed1 +--- + src/nfc/tags/rw_i93.cc | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/src/nfc/tags/rw_i93.cc b/src/nfc/tags/rw_i93.cc +index 1c64ea84..cb6d96da 100644 +--- a/src/nfc/tags/rw_i93.cc ++++ b/src/nfc/tags/rw_i93.cc +@@ -578,6 +578,15 @@ void rw_i93_send_to_upper(NFC_HDR* p_resp) { + case I93_CMD_GET_MULTI_BLK_SEC: + case I93_CMD_EXT_GET_MULTI_BLK_SEC: + ++ if (UINT16_MAX - length < NFC_HDR_SIZE) { ++ rw_data.i93_cmd_cmpl.status = NFC_STATUS_FAILED; ++ rw_data.i93_cmd_cmpl.command = p_i93->sent_cmd; ++ rw_cb.tcb.i93.sent_cmd = 0; ++ ++ event = RW_I93_CMD_CMPL_EVT; ++ break; ++ } ++ + /* forward tag data or security status */ + p_buff = (NFC_HDR*)GKI_getbuf((uint16_t)(length + NFC_HDR_SIZE)); + diff --git a/Patches/LineageOS-17.1/android_tools_apksig/360973-backport.patch b/Patches/LineageOS-17.1/android_tools_apksig/360973-backport.patch new file mode 100644 index 00000000..69ba11f3 --- /dev/null +++ b/Patches/LineageOS-17.1/android_tools_apksig/360973-backport.patch @@ -0,0 +1,1456 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Michael Groover +Date: Fri, 31 Mar 2023 14:30:21 -0500 +Subject: [PATCH] Limit the number of supported v1 and v2 signers + +The v1 and v2 APK Signature Schemes support multiple signers; this +was intended to allow multiple entities to sign an APK. Previously, +there were no limits placed on the number of signers that could +sign an APK, but this commit sets a hard limit of 10 supported +signers for these signature schemes to ensure a large number of +signers does not place undue burden on the platform. + +Bug: 266580022 +Test: gradlew test +(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:ea0632935646f2f6bf5822a5e9c97885269780bd) +Merged-In: I77f4218599511ff4f9f3790e4942a329d5a18da4 +Change-Id: I77f4218599511ff4f9f3790e4942a329d5a18da4 +--- + .../java/com/android/apksig/ApkVerifier.java | 29 +++++ + .../internal/apk/v1/V1SchemeSigner.java | 7 ++ + .../internal/apk/v1/V1SchemeVerifier.java | 7 ++ + .../internal/apk/v2/V2SchemeSigner.java | 8 ++ + .../internal/apk/v2/V2SchemeVerifier.java | 5 + + .../com/android/apksig/ApkSignerTest.java | 100 ++++++++++++++++++ + .../com/android/apksig/ApkVerifierTest.java | 31 ++++++ + .../com/android/apksig/v1-only-10-signers.apk | Bin 0 -> 18389 bytes + .../com/android/apksig/v1-only-11-signers.apk | Bin 0 -> 22297 bytes + .../com/android/apksig/v2-only-10-signers.apk | Bin 0 -> 20688 bytes + .../com/android/apksig/v2-only-11-signers.apk | Bin 0 -> 24784 bytes + 11 files changed, 187 insertions(+) + create mode 100644 src/test/resources/com/android/apksig/v1-only-10-signers.apk + create mode 100644 src/test/resources/com/android/apksig/v1-only-11-signers.apk + create mode 100644 src/test/resources/com/android/apksig/v2-only-10-signers.apk + create mode 100644 src/test/resources/com/android/apksig/v2-only-11-signers.apk + +diff --git a/src/main/java/com/android/apksig/ApkVerifier.java b/src/main/java/com/android/apksig/ApkVerifier.java +index 3e1e7da..cfbc8d2 100644 +--- a/src/main/java/com/android/apksig/ApkVerifier.java ++++ b/src/main/java/com/android/apksig/ApkVerifier.java +@@ -644,6 +644,15 @@ public class ApkVerifier { + } + + private void mergeFrom(ApkSigningBlockUtils.Result source) { ++ if (source == null) { ++ return; ++ } ++ if (source.containsErrors()) { ++ mErrors.addAll(source.getErrors()); ++ } ++ if (source.containsWarnings()) { ++ mWarnings.addAll(source.getWarnings()); ++ } + switch (source.signatureSchemeVersion) { + case ApkSigningBlockUtils.VERSION_APK_SIGNATURE_SCHEME_V2: + mVerifiedUsingV2Scheme = source.verified; +@@ -921,6 +930,16 @@ public class ApkVerifier { + */ + JAR_SIG_NO_SIGNATURES("No JAR signatures"), + ++ /** ++ * APK signature scheme v1 has exceeded the maximum number of jar signers. ++ *
    ++ *
  • Parameter 1: maximum allowed signers ({@code Integer})
  • ++ *
  • Parameter 2: total number of signers ({@code Integer})
  • ++ *
++ */ ++ JAR_SIG_MAX_SIGNATURES_EXCEEDED( ++ "APK Signature Scheme v1 only supports a maximum of %1$d signers, found %2$d"), ++ + /** + * APK does not contain any entries covered by JAR signatures. + */ +@@ -1349,6 +1368,16 @@ public class ApkVerifier { + "APK Signature Scheme v2 signature %1$s indicates the APK is signed using %2$s but " + + "no such signature was found. Signature stripped?"), + ++ /** ++ * APK signature scheme v2 has exceeded the maximum number of signers. ++ *
    ++ *
  • Parameter 1: maximum allowed signers ({@code Integer})
  • ++ *
  • Parameter 2: total number of signers ({@code Integer})
  • ++ *
++ */ ++ V2_SIG_MAX_SIGNATURES_EXCEEDED( ++ "APK Signature Scheme V2 only supports a maximum of %1$d signers, found %2$d"), ++ + /** + * APK Signature Scheme v2 signature contains no signers. + */ +diff --git a/src/main/java/com/android/apksig/internal/apk/v1/V1SchemeSigner.java b/src/main/java/com/android/apksig/internal/apk/v1/V1SchemeSigner.java +index f900211..6422af0 100644 +--- a/src/main/java/com/android/apksig/internal/apk/v1/V1SchemeSigner.java ++++ b/src/main/java/com/android/apksig/internal/apk/v1/V1SchemeSigner.java +@@ -16,6 +16,8 @@ + + package com.android.apksig.internal.apk.v1; + ++import static com.android.apksig.Constants.MAX_APK_SIGNERS; ++ + import com.android.apksig.apk.ApkFormatException; + import com.android.apksig.internal.asn1.Asn1DerEncoder; + import com.android.apksig.internal.asn1.Asn1EncodingException; +@@ -249,6 +251,11 @@ public abstract class V1SchemeSigner { + if (signerConfigs.isEmpty()) { + throw new IllegalArgumentException("At least one signer config must be provided"); + } ++ if (signerConfigs.size() > MAX_APK_SIGNERS) { ++ throw new IllegalArgumentException( ++ "APK Signature Scheme v1 only supports a maximum of " + MAX_APK_SIGNERS + ", " ++ + signerConfigs.size() + " provided"); ++ } + OutputManifestFile manifest = + generateManifestFile( + jarEntryDigestAlgorithm, jarEntryDigests, sourceManifestBytes); +diff --git a/src/main/java/com/android/apksig/internal/apk/v1/V1SchemeVerifier.java b/src/main/java/com/android/apksig/internal/apk/v1/V1SchemeVerifier.java +index 47d5b01..615215c 100644 +--- a/src/main/java/com/android/apksig/internal/apk/v1/V1SchemeVerifier.java ++++ b/src/main/java/com/android/apksig/internal/apk/v1/V1SchemeVerifier.java +@@ -16,6 +16,8 @@ + + package com.android.apksig.internal.apk.v1; + ++import static com.android.apksig.Constants.MAX_APK_SIGNERS; ++ + import com.android.apksig.ApkVerifier.Issue; + import com.android.apksig.ApkVerifier.IssueWithParams; + import com.android.apksig.apk.ApkFormatException; +@@ -303,6 +305,11 @@ public abstract class V1SchemeVerifier { + result.addError(Issue.JAR_SIG_NO_SIGNATURES); + return; + } ++ if (signers.size() > MAX_APK_SIGNERS) { ++ result.addError(Issue.JAR_SIG_MAX_SIGNATURES_EXCEEDED, MAX_APK_SIGNERS, ++ signers.size()); ++ return; ++ } + + // Verify each signer's signature block file .(RSA|DSA|EC) against the corresponding + // signature file .SF. Any error encountered for any signer terminates verification, to +diff --git a/src/main/java/com/android/apksig/internal/apk/v2/V2SchemeSigner.java b/src/main/java/com/android/apksig/internal/apk/v2/V2SchemeSigner.java +index d8e4723..03a0311 100644 +--- a/src/main/java/com/android/apksig/internal/apk/v2/V2SchemeSigner.java ++++ b/src/main/java/com/android/apksig/internal/apk/v2/V2SchemeSigner.java +@@ -16,6 +16,7 @@ + + package com.android.apksig.internal.apk.v2; + ++import static com.android.apksig.Constants.MAX_APK_SIGNERS; + import static com.android.apksig.internal.apk.ApkSigningBlockUtils.encodeAsSequenceOfLengthPrefixedElements; + import static com.android.apksig.internal.apk.ApkSigningBlockUtils.encodeAsSequenceOfLengthPrefixedPairsOfIntAndLengthPrefixedBytes; + import static com.android.apksig.internal.apk.ApkSigningBlockUtils.encodeCertificates; +@@ -28,6 +29,7 @@ import com.android.apksig.internal.apk.SignatureAlgorithm; + import com.android.apksig.internal.util.Pair; + import com.android.apksig.util.DataSource; + import com.android.apksig.util.RunnablesExecutor; ++ + import java.io.IOException; + import java.nio.ByteBuffer; + import java.nio.ByteOrder; +@@ -163,6 +165,12 @@ public abstract class V2SchemeSigner { + // FORMAT: + // * length-prefixed sequence of length-prefixed signer blocks. + ++ if (signerConfigs.size() > MAX_APK_SIGNERS) { ++ throw new IllegalArgumentException( ++ "APK Signature Scheme v2 only supports a maximum of " + MAX_APK_SIGNERS + ", " ++ + signerConfigs.size() + " provided"); ++ } ++ + List signerBlocks = new ArrayList<>(signerConfigs.size()); + int signerNumber = 0; + for (SignerConfig signerConfig : signerConfigs) { +diff --git a/src/main/java/com/android/apksig/internal/apk/v2/V2SchemeVerifier.java b/src/main/java/com/android/apksig/internal/apk/v2/V2SchemeVerifier.java +index 51c40bd..651ed5d 100644 +--- a/src/main/java/com/android/apksig/internal/apk/v2/V2SchemeVerifier.java ++++ b/src/main/java/com/android/apksig/internal/apk/v2/V2SchemeVerifier.java +@@ -16,6 +16,8 @@ + + package com.android.apksig.internal.apk.v2; + ++import static com.android.apksig.Constants.MAX_APK_SIGNERS; ++ + import com.android.apksig.ApkVerifier.Issue; + import com.android.apksig.apk.ApkFormatException; + import com.android.apksig.apk.ApkUtils; +@@ -225,6 +227,9 @@ public abstract class V2SchemeVerifier { + return; + } + } ++ if (signerCount > MAX_APK_SIGNERS) { ++ result.addError(Issue.V2_SIG_MAX_SIGNATURES_EXCEEDED, MAX_APK_SIGNERS, signerCount); ++ } + } + + /** +diff --git a/src/test/java/com/android/apksig/ApkSignerTest.java b/src/test/java/com/android/apksig/ApkSignerTest.java +index 1434017..729d96f 100644 +--- a/src/test/java/com/android/apksig/ApkSignerTest.java ++++ b/src/test/java/com/android/apksig/ApkSignerTest.java +@@ -635,6 +635,106 @@ public class ApkSignerTest { + } catch (ApkFormatException expected) {} + } + ++ @Test ++ public void testV1SigningAllowedWithMaximumNumberOfSigners() throws Exception { ++ // The APK Signature Scheme v1 supports a maximum of 10 signers; this test verifies a ++ // signing config with the maximum number of signers is allowed to sign the APK. ++ List signers = List.of( ++ getDefaultSignerConfigFromResources("dsa-1024"), ++ getDefaultSignerConfigFromResources("dsa-2048"), ++ getDefaultSignerConfigFromResources("dsa-3072"), ++ getDefaultSignerConfigFromResources("rsa-1024"), ++ getDefaultSignerConfigFromResources("rsa-2048"), ++ getDefaultSignerConfigFromResources("rsa-3072"), ++ getDefaultSignerConfigFromResources("rsa-4096"), ++ getDefaultSignerConfigFromResources("rsa-8192"), ++ getDefaultSignerConfigFromResources("ec-p256"), ++ getDefaultSignerConfigFromResources("ec-p384") ++ ); ++ sign("original.apk", ++ new ApkSigner.Builder(signers) ++ .setV1SigningEnabled(true) ++ .setV2SigningEnabled(false) ++ .setV3SigningEnabled(false) ++ .setV4SigningEnabled(false)); ++ } ++ ++ @Test ++ public void testV1SigningRejectedWithMoreThanMaximumNumberOfSigners() throws Exception { ++ // This test ensures a v1 signing config with more than the maximum supported number ++ // of signers will fail to sign. ++ List signers = List.of( ++ getDefaultSignerConfigFromResources("dsa-1024"), ++ getDefaultSignerConfigFromResources("dsa-2048"), ++ getDefaultSignerConfigFromResources("dsa-3072"), ++ getDefaultSignerConfigFromResources("rsa-1024"), ++ getDefaultSignerConfigFromResources("rsa-2048"), ++ getDefaultSignerConfigFromResources("rsa-3072"), ++ getDefaultSignerConfigFromResources("rsa-4096"), ++ getDefaultSignerConfigFromResources("rsa-8192"), ++ getDefaultSignerConfigFromResources("ec-p256"), ++ getDefaultSignerConfigFromResources("ec-p384"), ++ getDefaultSignerConfigFromResources("ec-p521") ++ ); ++ assertThrows(IllegalArgumentException.class, () -> ++ sign("original.apk", ++ new ApkSigner.Builder(signers) ++ .setV1SigningEnabled(true) ++ .setV2SigningEnabled(false) ++ .setV3SigningEnabled(false) ++ .setV4SigningEnabled(false))); ++ } ++ ++ @Test ++ public void testV2SigningAllowedWithMaximumNumberOfSigners() throws Exception { ++ // The APK Signature Scheme v2 supports a maximum of 10 signers; this test verifies a ++ // signing config with the maximum number of signers is allowed to sign the APK. ++ List signers = List.of( ++ getDefaultSignerConfigFromResources("dsa-1024"), ++ getDefaultSignerConfigFromResources("dsa-2048"), ++ getDefaultSignerConfigFromResources("dsa-3072"), ++ getDefaultSignerConfigFromResources("rsa-1024"), ++ getDefaultSignerConfigFromResources("rsa-2048"), ++ getDefaultSignerConfigFromResources("rsa-3072"), ++ getDefaultSignerConfigFromResources("rsa-4096"), ++ getDefaultSignerConfigFromResources("rsa-8192"), ++ getDefaultSignerConfigFromResources("ec-p256"), ++ getDefaultSignerConfigFromResources("ec-p384") ++ ); ++ sign("original.apk", ++ new ApkSigner.Builder(signers) ++ .setV1SigningEnabled(false) ++ .setV2SigningEnabled(true) ++ .setV3SigningEnabled(false) ++ .setV4SigningEnabled(false)); ++ } ++ ++ @Test ++ public void testV2SigningRejectedWithMoreThanMaximumNumberOfSigners() throws Exception { ++ // This test ensures a v2 signing config with more than the maximum supported number ++ // of signers will fail to sign. ++ List signers = List.of( ++ getDefaultSignerConfigFromResources("dsa-1024"), ++ getDefaultSignerConfigFromResources("dsa-2048"), ++ getDefaultSignerConfigFromResources("dsa-3072"), ++ getDefaultSignerConfigFromResources("rsa-1024"), ++ getDefaultSignerConfigFromResources("rsa-2048"), ++ getDefaultSignerConfigFromResources("rsa-3072"), ++ getDefaultSignerConfigFromResources("rsa-4096"), ++ getDefaultSignerConfigFromResources("rsa-8192"), ++ getDefaultSignerConfigFromResources("ec-p256"), ++ getDefaultSignerConfigFromResources("ec-p384"), ++ getDefaultSignerConfigFromResources("ec-p521") ++ ); ++ assertThrows(IllegalArgumentException.class, () -> ++ sign("original.apk", ++ new ApkSigner.Builder(signers) ++ .setV1SigningEnabled(false) ++ .setV2SigningEnabled(true) ++ .setV3SigningEnabled(false) ++ .setV4SigningEnabled(false))); ++ } ++ + @Test + public void testWeirdZipCompressionMethod() throws Exception { + // Any ZIP compression method other than STORED is treated as DEFLATED by Android. +diff --git a/src/test/java/com/android/apksig/ApkVerifierTest.java b/src/test/java/com/android/apksig/ApkVerifierTest.java +index 351d0a8..2392b88 100644 +--- a/src/test/java/com/android/apksig/ApkVerifierTest.java ++++ b/src/test/java/com/android/apksig/ApkVerifierTest.java +@@ -239,6 +239,20 @@ public class ApkVerifierTest { + "v1-only-with-dsa-sha256-2.16.840.1.101.3.4.3.2-%s.apk", DSA_KEY_NAMES); + } + ++ @Test ++ public void testV1MaxSupportedSignersAccepted() throws Exception { ++ // The APK Signature Scheme V1 supports a maximum of 10 signers; this test ensures an ++ // APK signed with that many signers successfully verifies. ++ assertVerified(verify("v1-only-10-signers.apk")); ++ } ++ ++ @Test ++ public void testV1MoreThanMaxSupportedSignersRejected() throws Exception { ++ // This test ensure an APK signed with more than the supported number of signers fails ++ // to verify. ++ assertVerificationFailure("v1-only-11-signers.apk", Issue.JAR_SIG_MAX_SIGNATURES_EXCEEDED); ++ } ++ + @Test + public void testV2StrippedRejected() throws Exception { + // APK signed with v1 and v2 schemes, but v2 signature was stripped from the file (by using +@@ -630,6 +644,23 @@ public class ApkVerifierTest { + Issue.V2_SIG_NO_SUPPORTED_SIGNATURES); + } + ++ @Test ++ public void testV2MaxSupportedSignersAccepted() throws Exception { ++ // The APK Signature Scheme v2 supports a maximum of 10 signers; this test ensures an ++ // APK signed with that many signers successfully verifies. ++ assertVerified(verifyForMinSdkVersion("v2-only-10-signers.apk", AndroidSdkVersion.N)); ++ } ++ ++ @Test ++ public void testV2MoreThanMaxSupportedSignersRejected() throws Exception { ++ // This test ensure an APK signed with more than the supported number of signers fails ++ // to verify. ++ assertVerificationFailure( ++ verifyForMinSdkVersion("v2-only-11-signers.apk", AndroidSdkVersion.N), ++ Issue.V2_SIG_MAX_SIGNATURES_EXCEEDED); ++ } ++ ++ + @Test + public void testCorrectCertUsedFromPkcs7SignedDataCertsSet() throws Exception { + // Obtained by prepending the rsa-1024 certificate to the PKCS#7 SignedData certificates set +diff --git a/src/test/resources/com/android/apksig/v1-only-10-signers.apk b/src/test/resources/com/android/apksig/v1-only-10-signers.apk +new file mode 100644 +index 0000000000000000000000000000000000000000..198beeb651079d24338984de7f32e8e0c7b4ff78 +GIT binary patch +literal 18389 +zcmeIabyQr-5-&VB!9s#da0$WP-9mssa0%}2?(P=c-Q9x+_rcwQ1ef3rZ*nxrJ?DJq +ze($fh*6mrnT4wfd*RI{w)m>FR(&7-1Z~y=-0F($h2tN);c|rgH-!c*a5@4-oV_|2l +zqh~{-Wo@JLFaQ960}y`s77X-zFaR!~0#t&2{A&VrzWluoDp5dL5R{RT<&4ao2>2~6 +z3G^+j2?XV20R+^l-C3Pwot2#}1f71Jt(~m|Js&#jx?>4C1G=-iGYBlq^$2VoEC_53 +zt@ZTO00ew%o)K%FW#53-JWD_gf?qp8pg*)hH~66qy4kPoZ*+kZfOUZb03M*K7Qh^! +z3$O-Q0E|E-4XAAi`q%*U06G9WP`?qt7T^Tx*8!C_pwbr9V-D*1^>^RE{@+dnpmzmg +z1wal|etVbS(zo}?1S-Gv|B^soko;Z;l`x2ftpt|MCpo>A}FT?bo@b%1<`2XAce2@R_8U6`h%UVg`{|5gXPozQeiVA>*{dQkMj_=XF +zNgKbpuC;}cuB4W^k-nadEsdj@X_#D-ISM~2cT+N(KS>Xtw@xotFe)sC3HVC_Ar$cE +zuf4#9;5c+rG__Jgc~9 +zjNnItmF|v*EztbP!{M@O@oXf}P3Km^l{7qXMTj1NhYZt2zQ%bReI<yZX7jzat(dIt3q2LBw{RHDL6tCdzd{E$f8q6F0uQl- +zaX|r-Xy%Ll`fY~-?!0-IqAg3qJ5N{>-Etd@HE8o)iZaUTffbX*^7T4_SKGzb5p`*4 +z9~=$dnC-IE5W8qQrAFT^vz2Oj%2Pgc){G=Xpz4wRfXw$Y`PWF>e{xHxbDn +z3>eCk7#2(VDcpr+d*h--rhDO84x#WYj&?Pq#bICpC+b@EpfMW={ZGRd9yDxq +zOtoxmKuShe&oL}U(hxLUdsoc$S&fowqt)cdp8*DS|(Uq1_f%?i|%Ka=kAA%OLMBemAf${9_D7@M?FZ*kG` +z*qrK?=)`WoGtX;@px}YVW6(nG6XIY_>*naNzVJrds)R|7{RtT#7GN_!oQ&V?2GLWE +z;GSL=ZLC`f;uHSa=Uk`*!Wu|wQJl_p?D_bY@A;RBSE9HHJ*xvF76tGKEF#li!vJ@L +z8Tw!ufZ52@huHWnx50Jh{TASV5#$x9rwQ4_>#?TUApG9$%13z2#$sI0qA$?FdE +zX&qM)?{2qae8!4mrpjf04G{O0 +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 +zEdXJvXh3)%(%Z_KU-#u>y8la`VV% +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 +z_DLu*e2MNaKG( +z^lyY{*tuAK7bHYnAR+p}to{cZf03dp%^#&`0whJT|0G43ASt3jhNt~aind{wC|!&u +z$mIWx6rn?J`uF&6lKJO-GscJzl!3*V5NN;DB>;?dKAA$X&_y;P80tY{i4S^a48};z +zS&ae_QZhmjmsLBlGS}=h(lpLuB>t%~Sbu%kDYxA~!~JsJIbG|rY(ExkMCEz8&C$E~ +zx6fnMif;`)o}ViFRY4~fHPF0y`kOdW$NVBrg(;4*$wBK8;+Kkblt)qzk6Bh6G|PN= +zB&9<{S_IPs*21$)ItDdfhV@YbtHpR*k7FeUZ!y2OTq1$%KZS-+B!fC1n!>3c;ys(n +zIq7Q@8~mWB_=q^3XqV&?Uw67U!x(`D%Rs^K{>>FNC2iWN&22d(@UZQb|0%aJ2Jd}S +zq}CiSMQPY6?+~NuKE2^SWKWnESDmGBICyA*j~^~2LT8eVKx2C+nc2@=N{ePks^k8zoO$2(E&OCuKf3xB#8!{ +zCSl?zVI~PSD4oY(!B$lINa|_p>P(sIYDsIq)z)lqCu*?GZ!ukkj6R$u4jG|)yKFw_ +zG`6;s#dtEJ3*<1qdt*HE=p?DEr2B;yQC@Xo?i^@lXFnluo@RzD@z7RmCn(h0HnS{c +zK5~8hFt{teYb}cwZq|0<5HDPQU)4XvsNH&8@*Y?7vjG9TZ3q>92xds%Wi=1H2JS)h +z6i|(AsYBmK@3Q?i5&DF{NDuu9L?!e-oFgBcud)(i0v6UIaR8DHnGZj9G-2oC^?c=? +zszIL}US$3KM1~?0yWM!0xIIprS>*z-XszC&NPj5RZ4jSU-X*{Dd|0K-AFAMs_BM2W +zZYYuJtng+`5tcZK`}IBjvZ1lZ(Pm#qZT-q(>;A&xR;Q~==Sm?DG+GBy{c}VdMI5Fw +zKufYr+Va3Y5w8C`^e@#UqX+epoP6{b%1P7WP+VOmeJ+~X|_X16UG;=XV#OP +zR`le@p^cCGL87gkSa|AY=N#)(g-sp*pbr0IF~rP3|37W`Z?qwv#7Dn8ketGRyrX}~ +z#b0DqU;hVXxC4^a2^f%XK+qjRodxL2^0Y@zADv7@0UE;GSD*(DW#6V9cMgT8;U$tR`S%VgDej*jU2f%PJF)1zA%E24@gtN-kRJ>&O^d +zobCD45vion@NT`CV8$B-ro(Ak|&mWB8`C;aK=Z@^)$Ohg^;4!{sIi +z4koKRZ2eV>rqLaGKKW54<5U_Qcm?#kkhC9JjfPq +zlRX_f{oVb-{2AFm{k;vw;A#N5A_+}dTwhUz+tD!#^_w>~sd0mk)mZr^dFqz~;>N*E +zcIq6pySxxZ50V1+eaDjC1*B4Hygw;4B=CNj_WZGOb>tg#QaRPk#^Ct@=ohs{&_eI=SPP^lEXPR!Cu$$!P1eD +zkFr9$+2>OukEav|>bLZ}=Jf;eE_Iv(r*RsL>MY%wH`t09=~QZEM;5&5`Hm-R7yG@5 +z`?+E1Zo(w2<;(wmYe;Yf&^`zmR1mw941mz!W%YU#DQ~_-{jed-s$OXktrNBg2 +zQ(KFG9B5*wuW4#(XsB&$u8l+^8s#5fqC@UCVc2Y6O|<11+s=-44KogAR_t{H3S#9+tgwTzq2t +zqvMgiq-p035fPSh`pg>k4YzxIk6lhqMODvku^$Ru%u+Nt0*s=cOKBbTJGAXx2ixDY +zP^sH{TsIQ$I6QK+m_N4(VMRw%&Ck!z@#rnG%i`=s)#z!#lSN+~d(Twcq1mk{h7^Xd +zHTTNN4+Y6lx!m2-!>HN0*2!@yLMj3dh2gm}IfMGwfxtQSv4hwy0$SaQgOJD-=*|z6?Iz +zNyjb&BW99PUGXkb8j9&NR}(vz`&;|uWSn#wQrE35GDIK7q?W@HvuAJ1ZmR9{xjbwg +zHN!*j`uBxa7g<{NfGt63ULm?L!E* +z!4k!WC6cAO2W2f&R!w`Yd(`Jbfld6L2I^!7eZ^&`LdX65i!3yc7I>DTjRE=Na~t48 +z<>NLPG%$>I3XbgXOc_T#C#TxHnld8E>i$w??{lZeIwg7Ez2m`@jrn>_&CVuc-BEQ> +zigArOFdNuPEh&zejM?I~1ALJni-1~@r%;3Il@cvIK_`wv?DNF}`tqUhfq!en$~4_- +zRZHi-`_oP?x)E7^8(WKQI#$sau8Fq`yc?U~QELt81J8`$eWTSEB(z+5HWM(8Gk4oX +zJAEWfkX$z-rdVt53(plxU1YDYm%)e2lRaWscx1&K`v=!`Uev4+J-or|pIzd@ML~M?3UiBWzH+2S +zOx#ogWqETr!Af}MDB$8`nWCIkt!(Jdalm}3ClAe-^u>sK8rL@cdi&Ak%{!Xu=sXis +z*$Zx>N2@V4?#tX%cv2kwT}X?MH%!N!-O_nIb9)g=D&4)tGa`jhs)NlSkF+Dfe=|EX +z(Xs!}9Qd#HSy}oaY#gAF{XkIukJ?B8`pPsInNCC3=3^sT#2nF +z42?{1>@G4$3$le_jTMW-U&BtJ7mnKXa_knp$}%je@n<%bi^&2`56@@Fuifno0rwy5 +zZ?9=^n +z77i75#;?czq=qN3J!8zd(O>D_#QM1sf?*)bRnuK-5V-99c_eT?Bb#S+oi +zW;Erlep78mTpK1Qt`^2frV*LTAqi}R!5Vt#K;ckhs8FGGFv)-uJNzOXZ?;UZ#qxv? +zocHX#>*%bOa&A+~4v#l&=2}?J>HbhMwxFf)8o{RV(&|gGCxVIk-X}w!p=acaRrfLz +zje4-k6(WV{gU9A)gI|cEHkYTl9x)$973xRWNwkzDG0dBNnS8}a5i}R7zl&g*(mmIRYXKG9O+$j6IYun=ZS +zWj7)`^rHuUk$z`o7#OL>Ht~x@gYjybtyO*-pJh!t-P(KiCg3YiWYRI}i?r)sEiMNp +zlB#ei+P$6vpgFknI3R$zsXi2ioko^kTL%?$T8z9^F$u=rGCex+e>3A$aZ#C~qdFj^ +z7-Ld6zb^VR_kog)O}t8@t9pr2B-_mt_%%XFt9b3)LZ$9w*BtLrMHAq35b?D!h*%;V3xg +zD74&sNcaa50{GYPbr|mR(#6;OjlQh+qas$Pp@mJX1t(@D(0x8t8%OY6ZBL{&7{#_lM +zxGd4z%<-*ie3y=M;nooRGc3vpDbQ?SyQ-olN-+y!R@$j>)6`$=BK4l=(zL@h3mSTf+>+W +zn6@z&+?SYVeyno!g^!3KRznxn+wed52!@72ZgOoIuA|9_jJ+y`%4OzZd-^~+_MVHk +zw&aVcN!hW|GxN^;phUMFl^iCwUF@;8N|Oc`M)$di}UD=w*VO<|H>bC?Vvc?-j-Fa@4b=HbnYTtK#6V|cp +z8|6Hd4er{_zaVu;KTWS%R6^6c37JcRjL)`GM6P4G3BG$zm!;*LYH5*FgO;u(7bj25 +z!?P9ZMSUJAtH$v_tT0$h;$`xsk#LWT+C0;TlDGmJ)tihO{rFGu3G7TStKNz9ol3B2>j +zYU>V#fh%c!ebAU-o6MI%)zXYbI)pY?IJ*&$9b-6i_XD5@JsB$XR;Y!RDM_GL9|D79~WK(%)rw*xD2u9){B5YYmr*erTT)yIjG>lddNfB +zJbhV76KGCj+oLQZ=C?Q)OcV(5DQjHuyjOmL7msnFw~lkksn`FVEEco1F>shS?LOY& +z(xlajIVIX|;Bt#j=lRham=n8fGY68L +z6VoI-YTC+OPiO~@a2-OLneHCzFoD$hfKob%a#hTiF#fuNcv3$R1Ruu_Y3L@sA4o-# +zDiL~E5J;T`^$KHxs+fYY$kXy|IJV9??wyYATU`ztF5U5k_=zG_ZKKUT_{jj^)L%bS +z^?#`i&Ib5A8i{HhB2|UR2mQ>F4*^>24h9mA;xmU3m?9zEVm-1igyj|bEPO8DA>2LY +z2xD21fS|HJy4}oY^z|qd*qh*V_B|8N0Er8}S0^%TIaK|Px=`&*>?@5;fDbZr+EV1Y)=BQ6%yAsLx5QoCzY0HFquez&9oahEoomIj +zPreA1Z3Je3FMi1n=w(?9jUe`BA0{$8Q3h{_1M1-K(mJ9X;;?_dCrVh6;k)Ow3(5B; +zOfByYgX)Hc-_#@b!b}xpSyxbbE1IMpy3>{}|HgHH{)ludE3PPN4pTlf`7nlri0P$i^J-2NUfmtIJM#TJc*zrdpO3FLLv-)mOd)=SGR+1p1Np2s;|*a?kmf}dy{o5ySpWgWz?7)w9j +z^T=v?^3y_h3KIfUf(BoF2$D8{F0wWj`-pfg`wf-H&BdXu;h9C=-AgA4nh(>wxnDS~W(xf`i&7mX@brTki^n@S +zqnjNl-{9DU3)P5gyM~$o(dxfe+T(@#if-uyFit}?x}A_U5O2aja#%k@FXKAGd9B(V +z&DI5BFqhCyNi!8L)+x@8;ajx0_aQ7lm^P`(#!Nv5&wy*kZl8@iYL?*a4IUy23CXe` +zRce-{lH9G2=!%YDH&jk!s@m#Y@4`|K+SEx)&_Ds|ImdLLJaqrC6~+Vynw7LDV|)-I +z*WKq=T@%Bi`mYZQc8p+g%YVQEO?2z}YIGauj5(-+oumR7za +zO)Ov@*F}*oK1t*c6RRhTMrwrDA*OH7o^Ss$Gi^rv3Po~G7#B*y_|uaKPt#czEjFpt +z&3&~IJncPR6UEAkY30eN`Yh&80twDWAv2Lb;+G3!g@@#{dA=r)K$-?-`Nx| +z4CG$C(bsvxx1mYAE@y8l+3#BKoej88Zd^CzfXcZLtaaalUE%0|WDd;$JW)-oAK60; +zmscMF16Hi%b3Z2W6M*>~uSgzUAchKwJFMPSsLLPa&+lic{G*bhD{{NDox^DBfM28o^lm7%#kf7*`5kpoXpDb0Hw? +z#V)?1j|?=sD_uVkUI}v3t+A)$;vJLqdUGH9}iNWs00w&~R=-7F)5AV5!pp +zP{JxswSB^;lpSVhgV{Y-E;xb|nOgBRH>HiiNoP3rc2Mx^!*HiiXQzPs9@i16Q)oyw +zLNdxG-M7tH%hh`rNkX+T6oPz<_^^+B7Sxi)RRLaMFT@Uotw+?l2d= +zT4;O2>bxg-h=Gde0qRGUDKus_dJhWrc?a^g|DZA@`QM6(2+PXRNQ&qUNs9aO0X$cm +zK6`vsqH-^7Y!rauWieJ}Mx<`)`Ygdxz{tRuw@^Mp^m29&{wNyYy@HHk?1$MKa}`{O +zRfS3q3F&R@_<)qA-#i~49K;vusopSvY3Q6I6cZK$R_Q)dMIugt8Cebq$q=k{LTNHM +zIyk^?mso*+!TDGUu?AW_c3OBTz(>JF#^#RE0VLJf< +zd^SU%LeoEiI&%vIW9J=Fr$!>FE7jKVb!y>~bN=wjH3TV5RWkCC7;DW|dpH=pCt2K% +z_u1w3x*JJeg7?sVFgm%{q50dLmjl@^#-1;VET{NOEk)db*aZd-2l)FxX8`f;yY!!b +z)$r|lR1jRGNyIqF%JZKH{~tvBI1n6gzk~QQ`0i&KevUNz +zlZKWTe*qvY_%p!Yzl$dP{{;9Jy7V)`&v80`k^oNlR|x-1!;f6RBmN2D*VvAqN%%RC +z;ZG8DN&W)hzoB4&>?eRzm_Vu=2)5dJG7*x7%A_#46edGGQk +w5uTv`>G**YzwcyzevY42;-3(veBVKQry!-pp+HkF0DuYlkbr8*{NGyt2buzz&Hw-a + +literal 0 +HcmV?d00001 + +diff --git a/src/test/resources/com/android/apksig/v1-only-11-signers.apk b/src/test/resources/com/android/apksig/v1-only-11-signers.apk +new file mode 100644 +index 0000000000000000000000000000000000000000..95e6c61e2f6f1b75c0941c21a8e728d60821894a +GIT binary patch +literal 22297 +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 +z6G!97 +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 +z+bS*?E$ow+nNbavl}Pi5M8K1cC5&#J;?k +zF?e0C_lp%r>PGzzA0q3Xr@ksPusTeJi92GoSyU{I7H!s96&Vhvxewt`E4t=)U5}`h +z27njr=yB=NgoI9I4~pg%h~sCXkU+4zN1$W5ih*-M@i(fxDdCe|8;8!Pj3 +zv#H14cXq=$lrnVty+`WX6n*xM6YmDLJ&mCxqZ>Mm?$!Ep=8y`aEhPo*PVZORGergQ +zLAh*&Y7VqfCkeFc3ze%Dg`}1(oAo)%UeLBx4?rBjfALDmNJslWb@+GGq4Sq_p9=wU +z3ISLj{kIwK2N!>lRYToBXv2dlzyhc%V0D1s15}e~)Q{kmxo_?8juZS?#SpTFzPDa(b +z_UZm{9;wv1@!|IQ`SJ1T`SE^IvDCTl`S#9n?7^O*e4AQtAT0KI6=ESKr4u1k2!q{T +zCcwf)_rqWq<{o$hYU=#=or#@D`J<4R%Oi!;EAce>fE6#X|=V)UO4YM|N +z80kLI_#ML(WGXCJV5YP8R7^Q=NZVV_|2y{Y1VQKY`*zvW(cOYovY;87=S+?~gqe%sxo1+2W +z#->I<$^XPPqRvECF8QeX(@Vw(iw6C5qq3%){PH!r(b(DWbKyC0aNQ^;r_-20HrT5& +zF^P~ye&>#s(e@38zNp$W*>d@O!4|iZbej51`m;J1yg%Km2FY}*sg?ob(s}GCeHDeD +z208`m8Ei!5J)xsv$K*+Zkv|M3lO~NZ2aE(B#KpWWG%KDqA+8EoC0#j#BL+h)=(9cb +z$n>jA()5QE%A>)E9cI=hi}mXfN%ECEP1}p?;Zv8e4U?obCHk~B*W@kW*GeQT;wASj +zrib3<;#`x-Z7-t3(JJsH>@>!jBGj>s23kG2G0GrrlJM>A!x1*Eb(e|Wr5(L`KDUN4 +zuft5p8GldgsoWLm>8Al_Ep*g#S691L&|JuPa(2VA#W(+9e)z+So*W>6;(yDRe>Z@F +z<4waeAz=CP3n2f&!Tc{a0xAHj)8vl<6uE!^iroJgK%oT)pvVBI^tWjLoFlH1Ft?Wt +zke}fvAr<@k;igH +zj%QzyLl%1E==KfwvMXt)uDs=t2VAuO@kBXDjN}0RC +zJW5XMO0}>kAI6nQ)n2l(yu!Uzgya<-PN>Jq#}ftTNWjY3JvAsP%G>6j(FyzdzeFc= +zC)tO9A5t2sL${2|Ef3G5780ab;l7PlGK``@Fl#UMg3RGb^q=uciaO_3^P}_iNj`TS +z9J7#=?oM!()>6)xyPG<=J>EMeA!eu1lD=~On#wz*wSL$QqenAIjrN^pJCdTjPo?5MA7TJqv@eIo|3f^;D9_!5F?wDNJ= +z8s1vdle~r@tGc7cBWk^nZx^SxfilI(P8r^d)k(TF1v`0iLi+`bgP@a~P-m}l5*=;%H7 +zv>)W6nh@u=v9#D{U=;0eOi3+qZ|{OcZ8o3|zB7UGi_u(?&~feEO+-7-JnRte@|7@y +zciWAaVXk>DyjK3^Du0K$3Nlib;u*`tB`@kcFx1Ac@)#oMoB#UwmW1lcY$0Emb9!Oc +z(Q@;#^ay+p=fK$Z%b5xbv+!YDt1I8~P4y=Ji`a*O`4tXqBzQ71^gZImim_@@adQcz +z)!mUq8^O7=z?+NJk7djnrNd9ogO)43c_^kt@5emSIreF{I?iq%WT|Fj^32TTZ#eN^ +zZ6-80Z*$XNh_DO~!K~^Z7|y$TWb%3!jv`dldiqS~gbKmchnfM)($2X5&FsuT!}>pu +z;NLQ}vJ695*Z^_+UjX^vX6Ikn2$-EMVqIvKg0On+++-bc-WeSk7uvbH5!g%_o0wra +z+(}u=m(H +zb~(y^#&HS!5x=4{i;aPNF&Rt&tT*S&6PTQUkB$r}Ca@S(NaIw=*HvpE2oxVL-B+kg +z3FvY-IUryWZ+HDp9T{{9OmBEVxUW9B +zjnC_-<~F4saQRSYZieMt9uKEr@>`p3;_jNRY>BT5h +ziWH;`o>-g@elLvNT$b*3#&{N0Xc*xj(NdaBw`j35O-BDQXd%>a6<$D%DUZ-b{#%cn +zCa%XTJ<=HBGh^?oh)GzdjT4&gP;OPiHK#DnYxIZ%dvNM}6l)K&#j$0R%Cymw*XrKu +zB9jIBWNi!w%agwyHzH1}j4lUV^~obgGk@Fecw7#VWxB0zjPxYJ`SKnVsD(=DgAf<( +z_=$g{|5Yg(TAHa{!ZQ9)f`)c$rT_N2yjhofN8iyDOvQy<23lQ_ZXMb3>X#%UH4bG5 +zkr^NqCl4+sSYUVcm!h!C$Zz+yLB;G=V^V5n!I*pIXBPotb1vmK6{&jagVM^eW`&De +z!lbz`GobEA;@RK!!0fjulFkJLi+ +zZxd%b3fMZA$eJ&f@4Ib3di0Q(F5*KUc-mA#^ftV=QZD?cd7{Xi{;!Tk_(qOHQL!Ij=4Nd(Ffo;d{?biqCsY9mI-xN3=k&~% +zkX$>WmN&qmEDCGXl$IH^?Ji2@a6~&@C7025NRb|&rgE6KCQJsbf$?oWOdua1+GSm}B7bx2zkdkpT=k3kJe&>U +z*2B9beM&n^t6o$>)wc_lONfBOvQ|W*XT1w@_)L?f^Eu7hD!CdZLq{QAk${V9FV36t +zI#OPP?S(*TsD{wnY^M?Lh=bBH)0do}9241xm=g8;R08F&^;_Z*W{B#LLblgl*CCNv +zg^)E`qrPFyz5b&tC7(lnVpm`}5N}aji$iRiQk5gM-WfH74V#MSXNqKyt}~mxrw<=H +zy4G@MJipvoMZa)&0YSssa_>$aw-`xSU2jBAAXPY3;XsyQHZM~p9TLL5bOa|IedS&j +z#ad4)(P_JKO^rc%Nky3`eHpyu9S%;=43Ykr0C{CBkvL!$ohMdpLkwqn8v%YBKMv2^Y~FgHvNom+M$Woig!$y95hg)#3-lkl~ddJ(0;NrtBX&R=J-|!43lKJ +za{AT1xJ+iHd=;|tOIK(>PiO2-W}|;~J9TBEersyh1?f&QVp=6jIh))CBP^p81h=&w3PBgDUQr(>jB|hn54Jf*kn?pW}-JLXG|1 +zFg-*r=Pi+%Myy*zqbQRm{V +zH=BLEA5M|Aj35U5irrt#x?=AQ%?v=a8iz7UeH&{PE7B;KDEsgPgwh +z)EnA~C0GlaZlQm~Jc28IJ*bjFs9G7j6UJLxkU-=w1ncV@osMeO7fmFTTmjq51WWXp +z-=HuysFEQVgCsrQj&1Ln?b+q*xz+Ww;no93fEPbf-9E-5+FuR`T2thmdH|^|2n*2q +zcqFoIh;$_!55zlb9#{y`CrB{pkLzp#z{+^g%XJ8Tpw@S&^DwzUFX0}sXK1U+xVRMq +zF&!4Z<09kWz+%A}tVd>Eff6@7WEXNQdQcI48xl5P*)1O~_{U)^gEd@8CbyU!I}h#3AthXhb6L$o`qyUVlxv +z&z0g}>R4rB3S@|p-Tq^)Tdm{~(gNG5M@#(8Gg;N$CR5;`Nq+& +zAj>=XfqhKNp%DZ=tRwgq7pfo)@uPY;ht$qUr&z4(&-jUJay-xM4k7tIcxh!lVcAtmM)wQi27+BkFgDwFsHGfdSR(2@F)ZDnMhl4@ +zb{0x0~Ct0+AB +z3a{z$_kia_rfF;}^ewIQqRd>h1PvA-U$f2jD?$v6*q}|Zq1ea>(Wfgze9kpR1Rmr7f)K`c@%JlvKbtsgER6 +ze38T(CR&FV1K$XvM?l+=z1XocH)}yah9tQlhz%}b+WuzB%Y2?mhebMV_gG`>gYFTx +znQ}$>tm<@BT^3_IU*czz5D31qUU5af+LSIcK?8=G0h(`}l$D6HvUbHwgSj_ihI(&! +zwzUbi6dcVZ2i)p>vVopc8n?{Zz;kZ+YdrR#*4PGK8AHDUy-`o98#{svSJWH>9xdO@ +z=X_1(#Rc{~Uz0q$feRH7ciMO=*Hk>qUp&sz#Lf#e0Mne}RnsvlKQ4jGZr^mzM2S~) +z;HoN_&F4x~Y^`I1bGNH|$@rq_S$w!LGlsTVpCGt#8vhNZKm$|F_l8fD$(Y;98Koezjfg#&~xBRT^zAio@(R&cpE*2FLddKW&1Z&Ua6ag+58;GZxfCwF!Mj +z>|)OoVS8Cm{4@O)B&r9j6sym34T%K?Rj_Rl6{!lMK_j_|SuDjS{NG##M!2Dg;LmAy6udaFW{@U37(G?gs^noQAuEes&3b?sXfJzJvf{!6PPb(wAz+ +zSgkrjOBSe!{m9R=j05$`V?`-xS{dja_FnW<&~{9tTQSzOqDG?Ven_sj)rLr}T34go +zNAyLe$kszLn&(g4ff5rO?}o9o`- +zVLA%@7x4c=WwOw+{x8b+Z<+Zf8nsV6Z~!wOkpIoh|Amb|RA#&j1F|_*;0QVrZAc~I +zkV;iAtnRTYU!{SlBc>{!BN^Rlg&)3almU8{x#&UysUd}b0G-|%37%^2=$z}Q(`a4l +z?bx12>6-g#o5vpCCN8ZuY9UKk{d=f&WP}J`KU|wgAY33XA3Qv5)C3m(b_*c{g!XPP +z{pYt(?OTZvku1BMgzyZ$MqnUbJg5N?JO&)9uy3E)Z>74 +z1x6<;T-S%2$kmyzo1SxQQ9$tLbe!NOwev-lf#9k?ru%9{100RtbzPZMT!rO`Q%+>- +z!@!3~f&<~|4D+^@!@9Ms;@f*{RB6)4w_48%7IB{bwUolEM{CY(I%30@dsXoXb?IA} +z>)*KN2vaD->{4A<)4A*3x9RK~shwTs*5>-OY{lQ>?P@3t!5c+JD|l>!FIKH*C-8@G +zLPYqJ$)j9zo}7!l!u6@QHf^Jaoi3Je +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 + +literal 0 +HcmV?d00001 + +diff --git a/src/test/resources/com/android/apksig/v2-only-10-signers.apk b/src/test/resources/com/android/apksig/v2-only-10-signers.apk +new file mode 100644 +index 0000000000000000000000000000000000000000..ad34c14ced8a53dd4c5cbe18a147de6e99264bda +GIT binary patch +literal 20688 +zcmeHv1z1(hy8kXxK)NJ0-MHy)6r>SQxq#^Uh*a4$J?+osI*7*$H{h+hHD-qrq+LhCl1-G{| +zgS)ud!(A+#%*^yaaPbAdm<7Lzi-8vW%76m=TLm!aPi5c+Kb3)-eJfu)7X%J|4grCD +zflDKh9mo{q1hNNN0y#TSb^!jIL1rKmkSkDc3335>0QDw7?hNEEK#d(x^R3;*VE?xh +z9GEMB6(DsWznII5bTOaYKz>pGH347He!m8C6o6nbBNrDZ5Hhl}i<70@ov(dZf%@-b +zTwK6`^7n*_YUJQxU}t1&28;{A24MqVd~bVE#s|t5_q(WrUE~l2kRgzNuTuf8`2qT` +zrmw&TIs^GvnEuuHW_Fqq|LT2y9RK1s{MGnIPMVVc&iEHRQ32!?AB2i}abGIIA4j{8 +zHVHdZCwog%MI$>)b2Dcbc6VEwDD@^gJPCY}rZoN#+HUaxlOEx4d{icD2qRn?4}vS} +z50OR}G)Xr!N>6Nwet?dSPK56bA~5J6Qc+deBWLn+-X3}$U(H6m;oh_I)@#eeoSZ5~ +z0t;28D;c%O@QJ9P*E@Th;jnuqpB236qQmB-IY1QHD9;%dgm&YPu94vcV?U9bq0z@h +zdG2>~{S@#d~~~I#BeUY2Cdr$wO4fG-K=|TfMS-HFe(p2jgUK!S*|( +zwkOTh)611iPPe>5ny^fs?%V95>2_XO&y#f^;_>mch_xJT9lH17xTkjO^_gmY99 +z{h1Zb(-9lAW8|}S?W98_GGV) +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 +zHb)ceoaJ*xUO6e3FQ;hU{o-@RnK9|Z)TV>R> +zj?HqYxC~y!W+hH85Bunlzt&Cos@tb%Q##{>o231zNN;>O-6xrpnLc#!c6SRKg@Ehp +z*eF|xb%^y#ll}HFr)hg~&bx)!hBiSM%1FGiZ$lPJdbo0`MtkW|c;I6rV_Ec;60V{s +zP47hf=mKAN6n=zMHx!8FPtiz?d=yIHi$zDR6h_ZBZhD&)e&0(<9Cv#-jA=;c5tWp` +z=UoG{AzvF3m*J%{J(>8LD+@U%uJL@mZoMB`Oe?xWd+|N9`6RRvi<|Pnopt+HlaIy( +zK6a!r_q8zL9aBbpn(GzJ(yQ`sj46*;k3c7VRn*gR?Xx*IJJreH;hHSku?<O~h +z%b4ycU6q*Gb~EeU7eWkWPGDFO6+3%620xoA>O6-nt*%tty<)SIg~Vx3SYm71vmh=&5QxPhB5p^?sBSQ3TMv*T07B4T3(UFJ#H%>W>?NY=KPcaOS~?kTAu>)aE5yR +zs(F;%Qgo)b=hIhu;+It4<$Gdd()eb-%L?Kx*%uCrWG*GSD}}tv?p=@Lx3QA1A3qvM +zdZ3u}M)2dzUFh2T{e87;QfI>C$qM7z#OsXWjKr?nHf8l6_ufz-TtEUiD4%iLW&`F% +z_e!up%@PV}boTUfH9YeYtU?cm#C839tX17WlQ8(}Nt_^ymID*42sux6!(~Of +zG%os{{JG(FxGCpqE8w?%O}}#Hocz&o-N+*2mp{F1x!ag^H++h5+-Q=^h__&bDW7>T +z83MQSIlU}S!U&=H)IG&Ce>6J#yxziKiz2mx7FxxrT$x~|5ob1mHPj6 +zrEUf6DpUcX)&F#+fifIWpZ{z}!UgE#@GT^31B7L9zB|)>m+KWjo3A(_(2-Fub|ge# +zPzVB-0~>+$ZA${h%!JJW@RomYrn!0e5kEN7--^HNqlLix7LyZ!fd4i;6pR9u1i=an +za73v4Z{WoSqLguLv1F~`MYtQ3neo0<${C6st!;gmP=_%SO_-@(DEN?K=j1MD3f(i5 +z$esWf6zG(6?c~NEY}+^(XSFZ +za?7fzHYz8Y*wg^S$D=lvy>qEm_h+3~%_iudPffC!7>s1B+;qlC$bXxgr*kpX{~VjG +zfv2thFQCm8=;QbeZMFc~@V=uhOrwQ-w5Epc{|RmU2tE!j4nA%Uo{KOr=S30mw;}?c +z0~dk)4WVd%L#P4gUoe7Pp%3O%p1dXeVH>kp#JEF-5jXtsdcf+ +za*)yFrDldJ#suW$YzwW%&_VcJKQhlp($s&9i+RMoVS%8YN=F!-*kU +z#2GC|<_)CW_h;Flf-j`Z)tNgP035!iU%-tD)YmxI>-}m*ElWPRQ?c8$^ZI1f+$Y09$ysE)>(=Nzk8H+e6V9}E)qZB#yV|R)-d+>TxwE9!6Xaf?h(z8S+ +z-I-^Fi~00htmvPFD7;}nmzNqv(O-{h49Y7agFb8skDFnfG5*OISQWMF2>CHoR6pJq}wqa6> +zMeSwJ(`upJt~;$5{J1fC?v&LRu +z&dClVEFw`uk|9goez2t!kq@7qf+oF*p!>z0{y$A&3Lplz{|Ch2Gav$o-^Ab}AO`B+ +z#o)tj7oDqVcd3661K6J+&BMv@gAc&N#lgw>qZnKif7!=B?N4$*1N9F9UUN6{^{8eX +z#zD{Ot=eB0Q}3&EI={^7(WsPvl6s0(z3PKZFtteHx^Kic$=rH92qWwTtdO?`K8AR& +zg>(hBe`}r|%&M04Dv@D)#E4Plh#PdJ;H&k{D!gA+c*HCzoum1GajG| +zfr=STSWb;fYt998g%!{5%$`YZ1Q1>~ +z;36QbU}vYkIwKeyCxe=x2yT&0$eLlwNpwdP9gv_hT1chQ+BwFy$qALt&*d91c=6r# +zJlb1uG_){6iUW_xS?D&nN5~n2C~*<>`?yL~(A_sXn5B1J%HwtE&IgCMG>1m#-9i~& +z6y#7x>kN{5zR!-V;SYZ>QXQI!fB*6mMljVUoHMFLR-LMi9tbdn;6Eq=A_$u^wl9C0 +z0Pcnr)njmo7Av{^Pm17|4SrSxKTjyYbKo|IrpNUGOGJh8$rZkK{>PG^(^gP=6XZcx%-s<|^W?~1pXPtj2MIUK9VS7ZEfEzG8$S--km +z^2FMMvGjOix){XPdk6CDoPf(}#t~IYMXGYj%vICX@0xE8PM;(6h|4zUaig`z%o@#;skPbaU`oV^a_6WN*sRNExTQxJD2=Y +zCjxFpO^+H9ByivNEh{7Bbh=^PI}`wQ1^cxQULMw1W_cuam^!yC?)PzN2X}Z+`4VC7 +zNes!(3TvwFiTxA44}9^S-p@bFZN|JC0|f^Wj<#hqdEpK2Lg@h>0P^@-PXDQ#rlEmA +zdVmW4zCwTjoD&B?^zW_^0Idi*`xYq%)HCEi)pM9*Ia}T+iUoi}bB##keYBehtNSI_v +zX}8Y6xTc+i^FoSZbdhZRwjc2#tH4(hQo~yzN2yf|-6!$g_O*cr!GeBrgn^n%tA-AI +zt0^y$B#K@iJR!1pU4`Q}{?fPPv$0=B%P~TK+vR$w!yKHD+@o!ILf=xqtOHAHb*1Am +zKjQr&Dc9|KxDOU4KS8TL#mbwLK|RJ1#z+z2hmxjUh`Im)f5wy3p!v(WuWFWFnXVh9 +z(x`H)#p_VVz8#U(>>^mg;`;2H?TsQXLIo0>YMTO2(mACud`kT50^G|w?#HH +zH0%s=uB$djAGY|+x1F88oGw0k3F)1C#Cl3mxJOYN$TUwCP;9*?2Cc)IL^0_#^{4Nh +zJBRA+-b)ai9qyAk&HUuN5Ezh2v8IH1kPH*6SANK4B|VxM$T?SiEsdi#fChuXyZdnv +z6G<#O{vC&4xu@wMX6ypS<0;z&O`XACnWy8k4c8Nz$1M0oFP9^g$UaL78=C!Oo_^Wj +zugwzxHJcR|n}R8K6Ps|yn@&m$;Z&U=GJzi~Y#uG?LtFYW5*;9Y$Ffz#N#^orlywZ4 +z!6X&tAFY}f^{TUVt-wuOr|a#}!Oz|kx7~~zZIxf0nQ6g|lgh{C>D`7AD8_^&&0K1` +zI;rTJg)LkU31mh-qkLJKu^wKEyIr;rn7E0DV|eAAZ%yCA=%e?7stGG!u(E@45&1-{ +z=n4p?^7@T}iqhFZ=shBP4Gg@88E#(;U}cL}Yqz0oYIdzK7jF}r$a^KyVIwSM# +zM_poGc(=V3i`RtwjTfVbjE7d3xi;#l!^PU0--qzMOd}1!bGh}b +zBC$2L{tdrdkhqXA4?2Y0*XaOp2QPcVyoG1Qs9!ok7v}vaDugT!a}6zSB9^fiB=h7X +zZ#-=F30G9Ed>N_of}y{H|0#9dkXmaPc{D=aZoP|#fKO5m@72uZ#^ob@uVwqw(1!vg +zX^%1H*GwOB7aI{#@37tAX4ESR8MA=FyNkYW}q(XVSHaafYtlsC+x3`9Nk*P-7` +z+YJ=3t(>7NIt&tk>c(NE)`&0l(lYAT^k2F;@*ZxxM|CT4Tfrj#-EEyUfmeNUyC>2nhoov26m*0vOsu{p)WUq^%?AcRK*v@*yYv89m!)ki2 +zZ#7P08Mf#OER;UfMA*JJB4R1Dv9z9jjYYY}fzTDEeS9dvu%oAM+!>n2K6G2V`0)bH +z)yS#s!8Sa;PS>kOTf=l3Ihff_RCDxQVY0P&kHjx=1<*g;bIFFi>EIH`O_knQyGF_1AlKv<&Ik` +zg%vE#OtwXyw_xPuP)p#qwlNZ +zInq1J1pO#R|IGdR!|PrG9Kfd3-&e=qihpvyzP;`R&iQfhZ>!^&3vWF9>q{)@0h>z$ +z)Dv3ox!ShuLy>|nhj-B3s(f_Q1RCZ%dnD4)>)r97_Oh?`9&5OKi~IZCYp3#;3j&JP +zTIu%9WPEBL)6v(K^ +zgy9=(wJU0w7%qUh{iNRUNz-03G__LZZZJXUzRE*+!pu--)4!~YY~jqs_t37U#W8Wd +zXw0nJYKoEpdEh8>p|7Bj&G)&kV$l*+<{h$^hj*oInUmFziZ=1zv_wg9DLA2TBH0E_ +zT*JS$MnGGYx`|uU&|I?hp4pwAoD0vO#T+clx@OuxM)PES)eTY%&D43Zgm?N0PIRl8 +zxS==HkcowGblFD7{@|$ih7ZZF+@I>Q*45|A=0}b;VLW9uZwt@Wo;?1^{rP2szjl9s +z_m!ykG;Ue@)%A}YfaJ}p%$t&8rkWD9KC-^he!FdQwjYt9)^`@lE=k#05-}Ki)KwPY +z&>3uSl?0o&N6E1bgWQm}!ZoLPnL%E=!EeaZYc%R?m-z(|U(zc{(OpJDN9kJ=2C2w5 +zNc1>h_3HQ@!_gY$s==ds3Eqd4eaRS&mO1wX+LL5Ig^fgw^{RH*&j!{V>W56)?fL~) +z!uBi!dRjsi#Z@*KY*BYjY_2?acyPN-bA|+-VIW0@5=LF!@+!W;L{pXNiOhYNI3sP+ +z69x-~`gp_ya|Uu020=x4o!#g&xu>%Mqs%DFk9%A{hA%8k+FQ}yc~}#A+Nb8>aldNx +znU`B`49cm=+o#|viq8$99+9$UCgNI$UU$i@C+V$=63=cpmIey6XZH}3-@l_PaOVLC +z=g?t-I$Yi0ar?`5);Dbw(lU(Oj6~PN>p(V7SR%IB4)q)T%MRN$l^03KE{8s4k0{o> +zTMFu^NbkC?Q57B2mv;OJ3`w@CUmuvs37IN~sgM>jk +zpO@+>CAWrJ$!UA#jX1NA*;`(AIgUMxPI+idVRZaa#;WC9WRPjer74Gz`i6g} +zUDc5CVSfr+>&WV5F_7=0?#(iB9ff9MO|MsP6e8#H4#{JkDhgJI-|`6GLqB_2%0mAj +z#k#5-F|$+ehZK<|~eTZR)Wf +zMqCxrYiC7u=o2J;Q2@*VpbvlR$^Z3wk_3oiTqHL$C&_PDzdwI-;5P?;bKo}zzH;FE +z|M^R($ivkv@4zK(>`koU+?*=%UP>i?gBrp6&quN%O-=Q7ZCCK*hzeZcxzEi;Ih+;z0iaoSo#C + +literal 0 +HcmV?d00001 + +diff --git a/src/test/resources/com/android/apksig/v2-only-11-signers.apk b/src/test/resources/com/android/apksig/v2-only-11-signers.apk +new file mode 100644 +index 0000000000000000000000000000000000000000..674b6e4d7d67810c70aaf4255db90b710bf37d23 +GIT binary patch +literal 24784 +zcmeHw1z1(h*6`ubNOyPVp&Lm-T0-dt>F!P`K~j+p=|)1jB%~WDK^l~91o=05z1R1B +zz4!iK{P8`H!?X76HD_k+!5V`2G|FdQPvRgvS{v`lH{=ESp`Uf0%z#nknVc+rF?*%4@dJ6`D{D50SkS)jr +z~jvzQVCuc_s+sEI=FazyBXx!eA1Ne`E +zfM95EuWxH;V+zm(ql3_a4}SE$#jyeW_IbB$Ft;^W9%KO2KiZUmdp-dEv*nv$1A~G3 +zo0$G9`lhxTV*keuL;r6){0zXr`)iyC(6GuA> +z69q$C3o}zEXI6I`>nOEGTP!hb;l>ocC)C}dfyO;T5!eU}R$zK^Nh~m?OaNFCNx(SO +zz%VtjIXVsr2?-C|8-%0Zfv5aH`H+Oc-)V2?ZG0sQ{wMdIjSpVC#%3fG&%{s>l)GLa +z6d1e_5%BtGhcO)HWBf(ln^zkoCj49f^Ltn1 +zW`*;Tc*4~cp{P6;*U19~YYf}&`OiH>v`x~-k63Dz+$$+x9e*}@;Vsbqn9%03iE?he +zoWb#-*ONw6qtNZzxQtCSdKP29~H4&yPdrIX*jF@C~1V0BG$D5#|`yL%|ZHYOo%70-S8 +zu5QzE`ZeECYPIOArqp&vNqd1 +z)l^ +zRNd~|wm!TvIgPvMyIXw~hOa&0CDyDU)FI)sC<5cL4eB>UR}1H-qyWQ+!FXVM>^jZ` +z+|}W4R!9}R2+U5gZo!vdj}9(V{1bvC&0;= +zn7T(LD3}A{+OueD#%qz>%{7%gg_eD)EZNvqG?GWJRr0DD0cZO`UJCaDS6cAGee;9N +z?9fwdw7{kN``PXf_Lrpgv%?J3kCopBks}1kDlND33dYl-Bqp!c*_}4uG^P2x^x%Ii +zGJDq^`Jo?<$m3?Zph!1cHXnDll{r}>hY~I|eneVP0?>MXG_9D=C5pc;`8B%<&S;kg +zbQ{_6QZDQcMKuhIG*M?e;p_`~9kCBoi?PBK{;$KH&5M(g+r?zazz=Onar7c^L_DRy +zLyuUE?eBFlL97p-mmsBl7OoSiftQCg70{1c4sA#cc8q%P3MZUNYf{iwb!DR=bqh$Ah}?*9m^xVlHo|0 +z*yNj&yH|E8S5`G0q7vu19pjdI)ukilhCT0$ +za)EVwmZ#q+`y6p}7v5{Jt??1{`G~C~ZqpuWeC%LVjP0uj +z#?$}+2?SRH;E)Loh5~~TL0^NDWufr8=pl%3@QhDnhWKEhAz17f5HvVwbr@)51QRDi +z7Ip{+7lafKg`Ee&$;r;n&B4nK(ZWOF;)L+A^ZpI}^`JngT1X%i(+|>6074252mr;S +zrd$QEYMjfMW@}z*-W@O?IP9q7tua_ke<*U?r;ak>dMORHWBD3E=oH0Du8~%9a*t)$mzf{iF@vV3%K?djeED7bnb^x{BJ9e<_1#Y0 +zWrcjbs1`lsvUiEmQYFXT>frPT#R7xJN$QcoS-I1>y&4M|Ydyksf?TsPxqJ&TrFG?B +z#IbT$TST+9Y)9*CA~~Lmeq3o|j(`pb1_58g>Fuk$n4|j=J+g7dPwI80={-`OVv^|* +zV139-Wd3kEVJ;&e^rTJr>p^5-kQd(0iXqd=p)F6Xu}xIm!}!MGnAnb+*#dO4N!Vw} +z@>3AC)ClA>!R8nr>n4k*cMsnoT4%KGnR3Q`N}ty@X_~G!z_)&4PxT-($0(?vI)3^H +zt2;*-q6i@YWPk(}1{VhVS*HL()E9L!3sUsN9oF&`_%xaU2-)q&R517uT>oEpK)&sO +z1p^C#hJw2JNx-1lKoDjyHraz1$K=YR8;cY8kBC@oPK0j}hQQc<1j<#-6Ig_#q1uvN +zEN&UvvYS_S;0Du7gmdO8+5-9^@Rx$wN_a8NU#=sbT03d-d+5mum7``%A +zqlq@l4yw +zd2lh4_oA?0lbD}_$@)-LJNo4;N3<4uhr)tZA%<;+@X~WFhim_(s0I{@C;GD-S@GtS +z98kXdtH;4&BLvO`zMipJn#Nw}JgF=@A~=pu7u<7EXJ|bAO0zyrEyb^v_50+{AF+zR +z*5^W;UasmB<=!uxmg#C#J`K)^^hLmip3dM^)ET|55+oZ=nG22-$*8VDd|*yYvvn|O +zO1(67QqcK45bZGoa!?qtCS!;=S;jQ=4$_>h{iYtXW4LQ@kLo>TkrVcm^|>B~yGfT1 +z1if+RVJTm;2yeCB9UpIJ%IlyfeWhe+)J^g!ImvoYr*fZ49mPKWUXaDc9WVtb^_ppw +zArSSm?JIc?qF%qpteQ9}ks%v~WMLr7OrH<}fKMQPW?nBXlKZ_a((H;KvBRiSE*4}t +zwCBtyE(U63`uXZ(gSnA7 +z;vhzxJ^@Al^88M7|&zfQnvLNx~+kiz#;?KRuA|S1(o2lFXh-vkpoYr#o*)I@+R=QeMIn!i-gj +zIwM{l$bJTUkJjaKh4uJCO*7(Y2&KVgeJvF9&Uofm8UZ}Xdr`4rgCpf$O2$|Y5{CTd +zxnX`sxF5ZFtpq4lwUDkgoC3@Z#4)m11YP8HqHBB@@SK%sxQh3RB`<9I#*})IIOHQ1 +z+e_m(;~tz4>B6R +z1zeX8i824+iGJDPpL!x05JU^sPiTN*}_Y+FIJi~lhw>BOUtUL8S$j!B4uj+`0 +zV1UVOO3j83(h@~$+zY}&;U{RunLmg^^LTftsxdH)JL%?p^H0D<1pq|=Ze7$ppoU0- +z$$gmUkcQFJVQFi2s7tW&NVa*oh~6SfZu7bfef)axrU6Wj8)up$AE@$x#1`LcIu{X9 +z>%!nGBT@05M$Ie;4Ew@vwNQ-0f&{|=jSA4qPK1DU)3Xe_Y`3j!?x011Sh +z2O#iAEKyiUmWn6D)BUev2~G$v#~)$|4sM>GV~JbzFR{e8L4hzmfbRbsOF-Yo5&@vf +z0s0z_>u4bYq}bR(7rj9xrE#9SZ4MgjAm`(xrA*2PDWcansq2c~aWrMjjfnPHbFTw$ +z3S+{l(|sV9n3t^GYf|j2xWX5EVp;iTxpl&>6Fl%|dYHsLO(Ss{uecR0 +z-;Yy+4uh0AiNPiBj{Ar`rELqzRrh17!Ef&uR>(xS2+p&X}fHD9rbs(XZu0#ieqLLQ8~ +z&Tf|6Qub9e*f7rto-KN73i7gf0NFN(#y%AlNvO({1=iOr=rWdaBm3aXWT))|OwLx~ +z($>3)jl0>z#chE);fRrA*!1*a+<@cA4L+&F%7JNf#||cx8%ksta}OPlowjE(m#niX +zfB5JTFi-weW1nNw_Z{xfZo4`Xh>$H*o-oh_Etc{aE(&lJ2OK~ZU&CCmeTHpgDsPI$ +z*}u-^d`fg#DpyL{bnw+pla+X+Apfc->SLsdDDmX7E+0JMyw}ZJhht9V{kHNbsg9je +zXi;gbvYm2_9B$UJp#V)4@=dqXXcHQv1Qo*mWY`%$4)@sF6!aTt{Cg3h36(89~sZ2wGeX=fp7dM +z>`xQ)z9at#Tv?ZQH+PmwV&q6Lfj0&Tp5!i_f%EWciLP{f7146`rAs_-uUqfuW|Ok+&|YlMEM74!$jXjfNN3G4+l%vY{-cf* +z#=d3-tP8Tp)5TtaOx=or`e&t)+mT3wQw2TEQeVutSScUM>AQ0u{G9Z?EavMtpfL=^(35#`4nPcQLN}KE} +zvWd;_xtaDJ3qpo6CXp@i3LQ>ECP?;+CrRjnhRIpf<|>jg91wZ&5$!`Tyj44OPzzZe +zFqW8O=v!6ekXR(S$aF(2nhxy*Ke(T}R^%_`s^;{uTHC58i>fb+^;9%nao^qO@cYX2 +znJM_|*p=b3M^fsQj`%W(M;V9Sem$Wh^Fem4G{7^{&P6|Fn^-7e5w6c%txp +zM&M}P6?$v!_*gZI&yp}|!x>VDGl(Ap{tIT?Lg3;EU(XHr +zf{@+`?K7wBDy~D@F&7hz2{T!Bb7n7xr|sO>r6PSLCnk3U!Hf;r#Mlk|m*ZSn9xb5> +zWzTJ#lSP&z&1{ui6-XUJ!CbbP#u(BpoUfb`)aye$sPt3#B#sv@K0m8`yj|YKqaGkOAkgL +zj6crRC?b_aVokkK#WE{G&G)cR+}879uIL83gpt3W#t1fVJ~2j(l=W0ISXZD);iT=! +zT^w#FH{sZ91>&}EdaH+Q#i*IBM!Q?`e +z=hd=rMyXXu>^ND($5kDd@ekzb!oJ{kA+7Z~79jV3Uyc4Y>c5TpZ=?R(sQ*tl>XyK+ +zLIsdo{d+JC;N*b${C7JN&cGP^?4MV9sT7PO$gTaoSZNi>Tl$sq2Qs#K`?px7{ZkO +z_pxGv;7izdnKHMqBHi^%OnF8Xvxj2Fs#`xM)F97C<7TMk3%n%VzjWnDqG^GD+7svu +z4?QbcJ^krVzHI`F+q_;If)mL>?y&t-;zk>Gp!W~H?Ux9}+5Q-E_j-+dMM;$@q4DMI)7*w|;-rAK0F8`9fo +zb8ldnYt@SuzPmOMNENub-DH9S=1Ur=fkX(o*ol1Pv>D#8v45jVNOI5H+TeWqCbvK* +zOe=wjdNW%zfP6l+AM#x#%pGMK!iS+mQs@b2U1~{wHge;1s`l>*B!jhYN&TN=vlZ}d +zEB_PH<^qgy_%3ZWfV5%#khU=OW|Fb0Dw_W-Y2$r+d>!LcibtYT02x@GwDpXz% +zHk`iGL`P(VLsH7J+-d|pNbc%S?3pG>`RBZtN9+s}7~x7X@&s;T@7>KYeZQXme?{KD +zCC13YYsw~alX2{pNA9cJ-G_~b*a6+#m7x^5op +z4DaJzrDTA7OtKc~gOII*ry=MldnFaIW)}zMB99daVj2dwo;oKv{u^=ouW}g%NW7r{ +zA}0_04l)3MfqPM)b|axWRE3*?l3tKTiYAo8e|C=Ey>URHlpjAqd +zl*y=OBM7yr&Z}Y@=AQK_xel3Z9Ko-dp1b%M<_uqJ%aA!A$oWyVTz$afsoH40)R~ +z02N;+j5x}-n>|3bPCO_^e`yqIcQHkUgv{!-@l8WWg+|!d +zPjahssposg#bb1&iR9gN6W0xVQFrs=p_6n@kqiH18P5jgvo^b;NtkT1UhoN3@JF^U +zTKqv$f7#)mSw?7R3lPK%%nrKAVA3rQNg@qzBNM*zXLXD>je9>PQh8b}QU^<|*pkSg +zGvAWGl1sbGjC3kU>J0-78C9b0gr>D=eJafP60 +zdFZ){>qL2oI~Mk=Au#XXiW6|P1K?H|9s@PR6bvBsuX*dQ~$io+p3Q8 +zBTd+vd^j%mwQObdo{Yo-~Fml*Cn0%fp@^Q$T +zCM*%m@xvurC}!2nsYJSo5kq?AbDr@U2CMhg<4Gu+uuPd~yK6>mRccj5@Ux%1Tb +zo@Y~QHF}3S^mQ3#Xi`+XW^Ubh@*@mDqQ8~rz%>ql +zTaAhUYDhpRKz?7|Eb#m*!_|oml$)Wcq%KozmCDAL6Ej+Zl&zEG{xj>jt&EtM3hL`& +zCEd+e1#xGDOs+(2we?puXxNjp>UCAa%Y_41Vv +z-oEjnq;PxO>l2EFj)-~Wp`39#c5rfeLcCe5vbm0uL;GUOVC1d;g8Y9iFkV1HS{P8z +zAMrOdpibn#xBhqW_w5eVHNbCRpZWq&y^lXsFPa--y#R%C20?*C1mf=}XDComcVIz( +z$W1!}Zw38nbDWEtmy7=&>h~S}^`Jl~%Abit!GeGk9UAaOppd?8d5$c_aigczo#;WT +z2B~s2H90m6=Pp2!G`gAi%u;vColF!`cj~a1^PexO@h;7C<0(_(cI2w9IN$fPS$T`# +zVHq?oxp3L`EH>SihD4*q|0|trWej&JxQY_lA?n@k7e7?Tdc`fLyv6*ow~rUD#Xkk& +z-qYvA!7XEDrDU5I2#J+ONKk-kmPyE*XUI-;hZLL;Akdpjq)^*B#I(r@7B4O4>eG4g +zKJq+2Ty`)pH-wFa8j&^EsdJB%H3E@gLTZmO6)T_*X7*8vU7btgb!ct|hd4Ec#+KYd +z>E7jKQ$}kK5_+y>J+0!4h#RR4&A<*vdqWRJaf)$GvBIof@u>$4Od-^t>;N8^#R=Vy +zFNGiTlO@G#s3)4tBzAwW1HbI>M?3Jx2?cl#Jm$>gqBd|9FJJCOnV)UIh4`104fx)8 +zQRr!tvpNraO(;dOd(a3@atn0pWjx4N%qZ0GE{sc&t8h9Q_i4ZSVB&ar?0>ln!6O=7 +zuJH+d?Jk|gAYZ!bZ-By)F1nGs#VAx_6?3m*@!Hh8>_bKaA_5<~Lj}p^vj9wU)43L_ +zDYT+DRvz@l7n5^^AeP?8;FcR4PRn@*1PNt{@>x?C4HthYzif;?2k3K7o8Z^=Rvz

T-B=bzm-_C*KM(pfm^o+$s+UfRV&DMU+4y$=qeR +z@g!Bt5@*Sa>!SWgtNWP4he~&F +zb1t6|>~An9>s;Es;r+}T@9F*ai|o#`kK>?_VBE2`^hPhN!2@VofCqp+{?^lftEVZ5 +zAdoI#f`6&);xm&^9+Upjf-FiM*7>$W5Z3+4G6y&$4Aj@QpyuE +z&Xmwa5PAJvlkqN4EOwCa&=%v=uY(vQ$T6&89aZqfy*3FHr;zq|@wLd%(|TAec4 +zHcX~^z@-|mO&RlHL`I_vXBCz6i(jUbErw)6O!Q#9{GFIew4Tq&ay5wA0ag@+uL)QT +zbgVnoq||wgKg1=a4(d~5tbD~0*%N9Q=~l>{6o`zSv}#vMoCkG(eKs?H+!pR5=lQ8X +zU}5gsqTI8O=QYv8=>5SA(s~WE=sD|qN8Y>);B=bHENff+N>~Z(8rXD1RIiz^3r5$UDiVJY7cwyYgM0dA +zhkxy!08z8vaJJ5ybvL$-a8Pknq>G^Fd?Fq6+1xs9RS&wkA34z;+;<^Uf&bi0?wYKI +z4kd)3%2h21nu9ljrky +z+SsNQ{4&vnYQaH_aMxs`#p&A-#h7~~%Rz}dSQrLGAN{KOmdDc81Rf-8d_~O)&Vl6O +zF(b)C7)onD<&_mL3_|#YQX9LqErgnzUEm%}gh#Lt^;^%k*d5o1cY1YiWVc0L3pabKb7WITU7G(=Db~1*(7bN}W +z^3_Dx!W+)09JvxgrDcNv`G70RnjzKJFp_A9ob7fOHx943EY{RKTK)RDp4YnFRp?9p +zqLkOjOIs!{xe5*ODEC?JbJ6P-gbm8*UgB!5BTF#eEz+y0C$L|Y*pV~HBnv{g3ecwA +zNjV7Ow<({eDL4z}ht`QjO|BAM?WLyItLnd_GV5k@5ij#V-q(u0m0=BG +zq_l8bv{O+)b|*GNv{G5yH~3MVu3@e%q+hL*G;-(7jY2n{rDNl3x{RCnicoO13mwg)=f+s$lCOqI^{)Z@U}P +zKb1<~2W3lDTNv$_huta?BZ<%ArbQ-gRU?3IBnhmxbhHhjZPpHl@d` +z&9YC!;8}7@BXb#LjCab{`(}$J`L!CE!|NYJ@>TU=s$}lng+H{ToU~c+h*!r>YC&y$ +zt7kbuU=gOIZ`arc7@4QW2K4S;S8j0ICRc}nd#u<&q#^l3(a0}A>-Y(tSSZ6!yBPd=(5A8)f{tto-%#)B#^saZH8mXP+WkwgHp%C +zjr=mECI*`V&xbH1b|r2yk}u@gUh$QM$CeJP@|1|l&&(m6D9u3yALpFdHA#~)?k2ly +z(D<#EyrID$2OTvt(E>66_@m!`>bIZzH-5?sI2=J32&4YPt7BlyHLyYk-n_aEzYKq@ +zju#0ZujBN?8~(fS>rbzH@v{S)QvX;Te@Fiketm!43o83(;@?-t&u*jfh;J{kqz3M+ +z4p2^Nu5q^Q+J(Y~pha}hJSn +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 +Tg9RFHk9CIzHQe49++O|{heuzh + +literal 0 +HcmV?d00001 + diff --git a/Patches/LineageOS-17.1/android_vendor_nxp_opensource_commonsys_external_libnfc-nci/360974.patch b/Patches/LineageOS-17.1/android_vendor_nxp_opensource_commonsys_external_libnfc-nci/360974.patch new file mode 100644 index 00000000..59b6155f --- /dev/null +++ b/Patches/LineageOS-17.1/android_vendor_nxp_opensource_commonsys_external_libnfc-nci/360974.patch @@ -0,0 +1,57 @@ +From 17cb7edf8ad3aa239f39e4b823e881284f789343 Mon Sep 17 00:00:00 2001 +From: Alisher Alikhodjaev +Date: Tue, 2 May 2023 14:20:57 -0700 +Subject: [PATCH] OOBW in rw_i93_send_to_upper() + +Bug: 271849189 +Test: tag r/w +(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:dc9d09e1698725712628d394bf9be4c9003579e8) +Merged-In: I1d55954e56a3f995f8dd48bf484fe9fce02b2ed1 +Change-Id: I1d55954e56a3f995f8dd48bf484fe9fce02b2ed1 + +Change-Id: Ia10491e388a495a164462c73ced7ea1965808860 +--- + SN100x/src/nfc/tags/rw_i93.cc | 9 +++++++++ + src/nfc/tags/rw_i93.cc | 9 +++++++++ + 2 files changed, 18 insertions(+) + +diff --git a/SN100x/src/nfc/tags/rw_i93.cc b/SN100x/src/nfc/tags/rw_i93.cc +index f57ee763..062cc7e8 100755 +--- a/SN100x/src/nfc/tags/rw_i93.cc ++++ b/SN100x/src/nfc/tags/rw_i93.cc +@@ -598,6 +598,15 @@ void rw_i93_send_to_upper(NFC_HDR* p_resp) { + case I93_CMD_GET_MULTI_BLK_SEC: + case I93_CMD_EXT_GET_MULTI_BLK_SEC: + ++ if (UINT16_MAX - length < NFC_HDR_SIZE) { ++ rw_data.i93_cmd_cmpl.status = NFC_STATUS_FAILED; ++ rw_data.i93_cmd_cmpl.command = p_i93->sent_cmd; ++ rw_cb.tcb.i93.sent_cmd = 0; ++ ++ event = RW_I93_CMD_CMPL_EVT; ++ break; ++ } ++ + /* forward tag data or security status */ + p_buff = (NFC_HDR*)GKI_getbuf((uint16_t)(length + NFC_HDR_SIZE)); + +diff --git a/src/nfc/tags/rw_i93.cc b/src/nfc/tags/rw_i93.cc +index f47fc30c..f58d7f58 100644 +--- a/src/nfc/tags/rw_i93.cc ++++ b/src/nfc/tags/rw_i93.cc +@@ -598,6 +598,15 @@ void rw_i93_send_to_upper(NFC_HDR* p_resp) { + case I93_CMD_GET_MULTI_BLK_SEC: + case I93_CMD_EXT_GET_MULTI_BLK_SEC: + ++ if (UINT16_MAX - length < NFC_HDR_SIZE) { ++ rw_data.i93_cmd_cmpl.status = NFC_STATUS_FAILED; ++ rw_data.i93_cmd_cmpl.command = p_i93->sent_cmd; ++ rw_cb.tcb.i93.sent_cmd = 0; ++ ++ event = RW_I93_CMD_CMPL_EVT; ++ break; ++ } ++ + /* forward tag data or security status */ + p_buff = (NFC_HDR*)GKI_getbuf((uint16_t)(length + NFC_HDR_SIZE)); + diff --git a/Patches/LineageOS-17.1/android_vendor_qcom_opensource_commonsys_system_bt/360975.patch b/Patches/LineageOS-17.1/android_vendor_qcom_opensource_commonsys_system_bt/360975.patch new file mode 100644 index 00000000..94bb20de --- /dev/null +++ b/Patches/LineageOS-17.1/android_vendor_qcom_opensource_commonsys_system_bt/360975.patch @@ -0,0 +1,45 @@ +From 35912b629815d6481deabe9fcbebac83722367a6 Mon Sep 17 00:00:00 2001 +From: tyiu +Date: Tue, 28 Mar 2023 18:40:51 +0000 +Subject: [PATCH] Fix gatt_end_operation buffer overflow + +Added boundary check for gatt_end_operation to prevent writing out of +boundary. + +Since response of the GATT server is handled in +gatt_client_handle_server_rsp() and gatt_process_read_rsp(), the maximum +lenth that can be passed into the handlers is bounded by +GATT_MAX_MTU_SIZE, which is set to 517, which is greater than +GATT_MAX_ATTR_LEN which is set to 512. The fact that there is no spec +that gaurentees MTU response to be less than or equal to 512 bytes can +cause a buffer overflow when performing memcpy without length check. + +Bug: 261068592 +Test: No test since not affecting behavior +Tag: #security +Ignore-AOSP-First: security +(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:dd7298e982e4bbf0138a490562679c9a4a755200) +Merged-In: I49e2797cd9300ee4cd69f2c7fa5f0073db78b873 +Change-Id: I49e2797cd9300ee4cd69f2c7fa5f0073db78b873 +--- + stack/gatt/gatt_utils.cc | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/stack/gatt/gatt_utils.cc b/stack/gatt/gatt_utils.cc +index 291cd1062..eb2a12dbc 100644 +--- a/stack/gatt/gatt_utils.cc ++++ b/stack/gatt/gatt_utils.cc +@@ -1198,6 +1198,13 @@ void gatt_end_operation(tGATT_CLCB* p_clcb, tGATT_STATUS status, void* p_data) { + cb_data.att_value.handle = p_clcb->s_handle; + cb_data.att_value.len = p_clcb->counter; + ++ if (cb_data.att_value.len > GATT_MAX_ATTR_LEN) { ++ LOG(WARNING) << __func__ ++ << StringPrintf(" Large cb_data.att_value, size=%d", ++ cb_data.att_value.len); ++ cb_data.att_value.len = GATT_MAX_ATTR_LEN; ++ } ++ + if (p_data && p_clcb->counter) + memcpy(cb_data.att_value.value, p_data, cb_data.att_value.len); + } diff --git a/Scripts/LineageOS-17.1/Patch.sh b/Scripts/LineageOS-17.1/Patch.sh index 78abde5d..5a9f1d11 100644 --- a/Scripts/LineageOS-17.1/Patch.sh +++ b/Scripts/LineageOS-17.1/Patch.sh @@ -97,6 +97,7 @@ sed -i '75i$(my_res_package): PRIVATE_AAPT_FLAGS += --auto-add-overlay' core/aap awk -i inplace '!/updatable_apex.mk/' target/product/mainline_system.mk; #Disable APEX sed -i 's/PLATFORM_MIN_SUPPORTED_TARGET_SDK_VERSION := 23/PLATFORM_MIN_SUPPORTED_TARGET_SDK_VERSION := 28/' core/version_defaults.mk; #Set the minimum supported target SDK to Pie (GrapheneOS) #sed -i 's/PRODUCT_OTA_ENFORCE_VINTF_KERNEL_REQUIREMENTS := true/PRODUCT_OTA_ENFORCE_VINTF_KERNEL_REQUIREMENTS := false/' core/product_config.mk; #broken by hardenDefconfig +sed -i 's/2023-06-05/2023-07-05/' core/version_defaults.mk; #Bump Security String #R_asb_2023-07 #XXX fi; if enterAndClear "build/soong"; then @@ -118,6 +119,10 @@ if enterAndClear "external/conscrypt"; then if [ "$DOS_GRAPHENE_CONSTIFY" = true ]; then applyPatch "$DOS_PATCHES/android_external_conscrypt/0001-constify_JNINativeMethod.patch"; fi; #Constify JNINativeMethod tables (GrapheneOS) fi; +if enterAndClear "external/freetype"; then +applyPatch "$DOS_PATCHES/android_external_freetype/360951.patch"; #R_asb_2023-07 Cherry-pick two upstream changes +fi; + if [ "$DOS_GRAPHENE_MALLOC" = true ]; then if enterAndClear "external/hardened_malloc"; then applyPatch "$DOS_PATCHES/android_external_hardened_malloc/0001-Broken_Cameras.patch"; #Expand workaround to all camera executables (DivestOS) @@ -136,6 +141,18 @@ git fetch https://github.com/LineageOS/android_external_zlib refs/changes/70/352 fi; if enterAndClear "frameworks/base"; then +applyPatch "$DOS_PATCHES/android_frameworks_base/360952-backport.patch"; #R_asb_2023-07 Passpoint Add more check to limit the config size +applyPatch "$DOS_PATCHES/android_frameworks_base/360953-backport.patch"; #R_asb_2023-07 Sanitize VPN label to prevent HTML injection +applyPatch "$DOS_PATCHES/android_frameworks_base/360954.patch"; #R_asb_2023-07 Limit the number of supported v1 and v2 signers +applyPatch "$DOS_PATCHES/android_frameworks_base/360955.patch"; #R_asb_2023-07 Import translations. +applyPatch "$DOS_PATCHES/android_frameworks_base/360956.patch"; #R_asb_2023-07 Add size check on PPS#policy +applyPatch "$DOS_PATCHES/android_frameworks_base/360957.patch"; #R_asb_2023-07 Limit the ServiceFriendlyNames +applyPatch "$DOS_PATCHES/android_frameworks_base/360958-backport.patch"; #R_asb_2023-07 Only allow NEW_TASK flag when adjusting pending intents +applyPatch "$DOS_PATCHES/android_frameworks_base/360959.patch"; #R_asb_2023-07 Dismiss keyguard when simpin auth'd and security method is none. +applyPatch "$DOS_PATCHES/android_frameworks_base/360960.patch"; #R_asb_2023-07 Increase notification channel limit. +applyPatch "$DOS_PATCHES/android_frameworks_base/360961-backport.patch"; #R_asb_2023-07 Verify URI permissions for EXTRA_REMOTE_INPUT_HISTORY_ITEMS. +applyPatch "$DOS_PATCHES/android_frameworks_base/360962-backport.patch"; #R_asb_2023-07 Truncate ShortcutInfo Id +applyPatch "$DOS_PATCHES/android_frameworks_base/360963.patch"; #R_asb_2023-07 Visit URIs in landscape/portrait custom remote views. #applyPatch "$DOS_PATCHES/android_frameworks_base/272645.patch"; #ten-bt-sbc-hd-dualchannel: Add CHANNEL_MODE_DUAL_CHANNEL constant (ValdikSS) #applyPatch "$DOS_PATCHES/android_frameworks_base/272646-forwardport.patch"; #ten-bt-sbc-hd-dualchannel: Add Dual Channel into Bluetooth Audio Channel Mode developer options menu (ValdikSS) #applyPatch "$DOS_PATCHES/android_frameworks_base/272647.patch"; #ten-bt-sbc-hd-dualchannel: Allow SBC as HD audio codec in Bluetooth device configuration (ValdikSS) @@ -206,6 +223,7 @@ fi; fi; if enterAndClear "frameworks/opt/net/wifi"; then +#applyPatch "$DOS_PATCHES/android_frameworks_opt_net_wifi/360964-backport.patch"; #R_asb_2023-07 Add pre-share key check for wapi #XXX if [ "$DOS_GRAPHENE_CONSTIFY" = true ]; then applyPatch "$DOS_PATCHES/android_frameworks_opt_net_wifi/0001-constify_JNINativeMethod.patch"; fi; #Constify JNINativeMethod tables (GrapheneOS) applyPatch "$DOS_PATCHES/android_frameworks_opt_net_wifi/0002-Random_MAC.patch"; #Add support for always generating new random MAC (GrapheneOS) fi; @@ -364,12 +382,17 @@ applyPatch "$DOS_PATCHES/android_prebuilts_abi-dumps_vndk/0001-protobuf-avi.patc fi; if enterAndClear "system/bt"; then +applyPatch "$DOS_PATCHES/android_system_bt/360969.patch"; #R_asb_2023-07 Fix gatt_end_operation buffer overflow applyPatch "$DOS_PATCHES_COMMON/android_system_bt/0001-alloc_size.patch"; #Add alloc_size attributes to the allocator (GrapheneOS) #applyPatch "$DOS_PATCHES/android_system_bt/272648.patch"; #ten-bt-sbc-hd-dualchannel: Increase maximum Bluetooth SBC codec bitrate for SBC HD (ValdikSS) #applyPatch "$DOS_PATCHES/android_system_bt/272649.patch"; #ten-bt-sbc-hd-dualchannel: Explicit SBC Dual Channel (SBC HD) support (ValdikSS) #applyPatch "$DOS_PATCHES/android_system_bt/272650.patch"; #ten-bt-sbc-hd-dualchannel: Allow using alternative (higher) SBC HD bitrates with a property (ValdikSS) fi; +if enterAndClear "vendor/qcom/opensource/commonsys/system/bt"; then +applyPatch "$DOS_PATCHES/android_vendor_qcom_opensource_commonsys_system_bt/360975.patch"; #R_asb_2023-07 Fix gatt_end_operation buffer overflow +fi; + if enterAndClear "system/ca-certificates"; then rm -rf files; #Remove old certs cp -r "$DOS_PATCHES_COMMON/android_system_ca-certificates/files" .; #Copy the new ones into place @@ -394,6 +417,14 @@ applyPatch "$DOS_PATCHES/android_system_netd/0001-Network_Permission.patch"; #Ex applyPatch "$DOS_PATCHES/android_system_netd/0002-hosts_toggle.patch"; #Add a toggle to disable /etc/hosts lookup (DivestOS) fi; +if enterAndClear "system/nfc"; then +applyPatch "$DOS_PATCHES/android_system_nfc/360972.patch"; #R_asb_2023-07 OOBW in rw_i93_send_to_upper() +fi; + +if enterAndClear "vendor/nxp/opensource/commonsys/external/libnfc-nci"; then +applyPatch "$DOS_PATCHES/android_vendor_nxp_opensource_commonsys_external_libnfc-nci/360974.patch"; #R_asb_2023-07 OOBW in rw_i93_send_to_upper() +fi; + if enterAndClear "system/sepolicy"; then applyPatch "$DOS_PATCHES/android_system_sepolicy/0002-protected_files.patch"; #label protected_{fifos,regular} as proc_security (GrapheneOS) applyPatch "$DOS_PATCHES/android_system_sepolicy/0003-ptrace_scope-1.patch"; #Allow init to control kernel.yama.ptrace_scope (GrapheneOS) @@ -410,6 +441,10 @@ if enterAndClear "system/update_engine"; then git revert --no-edit c68499e3ff10f2a31f913e14f66aafb4ed94d42d; #Do not skip payload signature verification fi; +if enterAndClear "tools/apksig"; then +applyPatch "$DOS_PATCHES/android_tools_apksig/360973-backport.patch"; #R_asb_2023-07 Limit the number of supported v1 and v2 signers +fi; + if enterAndClear "vendor/lineage"; then rm build/target/product/security/lineage.x509.pem; #Remove Lineage keys rm -rf overlay/common/lineage-sdk/packages/LineageSettingsProvider/res/values/defaults.xml; #Remove analytics