diff options
57 files changed, 2507 insertions, 195 deletions
diff --git a/api/StubLibraries.bp b/api/StubLibraries.bp index a949ff5a331b..787fdee6ee16 100644 --- a/api/StubLibraries.bp +++ b/api/StubLibraries.bp @@ -1023,7 +1023,6 @@ stubs_defaults { api_levels_annotations_enabled: true, api_levels_annotations_dirs: [ "sdk-dir", - "api-versions-jars-dir", ], } diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index 8a8540602697..a624994d3571 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -6950,7 +6950,7 @@ public final class ActivityThread extends ClientTransactionHandler Slog.w(TAG, "Low overhead tracing feature is not enabled"); break; } - VMDebug.startLowOverheadTrace(); + VMDebug.startLowOverheadTraceForAllMethods(); break; default: try { diff --git a/core/java/android/security/flags.aconfig b/core/java/android/security/flags.aconfig index ceee898b0a9f..4249372268bc 100644 --- a/core/java/android/security/flags.aconfig +++ b/core/java/android/security/flags.aconfig @@ -43,7 +43,7 @@ flag { flag { name: "secure_array_zeroization" - namespace: "platform_security" + namespace: "security" description: "Enable secure array zeroization" bug: "320392352" metadata { diff --git a/core/java/com/android/internal/app/IntentForwarderActivity.java b/core/java/com/android/internal/app/IntentForwarderActivity.java index ee5bd65e76de..32eb08057363 100644 --- a/core/java/com/android/internal/app/IntentForwarderActivity.java +++ b/core/java/com/android/internal/app/IntentForwarderActivity.java @@ -684,14 +684,15 @@ public class IntentForwarderActivity extends Activity { } private void setMiniresolverPadding() { - Insets systemWindowInsets = - getWindowManager().getCurrentWindowMetrics().getWindowInsets().getInsets( - WindowInsets.Type.systemBars()); - View buttonContainer = findViewById(R.id.button_bar_container); - buttonContainer.setPadding(0, 0, 0, - systemWindowInsets.bottom + getResources().getDimensionPixelOffset( - R.dimen.resolver_button_bar_spacing)); + if (buttonContainer != null) { + Insets systemWindowInsets = + getWindowManager().getCurrentWindowMetrics().getWindowInsets().getInsets( + WindowInsets.Type.systemBars()); + buttonContainer.setPadding(0, 0, 0, + systemWindowInsets.bottom + getResources().getDimensionPixelOffset( + R.dimen.resolver_button_bar_spacing)); + } } @VisibleForTesting diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java index a1945352ae09..db65d31f59da 100644 --- a/core/java/com/android/internal/app/ResolverActivity.java +++ b/core/java/com/android/internal/app/ResolverActivity.java @@ -929,8 +929,11 @@ public class ResolverActivity extends Activity implements if (shouldUseMiniResolver()) { View buttonContainer = findViewById(R.id.button_bar_container); - buttonContainer.setPadding(0, 0, 0, mSystemWindowInsets.bottom - + getResources().getDimensionPixelOffset(R.dimen.resolver_button_bar_spacing)); + if (buttonContainer != null) { + buttonContainer.setPadding(0, 0, 0, mSystemWindowInsets.bottom + + getResources().getDimensionPixelOffset( + R.dimen.resolver_button_bar_spacing)); + } } // Need extra padding so the list can fully scroll up diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 201e0c8f364e..45c4ea08c09b 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -180,6 +180,7 @@ <protected-broadcast android:name="android.bluetooth.device.action.CONNECTION_ACCESS_CANCEL" /> <protected-broadcast android:name="android.bluetooth.device.action.CONNECTION_ACCESS_REQUEST" /> <protected-broadcast android:name="android.bluetooth.device.action.KEY_MISSING" /> + <protected-broadcast android:name="android.bluetooth.device.action.ENCRYPTION_CHANGE" /> <protected-broadcast android:name="android.bluetooth.device.action.SDP_RECORD" /> <protected-broadcast android:name="android.bluetooth.device.action.BATTERY_LEVEL_CHANGED" /> <protected-broadcast android:name="android.bluetooth.device.action.REMOTE_ISSUE_OCCURRED" /> @@ -8909,6 +8910,11 @@ android:permission="android.permission.BIND_JOB_SERVICE" > </service> + <service android:name="com.android.server.ZramMaintenance" + android:exported="false" + android:permission="android.permission.BIND_JOB_SERVICE" > + </service> + <service android:name="com.android.server.ZramWriteback" android:exported="false" android:permission="android.permission.BIND_JOB_SERVICE" > diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index cccd6ba36aaf..c01a8a95e021 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -5126,10 +5126,6 @@ <!-- Whether or not swipe up gesture's opt-in setting is available on this device --> <bool name="config_swipe_up_gesture_setting_available">true</bool> - <!-- Applications which are disabled unless matching a particular sku --> - <string-array name="config_disableApksUnlessMatchedSku_apk_list" translatable="false" /> - <string-array name="config_disableApkUnlessMatchedSku_skus_list" translatable="false" /> - <!-- Whether or not we should show the option to show battery percentage --> <bool name="config_battery_percentage_setting_available">true</bool> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index e8271029484c..a3d5be79cad2 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -4259,10 +4259,6 @@ <java-symbol type="integer" name="config_unfoldTransitionHalfFoldedTimeout" /> <java-symbol type="array" name="config_perDeviceStateRotationLockDefaults" /> - - <java-symbol type="array" name="config_disableApksUnlessMatchedSku_apk_list" /> - <java-symbol type="array" name="config_disableApkUnlessMatchedSku_skus_list" /> - <java-symbol type="string" name="config_misprovisionedDeviceModel" /> <java-symbol type="string" name="config_misprovisionedBrandValue" /> diff --git a/graphics/java/android/graphics/OWNERS b/graphics/java/android/graphics/OWNERS index ef8d26cc65b9..1ea197658f93 100644 --- a/graphics/java/android/graphics/OWNERS +++ b/graphics/java/android/graphics/OWNERS @@ -2,10 +2,10 @@ romainguy@google.com jreck@google.com -njawad@google.com sumir@google.com djsollen@google.com -scroggo@google.com +alecmouri@google.com +sallyqi@google.com per-file BLASTBufferQueue.java = file:/services/core/java/com/android/server/wm/OWNERS per-file FontFamily.java = file:fonts/OWNERS diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/SyncTransactionQueue.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/SyncTransactionQueue.java index bcd40a9a9765..c4696d5f44f4 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/SyncTransactionQueue.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/SyncTransactionQueue.java @@ -192,15 +192,22 @@ public final class SyncTransactionQueue { throw new IllegalStateException("Sync Transactions must be serialized. In Flight: " + mInFlight.mId + " - " + mInFlight.mWCT); } - mInFlight = this; if (DEBUG) Slog.d(TAG, "Sending sync transaction: " + mWCT); - if (mLegacyTransition != null) { - mId = new WindowOrganizer().startLegacyTransition(mLegacyTransition.getType(), - mLegacyTransition.getAdapter(), this, mWCT); - } else { - mId = new WindowOrganizer().applySyncTransaction(mWCT, this); + try { + if (mLegacyTransition != null) { + mId = new WindowOrganizer().startLegacyTransition(mLegacyTransition.getType(), + mLegacyTransition.getAdapter(), this, mWCT); + } else { + mId = new WindowOrganizer().applySyncTransaction(mWCT, this); + } + } catch (RuntimeException e) { + Slog.e(TAG, "Send failed", e); + // Finish current sync callback immediately. + onTransactionReady(mId, new SurfaceControl.Transaction()); + return; } if (DEBUG) Slog.d(TAG, " Sent sync transaction. Got id=" + mId); + mInFlight = this; mMainExecutor.executeDelayed(mOnReplyTimeout, REPLY_TIMEOUT); } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java index 8077aeebf27f..8cec017e9ec9 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java @@ -1080,9 +1080,12 @@ public class RecentsTransitionHandler implements Transitions.TransitionHandler, change, layer, info, t, mLeashMap); appearedTargets[nextTargetIdx++] = target; // reparent into the original `mInfo` since that's where we are animating. - final int rootIdx = TransitionUtil.rootIndexFor(change, mInfo); + final TransitionInfo.Root root = TransitionUtil.getRootFor(change, mInfo); final boolean wasClosing = closingIdx >= 0; - t.reparent(target.leash, mInfo.getRoot(rootIdx).getLeash()); + t.reparent(target.leash, root.getLeash()); + t.setPosition(target.leash, + change.getStartAbsBounds().left - root.getOffset().x, + change.getStartAbsBounds().top - root.getOffset().y); t.setLayer(target.leash, layer); if (wasClosing) { // App was previously visible and is closing diff --git a/media/java/android/media/MediaCodecInfo.java b/media/java/android/media/MediaCodecInfo.java index 782db358bf9f..cf54f6c77506 100644 --- a/media/java/android/media/MediaCodecInfo.java +++ b/media/java/android/media/MediaCodecInfo.java @@ -907,13 +907,13 @@ public final class MediaCodecInfo { /** @hide */ public String[] validFeatures() { Feature[] features = getValidFeatures(); - String[] res = new String[features.length]; - for (int i = 0; i < res.length; i++) { + ArrayList<String> res = new ArrayList(); + for (int i = 0; i < features.length; i++) { if (!features[i].mInternal) { - res[i] = features[i].mName; + res.add(features[i].mName); } } - return res; + return res.toArray(new String[0]); } private Feature[] getValidFeatures() { diff --git a/media/jni/OWNERS b/media/jni/OWNERS index e12d828733fa..fdddf13a0a23 100644 --- a/media/jni/OWNERS +++ b/media/jni/OWNERS @@ -4,5 +4,5 @@ per-file android_mtp_*.cpp=aprasath@google.com,anothermark@google.com,kumarashis # extra for TV related files per-file android_media_tv_*=hgchen@google.com,quxiangfang@google.com -per-file android_media_JetPlayer.cpp,android_media_MediaDataSource.cpp,android_media_MediaDataSource.h,android_media_MediaPlayer.java=set noparent -per-file android_media_JetPlayer.cpp,android_media_MediaDataSource.cpp,android_media_MediaDataSource.h,android_media_MediaPlayer.java=file:platform/frameworks/av:/media/janitors/media_solutions_OWNERS +per-file android_media_JetPlayer.cpp,android_media_MediaDataSource.cpp,android_media_MediaDataSource.h,android_media_MediaPlayer.cpp=set noparent +per-file android_media_JetPlayer.cpp,android_media_MediaDataSource.cpp,android_media_MediaDataSource.h,android_media_MediaPlayer.cpp=file:platform/frameworks/av:/media/janitors/media_solutions_OWNERS diff --git a/packages/SettingsLib/OWNERS b/packages/SettingsLib/OWNERS index e4bc7b4660e1..04df308e72a0 100644 --- a/packages/SettingsLib/OWNERS +++ b/packages/SettingsLib/OWNERS @@ -3,6 +3,7 @@ cantol@google.com chiujason@google.com cipson@google.com dsandler@android.com +dswliu@google.com edgarwang@google.com evanlaird@google.com jiannan@google.com diff --git a/packages/SystemUI/Android.bp b/packages/SystemUI/Android.bp index c3c23e305822..38bd29a8a503 100644 --- a/packages/SystemUI/Android.bp +++ b/packages/SystemUI/Android.bp @@ -596,6 +596,7 @@ android_library { "-Adagger.fastInit=enabled", "-Adagger.explicitBindingConflictsWithInject=ERROR", "-Adagger.strictMultibindingValidation=enabled", + "-Adagger.useBindingGraphFix=ENABLED", "-Aroom.schemaLocation=frameworks/base/packages/SystemUI/schemas", ], kotlincflags: ["-Xjvm-default=all"], @@ -773,6 +774,9 @@ android_library { use_resource_processor: true, manifest: "tests/AndroidManifest-base.xml", resource_dirs: [], + + kotlin_lang_version: "1.9", + additional_manifests: ["tests/AndroidManifest.xml"], srcs: [ "tests/src/**/*.kt", @@ -815,6 +819,10 @@ android_library { // TODO(b/352363800): Why do we need this? "-J-Xmx8192M", ], + javacflags: [ + "-Adagger.useBindingGraphFix=ENABLED", + ], + aaptflags: [ "--extra-packages", "com.android.systemui", @@ -904,7 +912,6 @@ android_robolectric_test { "truth", ], - instrumentation_for: "SystemUIRobo-stub", java_resource_dirs: ["tests/robolectric/config"], plugins: [ @@ -940,7 +947,6 @@ android_robolectric_test { "truth", ], - instrumentation_for: "SystemUIRobo-stub", java_resource_dirs: ["tests/robolectric/config"], plugins: [ diff --git a/packages/SystemUI/OWNERS b/packages/SystemUI/OWNERS index 795b39576391..7fadcc4e6065 100644 --- a/packages/SystemUI/OWNERS +++ b/packages/SystemUI/OWNERS @@ -39,6 +39,7 @@ florenceyang@google.com gallmann@google.com graciecheng@google.com gwasserman@google.com +helencheuk@google.com hwwang@google.com hyunyoungs@google.com ikateryna@google.com diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/OWNERS b/packages/SystemUI/src/com/android/systemui/keyguard/OWNERS index 208a17c0a220..ebe603b7428c 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/OWNERS +++ b/packages/SystemUI/src/com/android/systemui/keyguard/OWNERS @@ -2,6 +2,8 @@ set noparent # Bug component: 78010 +include /services/core/java/com/android/server/biometrics/OWNERS + amiko@google.com beverlyt@google.com bhinegardner@google.com diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/footer/ui/view/FooterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/footer/ui/view/FooterView.java index 5a616dfd1f63..2d36f1672666 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/footer/ui/view/FooterView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/footer/ui/view/FooterView.java @@ -138,10 +138,12 @@ public class FooterView extends StackScrollerDecorView { DumpUtilsKt.withIncreasedIndent(pw, () -> { pw.println("visibility: " + DumpUtilsKt.visibilityString(getVisibility())); pw.println("manageButton showHistory: " + mShowHistory); - pw.println("manageButton visibility: " - + DumpUtilsKt.visibilityString(mClearAllButton.getVisibility())); - pw.println("dismissButton visibility: " - + DumpUtilsKt.visibilityString(mClearAllButton.getVisibility())); + if (mManageOrHistoryButton != null) + pw.println("mManageOrHistoryButton visibility: " + + DumpUtilsKt.visibilityString(mManageOrHistoryButton.getVisibility())); + if (mClearAllButton != null) + pw.println("mClearAllButton visibility: " + + DumpUtilsKt.visibilityString(mClearAllButton.getVisibility())); }); } diff --git a/ravenwood/scripts/pta-framework.sh b/ravenwood/scripts/pta-framework.sh new file mode 100755 index 000000000000..224ab59e2e09 --- /dev/null +++ b/ravenwood/scripts/pta-framework.sh @@ -0,0 +1,91 @@ +#!/bin/bash +# 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. + +# +# Use "ravehleper pta" to create a shell script which: +# - Reads the text "policy" files +# - Convert to java annotations (using sed) +# + +set -e + + +# Uncomment it to always build ravenhelper (slow) +# ${BUILD_CMD:-m} ravenhelper + +# Get the target directory. Default to $ANDROID_BUILD_TOP. +TARGET_DIR="${TARGET_DIR:-${ANDROID_BUILD_TOP?\$ANDROID_BUILD_TOP must be set}}" + +echo "Target dir=$TARGET_DIR" + +cd "$TARGET_DIR" + +# Add -v or -d as needed. +extra_args="$@" + +OUT_SCRIPT="${OUT_SCRIPT:-/tmp/pta.sh}" + +rm -f "$OUT_SCRIPT" + +# If you want to run on other files, run this script with the following +# env vars predefined. + +POLICIES="${POLICIES:- +frameworks/base/ravenwood/texts/ravenwood-common-policies.txt +frameworks/base/ravenwood/texts/ravenwood-framework-policies.txt +}" + +SOURCES="${SOURCES:- +frameworks/base/core/java/ +frameworks/base/graphics/java/ +}" + +AAC="${AAC:-frameworks/base/ravenwood/texts/ravenwood-annotation-allowed-classes.txt}" + +with_flag() { + local flag="$1" + shift + + for arg in "$@"; do + echo "$flag $arg" + done +} + +run() { + echo "Running: $*" + "$@" +} + +run_pta() { + local extra_args="$@" + + run ${RAVENHELPER_CMD:-ravenhelper pta} \ + --output-script $OUT_SCRIPT \ + --annotation-allowed-classes-file $AAC \ + $(with_flag --policy-override-file $POLICIES) \ + $(with_flag --src $SOURCES) \ + $extra_args + + if ! [[ -f $OUT_SCRIPT ]] ; then + # no operations generated. + exit 0 + fi + + echo + echo "Created script at $OUT_SCRIPT. Run it with: sh $OUT_SCRIPT" + return 0 +} + +run_pta "$extra_args"
\ No newline at end of file diff --git a/ravenwood/texts/ravenwood-common-policies.txt b/ravenwood/texts/ravenwood-common-policies.txt index 83c31512eb70..fd4ea6cf40c2 100644 --- a/ravenwood/texts/ravenwood-common-policies.txt +++ b/ravenwood/texts/ravenwood-common-policies.txt @@ -1,5 +1,8 @@ # Ravenwood "policy" that should apply to all code. +# The "no-pta" marker is used to exclude the lines from "ravenhelper pta", +# which tries to convert policies to annotations. + # Keep all AIDL interfaces class :aidl keepclass @@ -13,8 +16,8 @@ class :sysprops keepclass class :r keepclass # Support APIs not available in standard JRE -class java.io.FileDescriptor keep +class java.io.FileDescriptor # no-pta method getInt$ @com.android.ravenwood.RavenwoodJdkPatch.getInt$ method setInt$ @com.android.ravenwood.RavenwoodJdkPatch.setInt$ -class java.util.LinkedHashMap keep +class java.util.LinkedHashMap # no-pta method eldest @com.android.ravenwood.RavenwoodJdkPatch.eldest diff --git a/ravenwood/texts/ravenwood-framework-policies.txt b/ravenwood/texts/ravenwood-framework-policies.txt index 26b6fe3d82ad..4033782c607e 100644 --- a/ravenwood/texts/ravenwood-framework-policies.txt +++ b/ravenwood/texts/ravenwood-framework-policies.txt @@ -1,62 +1,65 @@ # Ravenwood "policy" file for framework-minus-apex. +# The "no-pta" marker is used to exclude the lines from "ravenhelper pta", +# which tries to convert policies to annotations. + # To avoid VerifyError on nano proto files (b/324063814), we rename nano proto classes. # Note: The "rename" directive must use slashes (/) as a package name separator. rename com/.*/nano/ devicenano/ rename android/.*/nano/ devicenano/ # StatsD auto-generated -class com.android.internal.util.FrameworkStatsLog keepclass +class com.android.internal.util.FrameworkStatsLog keepclass # no-pta # Exported to Mainline modules; cannot use annotations -class com.android.internal.util.FastXmlSerializer keepclass -class com.android.internal.util.FileRotator keepclass -class com.android.internal.util.HexDump keepclass -class com.android.internal.util.IndentingPrintWriter keepclass -class com.android.internal.util.LocalLog keepclass -class com.android.internal.util.MessageUtils keepclass -class com.android.internal.util.TokenBucket keepclass -class android.os.HandlerExecutor keepclass -class android.util.BackupUtils keepclass -class android.util.IndentingPrintWriter keepclass -class android.util.LocalLog keepclass -class android.util.Pair keepclass -class android.util.Rational keepclass +class com.android.internal.util.FastXmlSerializer keepclass # no-pta +class com.android.internal.util.FileRotator keepclass # no-pta +class com.android.internal.util.HexDump keepclass # no-pta +class com.android.internal.util.IndentingPrintWriter keepclass # no-pta +class com.android.internal.util.LocalLog keepclass # no-pta +class com.android.internal.util.MessageUtils keepclass # no-pta +class com.android.internal.util.TokenBucket keepclass # no-pta +class android.os.HandlerExecutor keepclass # no-pta +class android.util.BackupUtils keepclass # no-pta +class android.util.IndentingPrintWriter keepclass # no-pta +class android.util.LocalLog keepclass # no-pta +class android.util.Pair keepclass # no-pta +class android.util.Rational keepclass # no-pta # From modules-utils; cannot use annotations -class com.android.internal.util.Preconditions keepclass -class com.android.internal.logging.InstanceId keepclass -class com.android.internal.logging.InstanceIdSequence keepclass -class com.android.internal.logging.UiEvent keepclass -class com.android.internal.logging.UiEventLogger keepclass +class com.android.internal.util.Preconditions keepclass # no-pta +class com.android.internal.logging.InstanceId keepclass # no-pta +class com.android.internal.logging.InstanceIdSequence keepclass # no-pta +class com.android.internal.logging.UiEvent keepclass # no-pta +class com.android.internal.logging.UiEventLogger keepclass # no-pta # From modules-utils; cannot use annotations -class com.android.modules.utils.BinaryXmlPullParser keepclass -class com.android.modules.utils.BinaryXmlSerializer keepclass -class com.android.modules.utils.FastDataInput keepclass -class com.android.modules.utils.FastDataOutput keepclass -class com.android.modules.utils.ModifiedUtf8 keepclass -class com.android.modules.utils.TypedXmlPullParser keepclass -class com.android.modules.utils.TypedXmlSerializer keepclass +class com.android.modules.utils.BinaryXmlPullParser keepclass # no-pta +class com.android.modules.utils.BinaryXmlSerializer keepclass # no-pta +class com.android.modules.utils.FastDataInput keepclass # no-pta +class com.android.modules.utils.FastDataOutput keepclass # no-pta +class com.android.modules.utils.ModifiedUtf8 keepclass # no-pta +class com.android.modules.utils.TypedXmlPullParser keepclass # no-pta +class com.android.modules.utils.TypedXmlSerializer keepclass # no-pta # Uri -class android.net.Uri keepclass -class android.net.UriCodec keepclass +class android.net.Uri keepclass # no-pta +class android.net.UriCodec keepclass # no-pta # Telephony -class android.telephony.PinResult keepclass +class android.telephony.PinResult keepclass # no-pta # Just enough to support mocking, no further functionality -class android.content.BroadcastReceiver keep +class android.content.BroadcastReceiver keep # no-pta method <init> ()V keep -class android.content.Context keep +class android.content.Context keep # no-pta method <init> ()V keep - method getSystemService (Ljava/lang/Class;)Ljava/lang/Object; keep -class android.content.pm.PackageManager + method getSystemService (Ljava/lang/Class;)Ljava/lang/Object; keep # no-pta +class android.content.pm.PackageManager # no-pta method <init> ()V keep -class android.text.ClipboardManager keep +class android.text.ClipboardManager keep # no-pta method <init> ()V keep # Just enough to allow ResourcesManager to run -class android.hardware.display.DisplayManagerGlobal keep +class android.hardware.display.DisplayManagerGlobal keep # no-pta method getInstance ()Landroid/hardware/display/DisplayManagerGlobal; ignore diff --git a/ravenwood/texts/ravenwood-services-policies.txt b/ravenwood/texts/ravenwood-services-policies.txt index 530e5c8f5986..e3be9afdba5c 100644 --- a/ravenwood/texts/ravenwood-services-policies.txt +++ b/ravenwood/texts/ravenwood-services-policies.txt @@ -1,12 +1,15 @@ # Ravenwood "policy" file for services.core. +# The "no-pta" marker is used to exclude the lines from "ravenhelper pta", +# which tries to convert policies to annotations. + # Auto-generated from XSD -class com.android.server.compat.config.Change keepclass -class com.android.server.compat.config.Config keepclass -class com.android.server.compat.config.XmlParser keepclass -class com.android.server.compat.overrides.ChangeOverrides keepclass -class com.android.server.compat.overrides.OverrideValue keepclass -class com.android.server.compat.overrides.Overrides keepclass -class com.android.server.compat.overrides.RawOverrideValue keepclass -class com.android.server.compat.overrides.XmlParser keepclass -class com.android.server.compat.overrides.XmlWriter keepclass
\ No newline at end of file +class com.android.server.compat.config.Change keepclass # no-pta +class com.android.server.compat.config.Config keepclass # no-pta +class com.android.server.compat.config.XmlParser keepclass # no-pta +class com.android.server.compat.overrides.ChangeOverrides keepclass # no-pta +class com.android.server.compat.overrides.OverrideValue keepclass # no-pta +class com.android.server.compat.overrides.Overrides keepclass # no-pta +class com.android.server.compat.overrides.RawOverrideValue keepclass # no-pta +class com.android.server.compat.overrides.XmlParser keepclass # no-pta +class com.android.server.compat.overrides.XmlWriter keepclass # no-pta
\ No newline at end of file diff --git a/ravenwood/texts/ravenwood-standard-options.txt b/ravenwood/texts/ravenwood-standard-options.txt index 3ec3e3ce2946..27223d8b72ff 100644 --- a/ravenwood/texts/ravenwood-standard-options.txt +++ b/ravenwood/texts/ravenwood-standard-options.txt @@ -5,6 +5,8 @@ # Keep all classes / methods / fields, but make the methods throw. --default-throw +--delete-finals + # Uncomment below lines to enable each feature. #--default-method-call-hook diff --git a/ravenwood/tools/hoststubgen/hoststubgen-standard-options.txt b/ravenwood/tools/hoststubgen/hoststubgen-standard-options.txt index 001943c18d6b..9c46a1646560 100644 --- a/ravenwood/tools/hoststubgen/hoststubgen-standard-options.txt +++ b/ravenwood/tools/hoststubgen/hoststubgen-standard-options.txt @@ -2,6 +2,8 @@ --debug +--delete-finals + # Uncomment below lines to enable each feature. #--default-method-call-hook diff --git a/ravenwood/tools/hoststubgen/src/com/android/hoststubgen/HostStubGen.kt b/ravenwood/tools/hoststubgen/src/com/android/hoststubgen/HostStubGen.kt index cc704b2b32ed..985947575a86 100644 --- a/ravenwood/tools/hoststubgen/src/com/android/hoststubgen/HostStubGen.kt +++ b/ravenwood/tools/hoststubgen/src/com/android/hoststubgen/HostStubGen.kt @@ -411,6 +411,8 @@ class HostStubGen(val options: HostStubGenOptions) { stats = stats, enablePreTrace = options.enablePreTrace.get, enablePostTrace = options.enablePostTrace.get, + deleteClassFinals = options.deleteFinals.get, + deleteMethodFinals = options.deleteFinals.get, ) outVisitor = BaseAdapter.getVisitor( classInternalName, classes, outVisitor, filter, diff --git a/ravenwood/tools/hoststubgen/src/com/android/hoststubgen/HostStubGenOptions.kt b/ravenwood/tools/hoststubgen/src/com/android/hoststubgen/HostStubGenOptions.kt index 55e853e3e2fb..ae9276f711e1 100644 --- a/ravenwood/tools/hoststubgen/src/com/android/hoststubgen/HostStubGenOptions.kt +++ b/ravenwood/tools/hoststubgen/src/com/android/hoststubgen/HostStubGenOptions.kt @@ -106,6 +106,8 @@ class HostStubGenOptions( var cleanUpOnError: SetOnce<Boolean> = SetOnce(false), + var deleteFinals: SetOnce<Boolean> = SetOnce(false), + var enableClassChecker: SetOnce<Boolean> = SetOnce(false), var enablePreTrace: SetOnce<Boolean> = SetOnce(false), var enablePostTrace: SetOnce<Boolean> = SetOnce(false), @@ -218,6 +220,8 @@ class HostStubGenOptions( "--gen-keep-all-file" -> ret.inputJarAsKeepAllFile.set(nextArg()) + "--delete-finals" -> ret.deleteFinals.set(true) + // Following options are for debugging. "--enable-class-checker" -> ret.enableClassChecker.set(true) "--no-class-checker" -> ret.enableClassChecker.set(false) @@ -293,6 +297,7 @@ class HostStubGenOptions( defaultMethodCallHook=$defaultMethodCallHook, policyOverrideFiles=${policyOverrideFiles.toTypedArray().contentToString()}, defaultPolicy=$defaultPolicy, + deleteFinals=$deleteFinals, cleanUpOnError=$cleanUpOnError, enableClassChecker=$enableClassChecker, enablePreTrace=$enablePreTrace, 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 c5500831e21a..9782f3d0f591 100644 --- a/ravenwood/tools/hoststubgen/src/com/android/hoststubgen/filters/TextFileFilterPolicyParser.kt +++ b/ravenwood/tools/hoststubgen/src/com/android/hoststubgen/filters/TextFileFilterPolicyParser.kt @@ -69,9 +69,9 @@ interface PolicyFileProcessor { fun onRename(pattern: Pattern, prefix: String) /** "class" directive. */ - fun onSimpleClassStart(className: String) + fun onClassStart(className: String) fun onSimpleClassPolicy(className: String, policy: FilterPolicyWithReason) - fun onSimpleClassEnd(className: String) + fun onClassEnd(className: String) fun onSubClassPolicy(superClassName: String, policy: FilterPolicyWithReason) fun onRedirectionClass(fromClassName: String, toClassName: String) @@ -162,10 +162,10 @@ class TextFileFilterPolicyBuilder( ) } - override fun onSimpleClassStart(className: String) { + override fun onClassStart(className: String) { } - override fun onSimpleClassEnd(className: String) { + override fun onClassEnd(className: String) { } override fun onSimpleClassPolicy(className: String, policy: FilterPolicyWithReason) { @@ -273,20 +273,23 @@ class TextFileFilterPolicyParser { private var rFilePolicy: FilterPolicyWithReason? = null /** Name of the file that's currently being processed. */ - var filename: String? = null + var filename: String = "" private set /** 1-based line number in the current file */ var lineNumber = -1 private set + /** Current line */ + var currentLineText = "" + 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 @@ -297,6 +300,7 @@ class TextFileFilterPolicyParser { break } lineNumber++ + currentLineText = line line = normalizeTextLine(line) // Remove comment and trim. if (line.isEmpty()) { continue @@ -312,7 +316,7 @@ class TextFileFilterPolicyParser { private fun finishLastClass() { currentClassName?.let { className -> - processor.onSimpleClassEnd(className) + processor.onClassEnd(className) currentClassName = null } } @@ -416,7 +420,7 @@ class TextFileFilterPolicyParser { if (fields.size <= 1) { throw ParseException("Class ('c') expects 1 or 2 fields.") } - val className = fields[1] + val className = fields[1].toHumanReadableClassName() // superClass is set when the class name starts with a "*". val superClass = resolveExtendingClass(className) @@ -436,6 +440,8 @@ class TextFileFilterPolicyParser { // It's a redirection class. val toClass = policyStr.substring(1) + currentClassName = className + processor.onClassStart(className) processor.onRedirectionClass(className, toClass) } else if (policyStr.startsWith("~")) { if (classType != SpecialClass.NotSpecial) { @@ -447,6 +453,8 @@ class TextFileFilterPolicyParser { // It's a class-load hook val callback = policyStr.substring(1) + currentClassName = className + processor.onClassStart(className) processor.onClassLoadHook(className, callback) } else { // Special case: if it's a class directive with no policy, then it encloses @@ -455,7 +463,6 @@ class TextFileFilterPolicyParser { if (policyStr == "") { if (classType == SpecialClass.NotSpecial && superClass == null) { currentClassName = className - processor.onSimpleClassStart(className) return } throw ParseException("Special class or subclass directive must have a policy") @@ -471,7 +478,7 @@ class TextFileFilterPolicyParser { // TODO: Duplicate check, etc if (superClass == null) { currentClassName = className - processor.onSimpleClassStart(className) + processor.onClassStart(className) processor.onSimpleClassPolicy(className, policy.withReason(FILTER_REASON)) } else { processor.onSubClassPolicy( diff --git a/ravenwood/tools/hoststubgen/src/com/android/hoststubgen/visitors/BaseAdapter.kt b/ravenwood/tools/hoststubgen/src/com/android/hoststubgen/visitors/BaseAdapter.kt index 261ef59c45c7..a08d1d605949 100644 --- a/ravenwood/tools/hoststubgen/src/com/android/hoststubgen/visitors/BaseAdapter.kt +++ b/ravenwood/tools/hoststubgen/src/com/android/hoststubgen/visitors/BaseAdapter.kt @@ -50,7 +50,13 @@ abstract class BaseAdapter( val errors: HostStubGenErrors, val stats: HostStubGenStats?, val enablePreTrace: Boolean, - val enablePostTrace: Boolean + val enablePostTrace: Boolean, + val deleteClassFinals: Boolean, + val deleteMethodFinals: Boolean, + // We don't remove finals from fields, because final fields have a stronger memory + // guarantee than non-final fields, see: + // https://docs.oracle.com/javase/specs/jls/se22/html/jls-17.html#jls-17.5 + // i.e. changing a final field to non-final _could_ result in different behavior. ) protected lateinit var currentPackageName: String @@ -58,14 +64,33 @@ abstract class BaseAdapter( protected var redirectionClass: String? = null protected lateinit var classPolicy: FilterPolicyWithReason + private fun isEnum(access: Int): Boolean { + return (access and Opcodes.ACC_ENUM) != 0 + } + + protected fun modifyClassAccess(access: Int): Int { + if (options.deleteClassFinals && !isEnum(access)) { + return access and Opcodes.ACC_FINAL.inv() + } + return access + } + + protected fun modifyMethodAccess(access: Int): Int { + if (options.deleteMethodFinals) { + return access and Opcodes.ACC_FINAL.inv() + } + return access + } + override fun visit( version: Int, - access: Int, + origAccess: Int, name: String, signature: String?, superName: String?, interfaces: Array<String>, ) { + val access = modifyClassAccess(origAccess) super.visit(version, access, name, signature, superName, interfaces) currentClassName = name currentPackageName = getPackageNameFromFullClassName(name) @@ -130,13 +155,14 @@ abstract class BaseAdapter( } } - override fun visitMethod( - access: Int, + final override fun visitMethod( + origAccess: Int, name: String, descriptor: String, signature: String?, exceptions: Array<String>?, ): MethodVisitor? { + val access = modifyMethodAccess(origAccess) if (skipMemberModificationNestCount > 0) { return super.visitMethod(access, name, descriptor, signature, exceptions) } @@ -176,6 +202,7 @@ abstract class BaseAdapter( if (newAccess == NOT_COMPATIBLE) { return null } + newAccess = modifyMethodAccess(newAccess) log.v( "Emitting %s.%s%s as %s %s", currentClassName, name, descriptor, diff --git a/ravenwood/tools/hoststubgen/src/com/android/hoststubgen/visitors/ImplGeneratingAdapter.kt b/ravenwood/tools/hoststubgen/src/com/android/hoststubgen/visitors/ImplGeneratingAdapter.kt index 567a69e43b58..70e7d46bb6cd 100644 --- a/ravenwood/tools/hoststubgen/src/com/android/hoststubgen/visitors/ImplGeneratingAdapter.kt +++ b/ravenwood/tools/hoststubgen/src/com/android/hoststubgen/visitors/ImplGeneratingAdapter.kt @@ -51,12 +51,13 @@ class ImplGeneratingAdapter( override fun visit( version: Int, - access: Int, + origAccess: Int, name: String, signature: String?, superName: String?, interfaces: Array<String> ) { + val access = modifyClassAccess(origAccess) super.visit(version, access, name, signature, superName, interfaces) classLoadHooks = filter.getClassLoadHooks(currentClassName) diff --git a/ravenwood/tools/hoststubgen/test-tiny-framework/golden-output.RELEASE_TARGET_JAVA_21/01-hoststubgen-test-tiny-framework-orig-dump.txt b/ravenwood/tools/hoststubgen/test-tiny-framework/golden-output.RELEASE_TARGET_JAVA_21/01-hoststubgen-test-tiny-framework-orig-dump.txt index 5e5ca62b49f0..b009b0957919 100644 --- a/ravenwood/tools/hoststubgen/test-tiny-framework/golden-output.RELEASE_TARGET_JAVA_21/01-hoststubgen-test-tiny-framework-orig-dump.txt +++ b/ravenwood/tools/hoststubgen/test-tiny-framework/golden-output.RELEASE_TARGET_JAVA_21/01-hoststubgen-test-tiny-framework-orig-dump.txt @@ -7,6 +7,8 @@ public interface android.hosttest.annotation.HostSideTestClassLoadHook extends j this_class: #x // android/hosttest/annotation/HostSideTestClassLoadHook super_class: #x // java/lang/Object interfaces: 1, fields: 0, methods: 1, attributes: 2 +Constant pool: +{ public abstract java.lang.String value(); descriptor: ()Ljava/lang/String; flags: (0x0401) ACC_PUBLIC, ACC_ABSTRACT @@ -30,6 +32,8 @@ public interface android.hosttest.annotation.HostSideTestIgnore extends java.lan this_class: #x // android/hosttest/annotation/HostSideTestIgnore super_class: #x // java/lang/Object interfaces: 1, fields: 0, methods: 0, attributes: 2 +Constant pool: +{ } SourceFile: "HostSideTestIgnore.java" RuntimeVisibleAnnotations: @@ -50,6 +54,8 @@ public interface android.hosttest.annotation.HostSideTestKeep extends java.lang. this_class: #x // android/hosttest/annotation/HostSideTestKeep super_class: #x // java/lang/Object interfaces: 1, fields: 0, methods: 0, attributes: 2 +Constant pool: +{ } SourceFile: "HostSideTestKeep.java" RuntimeVisibleAnnotations: @@ -70,6 +76,8 @@ public interface android.hosttest.annotation.HostSideTestRedirect extends java.l this_class: #x // android/hosttest/annotation/HostSideTestRedirect super_class: #x // java/lang/Object interfaces: 1, fields: 0, methods: 0, attributes: 2 +Constant pool: +{ } SourceFile: "HostSideTestRedirect.java" RuntimeVisibleAnnotations: @@ -90,6 +98,8 @@ public interface android.hosttest.annotation.HostSideTestRedirectionClass extend this_class: #x // android/hosttest/annotation/HostSideTestRedirectionClass super_class: #x // java/lang/Object interfaces: 1, fields: 0, methods: 1, attributes: 2 +Constant pool: +{ public abstract java.lang.String value(); descriptor: ()Ljava/lang/String; flags: (0x0401) ACC_PUBLIC, ACC_ABSTRACT @@ -113,6 +123,8 @@ public interface android.hosttest.annotation.HostSideTestRemove extends java.lan this_class: #x // android/hosttest/annotation/HostSideTestRemove super_class: #x // java/lang/Object interfaces: 1, fields: 0, methods: 0, attributes: 2 +Constant pool: +{ } SourceFile: "HostSideTestRemove.java" RuntimeVisibleAnnotations: @@ -133,6 +145,8 @@ public interface android.hosttest.annotation.HostSideTestStaticInitializerKeep e this_class: #x // android/hosttest/annotation/HostSideTestStaticInitializerKeep super_class: #x // java/lang/Object interfaces: 1, fields: 0, methods: 0, attributes: 2 +Constant pool: +{ } SourceFile: "HostSideTestStaticInitializerKeep.java" RuntimeVisibleAnnotations: @@ -153,6 +167,8 @@ public interface android.hosttest.annotation.HostSideTestSubstitute extends java this_class: #x // android/hosttest/annotation/HostSideTestSubstitute super_class: #x // java/lang/Object interfaces: 1, fields: 0, methods: 1, attributes: 2 +Constant pool: +{ public abstract java.lang.String suffix(); descriptor: ()Ljava/lang/String; flags: (0x0401) ACC_PUBLIC, ACC_ABSTRACT @@ -176,6 +192,8 @@ public interface android.hosttest.annotation.HostSideTestThrow extends java.lang this_class: #x // android/hosttest/annotation/HostSideTestThrow super_class: #x // java/lang/Object interfaces: 1, fields: 0, methods: 0, attributes: 2 +Constant pool: +{ } SourceFile: "HostSideTestThrow.java" RuntimeVisibleAnnotations: @@ -196,6 +214,8 @@ public interface android.hosttest.annotation.HostSideTestWholeClassKeep extends this_class: #x // android/hosttest/annotation/HostSideTestWholeClassKeep super_class: #x // java/lang/Object interfaces: 1, fields: 0, methods: 0, attributes: 2 +Constant pool: +{ } SourceFile: "HostSideTestWholeClassKeep.java" RuntimeVisibleAnnotations: @@ -216,6 +236,8 @@ public interface android.hosttest.annotation.tests.HostSideTestSuppress extends this_class: #x // android/hosttest/annotation/tests/HostSideTestSuppress super_class: #x // java/lang/Object interfaces: 1, fields: 0, methods: 0, attributes: 2 +Constant pool: +{ } SourceFile: "HostSideTestSuppress.java" RuntimeVisibleAnnotations: @@ -232,6 +254,8 @@ public class com.android.hoststubgen.test.tinyframework.IPretendingAidl$Stub$Pro this_class: #x // com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub$Proxy super_class: #x // java/lang/Object interfaces: 0, fields: 0, methods: 2, attributes: 3 +Constant pool: +{ public com.android.hoststubgen.test.tinyframework.IPretendingAidl$Stub$Proxy(); descriptor: ()V flags: (0x0001) ACC_PUBLIC @@ -273,6 +297,8 @@ public class com.android.hoststubgen.test.tinyframework.IPretendingAidl$Stub this_class: #x // com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub super_class: #x // java/lang/Object interfaces: 0, fields: 0, methods: 2, attributes: 3 +Constant pool: +{ public com.android.hoststubgen.test.tinyframework.IPretendingAidl$Stub(); descriptor: ()V flags: (0x0001) ACC_PUBLIC @@ -314,6 +340,8 @@ public interface com.android.hoststubgen.test.tinyframework.IPretendingAidl this_class: #x // com/android/hoststubgen/test/tinyframework/IPretendingAidl super_class: #x // java/lang/Object interfaces: 0, fields: 0, methods: 0, attributes: 3 +Constant pool: +{ } SourceFile: "IPretendingAidl.java" NestMembers: @@ -331,6 +359,8 @@ public class com.android.hoststubgen.test.tinyframework.R$Nested this_class: #x // com/android/hoststubgen/test/tinyframework/R$Nested super_class: #x // java/lang/Object interfaces: 0, fields: 1, methods: 2, attributes: 3 +Constant pool: +{ public static int[] ARRAY; descriptor: [I flags: (0x0009) ACC_PUBLIC, ACC_STATIC @@ -376,6 +406,8 @@ public class com.android.hoststubgen.test.tinyframework.R this_class: #x // com/android/hoststubgen/test/tinyframework/R super_class: #x // java/lang/Object interfaces: 0, fields: 0, methods: 1, attributes: 3 +Constant pool: +{ public com.android.hoststubgen.test.tinyframework.R(); descriptor: ()V flags: (0x0001) ACC_PUBLIC @@ -396,13 +428,15 @@ InnerClasses: public static #x= #x of #x; // Nested=class com/android/hoststubgen/test/tinyframework/R$Nested of class com/android/hoststubgen/test/tinyframework/R ## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotations.class Compiled from "TinyFrameworkAnnotations.java" -public class com.android.hoststubgen.test.tinyframework.TinyFrameworkAnnotations +public final class com.android.hoststubgen.test.tinyframework.TinyFrameworkAnnotations minor version: 0 major version: 65 - flags: (0x0021) ACC_PUBLIC, ACC_SUPER + flags: (0x0031) ACC_PUBLIC, ACC_FINAL, ACC_SUPER this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotations super_class: #x // java/lang/Object interfaces: 0, fields: 2, methods: 9, attributes: 2 +Constant pool: +{ public int keep; descriptor: I flags: (0x0001) ACC_PUBLIC @@ -433,9 +467,9 @@ public class com.android.hoststubgen.test.tinyframework.TinyFrameworkAnnotations x: #x() android.hosttest.annotation.HostSideTestKeep - public int addOne(int); + public final int addOne(int); descriptor: (I)I - flags: (0x0001) ACC_PUBLIC + flags: (0x0011) ACC_PUBLIC, ACC_FINAL Code: stack=2, locals=2, args_size=2 x: iload_1 @@ -505,18 +539,18 @@ public class com.android.hoststubgen.test.tinyframework.TinyFrameworkAnnotations 0 4 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotations; 0 4 1 value I - public static native int nativeAddThree(int); + public static final native int nativeAddThree(int); descriptor: (I)I - flags: (0x0109) ACC_PUBLIC, ACC_STATIC, ACC_NATIVE + flags: (0x0119) ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_NATIVE RuntimeInvisibleAnnotations: x: #x(#x=s#x) android.hosttest.annotation.HostSideTestSubstitute( suffix="_host" ) - private static int nativeAddThree_host(int); + private static final int nativeAddThree_host(int); descriptor: (I)I - flags: (0x000a) ACC_PRIVATE, ACC_STATIC + flags: (0x001a) ACC_PRIVATE, ACC_STATIC, ACC_FINAL Code: stack=2, locals=1, args_size=1 x: iload_0 @@ -578,6 +612,8 @@ public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHo this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkClassLoadHook super_class: #x // java/lang/Object interfaces: 0, fields: 1, methods: 3, attributes: 2 +Constant pool: +{ public static final java.util.Set<java.lang.Class<?>> sLoadedClasses; descriptor: Ljava/util/Set; flags: (0x0019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL @@ -640,6 +676,8 @@ public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassWideAn this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWideAnnotations super_class: #x // java/lang/Object interfaces: 0, fields: 2, methods: 6, attributes: 2 +Constant pool: +{ public int keep; descriptor: I flags: (0x0001) ACC_PUBLIC @@ -764,6 +802,8 @@ public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassWithIn this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializerDefault super_class: #x // java/lang/Object interfaces: 0, fields: 2, methods: 2, attributes: 2 +Constant pool: +{ public static boolean sInitialized; descriptor: Z flags: (0x0009) ACC_PUBLIC, ACC_STATIC @@ -818,6 +858,8 @@ public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassWithIn this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializerStub super_class: #x // java/lang/Object interfaces: 0, fields: 2, methods: 2, attributes: 2 +Constant pool: +{ public static boolean sInitialized; descriptor: Z flags: (0x0009) ACC_PUBLIC, ACC_STATIC @@ -878,6 +920,8 @@ public final class com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumC this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex super_class: #x // java/lang/Enum interfaces: 0, fields: 6, methods: 7, attributes: 3 +Constant pool: +{ public static final com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex RED; descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; flags: (0x4019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM @@ -1081,6 +1125,8 @@ public final class com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumS this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple super_class: #x // java/lang/Enum interfaces: 0, fields: 3, methods: 5, attributes: 3 +Constant pool: +{ public static final com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple CAT; descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple; flags: (0x4019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM @@ -1202,6 +1248,8 @@ public class com.android.hoststubgen.test.tinyframework.TinyFrameworkExceptionTe this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkExceptionTester super_class: #x // java/lang/Object interfaces: 0, fields: 0, methods: 2, attributes: 2 +Constant pool: +{ public com.android.hoststubgen.test.tinyframework.TinyFrameworkExceptionTester(); descriptor: ()V flags: (0x0001) ACC_PUBLIC @@ -1256,6 +1304,8 @@ public class com.android.hoststubgen.test.tinyframework.TinyFrameworkForTextPoli this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy super_class: #x // java/lang/Object interfaces: 0, fields: 2, methods: 17, attributes: 1 +Constant pool: +{ public int stub; descriptor: I flags: (0x0001) ACC_PUBLIC @@ -1507,6 +1557,8 @@ public class com.android.hoststubgen.test.tinyframework.TinyFrameworkLambdas$Nes this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested super_class: #x // java/lang/Object interfaces: 0, fields: 2, methods: 8, attributes: 5 +Constant pool: +{ public final java.util.function.Supplier<java.lang.Integer> mSupplier; descriptor: Ljava/util/function/Supplier; flags: (0x0011) ACC_PUBLIC, ACC_FINAL @@ -1661,6 +1713,8 @@ public class com.android.hoststubgen.test.tinyframework.TinyFrameworkLambdas this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas super_class: #x // java/lang/Object interfaces: 0, fields: 2, methods: 8, attributes: 5 +Constant pool: +{ public final java.util.function.Supplier<java.lang.Integer> mSupplier; descriptor: Ljava/util/function/Supplier; flags: (0x0011) ACC_PUBLIC, ACC_FINAL @@ -1816,6 +1870,8 @@ public class com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallR this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo super_class: #x // java/lang/Object interfaces: 0, fields: 0, methods: 3, attributes: 3 +Constant pool: +{ public com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace$ReplaceTo(); descriptor: ()V flags: (0x0001) ACC_PUBLIC @@ -1873,6 +1929,8 @@ public class com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallR this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace super_class: #x // java/lang/Object interfaces: 0, fields: 0, methods: 5, attributes: 5 +Constant pool: +{ public com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace(); descriptor: ()V flags: (0x0001) ACC_PUBLIC @@ -1984,6 +2042,8 @@ public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNative this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNative super_class: #x // java/lang/Object interfaces: 0, fields: 1, methods: 14, attributes: 2 +Constant pool: +{ int value; descriptor: I flags: (0x0000) @@ -2157,6 +2217,8 @@ public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNative_host this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host super_class: #x // java/lang/Object interfaces: 0, fields: 0, methods: 7, attributes: 2 +Constant pool: +{ public com.android.hoststubgen.test.tinyframework.TinyFrameworkNative_host(); descriptor: ()V flags: (0x0001) ACC_PUBLIC @@ -2263,6 +2325,8 @@ class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$1 ex this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1 super_class: #x // java/lang/Object interfaces: 1, fields: 0, methods: 3, attributes: 5 +Constant pool: +{ com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$1(com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses); descriptor: (Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;)V flags: (0x0000) @@ -2321,6 +2385,8 @@ class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$2 ex this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2 super_class: #x // java/lang/Object interfaces: 1, fields: 0, methods: 3, attributes: 5 +Constant pool: +{ com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$2(); descriptor: ()V flags: (0x0000) @@ -2375,6 +2441,8 @@ class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$3 ex this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3 super_class: #x // java/lang/Object interfaces: 1, fields: 0, methods: 3, attributes: 5 +Constant pool: +{ com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$3(com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses); descriptor: (Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;)V flags: (0x0000) @@ -2433,6 +2501,8 @@ class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$4 ex this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4 super_class: #x // java/lang/Object interfaces: 1, fields: 0, methods: 3, attributes: 5 +Constant pool: +{ com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$4(); descriptor: ()V flags: (0x0000) @@ -2487,6 +2557,8 @@ public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClass this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass super_class: #x // java/lang/Object interfaces: 0, fields: 1, methods: 1, attributes: 3 +Constant pool: +{ public int value; descriptor: I flags: (0x0001) ACC_PUBLIC @@ -2521,6 +2593,8 @@ public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClass this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass super_class: #x // java/lang/Object interfaces: 0, fields: 1, methods: 1, attributes: 3 +Constant pool: +{ public int value; descriptor: I flags: (0x0001) ACC_PUBLIC @@ -2558,6 +2632,8 @@ class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$Stat this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1 super_class: #x // java/lang/Object interfaces: 1, fields: 0, methods: 3, attributes: 5 +Constant pool: +{ com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$StaticNestedClass$1(); descriptor: ()V flags: (0x0000) @@ -2613,6 +2689,8 @@ public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClass this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$Double$NestedClass super_class: #x // java/lang/Object interfaces: 0, fields: 1, methods: 1, attributes: 3 +Constant pool: +{ public int value; descriptor: I flags: (0x0001) ACC_PUBLIC @@ -2647,6 +2725,8 @@ public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClass this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass super_class: #x // java/lang/Object interfaces: 0, fields: 1, methods: 2, attributes: 3 +Constant pool: +{ public int value; descriptor: I flags: (0x0001) ACC_PUBLIC @@ -2694,6 +2774,8 @@ public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClass this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass super_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass interfaces: 0, fields: 0, methods: 1, attributes: 3 +Constant pool: +{ public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$SubClass(int); descriptor: (I)V flags: (0x0001) ACC_PUBLIC @@ -2723,6 +2805,8 @@ public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClass this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses super_class: #x // java/lang/Object interfaces: 0, fields: 2, methods: 4, attributes: 4 +Constant pool: +{ public final java.util.function.Supplier<java.lang.Integer> mSupplier; descriptor: Ljava/util/function/Supplier; flags: (0x0011) ACC_PUBLIC, ACC_FINAL @@ -2827,6 +2911,8 @@ public class com.android.hoststubgen.test.tinyframework.TinyFrameworkPackageRedi this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkPackageRedirect super_class: #x // java/lang/Object interfaces: 0, fields: 0, methods: 2, attributes: 2 +Constant pool: +{ public com.android.hoststubgen.test.tinyframework.TinyFrameworkPackageRedirect(); descriptor: ()V flags: (0x0001) ACC_PUBLIC @@ -2869,6 +2955,8 @@ public class com.android.hoststubgen.test.tinyframework.TinyFrameworkRenamedClas this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkRenamedClassCaller super_class: #x // java/lang/Object interfaces: 0, fields: 0, methods: 2, attributes: 2 +Constant pool: +{ public com.android.hoststubgen.test.tinyframework.TinyFrameworkRenamedClassCaller(); descriptor: ()V flags: (0x0001) ACC_PUBLIC @@ -2911,6 +2999,8 @@ public class com.android.hoststubgen.test.tinyframework.TinyFrameworkToBeRenamed this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed super_class: #x // java/lang/Object interfaces: 0, fields: 1, methods: 2, attributes: 2 +Constant pool: +{ private final int mValue; descriptor: I flags: (0x0012) ACC_PRIVATE, ACC_FINAL @@ -2958,6 +3048,8 @@ public class com.android.hoststubgen.test.tinyframework.packagetest.A this_class: #x // com/android/hoststubgen/test/tinyframework/packagetest/A super_class: #x // java/lang/Object interfaces: 0, fields: 0, methods: 1, attributes: 1 +Constant pool: +{ public com.android.hoststubgen.test.tinyframework.packagetest.A(); descriptor: ()V flags: (0x0001) ACC_PUBLIC @@ -2981,6 +3073,8 @@ public class com.android.hoststubgen.test.tinyframework.packagetest.B this_class: #x // com/android/hoststubgen/test/tinyframework/packagetest/B super_class: #x // java/lang/Object interfaces: 0, fields: 0, methods: 1, attributes: 1 +Constant pool: +{ public com.android.hoststubgen.test.tinyframework.packagetest.B(); descriptor: ()V flags: (0x0001) ACC_PUBLIC @@ -3004,6 +3098,8 @@ public class com.android.hoststubgen.test.tinyframework.packagetest.sub.A this_class: #x // com/android/hoststubgen/test/tinyframework/packagetest/sub/A super_class: #x // java/lang/Object interfaces: 0, fields: 0, methods: 1, attributes: 1 +Constant pool: +{ public com.android.hoststubgen.test.tinyframework.packagetest.sub.A(); descriptor: ()V flags: (0x0001) ACC_PUBLIC @@ -3027,6 +3123,8 @@ public class com.android.hoststubgen.test.tinyframework.packagetest.sub.B this_class: #x // com/android/hoststubgen/test/tinyframework/packagetest/sub/B super_class: #x // java/lang/Object interfaces: 0, fields: 0, methods: 1, attributes: 1 +Constant pool: +{ public com.android.hoststubgen.test.tinyframework.packagetest.sub.B(); descriptor: ()V flags: (0x0001) ACC_PUBLIC @@ -3050,6 +3148,8 @@ public class com.android.hoststubgen.test.tinyframework.subclasstest.C1 this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/C1 super_class: #x // java/lang/Object interfaces: 0, fields: 0, methods: 1, attributes: 1 +Constant pool: +{ public com.android.hoststubgen.test.tinyframework.subclasstest.C1(); descriptor: ()V flags: (0x0001) ACC_PUBLIC @@ -3073,6 +3173,8 @@ public class com.android.hoststubgen.test.tinyframework.subclasstest.C2 extends this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/C2 super_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/C1 interfaces: 0, fields: 0, methods: 1, attributes: 1 +Constant pool: +{ public com.android.hoststubgen.test.tinyframework.subclasstest.C2(); descriptor: ()V flags: (0x0001) ACC_PUBLIC @@ -3096,6 +3198,8 @@ public class com.android.hoststubgen.test.tinyframework.subclasstest.C3 extends this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/C3 super_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/C2 interfaces: 0, fields: 0, methods: 1, attributes: 1 +Constant pool: +{ public com.android.hoststubgen.test.tinyframework.subclasstest.C3(); descriptor: ()V flags: (0x0001) ACC_PUBLIC @@ -3119,6 +3223,8 @@ public class com.android.hoststubgen.test.tinyframework.subclasstest.CA this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/CA super_class: #x // java/lang/Object interfaces: 0, fields: 0, methods: 1, attributes: 1 +Constant pool: +{ public com.android.hoststubgen.test.tinyframework.subclasstest.CA(); descriptor: ()V flags: (0x0001) ACC_PUBLIC @@ -3142,6 +3248,8 @@ public class com.android.hoststubgen.test.tinyframework.subclasstest.CB this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/CB super_class: #x // java/lang/Object interfaces: 0, fields: 0, methods: 1, attributes: 1 +Constant pool: +{ public com.android.hoststubgen.test.tinyframework.subclasstest.CB(); descriptor: ()V flags: (0x0001) ACC_PUBLIC @@ -3165,6 +3273,8 @@ public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_C1 ex this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/Class_C1 super_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/C1 interfaces: 0, fields: 0, methods: 1, attributes: 1 +Constant pool: +{ public com.android.hoststubgen.test.tinyframework.subclasstest.Class_C1(); descriptor: ()V flags: (0x0001) ACC_PUBLIC @@ -3188,6 +3298,8 @@ public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_C2 ex this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/Class_C2 super_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/C2 interfaces: 0, fields: 0, methods: 1, attributes: 1 +Constant pool: +{ public com.android.hoststubgen.test.tinyframework.subclasstest.Class_C2(); descriptor: ()V flags: (0x0001) ACC_PUBLIC @@ -3211,6 +3323,8 @@ public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_C3 ex this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/Class_C3 super_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/C3 interfaces: 0, fields: 0, methods: 1, attributes: 1 +Constant pool: +{ public com.android.hoststubgen.test.tinyframework.subclasstest.Class_C3(); descriptor: ()V flags: (0x0001) ACC_PUBLIC @@ -3234,6 +3348,8 @@ public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_CA ex this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/Class_CA super_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/CA interfaces: 0, fields: 0, methods: 1, attributes: 1 +Constant pool: +{ public com.android.hoststubgen.test.tinyframework.subclasstest.Class_CA(); descriptor: ()V flags: (0x0001) ACC_PUBLIC @@ -3257,6 +3373,8 @@ public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_CB ex this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/Class_CB super_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/CB interfaces: 0, fields: 0, methods: 1, attributes: 1 +Constant pool: +{ public com.android.hoststubgen.test.tinyframework.subclasstest.Class_CB(); descriptor: ()V flags: (0x0001) ACC_PUBLIC @@ -3280,6 +3398,8 @@ public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_CB_IA this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/Class_CB_IA super_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/CB interfaces: 1, fields: 0, methods: 1, attributes: 1 +Constant pool: +{ public com.android.hoststubgen.test.tinyframework.subclasstest.Class_CB_IA(); descriptor: ()V flags: (0x0001) ACC_PUBLIC @@ -3303,6 +3423,8 @@ public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_I1 im this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/Class_I1 super_class: #x // java/lang/Object interfaces: 1, fields: 0, methods: 1, attributes: 1 +Constant pool: +{ public com.android.hoststubgen.test.tinyframework.subclasstest.Class_I1(); descriptor: ()V flags: (0x0001) ACC_PUBLIC @@ -3326,6 +3448,8 @@ public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_I1_IA this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/Class_I1_IA super_class: #x // java/lang/Object interfaces: 2, fields: 0, methods: 1, attributes: 1 +Constant pool: +{ public com.android.hoststubgen.test.tinyframework.subclasstest.Class_I1_IA(); descriptor: ()V flags: (0x0001) ACC_PUBLIC @@ -3349,6 +3473,8 @@ public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_I2 im this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/Class_I2 super_class: #x // java/lang/Object interfaces: 1, fields: 0, methods: 1, attributes: 1 +Constant pool: +{ public com.android.hoststubgen.test.tinyframework.subclasstest.Class_I2(); descriptor: ()V flags: (0x0001) ACC_PUBLIC @@ -3372,6 +3498,8 @@ public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_I3 im this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/Class_I3 super_class: #x // java/lang/Object interfaces: 1, fields: 0, methods: 1, attributes: 1 +Constant pool: +{ public com.android.hoststubgen.test.tinyframework.subclasstest.Class_I3(); descriptor: ()V flags: (0x0001) ACC_PUBLIC @@ -3395,6 +3523,8 @@ public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_I3_IA this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/Class_I3_IA super_class: #x // java/lang/Object interfaces: 2, fields: 0, methods: 1, attributes: 1 +Constant pool: +{ public com.android.hoststubgen.test.tinyframework.subclasstest.Class_I3_IA(); descriptor: ()V flags: (0x0001) ACC_PUBLIC @@ -3418,6 +3548,8 @@ public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_IA im this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/Class_IA super_class: #x // java/lang/Object interfaces: 1, fields: 0, methods: 1, attributes: 1 +Constant pool: +{ public com.android.hoststubgen.test.tinyframework.subclasstest.Class_IA(); descriptor: ()V flags: (0x0001) ACC_PUBLIC @@ -3441,6 +3573,8 @@ public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_IA_I1 this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/Class_IA_I1 super_class: #x // java/lang/Object interfaces: 2, fields: 0, methods: 1, attributes: 1 +Constant pool: +{ public com.android.hoststubgen.test.tinyframework.subclasstest.Class_IA_I1(); descriptor: ()V flags: (0x0001) ACC_PUBLIC @@ -3464,6 +3598,8 @@ public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_IA_I3 this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/Class_IA_I3 super_class: #x // java/lang/Object interfaces: 2, fields: 0, methods: 1, attributes: 1 +Constant pool: +{ public com.android.hoststubgen.test.tinyframework.subclasstest.Class_IA_I3(); descriptor: ()V flags: (0x0001) ACC_PUBLIC @@ -3487,6 +3623,8 @@ public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_IB im this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/Class_IB super_class: #x // java/lang/Object interfaces: 1, fields: 0, methods: 1, attributes: 1 +Constant pool: +{ public com.android.hoststubgen.test.tinyframework.subclasstest.Class_IB(); descriptor: ()V flags: (0x0001) ACC_PUBLIC @@ -3510,6 +3648,8 @@ public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_IB_IA this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/Class_IB_IA super_class: #x // java/lang/Object interfaces: 2, fields: 0, methods: 1, attributes: 1 +Constant pool: +{ public com.android.hoststubgen.test.tinyframework.subclasstest.Class_IB_IA(); descriptor: ()V flags: (0x0001) ACC_PUBLIC @@ -3533,6 +3673,8 @@ public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_None this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/Class_None super_class: #x // java/lang/Object interfaces: 0, fields: 0, methods: 1, attributes: 1 +Constant pool: +{ public com.android.hoststubgen.test.tinyframework.subclasstest.Class_None(); descriptor: ()V flags: (0x0001) ACC_PUBLIC @@ -3556,6 +3698,8 @@ public interface com.android.hoststubgen.test.tinyframework.subclasstest.I1 this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/I1 super_class: #x // java/lang/Object interfaces: 0, fields: 0, methods: 0, attributes: 1 +Constant pool: +{ } SourceFile: "I1.java" ## Class: com/android/hoststubgen/test/tinyframework/subclasstest/I2.class @@ -3567,6 +3711,8 @@ public interface com.android.hoststubgen.test.tinyframework.subclasstest.I2 exte this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/I2 super_class: #x // java/lang/Object interfaces: 1, fields: 0, methods: 0, attributes: 1 +Constant pool: +{ } SourceFile: "I2.java" ## Class: com/android/hoststubgen/test/tinyframework/subclasstest/I3.class @@ -3578,6 +3724,8 @@ public interface com.android.hoststubgen.test.tinyframework.subclasstest.I3 exte this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/I3 super_class: #x // java/lang/Object interfaces: 1, fields: 0, methods: 0, attributes: 1 +Constant pool: +{ } SourceFile: "I3.java" ## Class: com/android/hoststubgen/test/tinyframework/subclasstest/IA.class @@ -3589,6 +3737,8 @@ public interface com.android.hoststubgen.test.tinyframework.subclasstest.IA this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/IA super_class: #x // java/lang/Object interfaces: 0, fields: 0, methods: 0, attributes: 1 +Constant pool: +{ } SourceFile: "IA.java" ## Class: com/android/hoststubgen/test/tinyframework/subclasstest/IB.class @@ -3600,6 +3750,8 @@ public interface com.android.hoststubgen.test.tinyframework.subclasstest.IB this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/IB super_class: #x // java/lang/Object interfaces: 0, fields: 0, methods: 0, attributes: 1 +Constant pool: +{ } SourceFile: "IB.java" ## Class: com/supported/UnsupportedClass.class @@ -3611,6 +3763,8 @@ public class com.supported.UnsupportedClass this_class: #x // com/supported/UnsupportedClass super_class: #x // java/lang/Object interfaces: 0, fields: 1, methods: 2, attributes: 2 +Constant pool: +{ private final int mValue; descriptor: I flags: (0x0012) ACC_PRIVATE, ACC_FINAL @@ -3658,6 +3812,8 @@ public class com.unsupported.UnsupportedClass this_class: #x // com/unsupported/UnsupportedClass super_class: #x // java/lang/Object interfaces: 0, fields: 0, methods: 2, attributes: 2 +Constant pool: +{ public com.unsupported.UnsupportedClass(int); descriptor: (I)V flags: (0x0001) ACC_PUBLIC diff --git a/ravenwood/tools/hoststubgen/test-tiny-framework/golden-output/01-hoststubgen-test-tiny-framework-orig-dump.txt b/ravenwood/tools/hoststubgen/test-tiny-framework/golden-output/01-hoststubgen-test-tiny-framework-orig-dump.txt index 103e152c7e39..ad413425801b 100644 --- a/ravenwood/tools/hoststubgen/test-tiny-framework/golden-output/01-hoststubgen-test-tiny-framework-orig-dump.txt +++ b/ravenwood/tools/hoststubgen/test-tiny-framework/golden-output/01-hoststubgen-test-tiny-framework-orig-dump.txt @@ -7,6 +7,8 @@ public interface android.hosttest.annotation.HostSideTestClassLoadHook extends j this_class: #x // android/hosttest/annotation/HostSideTestClassLoadHook super_class: #x // java/lang/Object interfaces: 1, fields: 0, methods: 1, attributes: 2 +Constant pool: +{ public abstract java.lang.String value(); descriptor: ()Ljava/lang/String; flags: (0x0401) ACC_PUBLIC, ACC_ABSTRACT @@ -30,6 +32,8 @@ public interface android.hosttest.annotation.HostSideTestIgnore extends java.lan this_class: #x // android/hosttest/annotation/HostSideTestIgnore super_class: #x // java/lang/Object interfaces: 1, fields: 0, methods: 0, attributes: 2 +Constant pool: +{ } SourceFile: "HostSideTestIgnore.java" RuntimeVisibleAnnotations: @@ -50,6 +54,8 @@ public interface android.hosttest.annotation.HostSideTestKeep extends java.lang. this_class: #x // android/hosttest/annotation/HostSideTestKeep super_class: #x // java/lang/Object interfaces: 1, fields: 0, methods: 0, attributes: 2 +Constant pool: +{ } SourceFile: "HostSideTestKeep.java" RuntimeVisibleAnnotations: @@ -70,6 +76,8 @@ public interface android.hosttest.annotation.HostSideTestRedirect extends java.l this_class: #x // android/hosttest/annotation/HostSideTestRedirect super_class: #x // java/lang/Object interfaces: 1, fields: 0, methods: 0, attributes: 2 +Constant pool: +{ } SourceFile: "HostSideTestRedirect.java" RuntimeVisibleAnnotations: @@ -90,6 +98,8 @@ public interface android.hosttest.annotation.HostSideTestRedirectionClass extend this_class: #x // android/hosttest/annotation/HostSideTestRedirectionClass super_class: #x // java/lang/Object interfaces: 1, fields: 0, methods: 1, attributes: 2 +Constant pool: +{ public abstract java.lang.String value(); descriptor: ()Ljava/lang/String; flags: (0x0401) ACC_PUBLIC, ACC_ABSTRACT @@ -113,6 +123,8 @@ public interface android.hosttest.annotation.HostSideTestRemove extends java.lan this_class: #x // android/hosttest/annotation/HostSideTestRemove super_class: #x // java/lang/Object interfaces: 1, fields: 0, methods: 0, attributes: 2 +Constant pool: +{ } SourceFile: "HostSideTestRemove.java" RuntimeVisibleAnnotations: @@ -133,6 +145,8 @@ public interface android.hosttest.annotation.HostSideTestStaticInitializerKeep e this_class: #x // android/hosttest/annotation/HostSideTestStaticInitializerKeep super_class: #x // java/lang/Object interfaces: 1, fields: 0, methods: 0, attributes: 2 +Constant pool: +{ } SourceFile: "HostSideTestStaticInitializerKeep.java" RuntimeVisibleAnnotations: @@ -153,6 +167,8 @@ public interface android.hosttest.annotation.HostSideTestSubstitute extends java this_class: #x // android/hosttest/annotation/HostSideTestSubstitute super_class: #x // java/lang/Object interfaces: 1, fields: 0, methods: 1, attributes: 2 +Constant pool: +{ public abstract java.lang.String suffix(); descriptor: ()Ljava/lang/String; flags: (0x0401) ACC_PUBLIC, ACC_ABSTRACT @@ -176,6 +192,8 @@ public interface android.hosttest.annotation.HostSideTestThrow extends java.lang this_class: #x // android/hosttest/annotation/HostSideTestThrow super_class: #x // java/lang/Object interfaces: 1, fields: 0, methods: 0, attributes: 2 +Constant pool: +{ } SourceFile: "HostSideTestThrow.java" RuntimeVisibleAnnotations: @@ -196,6 +214,8 @@ public interface android.hosttest.annotation.HostSideTestWholeClassKeep extends this_class: #x // android/hosttest/annotation/HostSideTestWholeClassKeep super_class: #x // java/lang/Object interfaces: 1, fields: 0, methods: 0, attributes: 2 +Constant pool: +{ } SourceFile: "HostSideTestWholeClassKeep.java" RuntimeVisibleAnnotations: @@ -216,6 +236,8 @@ public interface android.hosttest.annotation.tests.HostSideTestSuppress extends this_class: #x // android/hosttest/annotation/tests/HostSideTestSuppress super_class: #x // java/lang/Object interfaces: 1, fields: 0, methods: 0, attributes: 2 +Constant pool: +{ } SourceFile: "HostSideTestSuppress.java" RuntimeVisibleAnnotations: @@ -232,6 +254,8 @@ public class com.android.hoststubgen.test.tinyframework.IPretendingAidl$Stub$Pro this_class: #x // com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub$Proxy super_class: #x // java/lang/Object interfaces: 0, fields: 0, methods: 2, attributes: 3 +Constant pool: +{ public com.android.hoststubgen.test.tinyframework.IPretendingAidl$Stub$Proxy(); descriptor: ()V flags: (0x0001) ACC_PUBLIC @@ -273,6 +297,8 @@ public class com.android.hoststubgen.test.tinyframework.IPretendingAidl$Stub this_class: #x // com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub super_class: #x // java/lang/Object interfaces: 0, fields: 0, methods: 2, attributes: 3 +Constant pool: +{ public com.android.hoststubgen.test.tinyframework.IPretendingAidl$Stub(); descriptor: ()V flags: (0x0001) ACC_PUBLIC @@ -314,6 +340,8 @@ public interface com.android.hoststubgen.test.tinyframework.IPretendingAidl this_class: #x // com/android/hoststubgen/test/tinyframework/IPretendingAidl super_class: #x // java/lang/Object interfaces: 0, fields: 0, methods: 0, attributes: 3 +Constant pool: +{ } SourceFile: "IPretendingAidl.java" NestMembers: @@ -331,6 +359,8 @@ public class com.android.hoststubgen.test.tinyframework.R$Nested this_class: #x // com/android/hoststubgen/test/tinyframework/R$Nested super_class: #x // java/lang/Object interfaces: 0, fields: 1, methods: 2, attributes: 3 +Constant pool: +{ public static int[] ARRAY; descriptor: [I flags: (0x0009) ACC_PUBLIC, ACC_STATIC @@ -376,6 +406,8 @@ public class com.android.hoststubgen.test.tinyframework.R this_class: #x // com/android/hoststubgen/test/tinyframework/R super_class: #x // java/lang/Object interfaces: 0, fields: 0, methods: 1, attributes: 3 +Constant pool: +{ public com.android.hoststubgen.test.tinyframework.R(); descriptor: ()V flags: (0x0001) ACC_PUBLIC @@ -396,13 +428,15 @@ InnerClasses: public static #x= #x of #x; // Nested=class com/android/hoststubgen/test/tinyframework/R$Nested of class com/android/hoststubgen/test/tinyframework/R ## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotations.class Compiled from "TinyFrameworkAnnotations.java" -public class com.android.hoststubgen.test.tinyframework.TinyFrameworkAnnotations +public final class com.android.hoststubgen.test.tinyframework.TinyFrameworkAnnotations minor version: 0 major version: 61 - flags: (0x0021) ACC_PUBLIC, ACC_SUPER + flags: (0x0031) ACC_PUBLIC, ACC_FINAL, ACC_SUPER this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotations super_class: #x // java/lang/Object interfaces: 0, fields: 2, methods: 9, attributes: 2 +Constant pool: +{ public int keep; descriptor: I flags: (0x0001) ACC_PUBLIC @@ -433,9 +467,9 @@ public class com.android.hoststubgen.test.tinyframework.TinyFrameworkAnnotations x: #x() android.hosttest.annotation.HostSideTestKeep - public int addOne(int); + public final int addOne(int); descriptor: (I)I - flags: (0x0001) ACC_PUBLIC + flags: (0x0011) ACC_PUBLIC, ACC_FINAL Code: stack=2, locals=2, args_size=2 x: iload_1 @@ -505,18 +539,18 @@ public class com.android.hoststubgen.test.tinyframework.TinyFrameworkAnnotations 0 4 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotations; 0 4 1 value I - public static native int nativeAddThree(int); + public static final native int nativeAddThree(int); descriptor: (I)I - flags: (0x0109) ACC_PUBLIC, ACC_STATIC, ACC_NATIVE + flags: (0x0119) ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_NATIVE RuntimeInvisibleAnnotations: x: #x(#x=s#x) android.hosttest.annotation.HostSideTestSubstitute( suffix="_host" ) - private static int nativeAddThree_host(int); + private static final int nativeAddThree_host(int); descriptor: (I)I - flags: (0x000a) ACC_PRIVATE, ACC_STATIC + flags: (0x001a) ACC_PRIVATE, ACC_STATIC, ACC_FINAL Code: stack=2, locals=1, args_size=1 x: iload_0 @@ -578,6 +612,8 @@ public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHo this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkClassLoadHook super_class: #x // java/lang/Object interfaces: 0, fields: 1, methods: 3, attributes: 2 +Constant pool: +{ public static final java.util.Set<java.lang.Class<?>> sLoadedClasses; descriptor: Ljava/util/Set; flags: (0x0019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL @@ -640,6 +676,8 @@ public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassWideAn this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWideAnnotations super_class: #x // java/lang/Object interfaces: 0, fields: 2, methods: 6, attributes: 2 +Constant pool: +{ public int keep; descriptor: I flags: (0x0001) ACC_PUBLIC @@ -764,6 +802,8 @@ public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassWithIn this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializerDefault super_class: #x // java/lang/Object interfaces: 0, fields: 2, methods: 2, attributes: 2 +Constant pool: +{ public static boolean sInitialized; descriptor: Z flags: (0x0009) ACC_PUBLIC, ACC_STATIC @@ -818,6 +858,8 @@ public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassWithIn this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializerStub super_class: #x // java/lang/Object interfaces: 0, fields: 2, methods: 2, attributes: 2 +Constant pool: +{ public static boolean sInitialized; descriptor: Z flags: (0x0009) ACC_PUBLIC, ACC_STATIC @@ -878,6 +920,8 @@ public final class com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumC this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex super_class: #x // java/lang/Enum interfaces: 0, fields: 6, methods: 7, attributes: 3 +Constant pool: +{ public static final com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex RED; descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; flags: (0x4019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM @@ -1081,6 +1125,8 @@ public final class com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumS this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple super_class: #x // java/lang/Enum interfaces: 0, fields: 3, methods: 5, attributes: 3 +Constant pool: +{ public static final com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple CAT; descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple; flags: (0x4019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM @@ -1202,6 +1248,8 @@ public class com.android.hoststubgen.test.tinyframework.TinyFrameworkExceptionTe this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkExceptionTester super_class: #x // java/lang/Object interfaces: 0, fields: 0, methods: 2, attributes: 2 +Constant pool: +{ public com.android.hoststubgen.test.tinyframework.TinyFrameworkExceptionTester(); descriptor: ()V flags: (0x0001) ACC_PUBLIC @@ -1256,6 +1304,8 @@ public class com.android.hoststubgen.test.tinyframework.TinyFrameworkForTextPoli this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy super_class: #x // java/lang/Object interfaces: 0, fields: 2, methods: 17, attributes: 1 +Constant pool: +{ public int stub; descriptor: I flags: (0x0001) ACC_PUBLIC @@ -1507,6 +1557,8 @@ public class com.android.hoststubgen.test.tinyframework.TinyFrameworkLambdas$Nes this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested super_class: #x // java/lang/Object interfaces: 0, fields: 2, methods: 8, attributes: 5 +Constant pool: +{ public final java.util.function.Supplier<java.lang.Integer> mSupplier; descriptor: Ljava/util/function/Supplier; flags: (0x0011) ACC_PUBLIC, ACC_FINAL @@ -1661,6 +1713,8 @@ public class com.android.hoststubgen.test.tinyframework.TinyFrameworkLambdas this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas super_class: #x // java/lang/Object interfaces: 0, fields: 2, methods: 8, attributes: 5 +Constant pool: +{ public final java.util.function.Supplier<java.lang.Integer> mSupplier; descriptor: Ljava/util/function/Supplier; flags: (0x0011) ACC_PUBLIC, ACC_FINAL @@ -1816,6 +1870,8 @@ public class com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallR this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo super_class: #x // java/lang/Object interfaces: 0, fields: 0, methods: 3, attributes: 3 +Constant pool: +{ public com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace$ReplaceTo(); descriptor: ()V flags: (0x0001) ACC_PUBLIC @@ -1873,6 +1929,8 @@ public class com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallR this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace super_class: #x // java/lang/Object interfaces: 0, fields: 0, methods: 5, attributes: 5 +Constant pool: +{ public com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace(); descriptor: ()V flags: (0x0001) ACC_PUBLIC @@ -1984,6 +2042,8 @@ public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNative this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNative super_class: #x // java/lang/Object interfaces: 0, fields: 1, methods: 14, attributes: 2 +Constant pool: +{ int value; descriptor: I flags: (0x0000) @@ -2157,6 +2217,8 @@ public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNative_host this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host super_class: #x // java/lang/Object interfaces: 0, fields: 0, methods: 7, attributes: 2 +Constant pool: +{ public com.android.hoststubgen.test.tinyframework.TinyFrameworkNative_host(); descriptor: ()V flags: (0x0001) ACC_PUBLIC @@ -2263,6 +2325,8 @@ class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$1 ex this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1 super_class: #x // java/lang/Object interfaces: 1, fields: 1, methods: 3, attributes: 5 +Constant pool: +{ final com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses this$0; descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses; flags: (0x1010) ACC_FINAL, ACC_SYNTHETIC @@ -2328,6 +2392,8 @@ class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$2 ex this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2 super_class: #x // java/lang/Object interfaces: 1, fields: 0, methods: 3, attributes: 5 +Constant pool: +{ com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$2(); descriptor: ()V flags: (0x0000) @@ -2382,6 +2448,8 @@ class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$3 ex this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3 super_class: #x // java/lang/Object interfaces: 1, fields: 1, methods: 3, attributes: 5 +Constant pool: +{ final com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses this$0; descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses; flags: (0x1010) ACC_FINAL, ACC_SYNTHETIC @@ -2447,6 +2515,8 @@ class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$4 ex this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4 super_class: #x // java/lang/Object interfaces: 1, fields: 0, methods: 3, attributes: 5 +Constant pool: +{ com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$4(); descriptor: ()V flags: (0x0000) @@ -2501,6 +2571,8 @@ public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClass this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass super_class: #x // java/lang/Object interfaces: 0, fields: 1, methods: 1, attributes: 3 +Constant pool: +{ public int value; descriptor: I flags: (0x0001) ACC_PUBLIC @@ -2535,6 +2607,8 @@ public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClass this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass super_class: #x // java/lang/Object interfaces: 0, fields: 2, methods: 1, attributes: 3 +Constant pool: +{ public int value; descriptor: I flags: (0x0001) ACC_PUBLIC @@ -2579,6 +2653,8 @@ class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$Stat this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1 super_class: #x // java/lang/Object interfaces: 1, fields: 0, methods: 3, attributes: 5 +Constant pool: +{ com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$StaticNestedClass$1(); descriptor: ()V flags: (0x0000) @@ -2634,6 +2710,8 @@ public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClass this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$Double$NestedClass super_class: #x // java/lang/Object interfaces: 0, fields: 1, methods: 1, attributes: 3 +Constant pool: +{ public int value; descriptor: I flags: (0x0001) ACC_PUBLIC @@ -2668,6 +2746,8 @@ public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClass this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass super_class: #x // java/lang/Object interfaces: 0, fields: 1, methods: 2, attributes: 3 +Constant pool: +{ public int value; descriptor: I flags: (0x0001) ACC_PUBLIC @@ -2715,6 +2795,8 @@ public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClass this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass super_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass interfaces: 0, fields: 0, methods: 1, attributes: 3 +Constant pool: +{ public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$SubClass(int); descriptor: (I)V flags: (0x0001) ACC_PUBLIC @@ -2744,6 +2826,8 @@ public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClass this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses super_class: #x // java/lang/Object interfaces: 0, fields: 2, methods: 4, attributes: 4 +Constant pool: +{ public final java.util.function.Supplier<java.lang.Integer> mSupplier; descriptor: Ljava/util/function/Supplier; flags: (0x0011) ACC_PUBLIC, ACC_FINAL @@ -2848,6 +2932,8 @@ public class com.android.hoststubgen.test.tinyframework.TinyFrameworkPackageRedi this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkPackageRedirect super_class: #x // java/lang/Object interfaces: 0, fields: 0, methods: 2, attributes: 2 +Constant pool: +{ public com.android.hoststubgen.test.tinyframework.TinyFrameworkPackageRedirect(); descriptor: ()V flags: (0x0001) ACC_PUBLIC @@ -2890,6 +2976,8 @@ public class com.android.hoststubgen.test.tinyframework.TinyFrameworkRenamedClas this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkRenamedClassCaller super_class: #x // java/lang/Object interfaces: 0, fields: 0, methods: 2, attributes: 2 +Constant pool: +{ public com.android.hoststubgen.test.tinyframework.TinyFrameworkRenamedClassCaller(); descriptor: ()V flags: (0x0001) ACC_PUBLIC @@ -2932,6 +3020,8 @@ public class com.android.hoststubgen.test.tinyframework.TinyFrameworkToBeRenamed this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed super_class: #x // java/lang/Object interfaces: 0, fields: 1, methods: 2, attributes: 2 +Constant pool: +{ private final int mValue; descriptor: I flags: (0x0012) ACC_PRIVATE, ACC_FINAL @@ -2979,6 +3069,8 @@ public class com.android.hoststubgen.test.tinyframework.packagetest.A this_class: #x // com/android/hoststubgen/test/tinyframework/packagetest/A super_class: #x // java/lang/Object interfaces: 0, fields: 0, methods: 1, attributes: 1 +Constant pool: +{ public com.android.hoststubgen.test.tinyframework.packagetest.A(); descriptor: ()V flags: (0x0001) ACC_PUBLIC @@ -3002,6 +3094,8 @@ public class com.android.hoststubgen.test.tinyframework.packagetest.B this_class: #x // com/android/hoststubgen/test/tinyframework/packagetest/B super_class: #x // java/lang/Object interfaces: 0, fields: 0, methods: 1, attributes: 1 +Constant pool: +{ public com.android.hoststubgen.test.tinyframework.packagetest.B(); descriptor: ()V flags: (0x0001) ACC_PUBLIC @@ -3025,6 +3119,8 @@ public class com.android.hoststubgen.test.tinyframework.packagetest.sub.A this_class: #x // com/android/hoststubgen/test/tinyframework/packagetest/sub/A super_class: #x // java/lang/Object interfaces: 0, fields: 0, methods: 1, attributes: 1 +Constant pool: +{ public com.android.hoststubgen.test.tinyframework.packagetest.sub.A(); descriptor: ()V flags: (0x0001) ACC_PUBLIC @@ -3048,6 +3144,8 @@ public class com.android.hoststubgen.test.tinyframework.packagetest.sub.B this_class: #x // com/android/hoststubgen/test/tinyframework/packagetest/sub/B super_class: #x // java/lang/Object interfaces: 0, fields: 0, methods: 1, attributes: 1 +Constant pool: +{ public com.android.hoststubgen.test.tinyframework.packagetest.sub.B(); descriptor: ()V flags: (0x0001) ACC_PUBLIC @@ -3071,6 +3169,8 @@ public class com.android.hoststubgen.test.tinyframework.subclasstest.C1 this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/C1 super_class: #x // java/lang/Object interfaces: 0, fields: 0, methods: 1, attributes: 1 +Constant pool: +{ public com.android.hoststubgen.test.tinyframework.subclasstest.C1(); descriptor: ()V flags: (0x0001) ACC_PUBLIC @@ -3094,6 +3194,8 @@ public class com.android.hoststubgen.test.tinyframework.subclasstest.C2 extends this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/C2 super_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/C1 interfaces: 0, fields: 0, methods: 1, attributes: 1 +Constant pool: +{ public com.android.hoststubgen.test.tinyframework.subclasstest.C2(); descriptor: ()V flags: (0x0001) ACC_PUBLIC @@ -3117,6 +3219,8 @@ public class com.android.hoststubgen.test.tinyframework.subclasstest.C3 extends this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/C3 super_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/C2 interfaces: 0, fields: 0, methods: 1, attributes: 1 +Constant pool: +{ public com.android.hoststubgen.test.tinyframework.subclasstest.C3(); descriptor: ()V flags: (0x0001) ACC_PUBLIC @@ -3140,6 +3244,8 @@ public class com.android.hoststubgen.test.tinyframework.subclasstest.CA this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/CA super_class: #x // java/lang/Object interfaces: 0, fields: 0, methods: 1, attributes: 1 +Constant pool: +{ public com.android.hoststubgen.test.tinyframework.subclasstest.CA(); descriptor: ()V flags: (0x0001) ACC_PUBLIC @@ -3163,6 +3269,8 @@ public class com.android.hoststubgen.test.tinyframework.subclasstest.CB this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/CB super_class: #x // java/lang/Object interfaces: 0, fields: 0, methods: 1, attributes: 1 +Constant pool: +{ public com.android.hoststubgen.test.tinyframework.subclasstest.CB(); descriptor: ()V flags: (0x0001) ACC_PUBLIC @@ -3186,6 +3294,8 @@ public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_C1 ex this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/Class_C1 super_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/C1 interfaces: 0, fields: 0, methods: 1, attributes: 1 +Constant pool: +{ public com.android.hoststubgen.test.tinyframework.subclasstest.Class_C1(); descriptor: ()V flags: (0x0001) ACC_PUBLIC @@ -3209,6 +3319,8 @@ public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_C2 ex this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/Class_C2 super_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/C2 interfaces: 0, fields: 0, methods: 1, attributes: 1 +Constant pool: +{ public com.android.hoststubgen.test.tinyframework.subclasstest.Class_C2(); descriptor: ()V flags: (0x0001) ACC_PUBLIC @@ -3232,6 +3344,8 @@ public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_C3 ex this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/Class_C3 super_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/C3 interfaces: 0, fields: 0, methods: 1, attributes: 1 +Constant pool: +{ public com.android.hoststubgen.test.tinyframework.subclasstest.Class_C3(); descriptor: ()V flags: (0x0001) ACC_PUBLIC @@ -3255,6 +3369,8 @@ public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_CA ex this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/Class_CA super_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/CA interfaces: 0, fields: 0, methods: 1, attributes: 1 +Constant pool: +{ public com.android.hoststubgen.test.tinyframework.subclasstest.Class_CA(); descriptor: ()V flags: (0x0001) ACC_PUBLIC @@ -3278,6 +3394,8 @@ public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_CB ex this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/Class_CB super_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/CB interfaces: 0, fields: 0, methods: 1, attributes: 1 +Constant pool: +{ public com.android.hoststubgen.test.tinyframework.subclasstest.Class_CB(); descriptor: ()V flags: (0x0001) ACC_PUBLIC @@ -3301,6 +3419,8 @@ public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_CB_IA this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/Class_CB_IA super_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/CB interfaces: 1, fields: 0, methods: 1, attributes: 1 +Constant pool: +{ public com.android.hoststubgen.test.tinyframework.subclasstest.Class_CB_IA(); descriptor: ()V flags: (0x0001) ACC_PUBLIC @@ -3324,6 +3444,8 @@ public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_I1 im this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/Class_I1 super_class: #x // java/lang/Object interfaces: 1, fields: 0, methods: 1, attributes: 1 +Constant pool: +{ public com.android.hoststubgen.test.tinyframework.subclasstest.Class_I1(); descriptor: ()V flags: (0x0001) ACC_PUBLIC @@ -3347,6 +3469,8 @@ public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_I1_IA this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/Class_I1_IA super_class: #x // java/lang/Object interfaces: 2, fields: 0, methods: 1, attributes: 1 +Constant pool: +{ public com.android.hoststubgen.test.tinyframework.subclasstest.Class_I1_IA(); descriptor: ()V flags: (0x0001) ACC_PUBLIC @@ -3370,6 +3494,8 @@ public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_I2 im this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/Class_I2 super_class: #x // java/lang/Object interfaces: 1, fields: 0, methods: 1, attributes: 1 +Constant pool: +{ public com.android.hoststubgen.test.tinyframework.subclasstest.Class_I2(); descriptor: ()V flags: (0x0001) ACC_PUBLIC @@ -3393,6 +3519,8 @@ public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_I3 im this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/Class_I3 super_class: #x // java/lang/Object interfaces: 1, fields: 0, methods: 1, attributes: 1 +Constant pool: +{ public com.android.hoststubgen.test.tinyframework.subclasstest.Class_I3(); descriptor: ()V flags: (0x0001) ACC_PUBLIC @@ -3416,6 +3544,8 @@ public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_I3_IA this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/Class_I3_IA super_class: #x // java/lang/Object interfaces: 2, fields: 0, methods: 1, attributes: 1 +Constant pool: +{ public com.android.hoststubgen.test.tinyframework.subclasstest.Class_I3_IA(); descriptor: ()V flags: (0x0001) ACC_PUBLIC @@ -3439,6 +3569,8 @@ public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_IA im this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/Class_IA super_class: #x // java/lang/Object interfaces: 1, fields: 0, methods: 1, attributes: 1 +Constant pool: +{ public com.android.hoststubgen.test.tinyframework.subclasstest.Class_IA(); descriptor: ()V flags: (0x0001) ACC_PUBLIC @@ -3462,6 +3594,8 @@ public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_IA_I1 this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/Class_IA_I1 super_class: #x // java/lang/Object interfaces: 2, fields: 0, methods: 1, attributes: 1 +Constant pool: +{ public com.android.hoststubgen.test.tinyframework.subclasstest.Class_IA_I1(); descriptor: ()V flags: (0x0001) ACC_PUBLIC @@ -3485,6 +3619,8 @@ public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_IA_I3 this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/Class_IA_I3 super_class: #x // java/lang/Object interfaces: 2, fields: 0, methods: 1, attributes: 1 +Constant pool: +{ public com.android.hoststubgen.test.tinyframework.subclasstest.Class_IA_I3(); descriptor: ()V flags: (0x0001) ACC_PUBLIC @@ -3508,6 +3644,8 @@ public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_IB im this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/Class_IB super_class: #x // java/lang/Object interfaces: 1, fields: 0, methods: 1, attributes: 1 +Constant pool: +{ public com.android.hoststubgen.test.tinyframework.subclasstest.Class_IB(); descriptor: ()V flags: (0x0001) ACC_PUBLIC @@ -3531,6 +3669,8 @@ public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_IB_IA this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/Class_IB_IA super_class: #x // java/lang/Object interfaces: 2, fields: 0, methods: 1, attributes: 1 +Constant pool: +{ public com.android.hoststubgen.test.tinyframework.subclasstest.Class_IB_IA(); descriptor: ()V flags: (0x0001) ACC_PUBLIC @@ -3554,6 +3694,8 @@ public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_None this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/Class_None super_class: #x // java/lang/Object interfaces: 0, fields: 0, methods: 1, attributes: 1 +Constant pool: +{ public com.android.hoststubgen.test.tinyframework.subclasstest.Class_None(); descriptor: ()V flags: (0x0001) ACC_PUBLIC @@ -3577,6 +3719,8 @@ public interface com.android.hoststubgen.test.tinyframework.subclasstest.I1 this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/I1 super_class: #x // java/lang/Object interfaces: 0, fields: 0, methods: 0, attributes: 1 +Constant pool: +{ } SourceFile: "I1.java" ## Class: com/android/hoststubgen/test/tinyframework/subclasstest/I2.class @@ -3588,6 +3732,8 @@ public interface com.android.hoststubgen.test.tinyframework.subclasstest.I2 exte this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/I2 super_class: #x // java/lang/Object interfaces: 1, fields: 0, methods: 0, attributes: 1 +Constant pool: +{ } SourceFile: "I2.java" ## Class: com/android/hoststubgen/test/tinyframework/subclasstest/I3.class @@ -3599,6 +3745,8 @@ public interface com.android.hoststubgen.test.tinyframework.subclasstest.I3 exte this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/I3 super_class: #x // java/lang/Object interfaces: 1, fields: 0, methods: 0, attributes: 1 +Constant pool: +{ } SourceFile: "I3.java" ## Class: com/android/hoststubgen/test/tinyframework/subclasstest/IA.class @@ -3610,6 +3758,8 @@ public interface com.android.hoststubgen.test.tinyframework.subclasstest.IA this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/IA super_class: #x // java/lang/Object interfaces: 0, fields: 0, methods: 0, attributes: 1 +Constant pool: +{ } SourceFile: "IA.java" ## Class: com/android/hoststubgen/test/tinyframework/subclasstest/IB.class @@ -3621,6 +3771,8 @@ public interface com.android.hoststubgen.test.tinyframework.subclasstest.IB this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/IB super_class: #x // java/lang/Object interfaces: 0, fields: 0, methods: 0, attributes: 1 +Constant pool: +{ } SourceFile: "IB.java" ## Class: com/supported/UnsupportedClass.class @@ -3632,6 +3784,8 @@ public class com.supported.UnsupportedClass this_class: #x // com/supported/UnsupportedClass super_class: #x // java/lang/Object interfaces: 0, fields: 1, methods: 2, attributes: 2 +Constant pool: +{ private final int mValue; descriptor: I flags: (0x0012) ACC_PRIVATE, ACC_FINAL @@ -3679,6 +3833,8 @@ public class com.unsupported.UnsupportedClass this_class: #x // com/unsupported/UnsupportedClass super_class: #x // java/lang/Object interfaces: 0, fields: 0, methods: 2, attributes: 2 +Constant pool: +{ public com.unsupported.UnsupportedClass(int); descriptor: (I)V flags: (0x0001) ACC_PUBLIC diff --git a/ravenwood/tools/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotations.java b/ravenwood/tools/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotations.java index 3415deb957ed..674937d15424 100644 --- a/ravenwood/tools/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotations.java +++ b/ravenwood/tools/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotations.java @@ -28,7 +28,7 @@ import android.hosttest.annotation.HostSideTestThrow; @HostSideTestKeep @HostSideTestClassLoadHook( "com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook.onClassLoaded") -public class TinyFrameworkAnnotations { +public final class TinyFrameworkAnnotations { @HostSideTestKeep public TinyFrameworkAnnotations() { } @@ -42,7 +42,7 @@ public class TinyFrameworkAnnotations { public int remove; @HostSideTestKeep - public int addOne(int value) { + public final int addOne(int value) { return value + 1; } @@ -61,10 +61,10 @@ public class TinyFrameworkAnnotations { } @HostSideTestSubstitute(suffix = "_host") - public static native int nativeAddThree(int value); + public final static native int nativeAddThree(int value); // This method is private, but at runtime, it'll inherit the visibility of the original method - private static int nativeAddThree_host(int value) { + private final static int nativeAddThree_host(int value) { return value + 3; } diff --git a/ravenwood/tools/ravenhelper/Android.bp b/ravenwood/tools/ravenhelper/Android.bp new file mode 100644 index 000000000000..a7ee4684506e --- /dev/null +++ b/ravenwood/tools/ravenhelper/Android.bp @@ -0,0 +1,26 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + +java_binary_host { + name: "ravenhelper", + main_class: "com.android.platform.test.ravenwood.ravenhelper.RavenHelperMain", + srcs: ["src/**/*.kt"], + static_libs: [ + "guava", + "hoststubgen-lib", + "junit", + "metalava-gradle-plugin-deps", // Get lint/PSI related classes from here. + "ow2-asm", + "ow2-asm-analysis", + "ow2-asm-commons", + "ow2-asm-tree", + "ow2-asm-util", + ], + visibility: ["//visibility:public"], +} diff --git a/ravenwood/tools/ravenhelper/src/com/android/platform/test/ravenwood/ravenhelper/RavenHelperMain.kt b/ravenwood/tools/ravenhelper/src/com/android/platform/test/ravenwood/ravenhelper/RavenHelperMain.kt new file mode 100644 index 000000000000..e6efbf6c5223 --- /dev/null +++ b/ravenwood/tools/ravenhelper/src/com/android/platform/test/ravenwood/ravenhelper/RavenHelperMain.kt @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2025 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. + */ +@file:JvmName("RavenHelperMain") +package com.android.platform.test.ravenwood.ravenhelper + +/* + * This file contains the main entry point for the "ravenhelper" command, which + * contains subcommands to help various tasks. + */ + +import com.android.hoststubgen.GeneralUserErrorException +import com.android.hoststubgen.LogLevel +import com.android.hoststubgen.executableName +import com.android.hoststubgen.log +import com.android.hoststubgen.runMainWithBoilerplate +import com.android.platform.test.ravenwood.ravenhelper.policytoannot.PtaProcessor + +interface SubcommandHandler { + fun handle(args: List<String>) +} + +fun usage() { + System.out.println(""" + Usage: + ravenhelper SUBCOMMAND options... + + Subcommands: + pta: "policy-to-annotations" Convert policy file to annotations. + (See the pta-framework.sh script for usage.) 1 + + """.trimIndent()) +} + +fun main(args: Array<String>) { + executableName = "RavenHelper" + log.setConsoleLogLevel(LogLevel.Info) + + runMainWithBoilerplate { + log.i("$executableName started") + + if (args.size == 0) { + usage() + return + } + + // Find the subcommand handler. + val subcommand = args[0] + val handler: SubcommandHandler = when (subcommand) { + "pta" -> PtaProcessor() + else -> { + usage() + throw GeneralUserErrorException("Unknown subcommand '$subcommand'") + } + } + + // Run the subcommand. + handler.handle(args.copyOfRange(1, args.size).toList()) + } +} diff --git a/ravenwood/tools/ravenhelper/src/com/android/platform/test/ravenwood/ravenhelper/policytoannot/Annotations.kt b/ravenwood/tools/ravenhelper/src/com/android/platform/test/ravenwood/ravenhelper/policytoannot/Annotations.kt new file mode 100644 index 000000000000..4a11259a8ef7 --- /dev/null +++ b/ravenwood/tools/ravenhelper/src/com/android/platform/test/ravenwood/ravenhelper/policytoannot/Annotations.kt @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2025 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. + */ + +package com.android.platform.test.ravenwood.ravenhelper.policytoannot + +import com.android.hoststubgen.filters.FilterPolicy + + +/** + * This class knows about the Ravenwood annotations. + */ +class Annotations { + enum class Target { + Class, + Field, + Method, + } + + fun get(policy: FilterPolicy, target: Target): String? { + return when (policy) { + FilterPolicy.Keep -> + if (target == Target.Class) { + "@android.ravenwood.annotation.RavenwoodKeepPartialClass" + } else { + "@android.ravenwood.annotation.RavenwoodKeep" + } + FilterPolicy.KeepClass -> + "@android.ravenwood.annotation.RavenwoodKeepWholeClass" + FilterPolicy.Substitute -> + "@android.ravenwood.annotation.RavenwoodReplace" + FilterPolicy.Redirect -> + "@android.ravenwood.annotation.RavenwoodRedirect" + FilterPolicy.Throw -> + "@android.ravenwood.annotation.RavenwoodThrow" + FilterPolicy.Ignore -> null // Ignore has no annotation. (because it's not very safe.) + FilterPolicy.Remove -> + "@android.ravenwood.annotation.RavenwoodRemove" + } + } + + private fun withArg(annot: String, arg: String): String { + return "@$annot(\"$arg\")" + } + + fun getClassLoadHookAnnotation(arg: String): String { + return withArg("android.ravenwood.annotation.RavenwoodClassLoadHook", arg) + } + + fun getRedirectionClassAnnotation(arg: String): String { + return withArg("android.ravenwood.annotation.RavenwoodRedirectionClass", arg) + } +} + diff --git a/ravenwood/tools/ravenhelper/src/com/android/platform/test/ravenwood/ravenhelper/policytoannot/Operations.kt b/ravenwood/tools/ravenhelper/src/com/android/platform/test/ravenwood/ravenhelper/policytoannot/Operations.kt new file mode 100644 index 000000000000..3531ba951b1c --- /dev/null +++ b/ravenwood/tools/ravenhelper/src/com/android/platform/test/ravenwood/ravenhelper/policytoannot/Operations.kt @@ -0,0 +1,201 @@ +/* + * Copyright (C) 2025 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. + */ +package com.android.platform.test.ravenwood.ravenhelper.policytoannot + +/* + * This file contains classes and functions about file edit operations, such as + * "insert a line", "delete a line". + */ + + +import com.android.hoststubgen.log +import java.io.BufferedWriter +import java.io.File + +enum class SourceOperationType { + /** Insert a line */ + Insert, + + /** delete a line */ + Delete, + + /** Insert a text at the beginning of a line */ + Prepend, +} + +data class SourceOperation( + /** Target file to edit. */ + val sourceFile: String, + + /** 1-based line number. Use -1 to add at the end of the file. */ + val lineNumber: Int, + + /** Operation type.*/ + val type: SourceOperationType, + + /** Operand -- text to insert or prepend. Ignored for delete. */ + val text: String = "", + + /** Human-readable description of why this operation was created */ + val description: String, +) { + override fun toString(): String { + return "SourceOperation(sourceFile='$sourceFile', " + + "lineNumber=$lineNumber, type=$type, text='$text' desc='$description')" + } +} + +/** + * Stores list of [SourceOperation]s for each file. + */ +class SourceOperations { + var size: Int = 0 + private set + private val fileOperations = mutableMapOf<String, MutableList<SourceOperation>>() + + fun add(op: SourceOperation) { + log.forVerbose { + log.v("Adding operation: $op") + } + size++ + fileOperations[op.sourceFile]?.let { ops -> + ops.add(op) + return + } + fileOperations[op.sourceFile] = mutableListOf(op) + } + + /** + * Get the collected [SourceOperation]s for each file. + */ + fun getOperations(): MutableMap<String, MutableList<SourceOperation>> { + return fileOperations + } +} + +/** + * Create a shell script to apply all the operations (using sed). + */ +fun createShellScript(ops: SourceOperations, writer: BufferedWriter) { + // File header. + // Note ${'$'} is an ugly way to put a dollar sign ($) in a multi-line string. + writer.write( + """ + #!/bin/bash + + set -e # Finish when any command fails. + + function apply() { + local file="${'$'}1" + + # The script is given via stdin. Write it to file. + local sed="/tmp/pta-script.sed.tmp" + cat > "${'$'}sed" + + echo "Running: sed -i -f \"${'$'}sed\" \"${'$'}file\"" + + if ! sed -i -f "${'$'}sed" "${'$'}file" ; then + echo 'Failed!' 1>&2 + return 1 + fi + } + + """.trimIndent() + ) + + ops.getOperations().toSortedMap().forEach { (origFile, ops) -> + val file = File(origFile).absolutePath + + writer.write("\n") + + writer.write("#") + writer.write("=".repeat(78)) + writer.write("\n") + + writer.write("\n") + + writer.write("apply \"$file\" <<'__END_OF_SCRIPT__'\n") + toSedScript(ops, writer) + writer.write("__END_OF_SCRIPT__\n") + } + + writer.write("\n") + + writer.write("echo \"All files updated successfully!\"\n") + writer.flush() +} + +/** + * Create a sed script to apply a list of operations. + */ +private fun toSedScript(ops: List<SourceOperation>, writer: BufferedWriter) { + ops.sortedBy { it.lineNumber }.forEach { op -> + if (op.text.contains('\n')) { + throw RuntimeException("Operation $op may not contain newlines.") + } + + // Convert each operation to a sed operation. Examples: + // + // - Insert "abc" to line 2 + // 2i\ + // abc + // + // - Insert "abc" to the end of the file + // $a\ + // abc + // + // - Delete line 2 + // 2d + // + // - Prepend abc to line 2 + // 2s/^/abc/ + // + // The line numbers are all the line numbers in the original file. Even though + // the script itself will change them because of inserts and deletes, we don't need to + // change the line numbers in the script. + + // Write the target line number. + writer.write("\n") + writer.write("# ${op.description}\n") + if (op.lineNumber >= 0) { + writer.write(op.lineNumber.toString()) + } else { + writer.write("$") + } + + when (op.type) { + SourceOperationType.Insert -> { + if (op.lineNumber >= 0) { + writer.write("i\\\n") // "Insert" + } else { + // If it's the end of the file, we need to use "a" (append) + writer.write("a\\\n") + } + writer.write(op.text) + writer.write("\n") + } + SourceOperationType.Delete -> { + writer.write("d\n") + } + SourceOperationType.Prepend -> { + if (op.text.contains('/')) { + TODO("Operation $op contains character(s) that needs to be escaped.") + } + writer.write("s/^/${op.text}/\n") + } + } + } +}
\ No newline at end of file diff --git a/ravenwood/tools/ravenhelper/src/com/android/platform/test/ravenwood/ravenhelper/policytoannot/PtaOptions.kt b/ravenwood/tools/ravenhelper/src/com/android/platform/test/ravenwood/ravenhelper/policytoannot/PtaOptions.kt new file mode 100644 index 000000000000..08bd95fd532b --- /dev/null +++ b/ravenwood/tools/ravenhelper/src/com/android/platform/test/ravenwood/ravenhelper/policytoannot/PtaOptions.kt @@ -0,0 +1,106 @@ +/* + * Copyright (C) 2025 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. + */ +package com.android.platform.test.ravenwood.ravenhelper.policytoannot + +import com.android.hoststubgen.ArgIterator +import com.android.hoststubgen.ArgumentsException +import com.android.hoststubgen.SetOnce +import com.android.hoststubgen.ensureFileExists +import com.android.hoststubgen.log + +/** + * Options for the "ravenhelper pta" subcommand. + */ +class PtaOptions( + /** Text policy files */ + var policyOverrideFiles: MutableList<String> = mutableListOf(), + + /** Annotation allowed list file. */ + var annotationAllowedClassesFile: SetOnce<String?> = SetOnce(null), + + /** Source files or directories. */ + var sourceFilesOrDirectories: MutableList<String> = mutableListOf(), + + /** Output script file. */ + var outputScriptFile: SetOnce<String?> = SetOnce(null), + + /** Dump the operations (for debugging) */ + var dumpOperations: SetOnce<Boolean> = SetOnce(false), +) { + companion object { + fun parseArgs(args: List<String>): PtaOptions { + val ret = PtaOptions() + val ai = ArgIterator.withAtFiles(args.toTypedArray()) + + while (true) { + val arg = ai.nextArgOptional() ?: break + + fun nextArg(): String = ai.nextArgRequired(arg) + + if (log.maybeHandleCommandLineArg(arg) { nextArg() }) { + continue + } + try { + when (arg) { + // TODO: Write help + "-h", "--help" -> TODO("Help is not implemented yet") + + "-p", "--policy-override-file" -> + ret.policyOverrideFiles.add(nextArg().ensureFileExists()) + + "-a", "--annotation-allowed-classes-file" -> + ret.annotationAllowedClassesFile.set(nextArg().ensureFileExists()) + + "-s", "--src" -> + ret.sourceFilesOrDirectories.add(nextArg().ensureFileExists()) + + "--dump" -> + ret.dumpOperations.set(true) + + "-o", "--output-script" -> + ret.outputScriptFile.set(nextArg()) + + else -> throw ArgumentsException("Unknown option: $arg") + } + } catch (e: SetOnce.SetMoreThanOnceException) { + throw ArgumentsException("Duplicate or conflicting argument found: $arg") + } + } + + if (ret.policyOverrideFiles.size == 0) { + throw ArgumentsException("Must specify at least one policy file") + } + + if (ret.sourceFilesOrDirectories.size == 0) { + throw ArgumentsException("Must specify at least one source path") + } + + return ret + } + } + + override fun toString(): String { + return """ + PtaOptions{ + policyOverrideFiles=$policyOverrideFiles + annotationAllowedClassesFile=$annotationAllowedClassesFile + sourceFilesOrDirectories=$sourceFilesOrDirectories + outputScriptFile=$outputScriptFile + dumpOperations=$dumpOperations + } + """.trimIndent() + } +}
\ No newline at end of file diff --git a/ravenwood/tools/ravenhelper/src/com/android/platform/test/ravenwood/ravenhelper/policytoannot/PtaProcessor.kt b/ravenwood/tools/ravenhelper/src/com/android/platform/test/ravenwood/ravenhelper/policytoannot/PtaProcessor.kt new file mode 100644 index 000000000000..5984e4fc8f9f --- /dev/null +++ b/ravenwood/tools/ravenhelper/src/com/android/platform/test/ravenwood/ravenhelper/policytoannot/PtaProcessor.kt @@ -0,0 +1,479 @@ +/* + * Copyright (C) 2025 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. + */ +package com.android.platform.test.ravenwood.ravenhelper.policytoannot + +import com.android.hoststubgen.LogLevel +import com.android.hoststubgen.asm.CLASS_INITIALIZER_NAME +import com.android.hoststubgen.asm.toJvmClassName +import com.android.hoststubgen.filters.FilterPolicyWithReason +import com.android.hoststubgen.filters.PolicyFileProcessor +import com.android.hoststubgen.filters.SpecialClass +import com.android.hoststubgen.filters.TextFileFilterPolicyParser +import com.android.hoststubgen.filters.TextFilePolicyMethodReplaceFilter +import com.android.hoststubgen.log +import com.android.hoststubgen.utils.ClassFilter +import com.android.platform.test.ravenwood.ravenhelper.SubcommandHandler +import com.android.platform.test.ravenwood.ravenhelper.psi.createUastEnvironment +import com.android.platform.test.ravenwood.ravenhelper.sourcemap.AllClassInfo +import com.android.platform.test.ravenwood.ravenhelper.sourcemap.ClassInfo +import com.android.platform.test.ravenwood.ravenhelper.sourcemap.MethodInfo +import com.android.platform.test.ravenwood.ravenhelper.sourcemap.SourceLoader +import java.io.BufferedWriter +import java.io.FileOutputStream +import java.io.FileReader +import java.io.OutputStreamWriter +import java.util.regex.Pattern + +/** + * This is the main routine of the "pta" -- policy-to-annotation -- subcommands. + */ +class PtaProcessor : SubcommandHandler { + override fun handle(args: List<String>) { + val options = PtaOptions.parseArgs(args) + + log.v("Options: $options") + + val converter = TextPolicyToAnnotationConverter( + options.policyOverrideFiles, + options.sourceFilesOrDirectories, + options.annotationAllowedClassesFile.get, + Annotations(), + options.dumpOperations.get || log.isEnabled(LogLevel.Debug), + ) + converter.process() + + val ops = converter.resultOperations + + if (ops.size == 0) { + log.i("No files need to be updated.") + return + } + + val scriptWriter = BufferedWriter(OutputStreamWriter( + options.outputScriptFile.get?.let { file -> + FileOutputStream(file) + } ?: System.out + )) + + scriptWriter.use { writer -> + options.outputScriptFile.get?.let { + log.i("Creating script file at $it ...") + } + createShellScript(ops, writer) + } + } +} + +/** + * This class implements the actual logic. + */ +private class TextPolicyToAnnotationConverter( + val policyFiles: List<String>, + val sourceFilesOrDirectories: List<String>, + val annotationAllowedClassesFile: String?, + val annotations: Annotations, + val dumpOperations: Boolean, +) { + private val annotationAllowedClasses: ClassFilter = annotationAllowedClassesFile.let { file -> + if (file == null) { + ClassFilter.newNullFilter(true) // Allow all classes + } else { + ClassFilter.loadFromFile(file, false) + } + } + + val resultOperations = SourceOperations() + private val classes = AllClassInfo() + private val policyParser = TextFileFilterPolicyParser() + private val annotationNeedingClasses = mutableSetOf<String>() + + /** + * Entry point. + */ + fun process() { + // First, load + val env = createUastEnvironment() + try { + loadSources() + + processPolicies() + + addToAnnotationsAllowedListFile() + + if (dumpOperations) { + log.withIndent { + resultOperations.getOperations().toSortedMap().forEach { (file, ops) -> + log.i("ops: $file") + ops.forEach { op -> + log.i(" line: ${op.lineNumber}: ${op.type}: \"${op.text}\" " + + "(${op.description})") + } + } + } + } + } finally { + env.dispose() + } + } + + /** + * Load all the java source files into [classes]. + */ + private fun loadSources() { + val env = createUastEnvironment() + try { + val loader = SourceLoader(env) + loader.load(sourceFilesOrDirectories, classes) + } finally { + env.dispose() + } + } + + private fun addToAnnotationsAllowedListFile() { + log.i("Generating operations to update annotation allowlist file...") + log.withIndent { + annotationNeedingClasses.sorted().forEach { className -> + if (!annotationAllowedClasses.matches(className.toJvmClassName())) { + resultOperations.add( + SourceOperation( + annotationAllowedClassesFile!!, + -1, // add to the end + SourceOperationType.Insert, + className, + "add to annotation allowlist" + )) + } + } + } + } + + /** + * Process the policy files with [Processor]. + */ + private fun processPolicies() { + log.i("Loading the policy files and generating operations...") + log.withIndent { + policyFiles.forEach { policyFile -> + log.i("Parsing $policyFile ...") + log.withIndent { + policyParser.parse(FileReader(policyFile), policyFile, Processor()) + } + } + } + } + + private inner class Processor : PolicyFileProcessor { + + var classPolicyText = "" + var classPolicyLine = -1 + + // Whether the current class has a skip marker, in which case we ignore all members. + // Applicable only within a "simple class" + var classSkipping = false + + var classLineConverted = false + var classHasMember = false + + private fun currentLineHasSkipMarker(): Boolean { + val ret = policyParser.currentLineText.contains("no-pta") + + if (ret) { + log.forVerbose { + log.v("Current line has a skip marker: ${policyParser.currentLineText}") + } + } + + return ret + } + + private fun shouldSkipCurrentLine(): Boolean { + // If a line contains a special marker "no-pta", we'll skip it. + return classSkipping || currentLineHasSkipMarker() + } + + /** Print a warning about an unsupported policy directive. */ + private fun warnOnPolicy(message: String, policyLine: String, lineNumber: Int) { + log.w("Warning: $message") + log.w(" policy: \"$policyLine\"") + log.w(" at ${policyParser.filename}:$lineNumber") + } + + /** Print a warning about an unsupported policy directive. */ + private fun warnOnCurrentPolicy(message: String) { + warnOnPolicy(message, policyParser.currentLineText, policyParser.lineNumber) + } + + /** Print a warning about an unsupported policy directive on the class line. */ + private fun warnOnClassPolicy(message: String) { + warnOnPolicy(message, classPolicyText, classPolicyLine) + } + + override fun onPackage(name: String, policy: FilterPolicyWithReason) { + warnOnCurrentPolicy("'package' directive isn't supported (yet).") + } + + override fun onRename(pattern: Pattern, prefix: String) { + // Rename will never be supported, so don't show a warning. + } + + private fun addOperation(op: SourceOperation) { + resultOperations.add(op) + } + + private fun commentOutPolicy(lineNumber: Int, description: String) { + addOperation( + SourceOperation( + policyParser.filename, + lineNumber, + SourceOperationType.Prepend, + "#[PTA]: ", // comment out. + description, + ) + ) + } + + override fun onClassStart(className: String) { + classSkipping = currentLineHasSkipMarker() + classLineConverted = false + classHasMember = false + classPolicyLine = policyParser.lineNumber + classPolicyText = policyParser.currentLineText + } + + override fun onClassEnd(className: String) { + if (classSkipping) { + classSkipping = false + return + } + if (!classLineConverted) { + // Class line is still needed in the policy file. + // (Because the source file wasn't found.) + return + } + if (!classHasMember) { + commentOutPolicy(classPolicyLine, "remove class policy on $className") + } else { + warnOnClassPolicy( + "Class policy on $className can't be removed because it still has members.") + } + } + + private fun findClass(className: String): ClassInfo? { + val ci = classes.findClass(className) + if (ci == null) { + warnOnCurrentPolicy("Class not found: $className") + } + return ci + } + + private fun addClassAnnotation( + className: String, + annotation: String, + ): Boolean { + val ci = findClass(className) ?: return false + + // Add the annotation to the source file. + addOperation( + SourceOperation( + ci.location.file, + ci.location.line, + SourceOperationType.Insert, + ci.location.getIndent() + annotation, + "add class annotation to $className" + ) + ) + annotationNeedingClasses.add(className) + return true + } + + override fun onSimpleClassPolicy(className: String, policy: FilterPolicyWithReason) { + if (shouldSkipCurrentLine()) { + return + } + log.v("Found simple class policy: $className - ${policy.policy}") + + val annot = annotations.get(policy.policy, Annotations.Target.Class)!! + if (addClassAnnotation(className, annot)) { + classLineConverted = true + } + } + + override fun onSubClassPolicy(superClassName: String, policy: FilterPolicyWithReason) { + warnOnCurrentPolicy("Subclass policies isn't supported (yet).") + } + + override fun onRedirectionClass(fromClassName: String, toClassName: String) { + if (shouldSkipCurrentLine()) { + return + } + + log.v("Found class redirection: $fromClassName - $toClassName") + + if (addClassAnnotation( + fromClassName, + annotations.getRedirectionClassAnnotation(toClassName), + )) { + commentOutPolicy(policyParser.lineNumber, + "remove class redirection policy on $fromClassName") + } + } + + override fun onClassLoadHook(className: String, callback: String) { + if (shouldSkipCurrentLine()) { + return + } + + log.v("Found class load hook: $className - $callback") + + if (addClassAnnotation( + className, + annotations.getClassLoadHookAnnotation(callback), + )) { + commentOutPolicy(policyParser.lineNumber, + "remove class load hook policy on $className") + } + } + + override fun onSpecialClassPolicy(type: SpecialClass, policy: FilterPolicyWithReason) { + // This can't be converted to an annotation, so don't show a warning. + } + + override fun onField(className: String, fieldName: String, policy: FilterPolicyWithReason) { + if (shouldSkipCurrentLine()) { + return + } + + log.v("Found field policy: $className.$fieldName - ${policy.policy}") + + val ci = findClass(className) ?: return + + ci.findField(fieldName)?.let { fi -> + val annot = annotations.get(policy.policy, Annotations.Target.Field)!! + + addOperation( + SourceOperation( + fi.location.file, + fi.location.line, + SourceOperationType.Insert, + fi.location.getIndent() + annot, + "add annotation to field $className.$fieldName", + ) + ) + commentOutPolicy(policyParser.lineNumber, + "remove field policy $className.$fieldName") + + annotationNeedingClasses.add(className) + } ?: { + warnOnCurrentPolicy("Field not found: $className.$fieldName") + } + } + + override fun onSimpleMethodPolicy( + className: String, + methodName: String, + methodDesc: String, + policy: FilterPolicyWithReason + ) { + if (shouldSkipCurrentLine()) { + return + } + val readableName = "$className.$methodName$methodDesc" + log.v("Found simple method policy: $readableName - ${policy.policy}") + + + // Inner method to get the matching methods for this policy. + // + // If this policy can't be converted for any reason, it'll return null. + // Otherwise, it'll return a pair of method list and the annotation string. + fun getMethods(): Pair<List<MethodInfo>, String>? { + if (methodName == CLASS_INITIALIZER_NAME) { + warnOnClassPolicy("Policy for class initializers not supported.") + return null + } + val ci = findClass(className) ?: return null + val methods = ci.findMethods(methodName, methodDesc) + if (methods == null) { + warnOnCurrentPolicy("Method not found: $readableName") + return null + } + + // If the policy is "ignore", we can't convert it to an annotation, in which case + // annotations.get() will return null. + val annot = annotations.get(policy.policy, Annotations.Target.Method) + if (annot == null) { + warnOnCurrentPolicy("Annotation for policy '${policy.policy}' isn't available") + return null + } + return Pair(methods, annot) + } + + val methodsAndAnnot = getMethods() + + if (methodsAndAnnot == null) { + classHasMember = true + return // This policy can't converted. + } + val methods = methodsAndAnnot.first + val annot = methodsAndAnnot.second + + var found = false + methods.forEach { mi -> + found = true + addOperation( + SourceOperation( + mi.location.file, + mi.location.line, + SourceOperationType.Insert, + mi.location.getIndent() + annot, + "add annotation to method $readableName", + ) + ) + } + if (found) { + commentOutPolicy( + policyParser.lineNumber, + "remove method policy $readableName" + ) + + annotationNeedingClasses.add(className) + } else { + warnOnCurrentPolicy("Method not found: $readableName") + } + } + + override fun onMethodInClassReplace( + className: String, + methodName: String, + methodDesc: String, + targetName: String, + policy: FilterPolicyWithReason + ) { + warnOnCurrentPolicy("Found method replace but it's not supported yet: " + + "$className.$methodName$methodDesc - $targetName") + } + + override fun onMethodOutClassReplace( + className: String, + methodName: String, + methodDesc: String, + replaceSpec: TextFilePolicyMethodReplaceFilter.MethodCallReplaceSpec, + policy: FilterPolicyWithReason + ) { + // This can't be converted to an annotation. + classHasMember = true + } + } +}
\ No newline at end of file diff --git a/ravenwood/tools/ravenhelper/src/com/android/platform/test/ravenwood/ravenhelper/psi/PsiUtil.kt b/ravenwood/tools/ravenhelper/src/com/android/platform/test/ravenwood/ravenhelper/psi/PsiUtil.kt new file mode 100644 index 000000000000..6775135e1ac5 --- /dev/null +++ b/ravenwood/tools/ravenhelper/src/com/android/platform/test/ravenwood/ravenhelper/psi/PsiUtil.kt @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2025 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. + */ +package com.android.platform.test.ravenwood.ravenhelper.psi + +import com.android.tools.lint.UastEnvironment + +// PSI is a library to parse Java/Kotlin source files, which is part of JetBrains' IntelliJ/ +// Android Studio, and other IDEs. +// +// PSI is normally used by IntelliJ's plugins, and as such, there isn't really a good documentation +// on how to use it from a standalone program. However, fortunately, Android Studio's Lint +// and Metalava both use PSI. Metalava reuses some of the APIs exposed by Lint. We also use the +// same Lint APIs used by Metalava here. +// +// Some code pointers around the relevant projects: +// +// - We stole code from Metalava, but the recent version of Metalava is too complicated, +// and hard to understand. Older Metalava, such as this one: +// https://android.git.corp.google.com/platform/tools/metalava/+/refs/heads/android13-dev +// is easier to understand. +// +// - PSI is source code is available in IntelliJ's code base: +// https://github.com/JetBrains/intellij-community.git +// +// - Lint is in Android studio. +// https://android.googlesource.com/platform/tools/base/+/studio-master-dev/source.md + + +/** + * Create [UastEnvironment] enough to parse Java source files. + */ +fun createUastEnvironment(): UastEnvironment { + val config = UastEnvironment.Configuration.create( + enableKotlinScripting = false, + useFirUast = false, + ) + + config.javaLanguageLevel = com.intellij.pom.java.LanguageLevel.JDK_21 + + // The following code exists in Metalava, but we don't seem to need it. + // We may need to when we need to support kotlin. +// config.kotlinLanguageLevel = kotlinLanguageLevel +// config.addSourceRoots(listOf(File(root))) +// config.addClasspathRoots(classpath.map { it.absoluteFile }) +// options.jdkHome?.let { +// if (options.isJdkModular(it)) { +// config.kotlinCompilerConfig.put(JVMConfigurationKeys.JDK_HOME, it) +// config.kotlinCompilerConfig.put(JVMConfigurationKeys.NO_JDK, false) +// } +// } + + return UastEnvironment.create(config) +} diff --git a/ravenwood/tools/ravenhelper/src/com/android/platform/test/ravenwood/ravenhelper/sourcemap/SourceMapGenerator.kt b/ravenwood/tools/ravenhelper/src/com/android/platform/test/ravenwood/ravenhelper/sourcemap/SourceMapGenerator.kt new file mode 100644 index 000000000000..58e4497f9f9c --- /dev/null +++ b/ravenwood/tools/ravenhelper/src/com/android/platform/test/ravenwood/ravenhelper/sourcemap/SourceMapGenerator.kt @@ -0,0 +1,419 @@ +/* + * Copyright (C) 2025 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. + */ +package com.android.platform.test.ravenwood.ravenhelper.sourcemap + +/* + * This file contains classes used to parse Java source files to build "source map" which + * basically tells you what classes/methods/fields are declared in what line of what file. + */ + +import com.android.hoststubgen.GeneralUserErrorException +import com.android.hoststubgen.log +import com.android.tools.lint.UastEnvironment +import com.intellij.openapi.editor.Document +import com.intellij.openapi.vfs.StandardFileSystems +import com.intellij.psi.PsiClass +import com.intellij.psi.PsiClassOwner +import com.intellij.psi.PsiElement +import com.intellij.psi.PsiFile +import com.intellij.psi.PsiManager +import com.intellij.psi.PsiMethod +import com.intellij.psi.PsiNameIdentifierOwner +import com.intellij.psi.SyntheticElement +import java.io.File + + +/** + * Represents the location of an item. (class, field or method) + */ +data class Location ( + /** Full path filename. */ + val file: String, + + /** 1-based line number */ + val line: Int, + + /** Indent of the line */ + val indent: Int, +) { + + fun getIndent(): String { + return " ".repeat(indent) + } + + fun dump() { + log.i("Location: $file:$line (indent: $indent)") + } +} + +/** + * Represents the type of item. + */ +enum class ItemType { + Class, + Field, + Method, +} + +/** Holds a field's location. */ +data class FieldInfo ( + val name: String, + val location: Location, +) { + fun dump() { + log.i("Field: $name") + log.withIndent { + location.dump() + } + } +} + +/** Holds a method's location. */ +data class MethodInfo ( + val name: String, + /** "Simplified" description. */ + val simpleDesc: String, + val location: Location, +) { + fun dump() { + log.i("Method: $name$simpleDesc") + log.withIndent { + location.dump() + } + } +} + +/** Holds a class's location and members. */ +data class ClassInfo ( + val fullName: String, + val location: Location, + val fields: MutableMap<String, FieldInfo> = mutableMapOf(), + val methods: MutableMap<String, MutableList<MethodInfo>> = mutableMapOf(), +) { + fun add(fi: FieldInfo) { + fields.put(fi.name, fi) + } + + fun add(mi: MethodInfo) { + val list = methods.get(mi.name) + if (list != null) { + list.add(mi) + } else { + methods.put(mi.name, mutableListOf(mi)) + } + } + + fun dump() { + log.i("Class: $fullName") + log.withIndent { + location.dump() + + // Sort and print fields and methods. + methods.toSortedMap().forEach { entry -> + entry.value.sortedBy { method -> method.simpleDesc }.forEach { + it.dump() + } + } + } + } + + /** Find a field by name */ + fun findField(fieldName: String): FieldInfo? { + return fields[fieldName] + } + + /** + * Find a field by name and descriptor. + * + * If [descriptor] is "*", then all methods with the name will be returned. + */ + fun findMethods(methodName: String, methodDesc: String): List<MethodInfo>? { + val list = methods[methodName] ?: return null + + // Wildcard method policy. + if (methodDesc == "*") { + return list + } + + val simpleDesc = simplifyMethodDesc(methodDesc) + list.forEach { mi -> + if (simpleDesc == mi.simpleDesc) { + return listOf(mi) + } + } + log.w("Method $fullName.$methodName found, but none match description '$methodDesc'") + return null + } +} + +/** + * Stores all classes + */ +data class AllClassInfo ( + val classes: MutableMap<String, ClassInfo> = mutableMapOf(), +) { + fun add(ci: ClassInfo) { + classes.put(ci.fullName, ci) + } + + fun dump() { + classes.toSortedMap { a, b -> a.compareTo(b) }.forEach { + it.value.dump() + } + } + + fun findClass(name: String): ClassInfo? { + return classes.get(name) + } +} + +fun typeToSimpleDesc(origType: String): String { + var type = origType + + // Detect arrays. + var arrayPrefix = "" + while (type.endsWith("[]")) { + arrayPrefix += "[" + type = type.substring(0, type.length - 2) + } + + // Delete generic parameters. (delete everything after '<') + type.indexOf('<').let { pos -> + if (pos >= 0) { + type = type.substring(0, pos) + } + } + + // Handle builtins. + val builtinType = when (type) { + "byte" -> "B" + "short" -> "S" + "int" -> "I" + "long" -> "J" + "float" -> "F" + "double" -> "D" + "boolean" -> "Z" + "char" -> "C" + "void" -> "V" + else -> null + } + + builtinType?.let { + return arrayPrefix + builtinType + } + + return arrayPrefix + "L" + type + ";" +} + +/** + * Get a "simple" description of a method. + * + * "Simple" descriptions are similar to "real" ones, except: + * - No return type. + * - No package names in type names. + */ +fun getSimpleDesc(method: PsiMethod): String { + val sb = StringBuilder() + + sb.append("(") + + val params = method.parameterList + for (i in 0..<params.parametersCount) { + val param = params.getParameter(i) + + val type = param?.type?.presentableText + + if (type == null) { + throw RuntimeException( + "Unable to decode parameter list from method from ${params.parent}") + } + + sb.append(typeToSimpleDesc(type)) + } + + sb.append(")") + + return sb.toString() +} + +private val reTypeFinder = "L.*/".toRegex() + +private fun simplifyMethodDesc(origMethodDesc: String): String { + // We don't need the return type, so remove everything after the ')'. + val pos = origMethodDesc.indexOf(')') + var desc = if (pos < 0) { origMethodDesc } else { origMethodDesc.substring(0, pos + 1) } + + // Then we remove the package names from all the class names. + // i.e. convert "Ljava/lang/String" to "LString". + + return desc.replace(reTypeFinder, "L") +} + +/** + * Class that reads and parses java source files using PSI and populate [AllClassInfo]. + */ +class SourceLoader( + val environment: UastEnvironment, +) { + private val fileSystem = StandardFileSystems.local() + private val manager = PsiManager.getInstance(environment.ideaProject) + + /** Classes that were parsed */ + private var numParsedClasses = 0 + + /** + * Main entry point. + */ + fun load(filesOrDirectories: List<String>, classes: AllClassInfo) { + val psiFiles = mutableListOf<PsiFile>() + log.i("Loading source files...") + log.iTime("Discovering source files") { + load(filesOrDirectories.map { File(it) }, psiFiles) + } + + log.i("${psiFiles.size} file(s) found.") + + if (psiFiles.size == 0) { + throw GeneralUserErrorException("No source files found.") + } + + log.iTime("Parsing source files") { + log.withIndent { + for (file in psiFiles.asSequence().distinct()) { + val classesInFile = (file as? PsiClassOwner)?.classes?.toList() + classesInFile?.forEach { clazz -> + loadClass(clazz)?.let { classes.add(it) } + + clazz.innerClasses.forEach { inner -> + loadClass(inner)?.let { classes.add(it) } + } + } + } + } + } + log.i("$numParsedClasses class(es) found.") + } + + private fun load(filesOrDirectories: List<File>, result: MutableList<PsiFile>) { + filesOrDirectories.forEach { + load(it, result) + } + } + + private fun load(file: File, result: MutableList<PsiFile>) { + if (file.isDirectory) { + file.listFiles()?.forEach { child -> + load(child, result) + } + return + } + + // It's a file + when (file.extension) { + "java" -> { + // Load it. + } + "kt" -> { + log.w("Kotlin not supported, not loading ${file.path}") + return + } + else -> return // Silently skip + } + fileSystem.findFileByPath(file.path)?.let { virtualFile -> + manager.findFile(virtualFile)?.let { psiFile -> + result.add(psiFile) + } + } + } + + private fun loadClass(clazz: PsiClass): ClassInfo? { + if (clazz is SyntheticElement) { + return null + } + log.forVerbose { + log.v("Class found: ${clazz.qualifiedName}") + } + numParsedClasses++ + + log.withIndent { + val ci = ClassInfo( + clazz.qualifiedName!!, + getLocation(clazz) ?: return null, + ) + + // Load fields. + clazz.fields.filter { it !is SyntheticElement }.forEach { + val name = it.name + log.forDebug { log.d("Field found: $name") } + val loc = getLocation(it) ?: return@forEach + ci.add(FieldInfo(name, loc)) + } + + // Load methods. + clazz.methods.filter { it !is SyntheticElement }.forEach { + val name = resolveMethodName(it) + val simpleDesc = getSimpleDesc(it) + log.forDebug { log.d("Method found: $name$simpleDesc") } + val loc = getLocation(it) ?: return@forEach + ci.add(MethodInfo(name, simpleDesc, loc)) + } + return ci + } + } + + private fun resolveMethodName(method: PsiMethod): String { + val clazz = method.containingClass!! + if (clazz.name == method.name) { + return "<init>" // It's a constructor. + } + return method.name + } + + private fun getLocation(elem: PsiElement): Location? { + val lineAndIndent = getLineNumberAndIndent(elem) + if (lineAndIndent == null) { + log.w("Unable to determine location of $elem") + return null + } + return Location( + elem.containingFile.originalFile.virtualFile.path, + lineAndIndent.first, + lineAndIndent.second, + ) + } + + private fun getLineNumberAndIndent(element: PsiElement): Pair<Int, Int>? { + val psiFile: PsiFile = element.containingFile ?: return null + val document: Document = psiFile.viewProvider.document ?: return null + + // Actual elements such as PsiClass, PsiMethod and PsiField contains the leading + // javadoc, etc, so use the "identifier"'s element, if available. + // For synthesized elements, this may return null. + val targetRange = ( + (element as PsiNameIdentifierOwner).nameIdentifier?.textRange ?: element.textRange + ) ?: return null + val lineNumber = document.getLineNumber(targetRange.startOffset) + val lineStartOffset = document.getLineStartOffset(lineNumber) + + val lineLeadingText = document.getText( + com.intellij.openapi.util.TextRange(lineStartOffset, targetRange.startOffset)) + + val indent = lineLeadingText.takeWhile { it.isWhitespace() }.length + + // Line numbers are 0-based, add 1 for human-readable format + return Pair(lineNumber + 1, indent) + } +}
\ No newline at end of file diff --git a/services/companion/java/com/android/server/companion/virtual/VirtualDeviceManagerService.java b/services/companion/java/com/android/server/companion/virtual/VirtualDeviceManagerService.java index f2c42f700921..97ed214b452b 100644 --- a/services/companion/java/com/android/server/companion/virtual/VirtualDeviceManagerService.java +++ b/services/companion/java/com/android/server/companion/virtual/VirtualDeviceManagerService.java @@ -838,13 +838,12 @@ public class VirtualDeviceManagerService extends SystemService { @Override public void onAuthenticationPrompt(int uid) { - synchronized (mVirtualDeviceManagerLock) { - for (int i = 0; i < mVirtualDevices.size(); i++) { - VirtualDeviceImpl device = mVirtualDevices.valueAt(i); - device.showToastWhereUidIsRunning(uid, - R.string.app_streaming_blocked_message_for_fingerprint_dialog, - Toast.LENGTH_LONG, Looper.getMainLooper()); - } + ArrayList<VirtualDeviceImpl> virtualDevicesSnapshot = getVirtualDevicesSnapshot(); + for (int i = 0; i < virtualDevicesSnapshot.size(); i++) { + VirtualDeviceImpl device = virtualDevicesSnapshot.get(i); + device.showToastWhereUidIsRunning(uid, + R.string.app_streaming_blocked_message_for_fingerprint_dialog, + Toast.LENGTH_LONG, Looper.getMainLooper()); } } diff --git a/services/core/Android.bp b/services/core/Android.bp index 4478232cbd36..717a2d46be0b 100644 --- a/services/core/Android.bp +++ b/services/core/Android.bp @@ -37,6 +37,7 @@ filegroup { ":framework_native_aidl", ":gsiservice_aidl", ":installd_aidl", + ":mmd_aidl", ":storaged_aidl", ":vold_aidl", ], @@ -242,6 +243,7 @@ java_library_static { "aconfig_new_storage_flags_lib", "powerstats_flags_lib", "locksettings_flags_lib", + "mmd_flags_lib", ], javac_shard_size: 50, javacflags: [ diff --git a/services/core/java/com/android/server/OWNERS b/services/core/java/com/android/server/OWNERS index 6858e2941ff9..ef769cf6217c 100644 --- a/services/core/java/com/android/server/OWNERS +++ b/services/core/java/com/android/server/OWNERS @@ -9,6 +9,7 @@ per-file DisplayThread.java = michaelwr@google.com, ogunwale@google.com # Zram writeback per-file ZramWriteback.java = minchan@google.com, rajekumar@google.com +per-file ZramMaintenance.java = kawasin@google.com # ServiceWatcher per-file ServiceWatcher.java = sooniln@google.com diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java index b4cdfb18c135..19676ebdbfcd 100644 --- a/services/core/java/com/android/server/StorageManagerService.java +++ b/services/core/java/com/android/server/StorageManagerService.java @@ -41,6 +41,7 @@ import static android.os.storage.OnObbStateChangeListener.ERROR_NOT_MOUNTED; import static android.os.storage.OnObbStateChangeListener.ERROR_PERMISSION_DENIED; import static android.os.storage.OnObbStateChangeListener.MOUNTED; import static android.os.storage.OnObbStateChangeListener.UNMOUNTED; +import static android.mmd.flags.Flags.mmdEnabled; import static com.android.internal.util.XmlUtils.readStringAttribute; import static com.android.internal.util.XmlUtils.writeStringAttribute; @@ -944,12 +945,17 @@ class StorageManagerService extends IStorageManager.Stub }); refreshZramSettings(); - // Schedule zram writeback unless zram is disabled by persist.sys.zram_enabled - String zramPropValue = SystemProperties.get(ZRAM_ENABLED_PROPERTY); - if (!zramPropValue.equals("0") - && mContext.getResources().getBoolean( + if (mmdEnabled()) { + // TODO: b/375432472 - Start zram maintenance only when zram is enabled. + ZramMaintenance.startZramMaintenance(mContext); + } else { + // Schedule zram writeback unless zram is disabled by persist.sys.zram_enabled + String zramPropValue = SystemProperties.get(ZRAM_ENABLED_PROPERTY); + if (!zramPropValue.equals("0") + && mContext.getResources().getBoolean( com.android.internal.R.bool.config_zramWriteback)) { - ZramWriteback.scheduleZramWriteback(mContext); + ZramWriteback.scheduleZramWriteback(mContext); + } } configureTranscoding(); @@ -976,7 +982,7 @@ class StorageManagerService extends IStorageManager.Stub // sole writer. SystemProperties.set(ZRAM_ENABLED_PROPERTY, desiredPropertyValue); // Schedule writeback only if zram is being enabled. - if (desiredPropertyValue.equals("1") + if (!mmdEnabled() && desiredPropertyValue.equals("1") && mContext.getResources().getBoolean( com.android.internal.R.bool.config_zramWriteback)) { ZramWriteback.scheduleZramWriteback(mContext); diff --git a/services/core/java/com/android/server/ZramMaintenance.java b/services/core/java/com/android/server/ZramMaintenance.java new file mode 100644 index 000000000000..cdb48122e321 --- /dev/null +++ b/services/core/java/com/android/server/ZramMaintenance.java @@ -0,0 +1,118 @@ +/* + * 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. + */ + +package com.android.server; + +import android.app.job.JobInfo; +import android.app.job.JobParameters; +import android.app.job.JobScheduler; +import android.app.job.JobService; +import android.content.ComponentName; +import android.content.Context; +import android.os.IBinder; +import android.os.IMmd; +import android.os.RemoteException; +import android.os.ServiceManager; +import android.os.SystemProperties; +import android.util.Slog; + +import java.time.Duration; + +/** + * Schedules zram maintenance (e.g. zram writeback, zram recompression). + * + * <p>ZramMaintenance notifies mmd the good timing to execute zram maintenance based on: + * + * <ul> + * <li>Enough interval has passed. + * <li>The system is idle. + * <li>The battery is not low. + * </ul> + */ +public class ZramMaintenance extends JobService { + private static final String TAG = ZramMaintenance.class.getName(); + // Job id must be unique across all clients of the same uid. ZramMaintenance uses the bug number + // as the job id. + private static final int JOB_ID = 375432472; + private static final ComponentName sZramMaintenance = + new ComponentName("android", ZramMaintenance.class.getName()); + + private static final String FIRST_DELAY_SECONDS_PROP = + "mm.zram.maintenance.first_delay_seconds"; + // The default is 1 hour. + private static final long DEFAULT_FIRST_DELAY_SECONDS = 3600; + private static final String PERIODIC_DELAY_SECONDS_PROP = + "mm.zram.maintenance.periodic_delay_seconds"; + // The default is 1 hour. + private static final long DEFAULT_PERIODIC_DELAY_SECONDS = 3600; + private static final String REQUIRE_DEVICE_IDLE_PROP = + "mm.zram.maintenance.require_device_idle"; + private static final boolean DEFAULT_REQUIRE_DEVICE_IDLE = + true; + private static final String REQUIRE_BATTERY_NOT_LOW_PROP = + "mm.zram.maintenance.require_battry_not_low"; + private static final boolean DEFAULT_REQUIRE_BATTERY_NOT_LOW = + true; + + @Override + public boolean onStartJob(JobParameters params) { + IBinder binder = ServiceManager.getService("mmd"); + if (binder != null) { + IMmd mmd = IMmd.Stub.asInterface(binder); + try { + mmd.doZramMaintenance(); + } catch (RemoteException e) { + Slog.e(TAG, "Failed to doZramMaintenance", e); + } + } else { + Slog.w(TAG, "binder not found"); + } + Duration delay = Duration.ofSeconds(SystemProperties.getLong(PERIODIC_DELAY_SECONDS_PROP, + DEFAULT_PERIODIC_DELAY_SECONDS)); + scheduleZramMaintenance(this, delay); + return true; + } + + @Override + public boolean onStopJob(JobParameters params) { + return false; + } + + /** + * Starts periodical zram maintenance. + */ + public static void startZramMaintenance(Context context) { + Duration delay = Duration.ofSeconds( + SystemProperties.getLong(FIRST_DELAY_SECONDS_PROP, DEFAULT_FIRST_DELAY_SECONDS)); + scheduleZramMaintenance(context, delay); + } + + private static void scheduleZramMaintenance(Context context, Duration delay) { + JobScheduler js = context.getSystemService(JobScheduler.class); + + if (js != null) { + js.schedule(new JobInfo.Builder(JOB_ID, sZramMaintenance) + .setMinimumLatency(delay.toMillis()) + .setRequiresDeviceIdle( + SystemProperties.getBoolean(REQUIRE_DEVICE_IDLE_PROP, + DEFAULT_REQUIRE_DEVICE_IDLE)) + .setRequiresBatteryNotLow( + SystemProperties.getBoolean(REQUIRE_BATTERY_NOT_LOW_PROP, + DEFAULT_REQUIRE_BATTERY_NOT_LOW)) + .build()); + } + } +} diff --git a/services/core/java/com/android/server/am/UidObserverController.java b/services/core/java/com/android/server/am/UidObserverController.java index 7eeec32cf24a..f13bfac58e77 100644 --- a/services/core/java/com/android/server/am/UidObserverController.java +++ b/services/core/java/com/android/server/am/UidObserverController.java @@ -77,6 +77,7 @@ public class UidObserverController { * This is for verifying the UID report flow. */ private static final boolean VALIDATE_UID_STATES = true; + @GuardedBy("mLock") private final ActiveUids mValidateUids; UidObserverController(@NonNull Handler handler) { @@ -282,31 +283,30 @@ public class UidObserverController { } mUidObservers.finishBroadcast(); - if (VALIDATE_UID_STATES && mUidObservers.getRegisteredCallbackCount() > 0) { - for (int j = 0; j < numUidChanges; ++j) { - final ChangeRecord item = mActiveUidChanges[j]; - if ((item.change & UidRecord.CHANGE_GONE) != 0) { - mValidateUids.remove(item.uid); - } else { - UidRecord validateUid = mValidateUids.get(item.uid); - if (validateUid == null) { - validateUid = new UidRecord(item.uid, null); - mValidateUids.put(item.uid, validateUid); - } - if ((item.change & UidRecord.CHANGE_IDLE) != 0) { - validateUid.setIdle(true); - } else if ((item.change & UidRecord.CHANGE_ACTIVE) != 0) { - validateUid.setIdle(false); + synchronized (mLock) { + if (VALIDATE_UID_STATES && mUidObservers.getRegisteredCallbackCount() > 0) { + for (int j = 0; j < numUidChanges; ++j) { + final ChangeRecord item = mActiveUidChanges[j]; + if ((item.change & UidRecord.CHANGE_GONE) != 0) { + mValidateUids.remove(item.uid); + } else { + UidRecord validateUid = mValidateUids.get(item.uid); + if (validateUid == null) { + validateUid = new UidRecord(item.uid, null); + mValidateUids.put(item.uid, validateUid); + } + if ((item.change & UidRecord.CHANGE_IDLE) != 0) { + validateUid.setIdle(true); + } else if ((item.change & UidRecord.CHANGE_ACTIVE) != 0) { + validateUid.setIdle(false); + } + validateUid.setSetProcState(item.procState); + validateUid.setCurProcState(item.procState); + validateUid.setSetCapability(item.capability); + validateUid.setCurCapability(item.capability); } - validateUid.setSetProcState(item.procState); - validateUid.setCurProcState(item.procState); - validateUid.setSetCapability(item.capability); - validateUid.setCurCapability(item.capability); } } - } - - synchronized (mLock) { for (int j = 0; j < numUidChanges; j++) { final ChangeRecord changeRecord = mActiveUidChanges[j]; changeRecord.isPending = false; @@ -433,7 +433,9 @@ public class UidObserverController { } UidRecord getValidateUidRecord(int uid) { - return mValidateUids.get(uid); + synchronized (mLock) { + return mValidateUids.get(uid); + } } void dump(@NonNull PrintWriter pw, @Nullable String dumpPackage) { @@ -488,12 +490,16 @@ public class UidObserverController { boolean dumpValidateUids(@NonNull PrintWriter pw, @Nullable String dumpPackage, int dumpAppId, @NonNull String header, boolean needSep) { - return mValidateUids.dump(pw, dumpPackage, dumpAppId, header, needSep); + synchronized (mLock) { + return mValidateUids.dump(pw, dumpPackage, dumpAppId, header, needSep); + } } void dumpValidateUidsProto(@NonNull ProtoOutputStream proto, @Nullable String dumpPackage, int dumpAppId, long fieldId) { - mValidateUids.dumpProto(proto, dumpPackage, dumpAppId, fieldId); + synchronized (mLock) { + mValidateUids.dumpProto(proto, dumpPackage, dumpAppId, fieldId); + } } static final class ChangeRecord { diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java index d82d77dd1ce1..2fb58f00df6e 100644 --- a/services/core/java/com/android/server/appop/AppOpsService.java +++ b/services/core/java/com/android/server/appop/AppOpsService.java @@ -2566,7 +2566,6 @@ public class AppOpsService extends IAppOpsService.Stub { Map<String, Ops> packages = uidState.pkgOps; Iterator<Map.Entry<String, Ops>> it = packages.entrySet().iterator(); - boolean uidChanged = false; while (it.hasNext()) { Map.Entry<String, Ops> ent = it.next(); String packageName = ent.getKey(); @@ -2599,7 +2598,6 @@ public class AppOpsService extends IAppOpsService.Stub { newMode, UserHandle.getUserId(curOp.uid)); changed = true; - uidChanged = true; final int uid = curOp.uidState.uid; callbacks = addCallbacks(callbacks, curOp.op, uid, packageName, previousMode, mOpModeWatchers.get(curOp.op)); diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index aa5925851a10..2a03dcbdfbc5 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -4240,8 +4240,6 @@ public class PackageManagerService implements PackageSender, TestUtilityService CarrierAppUtils.disableCarrierAppsUntilPrivileged( mContext.getOpPackageName(), UserHandle.USER_SYSTEM, mContext); - disableSkuSpecificApps(); - // Read the compatibilty setting when the system is ready. boolean compatibilityModeEnabled = android.provider.Settings.Global.getInt( mContext.getContentResolver(), @@ -4374,29 +4372,6 @@ public class PackageManagerService implements PackageSender, TestUtilityService } } - //TODO: b/111402650 - private void disableSkuSpecificApps() { - String[] apkList = mContext.getResources().getStringArray( - R.array.config_disableApksUnlessMatchedSku_apk_list); - String[] skuArray = mContext.getResources().getStringArray( - R.array.config_disableApkUnlessMatchedSku_skus_list); - if (ArrayUtils.isEmpty(apkList)) { - return; - } - String sku = SystemProperties.get("ro.boot.hardware.sku"); - if (!TextUtils.isEmpty(sku) && ArrayUtils.contains(skuArray, sku)) { - return; - } - final Computer snapshot = snapshotComputer(); - for (String packageName : apkList) { - setSystemAppHiddenUntilInstalled(snapshot, packageName, true); - final List<UserInfo> users = mInjector.getUserManagerInternal().getUsers(false); - for (int i = 0; i < users.size(); i++) { - setSystemAppInstallState(snapshot, packageName, false, users.get(i).id); - } - } - } - public PackageFreezer freezePackage(String packageName, int userId, String killReason, int exitInfoReason, InstallRequest request) { return freezePackage(packageName, userId, killReason, exitInfoReason, request, diff --git a/services/core/java/com/android/server/power/OWNERS b/services/core/java/com/android/server/power/OWNERS index c1fad33fef0f..a1531a810c3c 100644 --- a/services/core/java/com/android/server/power/OWNERS +++ b/services/core/java/com/android/server/power/OWNERS @@ -2,6 +2,8 @@ michaelwr@google.com santoscordon@google.com petsjonkin@google.com brup@google.com +flc@google.com +wilczynskip@google.com per-file ThermalManagerService.java=file:/THERMAL_OWNERS per-file LowPowerStandbyController.java=qingxun@google.com diff --git a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java index b35a0a772ff2..4b55f276026f 100644 --- a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java +++ b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java @@ -4853,7 +4853,7 @@ public class StatsPullAtomService extends SystemService { Slog.e(TAG, "Disconnected from keystore service. Cannot pull.", e); return StatsManager.PULL_SKIP; } catch (ServiceSpecificException e) { - Slog.e(TAG, "pulling keystore metrics failed", e); + Slog.e(TAG, "Pulling keystore atom with tag " + atomTag + " failed", e); return StatsManager.PULL_SKIP; } finally { Binder.restoreCallingIdentity(callingToken); diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java index 908f51b9cba9..ccac96948b0a 100644 --- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java +++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java @@ -1511,10 +1511,13 @@ public class StatusBarManagerService extends IStatusBarService.Stub implements D getUiState(displayId).setImeWindowState(vis, backDisposition, showImeSwitcher); mHandler.post(() -> { - if (mBar == null) return; - try { - mBar.setImeWindowStatus(displayId, vis, backDisposition, showImeSwitcher); - } catch (RemoteException ex) { } + IStatusBar bar = mBar; + if (bar != null) { + try { + bar.setImeWindowStatus(displayId, vis, backDisposition, showImeSwitcher); + } catch (RemoteException ex) { + } + } }); } } diff --git a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java index 9a3ad2d85de6..cebf1bee3439 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java +++ b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java @@ -1655,6 +1655,12 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks { activityIdleInternal(null /* idleActivity */, false /* fromTimeout */, true /* processPausingActivities */, null /* configuration */); + if (rootTask.getParent() == null) { + // The activities in the task may already be finishing. Then the task could be removed + // when performing the idle check. + return; + } + // Reparent all the tasks to the bottom of the display final DisplayContent toDisplay = mRootWindowContainer.getDisplayContent(DEFAULT_DISPLAY); diff --git a/tests/CompanionDeviceMultiDeviceTests/client/Android.bp b/tests/CompanionDeviceMultiDeviceTests/client/Android.bp index ce63fe89fe2e..02b639109931 100644 --- a/tests/CompanionDeviceMultiDeviceTests/client/Android.bp +++ b/tests/CompanionDeviceMultiDeviceTests/client/Android.bp @@ -45,7 +45,6 @@ android_test { ], optimize: { - proguard_compatibility: true, proguard_flags_files: ["proguard.flags"], }, } diff --git a/tests/vcn/java/com/android/server/vcn/routeselection/IpSecPacketLossDetectorTest.java b/tests/vcn/java/com/android/server/vcn/routeselection/IpSecPacketLossDetectorTest.java index 7b1e4cc62dab..c11b6bb3435d 100644 --- a/tests/vcn/java/com/android/server/vcn/routeselection/IpSecPacketLossDetectorTest.java +++ b/tests/vcn/java/com/android/server/vcn/routeselection/IpSecPacketLossDetectorTest.java @@ -38,7 +38,6 @@ import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.reset; -import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; diff --git a/tools/lint/framework/checks/src/main/java/com/google/android/lint/AndroidFrameworkIssueRegistry.kt b/tools/lint/framework/checks/src/main/java/com/google/android/lint/AndroidFrameworkIssueRegistry.kt index af753e5963a3..b62843ca3ff4 100644 --- a/tools/lint/framework/checks/src/main/java/com/google/android/lint/AndroidFrameworkIssueRegistry.kt +++ b/tools/lint/framework/checks/src/main/java/com/google/android/lint/AndroidFrameworkIssueRegistry.kt @@ -19,6 +19,7 @@ package com.google.android.lint import com.android.tools.lint.client.api.IssueRegistry import com.android.tools.lint.client.api.Vendor import com.android.tools.lint.detector.api.CURRENT_API +import com.google.android.lint.multiuser.PendingIntentGetActivityDetector import com.google.android.lint.parcel.SaferParcelChecker import com.google.auto.service.AutoService @@ -40,6 +41,7 @@ class AndroidFrameworkIssueRegistry : IssueRegistry() { PermissionMethodDetector.ISSUE_PERMISSION_METHOD_USAGE, PermissionMethodDetector.ISSUE_CAN_BE_PERMISSION_METHOD, FeatureAutomotiveDetector.ISSUE, + PendingIntentGetActivityDetector.ISSUE_PENDING_INTENT_GET_ACTIVITY, ) override val api: Int diff --git a/tools/lint/framework/checks/src/main/java/com/google/android/lint/multiuser/PendingIntentGetActivityDetector.kt b/tools/lint/framework/checks/src/main/java/com/google/android/lint/multiuser/PendingIntentGetActivityDetector.kt new file mode 100644 index 000000000000..b9f22ebfa8ec --- /dev/null +++ b/tools/lint/framework/checks/src/main/java/com/google/android/lint/multiuser/PendingIntentGetActivityDetector.kt @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2025 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. + */ + +package com.google.android.lint.multiuser + +import com.android.tools.lint.detector.api.Category +import com.android.tools.lint.detector.api.Detector +import com.android.tools.lint.detector.api.Implementation +import com.android.tools.lint.detector.api.Issue +import com.android.tools.lint.detector.api.JavaContext +import com.android.tools.lint.detector.api.Scope +import com.android.tools.lint.detector.api.Severity +import com.android.tools.lint.detector.api.SourceCodeScanner +import com.intellij.psi.PsiMethod +import java.util.EnumSet +import org.jetbrains.uast.UCallExpression + +/** + * Detector for flagging potential multiuser issues in `PendingIntent.getActivity()` calls. + * + * This detector checks for calls to `PendingIntent#getActivity()` and + * reports a warning if such a call is found, suggesting that the + * default user 0 context might not be the right one. + */ +class PendingIntentGetActivityDetector : Detector(), SourceCodeScanner { + + companion object { + + val description = """Flags potential multiuser issue in PendingIntent.getActivity() calls.""" + + val EXPLANATION = + """ + **Problem:** + + Calling `PendingIntent.getActivity()` in the `system_server` often accidentally uses the user 0 context. Moreover, since there's no explicit user parameter in the `getActivity` method, it can be hard to tell which user the `PendingIntent` activity is associated with, making the code error-prone and less readable. + + **Solution:** + + Always use the user aware methods to refer the correct user context. You can achieve this by: + + * **Using `PendingIntent.getActivityAsUser(...)`:** This API allows you to explicitly specify the user for the activity. + + ```java + PendingIntent.getActivityAsUser( + mContext, /*requestCode=*/0, intent, + PendingIntent.FLAG_IMMUTABLE, /*options=*/null, + UserHandle.of(mUserId)); + ``` + + **When to Ignore this Warning:** + + You can safely ignore this warning if you are certain that: + + * You've confirmed that the `PendingIntent` activity you're targeting is the correct one and is **rightly** associated with the context parameter passed into the `PendingIntent.getActivity` method. + + **Note:** If you are unsure about the user context, it's best to err on the side of caution and explicitly specify the user using the method specified above. + + **For any further questions, please reach out to go/multiuser-help.** + """.trimIndent() + + val ISSUE_PENDING_INTENT_GET_ACTIVITY: Issue = + Issue.create( + id = "PendingIntent#getActivity", + briefDescription = description, + explanation = EXPLANATION, + category = Category.SECURITY, + priority = 8, + severity = Severity.WARNING, + implementation = + Implementation( + PendingIntentGetActivityDetector::class.java, + EnumSet.of(Scope.JAVA_FILE, Scope.TEST_SOURCES), + ), + ) + } + + override fun getApplicableMethodNames() = listOf("getActivity") + + override fun visitMethodCall(context: JavaContext, node: UCallExpression, method: PsiMethod) { + // Check if the method call is PendingIntent.getActivity + if ( + context.evaluator.isMemberInClass(method, "android.app.PendingIntent") && + method.name == "getActivity" + ) { + context.report( + ISSUE_PENDING_INTENT_GET_ACTIVITY, + node, + context.getLocation(node), + "Using `PendingIntent.getActivity(...)` might not be multiuser-aware. " + + "Consider using the user aware method `PendingIntent.getActivityAsUser(...)`.", + ) + } + } +} diff --git a/tools/lint/framework/checks/src/test/java/com/google/android/lint/multiuser/PendingIntentGetActivityDetectorTest.kt b/tools/lint/framework/checks/src/test/java/com/google/android/lint/multiuser/PendingIntentGetActivityDetectorTest.kt new file mode 100644 index 000000000000..401055055232 --- /dev/null +++ b/tools/lint/framework/checks/src/test/java/com/google/android/lint/multiuser/PendingIntentGetActivityDetectorTest.kt @@ -0,0 +1,173 @@ +/* + * Copyright (C) 2025 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. + */ +package com.google.android.lint.multiuser + +import com.android.tools.lint.checks.infrastructure.LintDetectorTest +import com.android.tools.lint.checks.infrastructure.TestFile +import com.android.tools.lint.checks.infrastructure.TestLintTask +import com.android.tools.lint.detector.api.Detector +import com.android.tools.lint.detector.api.Issue + +@Suppress("UnstableApiUsage") +class PendingIntentGetActivityDetectorTest : LintDetectorTest() { + + override fun getDetector(): Detector = PendingIntentGetActivityDetector() + + override fun getIssues(): List<Issue> = + listOf(PendingIntentGetActivityDetector.ISSUE_PENDING_INTENT_GET_ACTIVITY) + + override fun lint(): TestLintTask = super.lint().allowMissingSdk(true) + + fun testPendingIntentGetActivity() { + lint() + .files( + java( + """ + package test.pkg; + + import android.app.PendingIntent; + import android.content.Context; + import android.content.Intent; + + public class TestClass { + private Context mContext; + + public void testMethod(Intent intent) { + PendingIntent.getActivity( + mContext, /*requestCode=*/0, intent, + PendingIntent.FLAG_IMMUTABLE, /*options=*/null + ); + } + } + """ + ) + .indented(), + *stubs, + ) + .issues(PendingIntentGetActivityDetector.ISSUE_PENDING_INTENT_GET_ACTIVITY) + .run() + .expect( + """ + src/test/pkg/TestClass.java:11: Warning: Using PendingIntent.getActivity(...) might not be multiuser-aware. Consider using the user aware method PendingIntent.getActivityAsUser(...). [PendingIntent#getActivity] + PendingIntent.getActivity( + ^ + 0 errors, 1 warnings + """ + ) + } + + fun testPendingIntentGetActivityAsUser() { + lint() + .files( + java( + """ + package test.pkg; + + import android.app.PendingIntent; + import android.content.Context; + import android.content.Intent; + import android.os.UserHandle; + + public class TestClass { + private Context mContext; + + public void testMethod(Intent intent) { + PendingIntent.getActivityAsUser( + mContext, /*requestCode=*/0, intent, + 0, /*options=*/null, + UserHandle.CURRENT + ); + } + } + """ + ) + .indented(), + *stubs, + ) + .issues(PendingIntentGetActivityDetector.ISSUE_PENDING_INTENT_GET_ACTIVITY) + .run() + .expectClean() + } + + private val pendingIntentStub: TestFile = + java( + """ + package android.app; + + import android.content.Context; + import android.content.Intent; + import android.os.UserHandle; + + public class PendingIntent { + public static boolean getActivity(Context context, int requestCode, Intent intent, int flags) { + return true; + } + + public static boolean getActivityAsUser( + Context context, + int requestCode, + Intent intent, + int flags, + UserHandle userHandle + ) { + return true; + } + } + """ + ) + + private val contxtStub: TestFile = + java( + """ + package android.content; + + import android.os.UserHandle; + + public class Context { + + public Context createContextAsUser(UserHandle userHandle, int flags) { + return this; + } + } + + """ + ) + + private val userHandleStub: TestFile = + java( + """ + package android.os; + + public class UserHandle { + + } + + """ + ) + + private val intentStub: TestFile = + java( + """ + package android.content; + + public class Intent { + + } + """ + ) + + private val stubs = arrayOf(pendingIntentStub, contxtStub, userHandleStub, intentStub) +} |