Merge "Show current event threshold in EVENT TRACKER POLICY SETTINGS "
diff --git a/core/java/android/app/assist/OWNERS b/core/java/android/app/assist/OWNERS
index e857c72..80ecaa4 100644
--- a/core/java/android/app/assist/OWNERS
+++ b/core/java/android/app/assist/OWNERS
@@ -3,3 +3,5 @@
markpun@google.com
lpeter@google.com
tymtsai@google.com
+hackz@google.com
+volnov@google.com
\ No newline at end of file
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index bb74e19..89da45b 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -1360,7 +1360,7 @@
String formatSize = MemoryProperties.memory_ddr_size().orElse("0KB");
long memSize = FileUtils.parseSize(formatSize);
- if (memSize == Long.MIN_VALUE) {
+ if (memSize <= 0) {
return FileUtils.roundStorageSize(getTotalMemory());
}
diff --git a/core/java/android/speech/OWNERS b/core/java/android/speech/OWNERS
index 462d8be..162e029 100644
--- a/core/java/android/speech/OWNERS
+++ b/core/java/android/speech/OWNERS
@@ -2,3 +2,4 @@
eugeniom@google.com
schfan@google.com
andreaambu@google.com
+hackz@google.com
\ No newline at end of file
diff --git a/core/java/android/view/contentcapture/OWNERS b/core/java/android/view/contentcapture/OWNERS
index 1a5cb1e4..d1eda96 100644
--- a/core/java/android/view/contentcapture/OWNERS
+++ b/core/java/android/view/contentcapture/OWNERS
@@ -5,3 +5,5 @@
markpun@google.com
lpeter@google.com
tymtsai@google.com
+hackz@google.com
+volnov@google.com
\ No newline at end of file
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 6919a76..7c8ea93 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -646,9 +646,7 @@
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 @@
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/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 277bdf3..35dc8e3 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/config.xml b/core/res/res/values/config.xml
index 4b05f99..031a666 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -4475,6 +4475,9 @@
<!-- Whether or not we should show the option to show battery percentage -->
<bool name="config_battery_percentage_setting_available">true</bool>
+ <!-- Default value set for battery percentage in status bar false = disabled, true = enabled -->
+ <bool name="config_defaultBatteryPercentageSetting">false</bool>
+
<!-- Whether or not battery saver should be "sticky" when manually enabled. -->
<bool name="config_batterySaverStickyBehaviourDisabled">false</bool>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 8a1b74d..5a1e0e8 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/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index ba1030b..716d1bd 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2359,6 +2359,7 @@
<java-symbol type="style" name="Animation.RecentApplications" />
<java-symbol type="integer" name="dock_enter_exit_duration" />
<java-symbol type="bool" name="config_battery_percentage_setting_available" />
+ <java-symbol type="bool" name="config_defaultBatteryPercentageSetting" />
<java-symbol type="string" name="nas_upgrade_notification_title" />
<java-symbol type="string" name="nas_upgrade_notification_content" />
<java-symbol type="string" name="nas_upgrade_notification_enable_action" />
diff --git a/core/tests/coretests/src/android/os/ProcessTest.java b/core/tests/coretests/src/android/os/ProcessTest.java
index 52846df..b2ffdc0 100644
--- a/core/tests/coretests/src/android/os/ProcessTest.java
+++ b/core/tests/coretests/src/android/os/ProcessTest.java
@@ -73,6 +73,7 @@
}
public void testGetAdvertisedMem() {
+ assertTrue(Process.getAdvertisedMem() > 0);
assertTrue(Process.getTotalMemory() <= Process.getAdvertisedMem());
}
}
diff --git a/libs/androidfw/include/androidfw/ObbFile.h b/libs/androidfw/include/androidfw/ObbFile.h
index 3dbf997d..38ece5c1 100644
--- a/libs/androidfw/include/androidfw/ObbFile.h
+++ b/libs/androidfw/include/androidfw/ObbFile.h
@@ -43,10 +43,6 @@
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 @@
/* 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 9e0a6eb..294ca9c 100644
--- a/native/android/storage_manager.cpp
+++ b/native/android/storage_manager.cpp
@@ -86,7 +86,7 @@
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 879181f..2d958a9 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.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 @@
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 6748e9c..6ef5d73 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 @@
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/systemui/battery/BatteryMeterView.java b/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterView.java
index 03d999f..9f948a7 100644
--- a/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterView.java
+++ b/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterView.java
@@ -325,7 +325,9 @@
// TODO(b/140051051)
final boolean systemSetting = 0 != whitelistIpcs(() -> Settings.System
.getIntForUser(getContext().getContentResolver(),
- SHOW_BATTERY_PERCENT, 0, UserHandle.USER_CURRENT));
+ SHOW_BATTERY_PERCENT, getContext().getResources().getBoolean(
+ com.android.internal.R.bool.config_defaultBatteryPercentageSetting)
+ ? 1 : 0, UserHandle.USER_CURRENT));
boolean shouldShow =
(mShowPercentAvailable && systemSetting && mShowPercentMode != MODE_OFF)
|| mShowPercentMode == MODE_ON
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index dcf1906..d285337 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -220,6 +220,7 @@
import android.telephony.SubscriptionManager;
import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener;
import android.telephony.SubscriptionPlan;
+import android.telephony.TelephonyCallback;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.text.format.DateUtils;
@@ -801,6 +802,16 @@
}
return buckets;
}
+
+ /** Require IPC call. Don't call when holding a lock. */
+ int getDefaultDataSubId() {
+ return SubscriptionManager.getDefaultDataSubscriptionId();
+ }
+
+ /** Require IPC call. Don't call when holding a lock. */
+ int getActivateDataSubId() {
+ return SubscriptionManager.getActiveDataSubscriptionId();
+ }
}
@VisibleForTesting
@@ -828,7 +839,7 @@
mSuppressDefaultPolicy = suppressDefaultPolicy;
mDeps = Objects.requireNonNull(deps, "missing Dependencies");
-
+ mActiveDataSubIdListener = new ActiveDataSubIdListener();
mPolicyFile = new AtomicFile(new File(systemDir, "netpolicy.xml"), "net-policy");
mAppOps = context.getSystemService(AppOpsManager.class);
@@ -1088,6 +1099,10 @@
}
});
+ // Listen for active data sub Id change, upon which data notifications is shown/hidden.
+ mContext.getSystemService(TelephonyManager.class).registerTelephonyCallback(executor,
+ mActiveDataSubIdListener);
+
// tell systemReady() that the service has been initialized
initCompleteSignal.countDown();
} finally {
@@ -1257,6 +1272,38 @@
};
/**
+ * Listener that watches for active data sub Id change, upon which data notifications are
+ * shown/hidden.
+ */
+ private final ActiveDataSubIdListener mActiveDataSubIdListener;
+ private class ActiveDataSubIdListener extends TelephonyCallback implements
+ TelephonyCallback.ActiveDataSubscriptionIdListener {
+ /**
+ * In most cases active data sub is the same as the default data sub, but if user enabled
+ * auto data switch {@link TelephonyManager#MOBILE_DATA_POLICY_AUTO_DATA_SWITCH},
+ * active data sub could be the non-default data sub.
+ *
+ * If the listener is initialized before the phone process is up, the IPC call to the
+ * static method of SubscriptionManager lead to INVALID_SUBSCRIPTION_ID to be returned,
+ * indicating the phone process is unable to determine a valid data sub Id at this point, in
+ * which case no data notifications should be shown anyway. Later on when an active data
+ * sub is known, notifications will be re-evaluated by this callback.
+ */
+ private int mDefaultDataSubId = mDeps.getDefaultDataSubId();
+ private int mActiveDataSubId = mDeps.getActivateDataSubId();
+ // Only listen to active data sub change is sufficient because default data sub change
+ // leads to active data sub change as well.
+ @Override
+ public void onActiveDataSubscriptionIdChanged(int subId) {
+ mActiveDataSubId = subId;
+ mDefaultDataSubId = mDeps.getDefaultDataSubId();
+ synchronized (mNetworkPoliciesSecondLock) {
+ updateNotificationsNL();
+ }
+ }
+ }
+
+ /**
* Listener that watches for {@link NetworkStatsManager} updates, which
* NetworkPolicyManagerService uses to check against {@link NetworkPolicy#warningBytes}.
*/
@@ -1445,6 +1492,9 @@
// ignore policies that aren't relevant to user
if (subId == INVALID_SUBSCRIPTION_ID) continue;
+ // ignore if the data sub is neither default nor active for data at the moment.
+ if (subId != mActiveDataSubIdListener.mDefaultDataSubId
+ && subId != mActiveDataSubIdListener.mActiveDataSubId) continue;
if (!policy.hasCycle()) continue;
final Pair<ZonedDateTime, ZonedDateTime> cycle = NetworkPolicyManager
diff --git a/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
index 7c7e2ee..012596e 100644
--- a/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
@@ -151,6 +151,7 @@
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.telephony.SubscriptionPlan;
+import android.telephony.TelephonyCallback;
import android.telephony.TelephonyManager;
import android.test.suitebuilder.annotation.MediumTest;
import android.text.TextUtils;
@@ -241,6 +242,7 @@
private static final String TEST_WIFI_NETWORK_KEY = "TestWifiNetworkKey";
private static final String TEST_IMSI = "310210";
private static final int TEST_SUB_ID = 42;
+ private static final int TEST_SUB_ID2 = 24;
private static final Network TEST_NETWORK = mock(Network.class, CALLS_REAL_METHODS);
private static NetworkTemplate sTemplateWifi = new NetworkTemplate.Builder(MATCH_WIFI)
@@ -282,6 +284,8 @@
private ArgumentCaptor<ConnectivityManager.NetworkCallback> mNetworkCallbackCaptor =
ArgumentCaptor.forClass(ConnectivityManager.NetworkCallback.class);
+ private TelephonyCallback.ActiveDataSubscriptionIdListener mActiveDataSubIdListener;
+
private ActivityManagerInternal mActivityManagerInternal;
private PackageManagerInternal mPackageManagerInternal;
@@ -357,6 +361,8 @@
private class TestDependencies extends NetworkPolicyManagerService.Dependencies {
private final SparseArray<NetworkStats.Bucket> mMockedStats = new SparseArray<>();
+ private int mMockDefaultDataSubId;
+ private int mMockedActiveDataSubId;
TestDependencies(Context context) {
super(context);
@@ -394,6 +400,21 @@
final NetworkStats.Bucket bucket = mMockedStats.get(uid);
setMockedTotalBytes(uid, bucket.getRxBytes() + rxBytes, bucket.getTxBytes() + txBytes);
}
+
+ void setDefaultAndActiveDataSubId(int defaultDataSubId, int activeDataSubId) {
+ mMockDefaultDataSubId = defaultDataSubId;
+ mMockedActiveDataSubId = activeDataSubId;
+ }
+
+ @Override
+ int getDefaultDataSubId() {
+ return mMockDefaultDataSubId;
+ }
+
+ @Override
+ int getActivateDataSubId() {
+ return mMockedActiveDataSubId;
+ }
}
@Before
@@ -551,6 +572,14 @@
NetworkPolicy defaultPolicy = mService.buildDefaultCarrierPolicy(0, "");
mDefaultWarningBytes = defaultPolicy.warningBytes;
mDefaultLimitBytes = defaultPolicy.limitBytes;
+
+ // Catch TelephonyCallback during systemReady().
+ ArgumentCaptor<TelephonyCallback> telephonyCallbackArgumentCaptor =
+ ArgumentCaptor.forClass(TelephonyCallback.class);
+ verify(mTelephonyManager).registerTelephonyCallback(any(),
+ telephonyCallbackArgumentCaptor.capture());
+ mActiveDataSubIdListener = (TelephonyCallback.ActiveDataSubscriptionIdListener)
+ telephonyCallbackArgumentCaptor.getValue();
}
@After
@@ -1243,6 +1272,7 @@
reset(mTelephonyManager, mNetworkManager, mNotifManager);
TelephonyManager tmSub = expectMobileDefaults();
+ clearInvocations(mNotifManager);
mService.updateNetworks();
@@ -1258,6 +1288,7 @@
reset(mTelephonyManager, mNetworkManager, mNotifManager);
TelephonyManager tmSub = expectMobileDefaults();
+ clearInvocations(mNotifManager);
mService.updateNetworks();
@@ -1275,6 +1306,7 @@
reset(mTelephonyManager, mNetworkManager, mNotifManager);
TelephonyManager tmSub = expectMobileDefaults();
expectDefaultCarrierConfig();
+ clearInvocations(mNotifManager);
mService.updateNetworks();
@@ -1291,6 +1323,7 @@
reset(mTelephonyManager, mNetworkManager, mNotifManager);
TelephonyManager tmSub = expectMobileDefaults();
+ clearInvocations(mNotifManager);
mService.updateNetworks();
@@ -1304,6 +1337,7 @@
{
reset(mTelephonyManager, mNetworkManager, mNotifManager);
TelephonyManager tmSub = expectMobileDefaults();
+ clearInvocations(mNotifManager);
mService.snoozeLimit(sTemplateCarrierMetered);
mService.updateNetworks();
@@ -1314,6 +1348,31 @@
verify(mNotifManager, atLeastOnce()).notifyAsUser(any(), eq(TYPE_LIMIT_SNOOZED),
isA(Notification.class), eq(UserHandle.ALL));
}
+ // The sub is no longer used for data(e.g. user uses another sub), hide the notifications.
+ {
+ reset(mTelephonyManager, mNetworkManager, mNotifManager);
+
+ notifyDefaultAndActiveDataSubIdChange(TEST_SUB_ID2, TEST_SUB_ID2);
+ verify(mNotifManager, atLeastOnce()).cancel(any(), eq(TYPE_LIMIT_SNOOZED));
+ }
+ // The sub is not active for data(e.g. due to auto data switch), but still default for data,
+ // show notification.
+ {
+ reset(mTelephonyManager, mNetworkManager, mNotifManager);
+
+ notifyDefaultAndActiveDataSubIdChange(TEST_SUB_ID, TEST_SUB_ID2);
+ verify(mNotifManager, atLeastOnce()).notifyAsUser(any(), eq(TYPE_LIMIT_SNOOZED),
+ isA(Notification.class), eq(UserHandle.ALL));
+ }
+ // The sub is active for data, but not the default(e.g. due to auto data switch),
+ // show notification.
+ {
+ reset(mTelephonyManager, mNetworkManager, mNotifManager);
+
+ notifyDefaultAndActiveDataSubIdChange(TEST_SUB_ID2, TEST_SUB_ID);
+ verify(mNotifManager, atLeastOnce()).notifyAsUser(any(), eq(TYPE_LIMIT_SNOOZED),
+ isA(Notification.class), eq(UserHandle.ALL));
+ }
}
@Test
@@ -2377,6 +2436,7 @@
String subscriberId) {
when(mSubscriptionManager.getActiveSubscriptionInfoList()).thenReturn(
createSubscriptionInfoList(subscriptionId));
+ notifyDefaultAndActiveDataSubIdChange(subscriptionId, subscriptionId);
TelephonyManager subTelephonyManager;
subTelephonyManager = mock(TelephonyManager.class);
@@ -2388,6 +2448,16 @@
}
/**
+ * Telephony Manager callback notifies data sub Id changes.
+ * @param defaultDataSubId The mock default data sub Id.
+ * @param activeDataSubId The mock active data sub Id.
+ */
+ private void notifyDefaultAndActiveDataSubIdChange(int defaultDataSubId, int activeDataSubId) {
+ mDeps.setDefaultAndActiveDataSubId(defaultDataSubId, activeDataSubId);
+ mActiveDataSubIdListener.onActiveDataSubscriptionIdChanged(activeDataSubId);
+ }
+
+ /**
* Creates mock {@link SubscriptionInfo} from subscription id.
*/
private List<SubscriptionInfo> createSubscriptionInfoList(int subId) {
diff --git a/tools/aapt2/cmd/Link.h b/tools/aapt2/cmd/Link.h
index 0170c4a..2f5d8d1 100644
--- a/tools/aapt2/cmd/Link.h
+++ b/tools/aapt2/cmd/Link.h
@@ -206,6 +206,11 @@
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 4219191..f8e7347 100644
--- a/tools/aapt2/link/ManifestFixer.cpp
+++ b/tools/aapt2/link/ManifestFixer.cpp
@@ -635,7 +635,7 @@
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 @@
// 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 a8707d9..70bfcfc 100644
--- a/tools/aapt2/link/ManifestFixer.h
+++ b/tools/aapt2/link/ManifestFixer.h
@@ -68,11 +68,12 @@
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 @@
// 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 098d0be..9204d22 100644
--- a/tools/aapt2/link/ManifestFixer_test.cpp
+++ b/tools/aapt2/link/ManifestFixer_test.cpp
@@ -892,6 +892,35 @@
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"