diff options
20 files changed, 195 insertions, 40 deletions
diff --git a/core/java/android/os/Binder.java b/core/java/android/os/Binder.java index 0cb7df73f9b7..5d0a723241b0 100644 --- a/core/java/android/os/Binder.java +++ b/core/java/android/os/Binder.java @@ -325,7 +325,24 @@ public class Binder implements IBinder { * @hide */ @CriticalNative - public static final native boolean isDirectlyHandlingTransaction(); + public static final native boolean isDirectlyHandlingTransactionNative(); + + private static boolean sIsHandlingBinderTransaction = false; + + /** + * @hide + */ + public static final boolean isDirectlyHandlingTransaction() { + return sIsHandlingBinderTransaction || isDirectlyHandlingTransactionNative(); + } + + /** + * This is Test API which will be used to override output of isDirectlyHandlingTransactionNative + * @hide + */ + public static void setIsDirectlyHandlingTransactionOverride(boolean isInTransaction) { + sIsHandlingBinderTransaction = isInTransaction; + } /** * Returns {@code true} if the current thread has had its identity diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java index 8d07a861a8c2..cdc8268fa7a1 100644 --- a/core/java/android/os/Parcel.java +++ b/core/java/android/os/Parcel.java @@ -63,6 +63,7 @@ import java.lang.reflect.Array; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -1551,6 +1552,9 @@ public final class Parcel { } } catch (ArithmeticException e) { Log.e(TAG, "ArithmeticException occurred while multiplying dimensions " + e); + BadParcelableException badParcelableException = new BadParcelableException("Estimated " + + "array length is too large. Array Dimensions:" + Arrays.toString(dimensions)); + SneakyThrow.sneakyThrow(badParcelableException); } ensureWithinMemoryLimit(typeSize, totalObjects); } @@ -1562,19 +1566,24 @@ public final class Parcel { } catch (ArithmeticException e) { Log.e(TAG, "ArithmeticException occurred while multiplying values " + typeSize + " and " + length + " Exception: " + e); + BadParcelableException badParcelableException = new BadParcelableException("Estimated " + + "allocation size is too large. typeSize: " + typeSize + " length: " + length); + SneakyThrow.sneakyThrow(badParcelableException); } boolean isInBinderTransaction = Binder.isDirectlyHandlingTransaction(); if (isInBinderTransaction && (estimatedAllocationSize > ARRAY_ALLOCATION_LIMIT)) { Log.e(TAG, "Trying to Allocate " + estimatedAllocationSize + " memory, In Binder Transaction : " + isInBinderTransaction); + BadParcelableException e = new BadParcelableException("Allocation of size " + + estimatedAllocationSize + " is above allowed limit of 1MB"); + SneakyThrow.sneakyThrow(e); } } @Nullable public final boolean[] createBooleanArray() { int N = readInt(); - // Assuming size of 4 byte for boolean. ensureWithinMemoryLimit(SIZE_BOOLEAN, N); // >>2 as a fast divide-by-4 works in the create*Array() functions // because dataAvail() will never return a negative number. 4 is @@ -1618,7 +1627,6 @@ public final class Parcel { @Nullable public short[] createShortArray() { int n = readInt(); - // Assuming size of 2 byte for short. ensureWithinMemoryLimit(SIZE_SHORT, n); if (n >= 0 && n <= (dataAvail() >> 2)) { short[] val = new short[n]; @@ -1658,7 +1666,6 @@ public final class Parcel { @Nullable public final char[] createCharArray() { int N = readInt(); - // Assuming size of 2 byte for char. ensureWithinMemoryLimit(SIZE_CHAR, N); if (N >= 0 && N <= (dataAvail() >> 2)) { char[] val = new char[N]; @@ -1697,7 +1704,6 @@ public final class Parcel { @Nullable public final int[] createIntArray() { int N = readInt(); - // Assuming size of 4 byte for int. ensureWithinMemoryLimit(SIZE_INT, N); if (N >= 0 && N <= (dataAvail() >> 2)) { int[] val = new int[N]; @@ -1736,7 +1742,6 @@ public final class Parcel { @Nullable public final long[] createLongArray() { int N = readInt(); - // Assuming size of 8 byte for long. ensureWithinMemoryLimit(SIZE_LONG, N); // >>3 because stored longs are 64 bits if (N >= 0 && N <= (dataAvail() >> 3)) { @@ -1776,7 +1781,6 @@ public final class Parcel { @Nullable public final float[] createFloatArray() { int N = readInt(); - // Assuming size of 4 byte for float. ensureWithinMemoryLimit(SIZE_FLOAT, N); // >>2 because stored floats are 4 bytes if (N >= 0 && N <= (dataAvail() >> 2)) { @@ -1816,7 +1820,6 @@ public final class Parcel { @Nullable public final double[] createDoubleArray() { int N = readInt(); - // Assuming size of 8 byte for double. ensureWithinMemoryLimit(SIZE_DOUBLE, N); // >>3 because stored doubles are 8 bytes if (N >= 0 && N <= (dataAvail() >> 3)) { diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp index 6919a76b84ba..7c8ea93894a5 100644 --- a/core/jni/AndroidRuntime.cpp +++ b/core/jni/AndroidRuntime.cpp @@ -646,9 +646,7 @@ int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv, bool zygote, bool p char saveResolvedClassesDelayMsOptsBuf[ sizeof("-Xps-save-resolved-classes-delay-ms:")-1 + PROPERTY_VALUE_MAX]; char profileMinSavePeriodOptsBuf[sizeof("-Xps-min-save-period-ms:")-1 + PROPERTY_VALUE_MAX]; - char profileMinFirstSaveOptsBuf[ - sizeof("-Xps-min-first-save-ms:")-1 + PROPERTY_VALUE_MAX]; - char madviseRandomOptsBuf[sizeof("-XX:MadviseRandomAccess:")-1 + PROPERTY_VALUE_MAX]; + char profileMinFirstSaveOptsBuf[sizeof("-Xps-min-first-save-ms:") - 1 + PROPERTY_VALUE_MAX]; char madviseWillNeedFileSizeVdex[ sizeof("-XMadviseWillNeedVdexFileSize:")-1 + PROPERTY_VALUE_MAX]; char madviseWillNeedFileSizeOdex[ @@ -861,13 +859,8 @@ int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv, bool zygote, bool p jitprithreadweightOptBuf, "-Xjitprithreadweight:"); - parseRuntimeOption("dalvik.vm.jittransitionweight", - jittransitionweightOptBuf, + parseRuntimeOption("dalvik.vm.jittransitionweight", jittransitionweightOptBuf, "-Xjittransitionweight:"); - /* - * Madvise related options. - */ - parseRuntimeOption("dalvik.vm.madvise-random", madviseRandomOptsBuf, "-XX:MadviseRandomAccess:"); /* * Use default platform configuration as limits for madvising, diff --git a/core/jni/android_util_Binder.cpp b/core/jni/android_util_Binder.cpp index b24dc8a9e63b..8bc52b874ae0 100644 --- a/core/jni/android_util_Binder.cpp +++ b/core/jni/android_util_Binder.cpp @@ -974,7 +974,7 @@ static jint android_os_Binder_getCallingUid() return IPCThreadState::self()->getCallingUid(); } -static jboolean android_os_Binder_isDirectlyHandlingTransaction() { +static jboolean android_os_Binder_isDirectlyHandlingTransactionNative() { return getCurrentServingCall() == BinderCallType::BINDER; } @@ -1082,7 +1082,8 @@ static const JNINativeMethod gBinderMethods[] = { // @CriticalNative { "getCallingUid", "()I", (void*)android_os_Binder_getCallingUid }, // @CriticalNative - { "isDirectlyHandlingTransaction", "()Z", (void*)android_os_Binder_isDirectlyHandlingTransaction }, + { "isDirectlyHandlingTransactionNative", "()Z", + (void*)android_os_Binder_isDirectlyHandlingTransactionNative }, // @CriticalNative { "clearCallingIdentity", "()J", (void*)android_os_Binder_clearCallingIdentity }, // @CriticalNative diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 277bdf388188..35dc8e37aaab 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -2328,6 +2328,8 @@ <p>Protection level: normal --> <permission android:name="android.permission.NFC_TRANSACTION_EVENT" + android:description="@string/permdesc_nfcTransactionEvent" + android:label="@string/permlab_nfcTransactionEvent" android:protectionLevel="normal" /> <!-- Allows applications to receive NFC preferred payment service information. @@ -4237,11 +4239,11 @@ android:protectionLevel="internal|preinstalled" /> <!-- Allows an application to subscribe to keyguard locked (i.e., showing) state. - <p>Protection level: internal|role - <p>Intended for use by ROLE_ASSISTANT only. + <p>Protection level: signature|role + <p>Intended for use by ROLE_ASSISTANT and signature apps only. --> <permission android:name="android.permission.SUBSCRIBE_TO_KEYGUARD_LOCKED_STATE" - android:protectionLevel="internal|role"/> + android:protectionLevel="signature|role"/> <!-- Must be required by a {@link android.service.autofill.AutofillService}, to ensure that only the system can bind to it. diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index 8a1b74d33065..5a1e0e8d6d47 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -1604,6 +1604,12 @@ with Near Field Communication (NFC) tags, cards, and readers.</string> <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. --> + <string name="permlab_nfcTransactionEvent">Secure Element transaction event</string> + <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. --> + <string name="permdesc_nfcTransactionEvent">Allows the app to receive information about + transactions happening on a Secure Element.</string> + + <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. --> <string name="permlab_disableKeyguard">disable your screen lock</string> <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. --> <string name="permdesc_disableKeyguard">Allows the app to disable the diff --git a/core/tests/coretests/src/android/os/ParcelTest.java b/core/tests/coretests/src/android/os/ParcelTest.java index e2fe87b4cfe3..4b993fadc1e0 100644 --- a/core/tests/coretests/src/android/os/ParcelTest.java +++ b/core/tests/coretests/src/android/os/ParcelTest.java @@ -246,4 +246,93 @@ public class ParcelTest { assertThrows(IllegalArgumentException.class, () -> Parcel.compareData(pA, -1, pB, iB, 0)); assertThrows(IllegalArgumentException.class, () -> Parcel.compareData(pA, 0, pB, -1, 0)); } + + /*** + * Tests for b/205282403 + * This test checks if allocations made over limit of 1MB for primitive types + * and 1M length for complex objects are not allowed. + */ + @Test + public void testAllocationsOverLimit_whenOverLimit_throws() { + Binder.setIsDirectlyHandlingTransactionOverride(true); + Parcel p = Parcel.obtain(); + p.setDataPosition(0); + p.writeInt(Integer.MAX_VALUE); + + p.setDataPosition(0); + assertThrows(BadParcelableException.class, () ->p.createBooleanArray()); + + p.setDataPosition(0); + assertThrows(BadParcelableException.class, () ->p.createCharArray()); + + p.setDataPosition(0); + assertThrows(BadParcelableException.class, () ->p.createIntArray()); + + p.setDataPosition(0); + assertThrows(BadParcelableException.class, () ->p.createLongArray()); + + p.setDataPosition(0); + assertThrows(BadParcelableException.class, () ->p.createBinderArray()); + + int[] dimensions = new int[]{Integer.MAX_VALUE, 100, 100}; + p.setDataPosition(0); + assertThrows(BadParcelableException.class, + () -> p.createFixedArray(int[][][].class, dimensions)); + + p.setDataPosition(0); + assertThrows(BadParcelableException.class, + () -> p.createFixedArray(String[][][].class, dimensions)); + + p.setDataPosition(0); + assertThrows(BadParcelableException.class, + () -> p.createFixedArray(IBinder[][][].class, dimensions)); + + p.recycle(); + Binder.setIsDirectlyHandlingTransactionOverride(false); + } + + /*** + * Tests for b/205282403 + * This test checks if allocations made under limit of 1MB for primitive types + * and 1M length for complex objects are allowed. + */ + @Test + public void testAllocations_whenWithinLimit() { + Binder.setIsDirectlyHandlingTransactionOverride(true); + Parcel p = Parcel.obtain(); + p.setDataPosition(0); + p.writeInt(100000); + + p.setDataPosition(0); + p.createByteArray(); + + p.setDataPosition(0); + p.createCharArray(); + + p.setDataPosition(0); + p.createIntArray(); + + p.setDataPosition(0); + p.createLongArray(); + + p.setDataPosition(0); + p.createBinderArray(); + + int[] dimensions = new int[]{ 100, 100, 100 }; + + p.setDataPosition(0); + int[][][] data = new int[100][100][100]; + p.writeFixedArray(data, 0, dimensions); + p.setDataPosition(0); + p.createFixedArray(int[][][].class, dimensions); + + p.setDataPosition(0); + IBinder[][][] parcelables = new IBinder[100][100][100]; + p.writeFixedArray(parcelables, 0, dimensions); + p.setDataPosition(0); + p.createFixedArray(IBinder[][][].class, dimensions); + + p.recycle(); + Binder.setIsDirectlyHandlingTransactionOverride(false); + } } diff --git a/core/tests/fuzzers/ParcelFuzzer/Android.bp b/core/tests/fuzzers/ParcelFuzzer/Android.bp index b71a06e3572e..eff19853fc7e 100644 --- a/core/tests/fuzzers/ParcelFuzzer/Android.bp +++ b/core/tests/fuzzers/ParcelFuzzer/Android.bp @@ -34,6 +34,7 @@ java_fuzz { "smoreland@google.com", "waghpawan@google.com", ], + triage_assignee: "cobark@google.com", // TODO(b/280770893) // Adds bugs to hotlist "AIDL fuzzers bugs" on buganizer hotlists: ["4637097"], }, diff --git a/core/tests/fuzzers/java_service_fuzzer/Android.bp b/core/tests/fuzzers/java_service_fuzzer/Android.bp index 6acb19852210..97538a5035f3 100644 --- a/core/tests/fuzzers/java_service_fuzzer/Android.bp +++ b/core/tests/fuzzers/java_service_fuzzer/Android.bp @@ -42,6 +42,7 @@ java_fuzz { "smoreland@google.com", "waghpawan@google.com", ], + triage_assignee: "cobark@google.com", // TODO(b/261539788) // Adds bugs to hotlist "AIDL fuzzers bugs" on buganizer hotlists: ["4637097"], }, diff --git a/libs/androidfw/include/androidfw/ObbFile.h b/libs/androidfw/include/androidfw/ObbFile.h index 3dbf997dc367..38ece5c1546f 100644 --- a/libs/androidfw/include/androidfw/ObbFile.h +++ b/libs/androidfw/include/androidfw/ObbFile.h @@ -43,10 +43,6 @@ public: bool removeFrom(const char* filename); bool removeFrom(int fd); - const char* getFileName() const { - return mFileName; - } - const String8 getPackageName() const { return mPackageName; } @@ -127,8 +123,6 @@ private: /* The encryption salt. */ unsigned char mSalt[8]; - const char* mFileName; - size_t mFooterStart; bool parseObbFile(int fd); diff --git a/native/android/storage_manager.cpp b/native/android/storage_manager.cpp index 9e0a6eb476d3..294ca9cfd3b4 100644 --- a/native/android/storage_manager.cpp +++ b/native/android/storage_manager.cpp @@ -86,7 +86,7 @@ protected: return nullptr; } - String16 fileName(obbFile->getFileName()); + String16 fileName(canonicalPath); String16 packageName(obbFile->getPackageName()); size_t length; const unsigned char* salt = obbFile->getSalt(&length); diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothUtils.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothUtils.java index 879181f0fbd6..2d958a919793 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothUtils.java +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothUtils.java @@ -6,6 +6,7 @@ import android.annotation.SuppressLint; import android.bluetooth.BluetoothClass; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothProfile; +import android.bluetooth.BluetoothCsipSetCoordinator; import android.content.Context; import android.content.Intent; import android.content.res.Resources; @@ -162,14 +163,21 @@ public class BluetoothUtils { resources, ((BitmapDrawable) pair.first).getBitmap()), pair.second); } + int hashCode; + if ((cachedDevice.getGroupId() != BluetoothCsipSetCoordinator.GROUP_ID_INVALID)) { + hashCode = new Integer(cachedDevice.getGroupId()).hashCode(); + } else { + hashCode = cachedDevice.getAddress().hashCode(); + } + return new Pair<>(buildBtRainbowDrawable(context, - pair.first, cachedDevice.getAddress().hashCode()), pair.second); + pair.first, hashCode), pair.second); } /** * Build Bluetooth device icon with rainbow */ - public static Drawable buildBtRainbowDrawable(Context context, Drawable drawable, + private static Drawable buildBtRainbowDrawable(Context context, Drawable drawable, int hashCode) { final Resources resources = context.getResources(); diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java index 6748e9cdb52e..6ef5d7347d31 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java @@ -1502,8 +1502,7 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice> refresh(); } - return new Pair<>(BluetoothUtils.buildBtRainbowDrawable( - mContext, pair.first, getAddress().hashCode()), pair.second); + return BluetoothUtils.getBtRainbowDrawableWithDescription(mContext, this); } void releaseLruCache() { diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinViewController.java index a16f30475654..8658c64e7993 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinViewController.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinViewController.java @@ -52,7 +52,7 @@ public class KeyguardSimPinViewController private ProgressDialog mSimUnlockProgressDialog; private CheckSimPin mCheckSimPinThread; - private int mRemainingAttempts; + private int mRemainingAttempts = -1; // Below flag is set to true during power-up or when a new SIM card inserted on device. // When this is true and when SIM card is PIN locked state, on PIN lock screen, message would // be displayed to inform user about the number of remaining PIN attempts left. diff --git a/services/core/java/com/android/server/DynamicSystemService.java b/services/core/java/com/android/server/DynamicSystemService.java index 27215b2fbf30..b0c1d05b0dd4 100644 --- a/services/core/java/com/android/server/DynamicSystemService.java +++ b/services/core/java/com/android/server/DynamicSystemService.java @@ -44,7 +44,7 @@ public class DynamicSystemService extends IDynamicSystemService.Stub { private static final String TAG = "DynamicSystemService"; private static final long MINIMUM_SD_MB = (30L << 10); private static final int GSID_ROUGH_TIMEOUT_MS = 8192; - private static final String PATH_DEFAULT = "/data/gsi/"; + private static final String PATH_DEFAULT = "/data/gsi/dsu/"; private Context mContext; private String mInstallPath, mDsuSlot; private volatile IGsiService mGsiService; diff --git a/services/usb/java/com/android/server/usb/UsbAlsaManager.java b/services/usb/java/com/android/server/usb/UsbAlsaManager.java index 42a5af7fdce3..3a8ef3370a53 100644 --- a/services/usb/java/com/android/server/usb/UsbAlsaManager.java +++ b/services/usb/java/com/android/server/usb/UsbAlsaManager.java @@ -71,6 +71,7 @@ public final class UsbAlsaManager { private static final int USB_VENDORID_SONY = 0x054C; private static final int USB_PRODUCTID_PS4CONTROLLER_ZCT1 = 0x05C4; private static final int USB_PRODUCTID_PS4CONTROLLER_ZCT2 = 0x09CC; + private static final int USB_PRODUCTID_PS5CONTROLLER = 0x0CE6; private static final int USB_DENYLIST_OUTPUT = 0x0001; private static final int USB_DENYLIST_INPUT = 0x0002; @@ -93,6 +94,9 @@ public final class UsbAlsaManager { USB_DENYLIST_OUTPUT), new DenyListEntry(USB_VENDORID_SONY, USB_PRODUCTID_PS4CONTROLLER_ZCT2, + USB_DENYLIST_OUTPUT), + new DenyListEntry(USB_VENDORID_SONY, + USB_PRODUCTID_PS5CONTROLLER, USB_DENYLIST_OUTPUT)); private static boolean isDeviceDenylisted(int vendorId, int productId, int flags) { diff --git a/tools/aapt2/cmd/Link.h b/tools/aapt2/cmd/Link.h index 0170c4a4c54b..2f5d8d19ebe5 100644 --- a/tools/aapt2/cmd/Link.h +++ b/tools/aapt2/cmd/Link.h @@ -206,6 +206,11 @@ class LinkCommand : public Command { AddOptionalFlag("--compile-sdk-version-name", "Version name to inject into the AndroidManifest.xml if none is present.", &options_.manifest_fixer_options.compile_sdk_version_codename); + AddOptionalSwitch( + "--no-compile-sdk-metadata", + "Suppresses output of compile SDK-related attributes in AndroidManifest.xml,\n" + "including android:compileSdkVersion and platformBuildVersion.", + &options_.manifest_fixer_options.no_compile_sdk_metadata); AddOptionalSwitch("--shared-lib", "Generates a shared Android runtime library.", &shared_lib_); AddOptionalSwitch("--static-lib", "Generate a static Android library.", &static_lib_); diff --git a/tools/aapt2/link/ManifestFixer.cpp b/tools/aapt2/link/ManifestFixer.cpp index 42191912775a..f8e734724018 100644 --- a/tools/aapt2/link/ManifestFixer.cpp +++ b/tools/aapt2/link/ManifestFixer.cpp @@ -635,7 +635,7 @@ bool ManifestFixer::Consume(IAaptContext* context, xml::XmlResource* doc) { root->InsertChild(0, std::move(uses_sdk)); } - if (options_.compile_sdk_version) { + if (!options_.no_compile_sdk_metadata && options_.compile_sdk_version) { xml::Attribute* attr = root->FindOrCreateAttribute(xml::kSchemaAndroid, "compileSdkVersion"); // Make sure we un-compile the value if it was set to something else. @@ -647,10 +647,9 @@ bool ManifestFixer::Consume(IAaptContext* context, xml::XmlResource* doc) { // Make sure we un-compile the value if it was set to something else. attr->compiled_value = {}; attr->value = options_.compile_sdk_version.value(); - } - if (options_.compile_sdk_version_codename) { + if (!options_.no_compile_sdk_metadata && options_.compile_sdk_version_codename) { xml::Attribute* attr = root->FindOrCreateAttribute(xml::kSchemaAndroid, "compileSdkVersionCodename"); diff --git a/tools/aapt2/link/ManifestFixer.h b/tools/aapt2/link/ManifestFixer.h index a8707d9d8623..70bfcfc1365a 100644 --- a/tools/aapt2/link/ManifestFixer.h +++ b/tools/aapt2/link/ManifestFixer.h @@ -68,11 +68,12 @@ struct ManifestFixerOptions { std::optional<std::string> revision_code_default; // The version of the framework being compiled against to set for 'android:compileSdkVersion' in - // the <manifest> tag. + // the <manifest> tag. Not used if no_compile_sdk_metadata is set. std::optional<std::string> compile_sdk_version; // The version codename of the framework being compiled against to set for - // 'android:compileSdkVersionCodename' in the <manifest> tag. + // 'android:compileSdkVersionCodename' in the <manifest> tag. Not used if no_compile_sdk_metadata + // is set. std::optional<std::string> compile_sdk_version_codename; // Whether validation errors should be treated only as warnings. If this is 'true', then an @@ -85,6 +86,9 @@ struct ManifestFixerOptions { // Whether to replace the manifest version with the the command line version bool replace_version = false; + + // Whether to suppress `android:compileSdkVersion*` and `platformBuildVersion*` attributes. + bool no_compile_sdk_metadata = false; }; // Verifies that the manifest is correctly formed and inserts defaults where specified with diff --git a/tools/aapt2/link/ManifestFixer_test.cpp b/tools/aapt2/link/ManifestFixer_test.cpp index 098d0be7f87d..9204d2276a17 100644 --- a/tools/aapt2/link/ManifestFixer_test.cpp +++ b/tools/aapt2/link/ManifestFixer_test.cpp @@ -892,6 +892,35 @@ TEST_F(ManifestFixerTest, InsertCompileSdkVersions) { EXPECT_THAT(attr->value, StrEq("P")); } +TEST_F(ManifestFixerTest, DoNotInsertCompileSdkVersions) { + std::string input = R"(<manifest package="com.pkg" />)"; + ManifestFixerOptions options; + options.no_compile_sdk_metadata = true; + options.compile_sdk_version = {"28"}; + options.compile_sdk_version_codename = {"P"}; + + std::unique_ptr<xml::XmlResource> manifest = VerifyWithOptions(input, options); + ASSERT_THAT(manifest, NotNull()); + + // There should be a declaration of kSchemaAndroid, even when the input + // didn't have one. + EXPECT_EQ(manifest->root->namespace_decls.size(), 1); + EXPECT_EQ(manifest->root->namespace_decls[0].prefix, "android"); + EXPECT_EQ(manifest->root->namespace_decls[0].uri, xml::kSchemaAndroid); + + xml::Attribute* attr = manifest->root->FindAttribute(xml::kSchemaAndroid, "compileSdkVersion"); + ASSERT_THAT(attr, IsNull()); + + attr = manifest->root->FindAttribute(xml::kSchemaAndroid, "compileSdkVersionCodename"); + ASSERT_THAT(attr, IsNull()); + + attr = manifest->root->FindAttribute("", "platformBuildVersionCode"); + ASSERT_THAT(attr, IsNull()); + + attr = manifest->root->FindAttribute("", "platformBuildVersionName"); + ASSERT_THAT(attr, IsNull()); +} + TEST_F(ManifestFixerTest, OverrideCompileSdkVersions) { std::string input = R"( <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="android" |