Merge "Crash during Task switch" into main
diff --git a/boot/Android.bp b/boot/Android.bp
index 6eead42..6159845 100644
--- a/boot/Android.bp
+++ b/boot/Android.bp
@@ -75,8 +75,8 @@
module: "art-bootclasspath-fragment",
},
{
- apex: "com.android.btservices",
- module: "com.android.btservices-bootclasspath-fragment",
+ apex: "com.android.bt",
+ module: "com.android.bt-bootclasspath-fragment",
},
{
apex: "com.android.configinfrastructure",
diff --git a/config/preloaded-classes-denylist b/config/preloaded-classes-denylist
index e3e929c..a6a1d16 100644
--- a/config/preloaded-classes-denylist
+++ b/config/preloaded-classes-denylist
@@ -1,5 +1,4 @@
android.content.AsyncTaskLoader$LoadTask
-android.media.MediaCodecInfo$CodecCapabilities$FeatureList
android.net.ConnectivityThread$Singleton
android.os.FileObserver
android.os.NullVibrator
diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java
index 1e45d6f..29578c9 100644
--- a/core/java/android/app/LoadedApk.java
+++ b/core/java/android/app/LoadedApk.java
@@ -1129,6 +1129,10 @@
@UnsupportedAppUsage
public ClassLoader getClassLoader() {
+ ClassLoader ret = mClassLoader;
+ if (ret != null) {
+ return ret;
+ }
synchronized (mLock) {
if (mClassLoader == null) {
createOrUpdateClassLoaderLocked(null /*addedPaths*/);
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 031380d..f815df6 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -5431,7 +5431,7 @@
/**
* Activities that can be safely invoked from a browser must support this
* category. For example, if the user is viewing a web page or an e-mail
- * and clicks on a link in the text, the Intent generated execute that
+ * and clicks on a link in the text, the Intent generated to execute that
* link will require the BROWSABLE category, so that only activities
* supporting this category will be considered as possible actions. By
* supporting this category, you are promising that there is nothing
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 14a802a..d4905f9 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -4614,6 +4614,7 @@
* the Android Keystore backed by an isolated execution environment. The version indicates
* which features are implemented in the isolated execution environment:
* <ul>
+ * <li>400: Inclusion of module information (via tag MODULE_HASH) in the attestation record.
* <li>300: Ability to include a second IMEI in the ID attestation record, see
* {@link android.app.admin.DevicePolicyManager#ID_TYPE_IMEI}.
* <li>200: Hardware support for Curve 25519 (including both Ed25519 signature generation and
@@ -4647,6 +4648,7 @@
* StrongBox</a>. If this feature has a version, the version number indicates which features are
* implemented in StrongBox:
* <ul>
+ * <li>400: Inclusion of module information (via tag MODULE_HASH) in the attestation record.
* <li>300: Ability to include a second IMEI in the ID attestation record, see
* {@link android.app.admin.DevicePolicyManager#ID_TYPE_IMEI}.
* <li>200: No new features for StrongBox (the Android Keystore environment backed by an
diff --git a/core/java/android/os/Debug.java b/core/java/android/os/Debug.java
index ef1e6c94..51aa06b 100644
--- a/core/java/android/os/Debug.java
+++ b/core/java/android/os/Debug.java
@@ -2741,4 +2741,12 @@
*/
public static native boolean logAllocatorStats();
+ /**
+ * Return the amount of memory (in kB) allocated by kernel drivers through CMA.
+ * @return a non-negative value or -1 on error.
+ *
+ * @hide
+ */
+ public static native long getKernelCmaUsageKb();
+
}
diff --git a/core/java/android/os/Looper.java b/core/java/android/os/Looper.java
index 0125905..2fe4871 100644
--- a/core/java/android/os/Looper.java
+++ b/core/java/android/os/Looper.java
@@ -70,6 +70,13 @@
private static final String TAG = "Looper";
+ private static class NoImagePreloadHolder {
+ // Enable/Disable verbose logging with a system prop. e.g.
+ // adb shell 'setprop log.looper.slow.verbose false && stop && start'
+ private static final boolean sVerboseLogging =
+ SystemProperties.getBoolean("log.looper.slow.verbose", false);
+ }
+
// sThreadLocal.get() will return null unless you've called prepare().
@UnsupportedAppUsage
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
@@ -246,17 +253,21 @@
}
}
if (logSlowDelivery) {
+ boolean slow = false;
+
+ if (!me.mSlowDeliveryDetected || NoImagePreloadHolder.sVerboseLogging) {
+ slow = showSlowLog(slowDeliveryThresholdMs, msg.when, dispatchStart,
+ "delivery", msg);
+ }
if (me.mSlowDeliveryDetected) {
- if ((dispatchStart - msg.when) <= 10) {
+ if (!slow && (dispatchStart - msg.when) <= 10) {
Slog.w(TAG, "Drained");
me.mSlowDeliveryDetected = false;
}
- } else {
- if (showSlowLog(slowDeliveryThresholdMs, msg.when, dispatchStart, "delivery",
- msg)) {
- // Once we write a slow delivery log, suppress until the queue drains.
- me.mSlowDeliveryDetected = true;
- }
+ } else if (slow) {
+ // A slow delivery is detected, suppressing further logs unless verbose logging
+ // is enabled.
+ me.mSlowDeliveryDetected = true;
}
}
if (logSlowDispatch) {
@@ -322,6 +333,23 @@
@android.ravenwood.annotation.RavenwoodReplace
private static int getThresholdOverride() {
+ // Allow overriding the threshold for all processes' main looper with a system prop.
+ // e.g. adb shell 'setprop log.looper.any.main.slow 1 && stop && start'
+ if (myLooper() == getMainLooper()) {
+ final int globalOverride = SystemProperties.getInt("log.looper.any.main.slow", -1);
+ if (globalOverride >= 0) {
+ return globalOverride;
+ }
+ }
+
+ // Allow overriding the threshold for all threads within a process with a system prop.
+ // e.g. adb shell 'setprop log.looper.1000.any.slow 1 && stop && start'
+ final int processOverride = SystemProperties.getInt("log.looper."
+ + Process.myUid() + ".any.slow", -1);
+ if (processOverride >= 0) {
+ return processOverride;
+ }
+
return SystemProperties.getInt("log.looper."
+ Process.myUid() + "."
+ Thread.currentThread().getName()
diff --git a/core/java/android/view/PointerIcon.java b/core/java/android/view/PointerIcon.java
index b21e85a..da3a817f 100644
--- a/core/java/android/view/PointerIcon.java
+++ b/core/java/android/view/PointerIcon.java
@@ -514,10 +514,14 @@
final TypedArray a = resources.obtainAttributes(
parser, com.android.internal.R.styleable.PointerIcon);
bitmapRes = a.getResourceId(com.android.internal.R.styleable.PointerIcon_bitmap, 0);
- hotSpotX = a.getDimension(com.android.internal.R.styleable.PointerIcon_hotSpotX, 0)
- * pointerScale;
- hotSpotY = a.getDimension(com.android.internal.R.styleable.PointerIcon_hotSpotY, 0)
- * pointerScale;
+ // Cast the hotspot dimensions to int before scaling to match the scaling logic of
+ // the bitmap, whose intrinsic size is also an int before it is scaled.
+ final int unscaledHotSpotX =
+ (int) a.getDimension(com.android.internal.R.styleable.PointerIcon_hotSpotX, 0);
+ final int unscaledHotSpotY =
+ (int) a.getDimension(com.android.internal.R.styleable.PointerIcon_hotSpotY, 0);
+ hotSpotX = unscaledHotSpotX * pointerScale;
+ hotSpotY = unscaledHotSpotY * pointerScale;
a.recycle();
} catch (Exception ex) {
throw new IllegalArgumentException("Exception parsing pointer icon resource.", ex);
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index d91963f..6bb8b0a 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -4479,7 +4479,7 @@
/**
* @hide
*/
- public Transaction setDesintationFrame(SurfaceControl sc, @NonNull Rect destinationFrame) {
+ public Transaction setDestinationFrame(SurfaceControl sc, @NonNull Rect destinationFrame) {
checkPreconditions(sc);
nativeSetDestinationFrame(mNativeObject, sc.mNativeObject,
destinationFrame.left, destinationFrame.top, destinationFrame.right,
@@ -4490,7 +4490,7 @@
/**
* @hide
*/
- public Transaction setDesintationFrame(SurfaceControl sc, int width, int height) {
+ public Transaction setDestinationFrame(SurfaceControl sc, int width, int height) {
checkPreconditions(sc);
nativeSetDestinationFrame(mNativeObject, sc.mNativeObject, 0, 0, width, height);
return this;
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index f0d2a34..31d8556 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -1092,7 +1092,7 @@
}
}
- surfaceUpdateTransaction.setDesintationFrame(mBlastSurfaceControl, mSurfaceWidth,
+ surfaceUpdateTransaction.setDestinationFrame(mBlastSurfaceControl, mSurfaceWidth,
mSurfaceHeight);
if (isHardwareAccelerated()) {
diff --git a/core/jni/android_os_Debug.cpp b/core/jni/android_os_Debug.cpp
index 3c2dccd..9ef17e8 100644
--- a/core/jni/android_os_Debug.cpp
+++ b/core/jni/android_os_Debug.cpp
@@ -729,6 +729,17 @@
return gpuPrivateMem / 1024;
}
+static jlong android_os_Debug_getKernelCmaUsageKb(JNIEnv* env, jobject clazz) {
+ jlong totalKernelCmaUsageKb = -1;
+ uint64_t size;
+
+ if (meminfo::ReadKernelCmaUsageKb(&size)) {
+ totalKernelCmaUsageKb = size;
+ }
+
+ return totalKernelCmaUsageKb;
+}
+
static jlong android_os_Debug_getDmabufMappedSizeKb(JNIEnv* env, jobject clazz) {
jlong dmabufPss = 0;
std::vector<dmabufinfo::DmaBuffer> dmabufs;
@@ -836,6 +847,7 @@
{"getGpuTotalUsageKb", "()J", (void*)android_os_Debug_getGpuTotalUsageKb},
{"isVmapStack", "()Z", (void*)android_os_Debug_isVmapStack},
{"logAllocatorStats", "()Z", (void*)android_os_Debug_logAllocatorStats},
+ {"getKernelCmaUsageKb", "()J", (void*)android_os_Debug_getKernelCmaUsageKb},
};
int register_android_os_Debug(JNIEnv *env)
diff --git a/core/res/res/xml/sms_short_codes.xml b/core/res/res/xml/sms_short_codes.xml
index 06cd44e..9b3a6cb 100644
--- a/core/res/res/xml/sms_short_codes.xml
+++ b/core/res/res/xml/sms_short_codes.xml
@@ -111,7 +111,7 @@
<shortcode country="cz" premium="90\\d{5}|90\\d{3}" free="116\\d{3}" />
<!-- Germany: 4-5 digits plus 1232xxx (premium codes from http://www.vodafone.de/infofaxe/537.pdf and http://premiumdienste.eplus.de/pdf/kodex.pdf), plus EU. To keep the premium regex from being too large, it only includes payment processors that have been used by SMS malware, with the regular pattern matching the other premium short codes. -->
- <shortcode country="de" pattern="\\d{4,5}|1232\\d{3}" premium="11(?:111|833)|1232(?:013|021|060|075|286|358)|118(?:44|80|86)|20[25]00|220(?:21|22|88|99)|221(?:14|21)|223(?:44|53|77)|224[13]0|225(?:20|59|90)|226(?:06|10|20|26|30|40|56|70)|227(?:07|33|39|66|76|78|79|88|99)|228(?:08|11|66|77)|23300|30030|3[12347]000|330(?:33|55|66)|33(?:233|331|366|533)|34(?:34|567)|37000|40(?:040|123|444|[3568]00)|41(?:010|414)|44(?:000|044|344|44[24]|544)|50005|50100|50123|50555|51000|52(?:255|783)|54(?:100|2542)|55(?:077|[24]00|222|333|55|[12369]55)|56(?:789|886)|60800|6[13]000|66(?:[12348]66|566|766|777|88|999)|68888|70(?:07|123|777)|76766|77(?:007|070|222|444|[567]77)|80(?:008|123|888)|82(?:002|[378]00|323|444|472|474|488|727)|83(?:005|[169]00|333|830)|84(?:141|300|32[34]|343|488|499|777|888)|85888|86(?:188|566|640|644|650|677|868|888)|870[24]9|871(?:23|[49]9)|872(?:1[0-8]|49|99)|87499|875(?:49|55|99)|876(?:0[1367]|1[1245678]|54|99)|877(?:00|99)|878(?:15|25|3[567]|8[12])|87999|880(?:08|44|55|77|99)|88688|888(?:03|10|8|89)|8899|90(?:009|999)|99999" free="116\\d{3}|81214|81215|47529|70296|83782|3011|73240|72438" />
+ <shortcode country="de" pattern="\\d{4,5}|1232\\d{3}" premium="11(?:111|833)|1232(?:013|021|060|075|286|358)|118(?:44|80|86)|20[25]00|220(?:21|22|88|99)|221(?:14|21)|223(?:44|53|77)|224[13]0|225(?:20|59|90)|226(?:06|10|20|26|30|40|56|70)|227(?:07|33|39|66|76|78|79|88|99)|228(?:08|11|66|77)|23300|30030|3[12347]000|330(?:33|55|66)|33(?:233|331|366|533)|34(?:34|567)|37000|40(?:040|123|444|[3568]00)|41(?:010|414)|44(?:000|044|344|44[24]|544)|50005|50100|50123|50555|51000|52(?:255|783)|54(?:100|2542)|55(?:077|[24]00|222|333|55|[12369]55)|56(?:789|886)|60800|6[13]000|66(?:[12348]66|566|766|777|88|999)|68888|70(?:07|123|777)|76766|77(?:007|070|222|444|[567]77)|80(?:008|123|888)|82(?:002|[378]00|323|444|472|474|488|727)|83(?:005|[169]00|333|830)|84(?:141|300|32[34]|343|488|499|777|888)|85888|86(?:188|566|640|644|650|677|868|888)|870[24]9|871(?:23|[49]9)|872(?:1[0-8]|49|99)|87499|875(?:49|55|99)|876(?:0[1367]|1[1245678]|54|99)|877(?:00|99)|878(?:15|25|3[567]|8[12])|87999|880(?:08|44|55|77|99)|88688|888(?:03|10|8|89)|8899|90(?:009|999)|99999" free="116\\d{3}|81214|81215|47529|70296|83782|3011|73240|72438|70997" />
<!-- Denmark: see http://iprs.webspacecommerce.com/Denmark-Premium-Rate-Numbers -->
<shortcode country="dk" pattern="\\d{4,5}" premium="1\\d{3}" free="116\\d{3}|4665" />
diff --git a/keystore/java/android/security/keystore/KeyStoreManager.java b/keystore/java/android/security/keystore/KeyStoreManager.java
index 740ccb5..13f1a72 100644
--- a/keystore/java/android/security/keystore/KeyStoreManager.java
+++ b/keystore/java/android/security/keystore/KeyStoreManager.java
@@ -312,9 +312,11 @@
* When passed into getSupplementaryAttestationInfo, getSupplementaryAttestationInfo returns the
* DER-encoded structure corresponding to the `Modules` schema described in the KeyMint HAL's
* KeyCreationResult.aidl. The SHA-256 hash of this encoded structure is what's included with
- * the tag in attestations.
+ * the tag in attestations. To ensure the returned encoded structure is the one attested to,
+ * clients should verify its SHA-256 hash matches the one in the attestation. Note that the
+ * returned structure can vary between boots.
*/
- // TODO(b/369375199): Replace with Tag.MODULE_HASH when flagging is removed.
+ // TODO(b/380020528): Replace with Tag.MODULE_HASH when KeyMint V4 is frozen.
public static final int MODULE_HASH = TagType.BYTES | 724;
/**
diff --git a/libs/WindowManager/Shell/multivalentScreenshotTests/Android.bp b/libs/WindowManager/Shell/multivalentScreenshotTests/Android.bp
index b6db6d9..4043a1c 100644
--- a/libs/WindowManager/Shell/multivalentScreenshotTests/Android.bp
+++ b/libs/WindowManager/Shell/multivalentScreenshotTests/Android.bp
@@ -38,7 +38,6 @@
android_robolectric_test {
name: "WMShellRobolectricScreenshotTests",
instrumentation_for: "WMShellRobolectricScreenshotTestApp",
- upstream: true,
java_resource_dirs: [
"robolectric/config",
],
diff --git a/libs/hwui/renderthread/VulkanManager.cpp b/libs/hwui/renderthread/VulkanManager.cpp
index e302393..a0d1cbc 100644
--- a/libs/hwui/renderthread/VulkanManager.cpp
+++ b/libs/hwui/renderthread/VulkanManager.cpp
@@ -674,7 +674,7 @@
VkSemaphore semaphore;
VkResult err = mCreateSemaphore(mDevice, &semaphoreInfo, nullptr, &semaphore);
ALOGE_IF(VK_SUCCESS != err,
- "VulkanManager::makeSwapSemaphore(): Failed to create semaphore");
+ "VulkanManager::finishFrame(): Failed to create semaphore");
if (err == VK_SUCCESS) {
sharedSemaphore = sp<SharedSemaphoreInfo>::make(mDestroySemaphore, mDevice, semaphore);
@@ -722,7 +722,7 @@
int fenceFd = -1;
VkResult err = mGetSemaphoreFdKHR(mDevice, &getFdInfo, &fenceFd);
- ALOGE_IF(VK_SUCCESS != err, "VulkanManager::swapBuffers(): Failed to get semaphore Fd");
+ ALOGE_IF(VK_SUCCESS != err, "VulkanManager::finishFrame(): Failed to get semaphore Fd");
drawResult.presentFence.reset(fenceFd);
} else {
ALOGE("VulkanManager::finishFrame(): Semaphore submission failed");
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java
index 493afde..df3310f 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java
@@ -451,6 +451,9 @@
mTelephonyListenerManager.removeServiceStateListener(mPhoneStateListener);
mGlobalSettings.unregisterContentObserverSync(mAirplaneModeObserver);
mConfigurationController.removeCallback(this);
+ if (mShowSilentToggle) {
+ mRingerModeTracker.getRingerMode().removeObservers(this);
+ }
}
protected Context getContext() {
diff --git a/ravenwood/Android.bp b/ravenwood/Android.bp
index 59043a83..8e99842 100644
--- a/ravenwood/Android.bp
+++ b/ravenwood/Android.bp
@@ -345,14 +345,41 @@
],
}
+// We define our own version of platform_compat_config's here, because:
+// - The original version (e.g. "framework-platform-compat-config) is built from
+// the output file of the device side jar, rather than the host jar, meaning
+// they're slow to build because they depend on D8/R8 output.
+// - The original services one ("services-platform-compat-config") is built from services.jar,
+// which includes service.permission, which is very slow to rebuild because of kotlin.
+//
+// Because we're re-defining the same compat-IDs that are defined elsewhere,
+// they should all have `include_in_merged_xml: false`. Otherwise, generating
+// merged_compat_config.xml would fail due to duplicate IDs.
+//
+// These module names must end with "compat-config" because these will be used as the filename,
+// and at runtime, we only loads files that match `*compat-config.xml`.
+platform_compat_config {
+ name: "ravenwood-framework-platform-compat-config",
+ src: ":framework-minus-apex-for-host",
+ include_in_merged_xml: false,
+ visibility: ["//visibility:private"],
+}
+
+platform_compat_config {
+ name: "ravenwood-services.core-platform-compat-config",
+ src: ":services.core-for-host",
+ include_in_merged_xml: false,
+ visibility: ["//visibility:private"],
+}
+
filegroup {
name: "ravenwood-data",
device_common_srcs: [
":system-build.prop",
":framework-res",
":ravenwood-empty-res",
- ":framework-platform-compat-config",
- ":services-platform-compat-config",
+ ":ravenwood-framework-platform-compat-config",
+ ":ravenwood-services.core-platform-compat-config",
"texts/ravenwood-build.prop",
],
device_first_srcs: [
@@ -616,6 +643,10 @@
"android.test.mock.ravenwood",
"ravenwood-helper-runtime",
"hoststubgen-helper-runtime.ravenwood",
+
+ // Note, when we include other services.* jars, we'll need to add
+ // platform_compat_config for that module too.
+ // See ravenwood-services.core-platform-compat-config above.
"services.core.ravenwood-jarjar",
"services.fakes.ravenwood-jarjar",
diff --git a/ravenwood/CleanSpec.mk b/ravenwood/CleanSpec.mk
new file mode 100644
index 0000000..50d2fab
--- /dev/null
+++ b/ravenwood/CleanSpec.mk
@@ -0,0 +1,45 @@
+# Copyright (C) 2024 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# If you don't need to do a full clean build but would like to touch
+# a file or delete some intermediate files, add a clean step to the end
+# of the list. These steps will only be run once, if they haven't been
+# run before.
+#
+# E.g.:
+# $(call add-clean-step, touch -c external/sqlite/sqlite3.h)
+# $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/STATIC_LIBRARIES/libz_intermediates)
+#
+# Always use "touch -c" and "rm -f" or "rm -rf" to gracefully deal with
+# files that are missing or have been moved.
+#
+# Use $(PRODUCT_OUT) to get to the "out/target/product/blah/" directory.
+# Use $(OUT_DIR) to refer to the "out" directory.
+#
+# If you need to re-do something that's already mentioned, just copy
+# the command and add it to the bottom of the list. E.g., if a change
+# that you made last week required touching a file and a change you
+# made today requires touching the same file, just copy the old
+# touch step and add it to the end of the list.
+#
+# *****************************************************************
+# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST ABOVE THE BANNER
+# *****************************************************************
+
+$(call add-clean-step, rm -rf $(OUT_DIR)/host/linux-x86/testcases/ravenwood-runtime)
+
+# ******************************************************************
+# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST ABOVE THIS BANNER
+# ******************************************************************
diff --git a/ravenwood/tools/hoststubgen/scripts/dump-jar b/ravenwood/tools/hoststubgen/scripts/dump-jar
index 8765245..998357b 100755
--- a/ravenwood/tools/hoststubgen/scripts/dump-jar
+++ b/ravenwood/tools/hoststubgen/scripts/dump-jar
@@ -89,7 +89,7 @@
# - Some other transient lines
# - Sometimes the javap shows mysterious warnings, so remove them too.
#
- # `/PATTERN-1/,/PATTERN-1/{//!d}` is a trick to delete lines between two patterns, without
+ # `/PATTERN-1/,/PATTERN-2/{//!d}` is a trick to delete lines between two patterns, without
# the start and the end lines.
sed -e 's/#[0-9][0-9]*/#x/g' \
-e 's/^\( *\)[0-9][0-9]*:/\1x:/' \
diff --git a/ravenwood/tools/hoststubgen/src/com/android/hoststubgen/HostStubGen.kt b/ravenwood/tools/hoststubgen/src/com/android/hoststubgen/HostStubGen.kt
index 6d8d7b7..cc704b2 100644
--- a/ravenwood/tools/hoststubgen/src/com/android/hoststubgen/HostStubGen.kt
+++ b/ravenwood/tools/hoststubgen/src/com/android/hoststubgen/HostStubGen.kt
@@ -27,7 +27,7 @@
import com.android.hoststubgen.filters.KeepNativeFilter
import com.android.hoststubgen.filters.OutputFilter
import com.android.hoststubgen.filters.SanitizationFilter
-import com.android.hoststubgen.filters.TextFileFilterPolicyParser
+import com.android.hoststubgen.filters.TextFileFilterPolicyBuilder
import com.android.hoststubgen.filters.printAsTextPolicy
import com.android.hoststubgen.utils.ClassFilter
import com.android.hoststubgen.visitors.BaseAdapter
@@ -179,9 +179,9 @@
// Next, "text based" filter, which allows to override polices without touching
// the target code.
if (options.policyOverrideFiles.isNotEmpty()) {
- val parser = TextFileFilterPolicyParser(allClasses, filter)
- options.policyOverrideFiles.forEach(parser::parse)
- filter = parser.createOutputFilter()
+ val builder = TextFileFilterPolicyBuilder(allClasses, filter)
+ options.policyOverrideFiles.forEach(builder::parse)
+ filter = builder.createOutputFilter()
}
// Apply the implicit filter.
diff --git a/ravenwood/tools/hoststubgen/src/com/android/hoststubgen/filters/TextFileFilterPolicyParser.kt b/ravenwood/tools/hoststubgen/src/com/android/hoststubgen/filters/TextFileFilterPolicyParser.kt
index 7462a8c..be1b6ca 100644
--- a/ravenwood/tools/hoststubgen/src/com/android/hoststubgen/filters/TextFileFilterPolicyParser.kt
+++ b/ravenwood/tools/hoststubgen/src/com/android/hoststubgen/filters/TextFileFilterPolicyParser.kt
@@ -23,10 +23,12 @@
import com.android.hoststubgen.log
import com.android.hoststubgen.normalizeTextLine
import com.android.hoststubgen.whitespaceRegex
-import java.io.File
-import java.io.PrintWriter
-import java.util.regex.Pattern
import org.objectweb.asm.tree.ClassNode
+import java.io.BufferedReader
+import java.io.FileReader
+import java.io.PrintWriter
+import java.io.Reader
+import java.util.regex.Pattern
/**
* Print a class node as a "keep" policy.
@@ -48,7 +50,7 @@
private const val FILTER_REASON = "file-override"
-private enum class SpecialClass {
+enum class SpecialClass {
NotSpecial,
Aidl,
FeatureFlags,
@@ -56,10 +58,58 @@
RFile,
}
-class TextFileFilterPolicyParser(
+/**
+ * This receives [TextFileFilterPolicyBuilder] parsing result.
+ */
+interface PolicyFileProcessor {
+ /** "package" directive. */
+ fun onPackage(name: String, policy: FilterPolicyWithReason)
+
+ /** "rename" directive. */
+ fun onRename(pattern: Pattern, prefix: String)
+
+ /** "class" directive. */
+ fun onSimpleClassStart(className: String)
+ fun onSimpleClassPolicy(className: String, policy: FilterPolicyWithReason)
+ fun onSimpleClassEnd(className: String)
+
+ fun onSubClassPolicy(superClassName: String, policy: FilterPolicyWithReason)
+ fun onRedirectionClass(fromClassName: String, toClassName: String)
+ fun onClassLoadHook(className: String, callback: String)
+ fun onSpecialClassPolicy(type: SpecialClass, policy: FilterPolicyWithReason)
+
+ /** "field" directive. */
+ fun onField(className: String, fieldName: String, policy: FilterPolicyWithReason)
+
+ /** "method" directive. */
+ fun onSimpleMethodPolicy(
+ className: String,
+ methodName: String,
+ methodDesc: String,
+ policy: FilterPolicyWithReason,
+ )
+ fun onMethodInClassReplace(
+ className: String,
+ methodName: String,
+ methodDesc: String,
+ targetName: String,
+ policy: FilterPolicyWithReason,
+ )
+ fun onMethodOutClassReplace(
+ className: String,
+ methodName: String,
+ methodDesc: String,
+ replaceSpec: TextFilePolicyMethodReplaceFilter.MethodCallReplaceSpec,
+ policy: FilterPolicyWithReason,
+ )
+}
+
+class TextFileFilterPolicyBuilder(
private val classes: ClassNodes,
fallback: OutputFilter
) {
+ private val parser = TextFileFilterPolicyParser()
+
private val subclassFilter = SubclassFilter(classes, fallback)
private val packageFilter = PackageFilter(subclassFilter)
private val imf = InMemoryOutputFilter(classes, packageFilter)
@@ -71,30 +121,19 @@
private val methodReplaceSpec =
mutableListOf<TextFilePolicyMethodReplaceFilter.MethodCallReplaceSpec>()
- private lateinit var currentClassName: String
-
/**
- * Read a given "policy" file and return as an [OutputFilter]
+ * Parse a given policy file. This method can be called multiple times to read from
+ * multiple files. To get the resulting filter, use [createOutputFilter]
*/
fun parse(file: String) {
- log.i("Loading offloaded annotations from $file ...")
- log.withIndent {
- var lineNo = 0
- try {
- File(file).forEachLine {
- lineNo++
- val line = normalizeTextLine(it)
- if (line.isEmpty()) {
- return@forEachLine // skip empty lines.
- }
- parseLine(line)
- }
- } catch (e: ParseException) {
- throw e.withSourceInfo(file, lineNo)
- }
- }
+ // We may parse multiple files, but we reuse the same parser, because the parser
+ // will make sure there'll be no dupplicating "special class" policies.
+ parser.parse(FileReader(file), file, Processor())
}
+ /**
+ * Generate the resulting [OutputFilter].
+ */
fun createOutputFilter(): OutputFilter {
var ret: OutputFilter = imf
if (typeRenameSpec.isNotEmpty()) {
@@ -112,14 +151,200 @@
return ret
}
+ private inner class Processor : PolicyFileProcessor {
+ override fun onPackage(name: String, policy: FilterPolicyWithReason) {
+ packageFilter.addPolicy(name, policy)
+ }
+
+ override fun onRename(pattern: Pattern, prefix: String) {
+ typeRenameSpec += TextFilePolicyRemapperFilter.TypeRenameSpec(
+ pattern, prefix
+ )
+ }
+
+ override fun onSimpleClassStart(className: String) {
+ }
+
+ override fun onSimpleClassEnd(className: String) {
+ }
+
+ override fun onSimpleClassPolicy(className: String, policy: FilterPolicyWithReason) {
+ imf.setPolicyForClass(className, policy)
+ }
+
+ override fun onSubClassPolicy(
+ superClassName: String,
+ policy: FilterPolicyWithReason,
+ ) {
+ log.i("class extends $superClassName")
+ subclassFilter.addPolicy( superClassName, policy)
+ }
+
+ override fun onRedirectionClass(fromClassName: String, toClassName: String) {
+ imf.setRedirectionClass(fromClassName, toClassName)
+ }
+
+ override fun onClassLoadHook(className: String, callback: String) {
+ imf.setClassLoadHook(className, callback)
+ }
+
+ override fun onSpecialClassPolicy(
+ type: SpecialClass,
+ policy: FilterPolicyWithReason,
+ ) {
+ log.i("class special $type $policy")
+ when (type) {
+ SpecialClass.NotSpecial -> {} // Shouldn't happen
+
+ SpecialClass.Aidl -> {
+ aidlPolicy = policy
+ }
+
+ SpecialClass.FeatureFlags -> {
+ featureFlagsPolicy = policy
+ }
+
+ SpecialClass.Sysprops -> {
+ syspropsPolicy = policy
+ }
+
+ SpecialClass.RFile -> {
+ rFilePolicy = policy
+ }
+ }
+ }
+
+ override fun onField(className: String, fieldName: String, policy: FilterPolicyWithReason) {
+ imf.setPolicyForField(className, fieldName, policy)
+ }
+
+ override fun onSimpleMethodPolicy(
+ className: String,
+ methodName: String,
+ methodDesc: String,
+ policy: FilterPolicyWithReason,
+ ) {
+ imf.setPolicyForMethod(className, methodName, methodDesc, policy)
+ }
+
+ override fun onMethodInClassReplace(
+ className: String,
+ methodName: String,
+ methodDesc: String,
+ targetName: String,
+ policy: FilterPolicyWithReason,
+ ) {
+ imf.setPolicyForMethod(className, methodName, methodDesc, policy)
+
+ // Make sure to keep the target method.
+ imf.setPolicyForMethod(
+ className,
+ targetName,
+ methodDesc,
+ FilterPolicy.Keep.withReason(FILTER_REASON)
+ )
+ // Set up the rename.
+ imf.setRenameTo(className, targetName, methodDesc, methodName)
+ }
+
+ override fun onMethodOutClassReplace(
+ className: String,
+ methodName: String,
+ methodDesc: String,
+ replaceSpec: TextFilePolicyMethodReplaceFilter.MethodCallReplaceSpec,
+ policy: FilterPolicyWithReason,
+ ) {
+ imf.setPolicyForMethod(className, methodName, methodDesc, policy)
+ methodReplaceSpec.add(replaceSpec)
+ }
+ }
+}
+
+/**
+ * Parses a filer policy text file.
+ */
+class TextFileFilterPolicyParser {
+ private lateinit var processor: PolicyFileProcessor
+ private var currentClassName: String? = null
+
+ private var aidlPolicy: FilterPolicyWithReason? = null
+ private var featureFlagsPolicy: FilterPolicyWithReason? = null
+ private var syspropsPolicy: FilterPolicyWithReason? = null
+ private var rFilePolicy: FilterPolicyWithReason? = null
+
+ /** Name of the file that's currently being processed. */
+ var filename: String? = null
+ private set
+
+ /** 1-based line number in the current file */
+ var lineNumber = -1
+ private set
+
+ /**
+ * Parse a given "policy" file.
+ */
+ fun parse(reader: Reader, inputName: String, processor: PolicyFileProcessor) {
+ filename = inputName
+
+ log.i("Parsing text policy file $inputName ...")
+ this.processor = processor
+ BufferedReader(reader).use { rd ->
+ lineNumber = 0
+ try {
+ while (true) {
+ var line = rd.readLine()
+ if (line == null) {
+ break
+ }
+ lineNumber++
+ line = normalizeTextLine(line) // Remove comment and trim.
+ if (line.isEmpty()) {
+ continue
+ }
+ parseLine(line)
+ }
+ finishLastClass()
+ } catch (e: ParseException) {
+ throw e.withSourceInfo(inputName, lineNumber)
+ }
+ }
+ }
+
+ private fun finishLastClass() {
+ currentClassName?.let { className ->
+ processor.onSimpleClassEnd(className)
+ currentClassName = null
+ }
+ }
+
+ private fun ensureInClass(directive: String): String {
+ return currentClassName ?:
+ throw ParseException("Directive '$directive' must follow a 'class' directive")
+ }
+
private fun parseLine(line: String) {
val fields = line.split(whitespaceRegex).toTypedArray()
when (fields[0].lowercase()) {
- "p", "package" -> parsePackage(fields)
- "c", "class" -> parseClass(fields)
- "f", "field" -> parseField(fields)
- "m", "method" -> parseMethod(fields)
- "r", "rename" -> parseRename(fields)
+ "p", "package" -> {
+ finishLastClass()
+ parsePackage(fields)
+ }
+ "c", "class" -> {
+ finishLastClass()
+ parseClass(fields)
+ }
+ "f", "field" -> {
+ ensureInClass("field")
+ parseField(fields)
+ }
+ "m", "method" -> {
+ ensureInClass("method")
+ parseMethod(fields)
+ }
+ "r", "rename" -> {
+ finishLastClass()
+ parseRename(fields)
+ }
else -> throw ParseException("Unknown directive \"${fields[0]}\"")
}
}
@@ -184,20 +409,20 @@
if (!policy.isUsableWithClasses) {
throw ParseException("Package can't have policy '$policy'")
}
- packageFilter.addPolicy(name, policy.withReason(FILTER_REASON))
+ processor.onPackage(name, policy.withReason(FILTER_REASON))
}
private fun parseClass(fields: Array<String>) {
if (fields.size < 3) {
throw ParseException("Class ('c') expects 2 fields.")
}
- currentClassName = fields[1]
+ val className = fields[1]
// superClass is set when the class name starts with a "*".
- val superClass = resolveExtendingClass(currentClassName)
+ val superClass = resolveExtendingClass(className)
// :aidl, etc?
- val classType = resolveSpecialClass(currentClassName)
+ val classType = resolveSpecialClass(className)
if (fields[2].startsWith("!")) {
if (classType != SpecialClass.NotSpecial) {
@@ -208,7 +433,8 @@
}
// It's a redirection class.
val toClass = fields[2].substring(1)
- imf.setRedirectionClass(currentClassName, toClass)
+
+ processor.onRedirectionClass(className, toClass)
} else if (fields[2].startsWith("~")) {
if (classType != SpecialClass.NotSpecial) {
// We could support it, but not needed at least for now.
@@ -218,7 +444,8 @@
}
// It's a class-load hook
val callback = fields[2].substring(1)
- imf.setClassLoadHook(currentClassName, callback)
+
+ processor.onClassLoadHook(className, callback)
} else {
val policy = parsePolicy(fields[2])
if (!policy.isUsableWithClasses) {
@@ -229,26 +456,27 @@
SpecialClass.NotSpecial -> {
// TODO: Duplicate check, etc
if (superClass == null) {
- imf.setPolicyForClass(
- currentClassName, policy.withReason(FILTER_REASON)
- )
+ currentClassName = className
+ processor.onSimpleClassStart(className)
+ processor.onSimpleClassPolicy(className, policy.withReason(FILTER_REASON))
} else {
- subclassFilter.addPolicy(
+ processor.onSubClassPolicy(
superClass,
- policy.withReason("extends $superClass")
+ policy.withReason("extends $superClass"),
)
}
}
-
SpecialClass.Aidl -> {
if (aidlPolicy != null) {
throw ParseException(
"Policy for AIDL classes already defined"
)
}
- aidlPolicy = policy.withReason(
+ val p = policy.withReason(
"$FILTER_REASON (special-class AIDL)"
)
+ processor.onSpecialClassPolicy(classType, p)
+ aidlPolicy = p
}
SpecialClass.FeatureFlags -> {
@@ -257,9 +485,11 @@
"Policy for feature flags already defined"
)
}
- featureFlagsPolicy = policy.withReason(
+ val p = policy.withReason(
"$FILTER_REASON (special-class feature flags)"
)
+ processor.onSpecialClassPolicy(classType, p)
+ featureFlagsPolicy = p
}
SpecialClass.Sysprops -> {
@@ -268,9 +498,11 @@
"Policy for sysprops already defined"
)
}
- syspropsPolicy = policy.withReason(
+ val p = policy.withReason(
"$FILTER_REASON (special-class sysprops)"
)
+ processor.onSpecialClassPolicy(classType, p)
+ syspropsPolicy = p
}
SpecialClass.RFile -> {
@@ -279,9 +511,11 @@
"Policy for R file already defined"
)
}
- rFilePolicy = policy.withReason(
+ val p = policy.withReason(
"$FILTER_REASON (special-class R file)"
)
+ processor.onSpecialClassPolicy(classType, p)
+ rFilePolicy = p
}
}
}
@@ -296,17 +530,16 @@
if (!policy.isUsableWithFields) {
throw ParseException("Field can't have policy '$policy'")
}
- require(this::currentClassName.isInitialized)
// TODO: Duplicate check, etc
- imf.setPolicyForField(currentClassName, name, policy.withReason(FILTER_REASON))
+ processor.onField(currentClassName!!, name, policy.withReason(FILTER_REASON))
}
private fun parseMethod(fields: Array<String>) {
if (fields.size < 3 || fields.size > 4) {
throw ParseException("Method ('m') expects 3 or 4 fields.")
}
- val name = fields[1]
+ val methodName = fields[1]
val signature: String
val policyStr: String
if (fields.size <= 3) {
@@ -323,44 +556,48 @@
throw ParseException("Method can't have policy '$policy'")
}
- require(this::currentClassName.isInitialized)
+ val className = currentClassName!!
- imf.setPolicyForMethod(
- currentClassName, name, signature,
- policy.withReason(FILTER_REASON)
- )
- if (policy == FilterPolicy.Substitute) {
- val fromName = policyStr.substring(1)
+ val policyWithReason = policy.withReason(FILTER_REASON)
+ if (policy != FilterPolicy.Substitute) {
+ processor.onSimpleMethodPolicy(className, methodName, signature, policyWithReason)
+ } else {
+ val targetName = policyStr.substring(1)
- if (fromName == name) {
+ if (targetName == methodName) {
throw ParseException(
"Substitution must have a different name"
)
}
- // Set the policy for the "from" method.
- imf.setPolicyForMethod(
- currentClassName, fromName, signature,
- FilterPolicy.Keep.withReason(FILTER_REASON)
- )
-
- val classAndMethod = splitWithLastPeriod(fromName)
+ val classAndMethod = splitWithLastPeriod(targetName)
if (classAndMethod != null) {
// If the substitution target contains a ".", then
// it's a method call redirect.
- methodReplaceSpec.add(
- TextFilePolicyMethodReplaceFilter.MethodCallReplaceSpec(
- currentClassName.toJvmClassName(),
- name,
+ val spec = TextFilePolicyMethodReplaceFilter.MethodCallReplaceSpec(
+ currentClassName!!.toJvmClassName(),
+ methodName,
signature,
classAndMethod.first.toJvmClassName(),
classAndMethod.second,
)
+ processor.onMethodOutClassReplace(
+ className,
+ methodName,
+ signature,
+ spec,
+ policyWithReason,
)
} else {
// It's an in-class replace.
// ("@RavenwoodReplace" equivalent)
- imf.setRenameTo(currentClassName, fromName, signature, name)
+ processor.onMethodInClassReplace(
+ className,
+ methodName,
+ signature,
+ targetName,
+ policyWithReason,
+ )
}
}
}
@@ -378,7 +615,7 @@
// applied. (Which is needed for services.jar)
val prefix = fields[2].trimStart('/')
- typeRenameSpec += TextFilePolicyRemapperFilter.TypeRenameSpec(
+ processor.onRename(
pattern, prefix
)
}
diff --git a/ravenwood/tools/hoststubgen/test-tiny-framework/diff-and-update-golden.sh b/ravenwood/tools/hoststubgen/test-tiny-framework/diff-and-update-golden.sh
index b389a67..8408a18 100755
--- a/ravenwood/tools/hoststubgen/test-tiny-framework/diff-and-update-golden.sh
+++ b/ravenwood/tools/hoststubgen/test-tiny-framework/diff-and-update-golden.sh
@@ -34,10 +34,11 @@
SCRIPT_NAME="${0##*/}"
-GOLDEN_DIR=golden-output
+GOLDEN_DIR=${GOLDEN_DIR:-golden-output}
mkdir -p $GOLDEN_DIR
-DIFF_CMD=${DIFF:-diff -u --ignore-blank-lines --ignore-space-change}
+# TODO(b/388562869) We shouldn't need `--ignore-matching-lines`, but the golden files may not have the "Constant pool:" lines.
+DIFF_CMD=${DIFF_CMD:-diff -u --ignore-blank-lines --ignore-space-change --ignore-matching-lines='^\(Constant.pool:\|{\)$'}
update=0
three_way=0
@@ -62,7 +63,7 @@
shift $(($OPTIND - 1))
# Build the dump files, which are the input of this test.
-run m dump-jar tiny-framework-dump-test
+run ${BUILD_CMD:=m} dump-jar tiny-framework-dump-test
# Get the path to the generate text files. (not the golden files.)
diff --git a/ravenwood/tools/hoststubgen/test-tiny-framework/tiny-framework-dump-test.py b/ravenwood/tools/hoststubgen/test-tiny-framework/tiny-framework-dump-test.py
index 88fa492..c35d6d1 100755
--- a/ravenwood/tools/hoststubgen/test-tiny-framework/tiny-framework-dump-test.py
+++ b/ravenwood/tools/hoststubgen/test-tiny-framework/tiny-framework-dump-test.py
@@ -28,8 +28,11 @@
# Run diff.
def run_diff(file1, file2):
+ # TODO(b/388562869) We shouldn't need `--ignore-matching-lines`, but the golden files may not have the "Constant pool:" lines.
command = ['diff', '-u', '--ignore-blank-lines',
- '--ignore-space-change', file1, file2]
+ '--ignore-space-change',
+ '--ignore-matching-lines=^\(Constant.pool:\|{\)$',
+ file1, file2]
print(' '.join(command))
result = subprocess.run(command, stderr=sys.stdout)
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index f5e1545..8de1295 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -12796,6 +12796,28 @@
}
}
+ final long kernelCmaUsage = Debug.getKernelCmaUsageKb();
+ if (kernelCmaUsage >= 0) {
+ pw.print(" Kernel CMA: ");
+ pw.println(stringifyKBSize(kernelCmaUsage));
+ // CMA memory can be in one of the following four states:
+ //
+ // 1. Free, in which case it is accounted for as part of MemFree, which
+ // is already considered in the lostRAM calculation below.
+ //
+ // 2. Allocated as part of a userspace allocated, in which case it is
+ // already accounted for in the total PSS value that was computed.
+ //
+ // 3. Allocated for storing compressed memory (ZRAM) on Android kernels.
+ // This is accounted for by calculating the amount of memory ZRAM
+ // consumes and including it in the lostRAM calculuation.
+ //
+ // 4. Allocated by a kernel driver, in which case, it is currently not
+ // attributed to any term that has been derived thus far. Since the
+ // allocations come from a kernel driver, add it to kernelUsed.
+ kernelUsed += kernelCmaUsage;
+ }
+
// Note: ION/DMA-BUF heap pools are reclaimable and hence, they are included as part of
// memInfo.getCachedSizeKb().
final long lostRAM = memInfo.getTotalSizeKb()
@@ -13313,12 +13335,32 @@
proto.write(MemInfoDumpProto.CACHED_KERNEL_KB, memInfo.getCachedSizeKb());
proto.write(MemInfoDumpProto.FREE_KB, memInfo.getFreeSizeKb());
}
+ // CMA memory can be in one of the following four states:
+ //
+ // 1. Free, in which case it is accounted for as part of MemFree, which
+ // is already considered in the lostRAM calculation below.
+ //
+ // 2. Allocated as part of a userspace allocated, in which case it is
+ // already accounted for in the total PSS value that was computed.
+ //
+ // 3. Allocated for storing compressed memory (ZRAM) on Android Kernels.
+ // This is accounted for by calculating hte amount of memory ZRAM
+ // consumes and including it in the lostRAM calculation.
+ //
+ // 4. Allocated by a kernel driver, in which case, it is currently not
+ // attributed to any term that has been derived thus far, so subtract
+ // it from lostRAM.
+ long kernelCmaUsage = Debug.getKernelCmaUsageKb();
+ if (kernelCmaUsage < 0) {
+ kernelCmaUsage = 0;
+ }
long lostRAM = memInfo.getTotalSizeKb()
- (ss[INDEX_TOTAL_PSS] - ss[INDEX_TOTAL_SWAP_PSS])
- memInfo.getFreeSizeKb() - memInfo.getCachedSizeKb()
// NR_SHMEM is subtracted twice (getCachedSizeKb() and getKernelUsedSizeKb())
+ memInfo.getShmemSizeKb()
- - memInfo.getKernelUsedSizeKb() - memInfo.getZramTotalSizeKb();
+ - memInfo.getKernelUsedSizeKb() - memInfo.getZramTotalSizeKb()
+ - kernelCmaUsage;
proto.write(MemInfoDumpProto.USED_PSS_KB, ss[INDEX_TOTAL_PSS] - cachedPss);
proto.write(MemInfoDumpProto.USED_KERNEL_KB, memInfo.getKernelUsedSizeKb());
proto.write(MemInfoDumpProto.LOST_RAM_KB, lostRAM);
diff --git a/services/core/java/com/android/server/location/fudger/LocationFudger.java b/services/core/java/com/android/server/location/fudger/LocationFudger.java
index 88a2697..27ad555 100644
--- a/services/core/java/com/android/server/location/fudger/LocationFudger.java
+++ b/services/core/java/com/android/server/location/fudger/LocationFudger.java
@@ -239,6 +239,15 @@
// requires latitude since longitudinal distances change with distance from equator.
private static double metersToDegreesLongitude(double distance, double lat) {
- return distance / APPROXIMATE_METERS_PER_DEGREE_AT_EQUATOR / Math.cos(Math.toRadians(lat));
+ // Needed to convert from longitude distance to longitude degree.
+ // X meters near the poles is more degrees than at the equator.
+ double cosLat = Math.cos(Math.toRadians(lat));
+ // If we are right on top of the pole, the degree is always 0.
+ // We return a very small value instead to avoid divide by zero errors
+ // later on.
+ if (cosLat == 0.0) {
+ return 0.0001;
+ }
+ return distance / APPROXIMATE_METERS_PER_DEGREE_AT_EQUATOR / cosLat;
}
}
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java
index 0d0cdd8..a0e5433 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsService.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java
@@ -137,6 +137,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
import com.android.internal.notification.SystemNotificationChannels;
+import com.android.internal.pm.RoSystemFeatures;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.DumpUtils;
import com.android.internal.util.IndentingPrintWriter;
@@ -1325,7 +1326,7 @@
mContext.enforceCallingOrSelfPermission(
Manifest.permission.MANAGE_WEAK_ESCROW_TOKEN,
"Requires MANAGE_WEAK_ESCROW_TOKEN permission.");
- if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) {
+ if (!RoSystemFeatures.hasFeatureAutomotive(mContext)) {
throw new IllegalArgumentException(
"Weak escrow token are only for automotive devices.");
}
@@ -3613,7 +3614,7 @@
}
// Escrow tokens are enabled on automotive builds.
- if (mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) {
+ if (RoSystemFeatures.hasFeatureAutomotive(mContext)) {
return;
}
diff --git a/services/incremental/IncrementalService.cpp b/services/incremental/IncrementalService.cpp
index a8e6f68..dae481a 100644
--- a/services/incremental/IncrementalService.cpp
+++ b/services/incremental/IncrementalService.cpp
@@ -1999,9 +1999,9 @@
// Create new lib file without signature info
incfs::NewFileParams libFileParams = {
.size = entry.uncompressed_length,
- .signature = {},
// Metadata of the new lib file is its relative path
.metadata = {targetLibPath.c_str(), (IncFsSize)targetLibPath.size()},
+ .signature = {},
};
incfs::FileId libFileId = idFromMetadata(targetLibPath);
if (auto res = mIncFs->makeFile(ifs->control, targetLibPathAbsolute, 0755, libFileId,
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index c80d6db..7972d9c 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -428,7 +428,7 @@
"/apex/com.android.uwb/javalib/service-uwb.jar";
private static final String UWB_SERVICE_CLASS = "com.android.server.uwb.UwbService";
private static final String BLUETOOTH_APEX_SERVICE_JAR_PATH =
- "/apex/com.android.btservices/javalib/service-bluetooth.jar";
+ "/apex/com.android.bt/javalib/service-bluetooth.jar";
private static final String BLUETOOTH_SERVICE_CLASS =
"com.android.server.bluetooth.BluetoothService";
private static final String DEVICE_LOCK_SERVICE_CLASS =
@@ -3038,13 +3038,8 @@
&& context.getPackageManager().hasSystemFeature(
PackageManager.FEATURE_BLUETOOTH_LE))) {
t.traceBegin("RangingService");
- // TODO: b/375264320 - Remove after RELEASE_RANGING_STACK is ramped to next.
- try {
- mSystemServiceManager.startServiceFromJar(RANGING_SERVICE_CLASS,
- RANGING_APEX_SERVICE_JAR_PATH);
- } catch (Throwable e) {
- Slog.d(TAG, "service-ranging.jar not found, not starting RangingService");
- }
+ mSystemServiceManager.startServiceFromJar(RANGING_SERVICE_CLASS,
+ RANGING_APEX_SERVICE_JAR_PATH);
t.traceEnd();
}
}
diff --git a/tools/systemfeatures/src/com/android/systemfeatures/SystemFeaturesGenerator.kt b/tools/systemfeatures/src/com/android/systemfeatures/SystemFeaturesGenerator.kt
index ea660b0..22d364e 100644
--- a/tools/systemfeatures/src/com/android/systemfeatures/SystemFeaturesGenerator.kt
+++ b/tools/systemfeatures/src/com/android/systemfeatures/SystemFeaturesGenerator.kt
@@ -263,7 +263,7 @@
.returns(Boolean::class.java)
.addParameter(CONTEXT_CLASS, "context")
.addParameter(String::class.java, "featureName")
- .addStatement("return context.getPackageManager().hasSystemFeature(featureName, 0)")
+ .addStatement("return context.getPackageManager().hasSystemFeature(featureName)")
.build()
)
}
diff --git a/tools/systemfeatures/tests/golden/RoFeatures.java.gen b/tools/systemfeatures/tests/golden/RoFeatures.java.gen
index ee97b26..730dacb 100644
--- a/tools/systemfeatures/tests/golden/RoFeatures.java.gen
+++ b/tools/systemfeatures/tests/golden/RoFeatures.java.gen
@@ -70,7 +70,7 @@
}
private static boolean hasFeatureFallback(Context context, String featureName) {
- return context.getPackageManager().hasSystemFeature(featureName, 0);
+ return context.getPackageManager().hasSystemFeature(featureName);
}
/**
diff --git a/tools/systemfeatures/tests/golden/RoNoFeatures.java.gen b/tools/systemfeatures/tests/golden/RoNoFeatures.java.gen
index 40c7db7..fe268c7 100644
--- a/tools/systemfeatures/tests/golden/RoNoFeatures.java.gen
+++ b/tools/systemfeatures/tests/golden/RoNoFeatures.java.gen
@@ -25,7 +25,7 @@
}
private static boolean hasFeatureFallback(Context context, String featureName) {
- return context.getPackageManager().hasSystemFeature(featureName, 0);
+ return context.getPackageManager().hasSystemFeature(featureName);
}
/**
diff --git a/tools/systemfeatures/tests/golden/RwFeatures.java.gen b/tools/systemfeatures/tests/golden/RwFeatures.java.gen
index 7bf8961..bcf978d 100644
--- a/tools/systemfeatures/tests/golden/RwFeatures.java.gen
+++ b/tools/systemfeatures/tests/golden/RwFeatures.java.gen
@@ -55,7 +55,7 @@
}
private static boolean hasFeatureFallback(Context context, String featureName) {
- return context.getPackageManager().hasSystemFeature(featureName, 0);
+ return context.getPackageManager().hasSystemFeature(featureName);
}
/**
diff --git a/tools/systemfeatures/tests/golden/RwNoFeatures.java.gen b/tools/systemfeatures/tests/golden/RwNoFeatures.java.gen
index eb7ec63..7bad5a2 100644
--- a/tools/systemfeatures/tests/golden/RwNoFeatures.java.gen
+++ b/tools/systemfeatures/tests/golden/RwNoFeatures.java.gen
@@ -14,7 +14,7 @@
*/
public final class RwNoFeatures {
private static boolean hasFeatureFallback(Context context, String featureName) {
- return context.getPackageManager().hasSystemFeature(featureName, 0);
+ return context.getPackageManager().hasSystemFeature(featureName);
}
/**
diff --git a/tools/systemfeatures/tests/src/SystemFeaturesGeneratorTest.java b/tools/systemfeatures/tests/src/SystemFeaturesGeneratorTest.java
index ed3f5c9..491b55e 100644
--- a/tools/systemfeatures/tests/src/SystemFeaturesGeneratorTest.java
+++ b/tools/systemfeatures/tests/src/SystemFeaturesGeneratorTest.java
@@ -76,28 +76,28 @@
// Also ensure we fall back to the PackageManager for feature APIs without an accompanying
// versioned feature definition.
- when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_WATCH, 0)).thenReturn(true);
+ when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_WATCH)).thenReturn(true);
assertThat(RwFeatures.hasFeatureWatch(mContext)).isTrue();
- when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_WATCH, 0)).thenReturn(false);
+ when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_WATCH)).thenReturn(false);
assertThat(RwFeatures.hasFeatureWatch(mContext)).isFalse();
}
@Test
public void testReadonlyDisabledWithDefinedFeatures() {
// Always fall back to the PackageManager for defined, explicit features queries.
- when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_WATCH, 0)).thenReturn(true);
+ when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_WATCH)).thenReturn(true);
assertThat(RwFeatures.hasFeatureWatch(mContext)).isTrue();
- when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_WATCH, 0)).thenReturn(false);
+ when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_WATCH)).thenReturn(false);
assertThat(RwFeatures.hasFeatureWatch(mContext)).isFalse();
- when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_WIFI, 0)).thenReturn(true);
+ when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_WIFI)).thenReturn(true);
assertThat(RwFeatures.hasFeatureWifi(mContext)).isTrue();
- when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_VULKAN, 0)).thenReturn(false);
+ when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_VULKAN)).thenReturn(false);
assertThat(RwFeatures.hasFeatureVulkan(mContext)).isFalse();
- when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTO, 0)).thenReturn(false);
+ when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTO)).thenReturn(false);
assertThat(RwFeatures.hasFeatureAuto(mContext)).isFalse();
// For defined and undefined features, conditional queries should report null (unknown).
@@ -139,9 +139,9 @@
assertThat(RoFeatures.maybeHasFeature(PackageManager.FEATURE_VULKAN, 100)).isFalse();
// VERSION=
- when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTO, 0)).thenReturn(false);
+ when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTO)).thenReturn(false);
assertThat(RoFeatures.hasFeatureAuto(mContext)).isFalse();
- when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTO, 0)).thenReturn(true);
+ when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTO)).thenReturn(true);
assertThat(RoFeatures.hasFeatureAuto(mContext)).isTrue();
assertThat(RoFeatures.maybeHasFeature(PackageManager.FEATURE_AUTO, -1)).isNull();
assertThat(RoFeatures.maybeHasFeature(PackageManager.FEATURE_AUTO, 0)).isNull();
@@ -149,9 +149,9 @@
// For feature APIs without an associated feature definition, conditional queries should
// report null, and explicit queries should report runtime-defined versions.
- when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_PC, 0)).thenReturn(true);
+ when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_PC)).thenReturn(true);
assertThat(RoFeatures.hasFeaturePc(mContext)).isTrue();
- when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_PC, 0)).thenReturn(false);
+ when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_PC)).thenReturn(false);
assertThat(RoFeatures.hasFeaturePc(mContext)).isFalse();
assertThat(RoFeatures.maybeHasFeature(PackageManager.FEATURE_PC, -1)).isNull();
assertThat(RoFeatures.maybeHasFeature(PackageManager.FEATURE_PC, 0)).isNull();