summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--AconfigFlags.bp14
-rw-r--r--Android.bp10
-rw-r--r--apex/jobscheduler/framework/java/android/os/PowerExemptionManager.java9
-rw-r--r--cmds/idmap2/libidmap2/RawPrintVisitor.cpp2
-rw-r--r--core/api/current.txt720
-rw-r--r--core/api/module-lib-current.txt10
-rw-r--r--core/api/module-lib-lint-baseline.txt12
-rw-r--r--core/api/system-current.txt645
-rw-r--r--core/api/system-lint-baseline.txt10
-rw-r--r--core/api/system-removed.txt14
-rw-r--r--core/api/test-current.txt107
-rw-r--r--core/api/test-lint-baseline.txt52
-rw-r--r--core/java/android/app/IUriGrantsManager.aidl3
-rw-r--r--core/java/android/app/WindowConfiguration.java17
-rw-r--r--core/java/android/app/usage/flags.aconfig9
-rw-r--r--core/java/android/companion/virtual/VirtualDeviceParams.java100
-rw-r--r--core/java/android/content/Intent.java10
-rw-r--r--core/java/android/content/pm/ArchivedPackageParcel.aidl1
-rw-r--r--core/java/android/content/pm/IPackageArchiverService.aidl3
-rw-r--r--core/java/android/content/pm/PackageArchiver.java52
-rw-r--r--core/java/android/content/pm/parsing/ApkLite.java19
-rw-r--r--core/java/android/content/pm/parsing/PackageLite.java17
-rw-r--r--core/java/android/hardware/camera2/CameraCharacteristics.java2
-rw-r--r--core/java/android/hardware/camera2/CameraDevice.java88
-rw-r--r--core/java/android/hardware/camera2/CaptureRequest.java3
-rw-r--r--core/java/android/hardware/camera2/CaptureResult.java3
-rw-r--r--core/java/android/inputmethodservice/NavigationBarController.java2
-rw-r--r--core/java/android/location/GeocoderParams.java (renamed from location/java/android/location/GeocoderParams.java)0
-rw-r--r--core/java/android/location/Geofence.java (renamed from location/java/android/location/Geofence.java)0
-rw-r--r--core/java/android/location/GnssSignalQuality.java (renamed from location/java/android/location/GnssSignalQuality.java)0
-rw-r--r--core/java/android/location/IFusedGeofenceHardware.aidl (renamed from location/java/android/location/IFusedGeofenceHardware.aidl)0
-rw-r--r--core/java/android/location/IGpsGeofenceHardware.aidl (renamed from location/java/android/location/IGpsGeofenceHardware.aidl)0
-rw-r--r--core/java/android/location/Location.aidl (renamed from location/java/android/location/Location.aidl)0
-rw-r--r--core/java/android/location/Location.java (renamed from location/java/android/location/Location.java)0
-rw-r--r--core/java/android/location/LocationTime.java (renamed from location/java/android/location/LocationTime.java)0
-rw-r--r--core/java/android/os/vibrator/flags.aconfig9
-rw-r--r--core/java/android/provider/Settings.java4
-rw-r--r--core/java/android/util/FeatureFlagUtils.java1
-rw-r--r--core/java/android/view/View.java152
-rw-r--r--core/java/android/view/inputmethod/RemoteInputConnectionImpl.java22
-rw-r--r--core/java/android/webkit/WebView.java12
-rw-r--r--core/java/android/webkit/WebViewProvider.java10
-rwxr-xr-xcore/java/android/widget/SearchView.java2
-rw-r--r--core/java/android/window/flags/windowing_sdk.aconfig7
-rw-r--r--core/java/com/android/internal/content/InstallLocationUtils.java6
-rw-r--r--core/java/com/android/internal/policy/DecorView.java3
-rw-r--r--core/java/com/android/internal/util/SettingsWrapper.java36
-rw-r--r--core/res/res/values/config.xml10
-rw-r--r--core/res/res/values/symbols.xml3
-rw-r--r--core/tests/coretests/src/android/app/activity/ActivityThreadTest.java12
-rw-r--r--libs/WindowManager/Jetpack/src/androidx/window/util/ExtensionHelper.java41
-rw-r--r--libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/WindowExtensionsTest.java2
-rw-r--r--libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/util/ExtensionHelperTest.java130
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java2
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java4
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java12
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleData.java13
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleDebugConfig.java13
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java8
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java6
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/compatui/UserAspectRatioSettingsWindowManager.java2
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java9
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DragPositioningCallbackUtilityTest.kt2
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/FluidResizeTaskPositionerTest.kt2
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/VeiledResizeTaskPositionerTest.kt2
-rw-r--r--libs/androidfw/tests/ConfigDescription_test.cpp6
-rw-r--r--libs/androidfw/tests/ResTable_test.cpp2
-rw-r--r--libs/input/PointerController.cpp8
-rw-r--r--libs/input/PointerController.h2
-rw-r--r--location/Android.bp8
-rw-r--r--location/api/current.txt724
-rw-r--r--location/api/module-lib-current.txt10
-rw-r--r--location/api/module-lib-lint-baseline.txt13
-rw-r--r--location/api/system-current.txt645
-rw-r--r--location/api/system-lint-baseline.txt11
-rw-r--r--location/api/system-removed.txt14
-rw-r--r--location/api/test-current.txt103
-rw-r--r--location/api/test-lint-baseline.txt54
-rw-r--r--location/java/Android.bp17
-rw-r--r--media/java/android/media/AudioManager.java4
-rw-r--r--media/java/android/media/RingtoneManager.java60
-rw-r--r--packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/CustomizedAppBar.kt12
-rw-r--r--packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/SearchScaffold.kt4
-rw-r--r--packages/SettingsProvider/src/android/provider/settings/backup/SystemSettings.java2
-rw-r--r--packages/SettingsProvider/src/android/provider/settings/validators/SystemSettingsValidators.java2
-rw-r--r--packages/SystemUI/Android.bp2
-rw-r--r--packages/SystemUI/compose/features/src/com/android/systemui/qs/footer/ui/compose/FooterActions.kt3
-rw-r--r--packages/SystemUI/res-keyguard/layout-land/keyguard_pin_view.xml25
-rw-r--r--packages/SystemUI/res-keyguard/layout-sw600dp-land/keyguard_pin_view.xml25
-rw-r--r--packages/SystemUI/res-keyguard/layout/keyguard_pin_view.xml203
-rw-r--r--packages/SystemUI/res-keyguard/layout/keyguard_pin_view_landscape.xml231
-rw-r--r--packages/SystemUI/res-keyguard/layout/keyguard_pin_view_portrait.xml218
-rw-r--r--packages/SystemUI/res/values-sw600dp/bools.xml8
-rw-r--r--packages/SystemUI/res/values/bools.xml8
-rw-r--r--packages/SystemUI/res/values/config.xml8
-rw-r--r--packages/SystemUI/res/values/ids.xml3
-rw-r--r--packages/SystemUI/res/xml/media_session_expanded.xml4
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardInputView.java5
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java14
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardSecurityViewFlipper.java8
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardSecurityViewFlipperController.java40
-rw-r--r--packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractor.kt7
-rw-r--r--packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModel.kt7
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/FalsingModule.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/communal/ui/view/layout/blueprints/DefaultCommunalBlueprint.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/communal/ui/view/layout/sections/DefaultCommunalWidgetSection.kt9
-rw-r--r--packages/SystemUI/src/com/android/systemui/controls/ui/ThumbnailBehavior.kt5
-rw-r--r--packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/display/data/repository/DisplayRepository.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/flags/Flags.kt35
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/shared/model/KeyguardBlueprint.kt31
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/shared/model/KeyguardSection.kt34
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBlueprintViewBinder.kt29
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/blueprints/DefaultKeyguardBlueprint.kt9
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/blueprints/ShortcutsBesideUdfpsKeyguardBlueprint.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/AlignShortcutsToUdfpsSection.kt76
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/BaseShortcutsSection.kt101
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultAmbientIndicationAreaSection.kt21
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultIndicationAreaSection.kt16
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultLockIconSection.kt28
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultNotificationStackScrollLayoutSection.kt32
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultSettingsPopupMenuSection.kt32
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultShortcutsSection.kt76
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultStatusViewSection.kt38
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/Extensions.kt8
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/SplitShadeGuidelines.kt7
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java14
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSFragment.java11
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/scene/KeyguardlessSceneContainerFrameworkModule.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/scene/SceneContainerFrameworkModule.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/scene/ShadelessSceneContainerFrameworkModule.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt12
-rw-r--r--packages/SystemUI/src/com/android/systemui/scene/shared/flag/SceneContainerFlags.kt136
-rw-r--r--packages/SystemUI/src/com/android/systemui/scene/shared/logger/SceneLogger.kt13
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/ShadeViewProviderModule.kt12
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/data/repository/ShadeRepository.kt56
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractor.kt34
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt14
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java37
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewController.kt91
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarTouchableRegionManager.java7
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.kt49
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityViewFlipperControllerTest.java5
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/communal/ui/view/layout/blueprints/DefaultCommunalBlueprintTest.kt2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/controls/ui/TemperatureControlBehaviorTest.kt98
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/CustomizationProviderTest.kt1
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorTest.kt8
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/OccludingAppDeviceEntryInteractorTest.kt1
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/blueprints/DefaultKeyguardBlueprintTest.kt31
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultIndicationAreaSectionTest.kt21
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultLockIconSectionTest.kt21
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardQuickAffordancesCombinedViewModelTest.kt1
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/recents/OverviewProxyServiceTest.kt2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt6
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt8
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/scene/shared/flag/SceneContainerFlagsTest.kt96
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotPolicyImplTest.kt8
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java1
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerBaseTest.java5
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/shade/data/repository/ShadeInteractorTest.kt59
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/shade/data/repository/ShadeRepositoryImplTest.kt31
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt8
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelTest.kt30
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java5
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewControllerTest.kt98
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogImplTest.java3
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/SysuiTestCase.java4
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorFactory.kt6
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneTestUtils.kt15
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/scene/shared/flag/FakeSceneContainerFlags.kt30
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/shade/data/repository/FakeShadeRepository.kt17
-rw-r--r--services/autofill/Android.bp15
-rw-r--r--services/autofill/bugfixes.aconfig8
-rw-r--r--services/autofill/features.aconfig1
-rw-r--r--services/autofill/java/com/android/server/autofill/AutofillManagerServiceShellCommand.java49
-rw-r--r--services/companion/java/com/android/server/companion/virtual/GenericWindowPolicyController.java113
-rw-r--r--services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java43
-rw-r--r--services/core/java/com/android/server/display/BrightnessMappingStrategy.java43
-rw-r--r--services/core/java/com/android/server/display/DisplayManagerService.java16
-rw-r--r--services/core/java/com/android/server/display/LogicalDisplayMapper.java31
-rw-r--r--services/core/java/com/android/server/display/SmallAreaDetectionController.java177
-rw-r--r--services/core/java/com/android/server/inputmethod/InputMethodManagerService.java20
-rw-r--r--services/core/java/com/android/server/notification/flags.aconfig7
-rw-r--r--services/core/java/com/android/server/pm/DeletePackageHelper.java7
-rw-r--r--services/core/java/com/android/server/pm/InstallPackageHelper.java8
-rw-r--r--services/core/java/com/android/server/pm/InstallRequest.java5
-rw-r--r--services/core/java/com/android/server/pm/PackageArchiverService.java229
-rw-r--r--services/core/java/com/android/server/pm/PackageInstallerSession.java36
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java2
-rw-r--r--services/core/java/com/android/server/pm/PackageMetrics.java2
-rw-r--r--services/core/java/com/android/server/pm/PackageRemovedInfo.java7
-rw-r--r--services/core/java/com/android/server/pm/PackageSetting.java2
-rw-r--r--services/core/java/com/android/server/pm/RemovePackageHelper.java14
-rw-r--r--services/core/java/com/android/server/pm/Settings.java7
-rw-r--r--services/core/java/com/android/server/pm/flags.aconfig8
-rw-r--r--services/core/java/com/android/server/pm/pkg/PackageUserState.java7
-rw-r--r--services/core/java/com/android/server/pm/pkg/PackageUserStateDefault.java5
-rw-r--r--services/core/java/com/android/server/pm/pkg/PackageUserStateImpl.java4
-rw-r--r--services/core/java/com/android/server/pm/pkg/PackageUserStateUtils.java34
-rw-r--r--services/core/java/com/android/server/pm/pkg/parsing/ParsingPackageUtils.java3
-rw-r--r--services/core/java/com/android/server/policy/PhoneWindowManager.java42
-rw-r--r--services/core/java/com/android/server/uri/UriGrantsManagerService.java42
-rw-r--r--services/core/java/com/android/server/utils/FoldSettingProvider.java102
-rw-r--r--services/core/java/com/android/server/utils/FoldSettingWrapper.java48
-rw-r--r--services/core/java/com/android/server/wm/ActivityTaskManagerService.java2
-rw-r--r--services/core/java/com/android/server/wm/Dimmer.java20
-rw-r--r--services/core/java/com/android/server/wm/DisplayContent.java22
-rw-r--r--services/core/java/com/android/server/wm/DisplayPolicy.java5
-rw-r--r--services/core/java/com/android/server/wm/DisplayRotation.java4
-rw-r--r--services/core/java/com/android/server/wm/LetterboxConfiguration.java4
-rw-r--r--services/core/java/com/android/server/wm/RootWindowContainer.java4
-rw-r--r--services/core/java/com/android/server/wm/Task.java5
-rw-r--r--services/core/java/com/android/server/wm/Transition.java9
-rw-r--r--services/core/java/com/android/server/wm/WindowContainer.java7
-rw-r--r--services/core/java/com/android/server/wm/WindowState.java35
-rw-r--r--services/core/java/com/android/server/wm/WindowToken.java12
-rw-r--r--services/core/jni/Android.bp1
-rw-r--r--services/core/jni/com_android_server_display_SmallAreaDetectionController.cpp67
-rw-r--r--services/core/jni/com_android_server_input_InputManagerService.cpp9
-rw-r--r--services/core/jni/onload.cpp2
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/RemoteBugreportManager.java31
-rw-r--r--services/tests/InputMethodSystemServerTests/src/com/android/inputmethodservice/InputMethodServiceTest.java20
-rw-r--r--services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageManagerServiceTest.java12
-rw-r--r--services/tests/displayservicetests/Android.bp1
-rw-r--r--services/tests/displayservicetests/src/com/android/server/display/AutomaticBrightnessControllerTest.java20
-rw-r--r--services/tests/displayservicetests/src/com/android/server/display/BrightnessMappingStrategyTest.java14
-rw-r--r--services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java11
-rw-r--r--services/tests/displayservicetests/src/com/android/server/display/LogicalDisplayMapperTest.java54
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/display/SmallAreaDetectionControllerTest.java138
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/pm/PackageArchiverServiceTest.java177
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/utils/FoldSettingProviderTest.java143
-rw-r--r--services/tests/servicestests/src/com/android/server/companion/virtual/audio/VirtualAudioControllerTest.java10
-rw-r--r--services/tests/wmtests/src/com/android/server/policy/ShortcutLoggingTests.java6
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java13
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java4
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/LetterboxConfigurationPersisterTest.java2
-rw-r--r--telecomm/java/android/telecom/CallEndpoint.java2
-rw-r--r--telephony/java/android/telephony/CarrierConfigManager.java6
-rw-r--r--tests/ChoreographerTests/src/main/java/android/view/choreographertests/AttachedChoreographerTest.java2
-rw-r--r--tools/hoststubgen/.gitignore3
-rw-r--r--tools/hoststubgen/README.md76
-rw-r--r--tools/hoststubgen/TEST_MAPPING6
-rw-r--r--tools/hoststubgen/common.sh116
-rw-r--r--tools/hoststubgen/hoststubgen/.gitignore1
-rw-r--r--tools/hoststubgen/hoststubgen/Android.bp303
-rw-r--r--tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestClassLoadHook.java38
-rw-r--r--tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestKeep.java43
-rw-r--r--tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestNativeSubstitutionClass.java35
-rw-r--r--tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestRemove.java39
-rw-r--r--tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestStub.java43
-rw-r--r--tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestSubstitute.java40
-rw-r--r--tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestThrow.java36
-rw-r--r--tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestWholeClassKeep.java34
-rw-r--r--tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestWholeClassStub.java35
-rw-r--r--tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/tests/HostSideTestSuppress.java31
-rw-r--r--tools/hoststubgen/hoststubgen/framework-policy-override.txt98
-rw-r--r--tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/android/test/AndroidTestCase.java27
-rw-r--r--tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/annotation/NonNull.java40
-rw-r--r--tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/annotation/Nullable.java47
-rw-r--r--tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/ext/junit/runners/AndroidJUnit4.java30
-rw-r--r--tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/filters/FlakyTest.java46
-rw-r--r--tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/filters/LargeTest.java44
-rw-r--r--tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/filters/MediumTest.java45
-rw-r--r--tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/filters/RequiresDevice.java30
-rw-r--r--tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/filters/SdkSuppress.java47
-rw-r--r--tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/filters/SmallTest.java46
-rw-r--r--tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/filters/Suppress.java36
-rw-r--r--tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/runner/AndroidJUnit4.java24
-rw-r--r--tools/hoststubgen/hoststubgen/helper-framework-runtime-src/framework/com/android/hoststubgen/nativesubstitution/Log_host.java61
-rw-r--r--tools/hoststubgen/hoststubgen/helper-framework-runtime-src/framework/com/android/hoststubgen/nativesubstitution/Parcel_host.java404
-rw-r--r--tools/hoststubgen/hoststubgen/helper-framework-runtime-src/framework/com/android/hoststubgen/nativesubstitution/SystemProperties_host.java56
-rw-r--r--tools/hoststubgen/hoststubgen/helper-framework-runtime-src/framework/com/android/hoststubgen/runtimehelper/ClassLoadHook.java182
-rw-r--r--tools/hoststubgen/hoststubgen/helper-framework-runtime-src/libcore-fake/dalvik/system/VMRuntime.java45
-rw-r--r--tools/hoststubgen/hoststubgen/helper-framework-runtime-src/libcore-fake/libcore/util/EmptyArray.java54
-rw-r--r--tools/hoststubgen/hoststubgen/helper-framework-runtime-src/libcore-fake/libcore/util/SneakyThrow.java33
-rw-r--r--tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostStubGenProcessedKeepClass.java34
-rw-r--r--tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostStubGenProcessedStubClass.java34
-rw-r--r--tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostTestException.java26
-rw-r--r--tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostTestSuite.java102
-rw-r--r--tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostTestUtils.java197
-rw-r--r--tools/hoststubgen/hoststubgen/hoststubgen-standard-options.txt39
-rw-r--r--tools/hoststubgen/hoststubgen/jarjar-rules.txt2
-rw-r--r--tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/Exceptions.kt48
-rw-r--r--tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGen.kt402
-rw-r--r--tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenErrors.kt24
-rw-r--r--tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenLogger.kt198
-rw-r--r--tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenOptions.kt307
-rw-r--r--tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/Main.kt55
-rw-r--r--tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/Utils.kt33
-rw-r--r--tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/asm/AsmUtils.kt177
-rw-r--r--tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/asm/ClassNodes.kt149
-rw-r--r--tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/AnnotationBasedFilter.kt401
-rw-r--r--tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/ClassWidePolicyPropagatingFilter.kt80
-rw-r--r--tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/ConstantFilter.kt69
-rw-r--r--tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/DelegatingFilter.kt72
-rw-r--r--tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/FilterPolicy.kt133
-rw-r--r--tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/FilterPolicyWithReason.kt66
-rw-r--r--tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/ImplicitOutputFilter.kt86
-rw-r--r--tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/InMemoryOutputFilter.kt138
-rw-r--r--tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/KeepAllClassesFilter.kt30
-rw-r--r--tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/OutputFilter.kt81
-rw-r--r--tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/StubIntersectingFilter.kt91
-rw-r--r--tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/TextFileFilterPolicyParser.kt213
-rw-r--r--tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/BaseAdapter.kt252
-rw-r--r--tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/BodyReplacingMethodVisitor.kt354
-rw-r--r--tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/ImplGeneratingAdapter.kt370
-rw-r--r--tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/StubGeneratingAdapter.kt85
-rw-r--r--tools/hoststubgen/hoststubgen/test-framework/Android.bp19
-rw-r--r--tools/hoststubgen/hoststubgen/test-framework/AndroidHostTest.bp44
-rw-r--r--tools/hoststubgen/hoststubgen/test-framework/AndroidTest-host.xml29
-rw-r--r--tools/hoststubgen/hoststubgen/test-framework/README.md27
-rwxr-xr-xtools/hoststubgen/hoststubgen/test-framework/run-test-without-atest.sh85
-rw-r--r--tools/hoststubgen/hoststubgen/test-framework/src/com/android/hoststubgen/frameworktest/ArrayMapTest.java737
-rw-r--r--tools/hoststubgen/hoststubgen/test-framework/src/com/android/hoststubgen/frameworktest/LogTest.java48
-rw-r--r--tools/hoststubgen/hoststubgen/test-tiny-framework/Android.bp141
-rw-r--r--tools/hoststubgen/hoststubgen/test-tiny-framework/AndroidTest-host.xml29
-rw-r--r--tools/hoststubgen/hoststubgen/test-tiny-framework/README.md27
-rwxr-xr-xtools/hoststubgen/hoststubgen/test-tiny-framework/diff-and-update-golden.sh134
-rw-r--r--tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/01-hoststubgen-test-tiny-framework-orig-dump.txt1671
-rw-r--r--tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/02-hoststubgen-test-tiny-framework-host-stub-dump.txt837
-rw-r--r--tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/03-hoststubgen-test-tiny-framework-host-impl-dump.txt1774
-rw-r--r--tools/hoststubgen/hoststubgen/test-tiny-framework/policy-override-tiny-framework.txt17
-rwxr-xr-xtools/hoststubgen/hoststubgen/test-tiny-framework/run-test-manually.sh132
-rwxr-xr-xtools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework-dump-test.py64
-rw-r--r--tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck.java57
-rw-r--r--tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations.java89
-rw-r--r--tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations.java74
-rw-r--r--tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassLoadHook.java33
-rw-r--r--tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializer.java30
-rw-r--r--tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkExceptionTester.java29
-rw-r--r--tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy.java66
-rw-r--r--tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkNative.java35
-rw-r--r--tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.java31
-rw-r--r--tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses.java87
-rw-r--r--tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-test/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkBenchmark.java70
-rw-r--r--tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-test/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassTest.java143
-rw-r--r--tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-test/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithAnnotTest.java66
-rw-r--r--tools/hoststubgen/scripts/Android.bp26
-rwxr-xr-xtools/hoststubgen/scripts/build-framework-hostside-jars-and-extract.sh35
-rwxr-xr-xtools/hoststubgen/scripts/build-framework-hostside-jars-without-genrules.sh76
-rwxr-xr-xtools/hoststubgen/scripts/dump-jar163
-rwxr-xr-xtools/hoststubgen/scripts/run-all-tests.sh45
-rwxr-xr-xtools/hoststubgen/scripts/run-ravenwood-test129
346 files changed, 19107 insertions, 3353 deletions
diff --git a/AconfigFlags.bp b/AconfigFlags.bp
index 9a417e9da3dd..aabe87f9787e 100644
--- a/AconfigFlags.bp
+++ b/AconfigFlags.bp
@@ -18,6 +18,7 @@ java_defaults {
// Add java_aconfig_libraries to here to add them to the core framework
srcs: [
+ ":android.app.usage.flags-aconfig-java{.generated_srcjars}",
":android.os.flags-aconfig-java{.generated_srcjars}",
":android.os.vibrator.flags-aconfig-java{.generated_srcjars}",
":android.security.flags-aconfig-java{.generated_srcjars}",
@@ -106,6 +107,19 @@ java_aconfig_library {
defaults: ["framework-minus-apex-aconfig-java-defaults"],
}
+// UsageStats
+aconfig_declarations {
+ name: "android.app.usage.flags-aconfig",
+ package: "android.app.usage",
+ srcs: ["core/java/android/app/usage/*.aconfig"],
+}
+
+java_aconfig_library {
+ name: "android.app.usage.flags-aconfig-java",
+ aconfig_declarations: "android.app.usage.flags-aconfig",
+ defaults: ["framework-minus-apex-aconfig-java-defaults"],
+}
+
// OS
aconfig_declarations {
name: "android.os.flags-aconfig",
diff --git a/Android.bp b/Android.bp
index 431f0b9317ac..57a5a3c6bff1 100644
--- a/Android.bp
+++ b/Android.bp
@@ -71,7 +71,6 @@ filegroup {
":framework-jobscheduler-sources", // jobscheduler is not a module for R
":framework-keystore-sources",
":framework-identity-sources",
- ":framework-location-sources",
":framework-mca-effect-sources",
":framework-mca-filterfw-sources",
":framework-mca-filterpacks-sources",
@@ -163,6 +162,12 @@ java_library {
//same purpose.
"//external/robolectric:__subpackages__",
"//frameworks/layoutlib:__subpackages__",
+
+ // This is for the same purpose as robolectric -- to build "framework.jar" for host-side
+ // testing.
+ // TODO: Once Ravenwood is stable, move the host side jar targets to this directory,
+ // and remove this line.
+ "//frameworks/base/tools/hoststubgen:__subpackages__",
],
}
@@ -177,7 +182,6 @@ java_defaults {
"graphics/java",
"identity/java",
"keystore/java",
- "location/java",
"media/java",
"media/mca/effect/java",
"media/mca/filterfw/java",
@@ -287,7 +291,6 @@ java_defaults {
":framework-jobscheduler-sources",
":framework-keystore-sources",
":framework-identity-sources",
- ":framework-location-sources",
":framework-mca-effect-sources",
":framework-mca-filterfw-sources",
":framework-mca-filterpacks-sources",
@@ -405,6 +408,7 @@ java_defaults {
"audiopolicy-aidl-java",
"sounddose-aidl-java",
"modules-utils-expresslog",
+ "hoststubgen-annotations",
],
}
diff --git a/apex/jobscheduler/framework/java/android/os/PowerExemptionManager.java b/apex/jobscheduler/framework/java/android/os/PowerExemptionManager.java
index 17076bc4eea4..66c1efca0000 100644
--- a/apex/jobscheduler/framework/java/android/os/PowerExemptionManager.java
+++ b/apex/jobscheduler/framework/java/android/os/PowerExemptionManager.java
@@ -419,6 +419,14 @@ public class PowerExemptionManager {
*/
public static final int REASON_SYSTEM_EXEMPT_APP_OP = 327;
+ /**
+ * Granted by {@link com.android.server.pm.PackageArchiverService} to the installer responsible
+ * for unarchiving an app.
+ *
+ * @hide
+ */
+ public static final int REASON_PACKAGE_UNARCHIVE = 328;
+
/** @hide The app requests out-out. */
public static final int REASON_OPT_OUT_REQUESTED = 1000;
@@ -502,6 +510,7 @@ public class PowerExemptionManager {
REASON_ACTIVE_DEVICE_ADMIN,
REASON_MEDIA_NOTIFICATION_TRANSFER,
REASON_PACKAGE_INSTALLER,
+ REASON_PACKAGE_UNARCHIVE,
})
@Retention(RetentionPolicy.SOURCE)
public @interface ReasonCode {}
diff --git a/cmds/idmap2/libidmap2/RawPrintVisitor.cpp b/cmds/idmap2/libidmap2/RawPrintVisitor.cpp
index 174d85c71828..9d04a7f87400 100644
--- a/cmds/idmap2/libidmap2/RawPrintVisitor.cpp
+++ b/cmds/idmap2/libidmap2/RawPrintVisitor.cpp
@@ -96,7 +96,7 @@ void RawPrintVisitor::visit(const IdmapData& data ATTRIBUTE_UNUSED) {
auto value = target_entry_value.second;
print(target_entry_value.first.to_string(), false, "config: %s",
- target_entry_value.first.toString().string());
+ target_entry_value.first.toString().c_str());
print(value.data_type, "type: %s",
utils::DataTypeToString(value.data_type).data());
diff --git a/core/api/current.txt b/core/api/current.txt
index 9f323e2d4d6d..0e5a5157c090 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -20415,513 +20415,6 @@ package android.inputmethodservice {
package android.location {
- public class Address implements android.os.Parcelable {
- ctor public Address(java.util.Locale);
- method public void clearLatitude();
- method public void clearLongitude();
- method public int describeContents();
- method public String getAddressLine(int);
- method public String getAdminArea();
- method public String getCountryCode();
- method public String getCountryName();
- method public android.os.Bundle getExtras();
- method public String getFeatureName();
- method public double getLatitude();
- method public java.util.Locale getLocale();
- method public String getLocality();
- method public double getLongitude();
- method public int getMaxAddressLineIndex();
- method public String getPhone();
- method public String getPostalCode();
- method public String getPremises();
- method public String getSubAdminArea();
- method public String getSubLocality();
- method public String getSubThoroughfare();
- method public String getThoroughfare();
- method public String getUrl();
- method public boolean hasLatitude();
- method public boolean hasLongitude();
- method public void setAddressLine(int, String);
- method public void setAdminArea(String);
- method public void setCountryCode(String);
- method public void setCountryName(String);
- method public void setExtras(android.os.Bundle);
- method public void setFeatureName(String);
- method public void setLatitude(double);
- method public void setLocality(String);
- method public void setLongitude(double);
- method public void setPhone(String);
- method public void setPostalCode(String);
- method public void setPremises(String);
- method public void setSubAdminArea(String);
- method public void setSubLocality(String);
- method public void setSubThoroughfare(String);
- method public void setThoroughfare(String);
- method public void setUrl(String);
- method public void writeToParcel(android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.location.Address> CREATOR;
- }
-
- @Deprecated public class Criteria implements android.os.Parcelable {
- ctor @Deprecated public Criteria();
- ctor @Deprecated public Criteria(android.location.Criteria);
- method @Deprecated public int describeContents();
- method @Deprecated public int getAccuracy();
- method @Deprecated public int getBearingAccuracy();
- method @Deprecated public int getHorizontalAccuracy();
- method @Deprecated public int getPowerRequirement();
- method @Deprecated public int getSpeedAccuracy();
- method @Deprecated public int getVerticalAccuracy();
- method @Deprecated public boolean isAltitudeRequired();
- method @Deprecated public boolean isBearingRequired();
- method @Deprecated public boolean isCostAllowed();
- method @Deprecated public boolean isSpeedRequired();
- method @Deprecated public void setAccuracy(int);
- method @Deprecated public void setAltitudeRequired(boolean);
- method @Deprecated public void setBearingAccuracy(int);
- method @Deprecated public void setBearingRequired(boolean);
- method @Deprecated public void setCostAllowed(boolean);
- method @Deprecated public void setHorizontalAccuracy(int);
- method @Deprecated public void setPowerRequirement(int);
- method @Deprecated public void setSpeedAccuracy(int);
- method @Deprecated public void setSpeedRequired(boolean);
- method @Deprecated public void setVerticalAccuracy(int);
- method @Deprecated public void writeToParcel(android.os.Parcel, int);
- field @Deprecated public static final int ACCURACY_COARSE = 2; // 0x2
- field @Deprecated public static final int ACCURACY_FINE = 1; // 0x1
- field @Deprecated public static final int ACCURACY_HIGH = 3; // 0x3
- field @Deprecated public static final int ACCURACY_LOW = 1; // 0x1
- field @Deprecated public static final int ACCURACY_MEDIUM = 2; // 0x2
- field @Deprecated @NonNull public static final android.os.Parcelable.Creator<android.location.Criteria> CREATOR;
- field @Deprecated public static final int NO_REQUIREMENT = 0; // 0x0
- field @Deprecated public static final int POWER_HIGH = 3; // 0x3
- field @Deprecated public static final int POWER_LOW = 1; // 0x1
- field @Deprecated public static final int POWER_MEDIUM = 2; // 0x2
- }
-
- public final class Geocoder {
- ctor public Geocoder(@NonNull android.content.Context);
- ctor public Geocoder(@NonNull android.content.Context, @NonNull java.util.Locale);
- method @Deprecated @Nullable public java.util.List<android.location.Address> getFromLocation(@FloatRange(from=-90.0, to=90.0) double, @FloatRange(from=-180.0, to=180.0) double, @IntRange int) throws java.io.IOException;
- method public void getFromLocation(@FloatRange(from=-90.0, to=90.0) double, @FloatRange(from=-180.0, to=180.0) double, @IntRange int, @NonNull android.location.Geocoder.GeocodeListener);
- method @Deprecated @Nullable public java.util.List<android.location.Address> getFromLocationName(@NonNull String, @IntRange int) throws java.io.IOException;
- method public void getFromLocationName(@NonNull String, @IntRange int, @NonNull android.location.Geocoder.GeocodeListener);
- method @Deprecated @Nullable public java.util.List<android.location.Address> getFromLocationName(@NonNull String, @IntRange int, @FloatRange(from=-90.0, to=90.0) double, @FloatRange(from=-180.0, to=180.0) double, @FloatRange(from=-90.0, to=90.0) double, @FloatRange(from=-180.0, to=180.0) double) throws java.io.IOException;
- method public void getFromLocationName(@NonNull String, @IntRange int, @FloatRange(from=-90.0, to=90.0) double, @FloatRange(from=-180.0, to=180.0) double, @FloatRange(from=-90.0, to=90.0) double, @FloatRange(from=-180.0, to=180.0) double, @NonNull android.location.Geocoder.GeocodeListener);
- method public static boolean isPresent();
- }
-
- public static interface Geocoder.GeocodeListener {
- method public default void onError(@Nullable String);
- method public void onGeocode(@NonNull java.util.List<android.location.Address>);
- }
-
- public final class GnssAntennaInfo implements android.os.Parcelable {
- method public int describeContents();
- method @FloatRange(from=0.0f) public double getCarrierFrequencyMHz();
- method @NonNull public android.location.GnssAntennaInfo.PhaseCenterOffset getPhaseCenterOffset();
- method @Nullable public android.location.GnssAntennaInfo.SphericalCorrections getPhaseCenterVariationCorrections();
- method @Nullable public android.location.GnssAntennaInfo.SphericalCorrections getSignalGainCorrections();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.location.GnssAntennaInfo> CREATOR;
- }
-
- public static class GnssAntennaInfo.Builder {
- ctor @Deprecated public GnssAntennaInfo.Builder();
- ctor public GnssAntennaInfo.Builder(double, @NonNull android.location.GnssAntennaInfo.PhaseCenterOffset);
- ctor public GnssAntennaInfo.Builder(@NonNull android.location.GnssAntennaInfo);
- method @NonNull public android.location.GnssAntennaInfo build();
- method @NonNull public android.location.GnssAntennaInfo.Builder setCarrierFrequencyMHz(@FloatRange(from=0.0f) double);
- method @NonNull public android.location.GnssAntennaInfo.Builder setPhaseCenterOffset(@NonNull android.location.GnssAntennaInfo.PhaseCenterOffset);
- method @NonNull public android.location.GnssAntennaInfo.Builder setPhaseCenterVariationCorrections(@Nullable android.location.GnssAntennaInfo.SphericalCorrections);
- method @NonNull public android.location.GnssAntennaInfo.Builder setSignalGainCorrections(@Nullable android.location.GnssAntennaInfo.SphericalCorrections);
- }
-
- public static interface GnssAntennaInfo.Listener {
- method public void onGnssAntennaInfoReceived(@NonNull java.util.List<android.location.GnssAntennaInfo>);
- }
-
- public static final class GnssAntennaInfo.PhaseCenterOffset implements android.os.Parcelable {
- ctor public GnssAntennaInfo.PhaseCenterOffset(double, double, double, double, double, double);
- method public int describeContents();
- method @FloatRange public double getXOffsetMm();
- method @FloatRange public double getXOffsetUncertaintyMm();
- method @FloatRange public double getYOffsetMm();
- method @FloatRange public double getYOffsetUncertaintyMm();
- method @FloatRange public double getZOffsetMm();
- method @FloatRange public double getZOffsetUncertaintyMm();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.location.GnssAntennaInfo.PhaseCenterOffset> CREATOR;
- }
-
- public static final class GnssAntennaInfo.SphericalCorrections implements android.os.Parcelable {
- ctor public GnssAntennaInfo.SphericalCorrections(@NonNull double[][], @NonNull double[][]);
- method public int describeContents();
- method @NonNull public double[][] getCorrectionUncertaintiesArray();
- method @NonNull public double[][] getCorrectionsArray();
- method @FloatRange(from=0.0f, to=180.0f) public double getDeltaPhi();
- method @FloatRange(from=0.0f, to=360.0f) public double getDeltaTheta();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.location.GnssAntennaInfo.SphericalCorrections> CREATOR;
- }
-
- public final class GnssAutomaticGainControl implements android.os.Parcelable {
- method public int describeContents();
- method @IntRange(from=0) public long getCarrierFrequencyHz();
- method public int getConstellationType();
- method @FloatRange(from=0xffffd8f0, to=10000) public double getLevelDb();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.location.GnssAutomaticGainControl> CREATOR;
- }
-
- public static final class GnssAutomaticGainControl.Builder {
- ctor public GnssAutomaticGainControl.Builder();
- ctor public GnssAutomaticGainControl.Builder(@NonNull android.location.GnssAutomaticGainControl);
- method @NonNull public android.location.GnssAutomaticGainControl build();
- method @NonNull public android.location.GnssAutomaticGainControl.Builder setCarrierFrequencyHz(@IntRange(from=0) long);
- method @NonNull public android.location.GnssAutomaticGainControl.Builder setConstellationType(int);
- method @NonNull public android.location.GnssAutomaticGainControl.Builder setLevelDb(@FloatRange(from=0xffffd8f0, to=10000) double);
- }
-
- public final class GnssCapabilities implements android.os.Parcelable {
- method public int describeContents();
- method @NonNull public java.util.List<android.location.GnssSignalType> getGnssSignalTypes();
- method public int hasAccumulatedDeltaRange();
- method public boolean hasAntennaInfo();
- method public boolean hasGeofencing();
- method @Deprecated public boolean hasGnssAntennaInfo();
- method public boolean hasLowPowerMode();
- method public boolean hasMeasurementCorrections();
- method public boolean hasMeasurementCorrectionsExcessPathLength();
- method public boolean hasMeasurementCorrectionsForDriving();
- method public boolean hasMeasurementCorrectionsLosSats();
- method public boolean hasMeasurementCorrectionsReflectingPlane();
- method public boolean hasMeasurementCorrelationVectors();
- method public boolean hasMeasurements();
- method public boolean hasMsa();
- method public boolean hasMsb();
- method public boolean hasNavigationMessages();
- method public boolean hasOnDemandTime();
- method public boolean hasPowerMultibandAcquisition();
- method public boolean hasPowerMultibandTracking();
- method public boolean hasPowerOtherModes();
- method public boolean hasPowerSinglebandAcquisition();
- method public boolean hasPowerSinglebandTracking();
- method public boolean hasPowerTotal();
- method public boolean hasSatelliteBlocklist();
- method public boolean hasSatellitePvt();
- method public boolean hasScheduling();
- method public boolean hasSingleShotFix();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field public static final int CAPABILITY_SUPPORTED = 1; // 0x1
- field public static final int CAPABILITY_UNKNOWN = 0; // 0x0
- field public static final int CAPABILITY_UNSUPPORTED = 2; // 0x2
- field @NonNull public static final android.os.Parcelable.Creator<android.location.GnssCapabilities> CREATOR;
- }
-
- public static final class GnssCapabilities.Builder {
- ctor public GnssCapabilities.Builder();
- ctor public GnssCapabilities.Builder(@NonNull android.location.GnssCapabilities);
- method @NonNull public android.location.GnssCapabilities build();
- method @NonNull public android.location.GnssCapabilities.Builder setGnssSignalTypes(@NonNull java.util.List<android.location.GnssSignalType>);
- method @NonNull public android.location.GnssCapabilities.Builder setHasAccumulatedDeltaRange(int);
- method @NonNull public android.location.GnssCapabilities.Builder setHasAntennaInfo(boolean);
- method @NonNull public android.location.GnssCapabilities.Builder setHasGeofencing(boolean);
- method @NonNull public android.location.GnssCapabilities.Builder setHasLowPowerMode(boolean);
- method @NonNull public android.location.GnssCapabilities.Builder setHasMeasurementCorrections(boolean);
- method @NonNull public android.location.GnssCapabilities.Builder setHasMeasurementCorrectionsExcessPathLength(boolean);
- method @NonNull public android.location.GnssCapabilities.Builder setHasMeasurementCorrectionsForDriving(boolean);
- method @NonNull public android.location.GnssCapabilities.Builder setHasMeasurementCorrectionsLosSats(boolean);
- method @NonNull public android.location.GnssCapabilities.Builder setHasMeasurementCorrectionsReflectingPlane(boolean);
- method @NonNull public android.location.GnssCapabilities.Builder setHasMeasurementCorrelationVectors(boolean);
- method @NonNull public android.location.GnssCapabilities.Builder setHasMeasurements(boolean);
- method @NonNull public android.location.GnssCapabilities.Builder setHasMsa(boolean);
- method @NonNull public android.location.GnssCapabilities.Builder setHasMsb(boolean);
- method @NonNull public android.location.GnssCapabilities.Builder setHasNavigationMessages(boolean);
- method @NonNull public android.location.GnssCapabilities.Builder setHasOnDemandTime(boolean);
- method @NonNull public android.location.GnssCapabilities.Builder setHasPowerMultibandAcquisition(boolean);
- method @NonNull public android.location.GnssCapabilities.Builder setHasPowerMultibandTracking(boolean);
- method @NonNull public android.location.GnssCapabilities.Builder setHasPowerOtherModes(boolean);
- method @NonNull public android.location.GnssCapabilities.Builder setHasPowerSinglebandAcquisition(boolean);
- method @NonNull public android.location.GnssCapabilities.Builder setHasPowerSinglebandTracking(boolean);
- method @NonNull public android.location.GnssCapabilities.Builder setHasPowerTotal(boolean);
- method @NonNull public android.location.GnssCapabilities.Builder setHasSatelliteBlocklist(boolean);
- method @NonNull public android.location.GnssCapabilities.Builder setHasSatellitePvt(boolean);
- method @NonNull public android.location.GnssCapabilities.Builder setHasScheduling(boolean);
- method @NonNull public android.location.GnssCapabilities.Builder setHasSingleShotFix(boolean);
- }
-
- public final class GnssClock implements android.os.Parcelable {
- method public int describeContents();
- method public double getBiasNanos();
- method @FloatRange(from=0.0f) public double getBiasUncertaintyNanos();
- method public double getDriftNanosPerSecond();
- method @FloatRange(from=0.0f) public double getDriftUncertaintyNanosPerSecond();
- method public long getElapsedRealtimeNanos();
- method @FloatRange(from=0.0f) public double getElapsedRealtimeUncertaintyNanos();
- method public long getFullBiasNanos();
- method public int getHardwareClockDiscontinuityCount();
- method public int getLeapSecond();
- method @FloatRange(from=0.0) public double getReferenceCarrierFrequencyHzForIsb();
- method @NonNull public String getReferenceCodeTypeForIsb();
- method public int getReferenceConstellationTypeForIsb();
- method public long getTimeNanos();
- method @FloatRange(from=0.0f) public double getTimeUncertaintyNanos();
- method public boolean hasBiasNanos();
- method public boolean hasBiasUncertaintyNanos();
- method public boolean hasDriftNanosPerSecond();
- method public boolean hasDriftUncertaintyNanosPerSecond();
- method public boolean hasElapsedRealtimeNanos();
- method public boolean hasElapsedRealtimeUncertaintyNanos();
- method public boolean hasFullBiasNanos();
- method public boolean hasLeapSecond();
- method public boolean hasReferenceCarrierFrequencyHzForIsb();
- method public boolean hasReferenceCodeTypeForIsb();
- method public boolean hasReferenceConstellationTypeForIsb();
- method public boolean hasTimeUncertaintyNanos();
- method public void writeToParcel(android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.location.GnssClock> CREATOR;
- }
-
- public final class GnssMeasurement implements android.os.Parcelable {
- method public int describeContents();
- method public double getAccumulatedDeltaRangeMeters();
- method public int getAccumulatedDeltaRangeState();
- method public double getAccumulatedDeltaRangeUncertaintyMeters();
- method @Deprecated public double getAutomaticGainControlLevelDb();
- method @FloatRange(from=0, to=63) public double getBasebandCn0DbHz();
- method @Deprecated public long getCarrierCycles();
- method public float getCarrierFrequencyHz();
- method @Deprecated public double getCarrierPhase();
- method @Deprecated public double getCarrierPhaseUncertainty();
- method @FloatRange(from=0, to=63) public double getCn0DbHz();
- method @NonNull public String getCodeType();
- method public int getConstellationType();
- method public double getFullInterSignalBiasNanos();
- method @FloatRange(from=0.0) public double getFullInterSignalBiasUncertaintyNanos();
- method public int getMultipathIndicator();
- method public double getPseudorangeRateMetersPerSecond();
- method public double getPseudorangeRateUncertaintyMetersPerSecond();
- method public long getReceivedSvTimeNanos();
- method public long getReceivedSvTimeUncertaintyNanos();
- method public double getSatelliteInterSignalBiasNanos();
- method @FloatRange(from=0.0) public double getSatelliteInterSignalBiasUncertaintyNanos();
- method public double getSnrInDb();
- method public int getState();
- method public int getSvid();
- method public double getTimeOffsetNanos();
- method @Deprecated public boolean hasAutomaticGainControlLevelDb();
- method public boolean hasBasebandCn0DbHz();
- method @Deprecated public boolean hasCarrierCycles();
- method public boolean hasCarrierFrequencyHz();
- method @Deprecated public boolean hasCarrierPhase();
- method @Deprecated public boolean hasCarrierPhaseUncertainty();
- method public boolean hasCodeType();
- method public boolean hasFullInterSignalBiasNanos();
- method public boolean hasFullInterSignalBiasUncertaintyNanos();
- method public boolean hasSatelliteInterSignalBiasNanos();
- method public boolean hasSatelliteInterSignalBiasUncertaintyNanos();
- method public boolean hasSnrInDb();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final int ADR_STATE_CYCLE_SLIP = 4; // 0x4
- field public static final int ADR_STATE_HALF_CYCLE_REPORTED = 16; // 0x10
- field public static final int ADR_STATE_HALF_CYCLE_RESOLVED = 8; // 0x8
- field public static final int ADR_STATE_RESET = 2; // 0x2
- field public static final int ADR_STATE_UNKNOWN = 0; // 0x0
- field public static final int ADR_STATE_VALID = 1; // 0x1
- field @NonNull public static final android.os.Parcelable.Creator<android.location.GnssMeasurement> CREATOR;
- field public static final int MULTIPATH_INDICATOR_DETECTED = 1; // 0x1
- field public static final int MULTIPATH_INDICATOR_NOT_DETECTED = 2; // 0x2
- field public static final int MULTIPATH_INDICATOR_UNKNOWN = 0; // 0x0
- field public static final int STATE_2ND_CODE_LOCK = 65536; // 0x10000
- field public static final int STATE_BDS_D2_BIT_SYNC = 256; // 0x100
- field public static final int STATE_BDS_D2_SUBFRAME_SYNC = 512; // 0x200
- field public static final int STATE_BIT_SYNC = 2; // 0x2
- field public static final int STATE_CODE_LOCK = 1; // 0x1
- field public static final int STATE_GAL_E1BC_CODE_LOCK = 1024; // 0x400
- field public static final int STATE_GAL_E1B_PAGE_SYNC = 4096; // 0x1000
- field public static final int STATE_GAL_E1C_2ND_CODE_LOCK = 2048; // 0x800
- field public static final int STATE_GLO_STRING_SYNC = 64; // 0x40
- field public static final int STATE_GLO_TOD_DECODED = 128; // 0x80
- field public static final int STATE_GLO_TOD_KNOWN = 32768; // 0x8000
- field public static final int STATE_MSEC_AMBIGUOUS = 16; // 0x10
- field public static final int STATE_SBAS_SYNC = 8192; // 0x2000
- field public static final int STATE_SUBFRAME_SYNC = 4; // 0x4
- field public static final int STATE_SYMBOL_SYNC = 32; // 0x20
- field public static final int STATE_TOW_DECODED = 8; // 0x8
- field public static final int STATE_TOW_KNOWN = 16384; // 0x4000
- field public static final int STATE_UNKNOWN = 0; // 0x0
- }
-
- public final class GnssMeasurementRequest implements android.os.Parcelable {
- method public int describeContents();
- method @IntRange(from=0) public int getIntervalMillis();
- method public boolean isFullTracking();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.location.GnssMeasurementRequest> CREATOR;
- field public static final int PASSIVE_INTERVAL = 2147483647; // 0x7fffffff
- }
-
- public static final class GnssMeasurementRequest.Builder {
- ctor public GnssMeasurementRequest.Builder();
- ctor public GnssMeasurementRequest.Builder(@NonNull android.location.GnssMeasurementRequest);
- method @NonNull public android.location.GnssMeasurementRequest build();
- method @NonNull public android.location.GnssMeasurementRequest.Builder setFullTracking(boolean);
- method @NonNull public android.location.GnssMeasurementRequest.Builder setIntervalMillis(@IntRange(from=0) int);
- }
-
- public final class GnssMeasurementsEvent implements android.os.Parcelable {
- method public int describeContents();
- method @NonNull public android.location.GnssClock getClock();
- method @NonNull public java.util.Collection<android.location.GnssAutomaticGainControl> getGnssAutomaticGainControls();
- method @NonNull public java.util.Collection<android.location.GnssMeasurement> getMeasurements();
- method public boolean hasIsFullTracking();
- method public boolean isFullTracking();
- method public void writeToParcel(android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.location.GnssMeasurementsEvent> CREATOR;
- }
-
- public static final class GnssMeasurementsEvent.Builder {
- ctor public GnssMeasurementsEvent.Builder();
- ctor public GnssMeasurementsEvent.Builder(@NonNull android.location.GnssMeasurementsEvent);
- method @NonNull public android.location.GnssMeasurementsEvent build();
- method @NonNull public android.location.GnssMeasurementsEvent.Builder clearIsFullTracking();
- method @NonNull public android.location.GnssMeasurementsEvent.Builder setClock(@NonNull android.location.GnssClock);
- method @NonNull public android.location.GnssMeasurementsEvent.Builder setGnssAutomaticGainControls(@NonNull java.util.Collection<android.location.GnssAutomaticGainControl>);
- method @NonNull public android.location.GnssMeasurementsEvent.Builder setIsFullTracking(boolean);
- method @NonNull public android.location.GnssMeasurementsEvent.Builder setMeasurements(@NonNull java.util.Collection<android.location.GnssMeasurement>);
- }
-
- public abstract static class GnssMeasurementsEvent.Callback {
- ctor public GnssMeasurementsEvent.Callback();
- method public void onGnssMeasurementsReceived(android.location.GnssMeasurementsEvent);
- method @Deprecated public void onStatusChanged(int);
- field @Deprecated public static final int STATUS_LOCATION_DISABLED = 2; // 0x2
- field @Deprecated public static final int STATUS_NOT_ALLOWED = 3; // 0x3
- field @Deprecated public static final int STATUS_NOT_SUPPORTED = 0; // 0x0
- field @Deprecated public static final int STATUS_READY = 1; // 0x1
- }
-
- public final class GnssNavigationMessage implements android.os.Parcelable {
- method public int describeContents();
- method @NonNull public byte[] getData();
- method @IntRange(from=0xffffffff, to=120) public int getMessageId();
- method public int getStatus();
- method @IntRange(from=1) public int getSubmessageId();
- method @IntRange(from=1, to=200) public int getSvid();
- method public int getType();
- method public void writeToParcel(android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.location.GnssNavigationMessage> CREATOR;
- field public static final int STATUS_PARITY_PASSED = 1; // 0x1
- field public static final int STATUS_PARITY_REBUILT = 2; // 0x2
- field public static final int STATUS_UNKNOWN = 0; // 0x0
- field public static final int TYPE_BDS_CNAV1 = 1283; // 0x503
- field public static final int TYPE_BDS_CNAV2 = 1284; // 0x504
- field public static final int TYPE_BDS_D1 = 1281; // 0x501
- field public static final int TYPE_BDS_D2 = 1282; // 0x502
- field public static final int TYPE_GAL_F = 1538; // 0x602
- field public static final int TYPE_GAL_I = 1537; // 0x601
- field public static final int TYPE_GLO_L1CA = 769; // 0x301
- field public static final int TYPE_GPS_CNAV2 = 260; // 0x104
- field public static final int TYPE_GPS_L1CA = 257; // 0x101
- field public static final int TYPE_GPS_L2CNAV = 258; // 0x102
- field public static final int TYPE_GPS_L5CNAV = 259; // 0x103
- field public static final int TYPE_IRN_L5CA = 1793; // 0x701
- field public static final int TYPE_QZS_L1CA = 1025; // 0x401
- field public static final int TYPE_SBS = 513; // 0x201
- field public static final int TYPE_UNKNOWN = 0; // 0x0
- }
-
- public abstract static class GnssNavigationMessage.Callback {
- ctor public GnssNavigationMessage.Callback();
- method public void onGnssNavigationMessageReceived(android.location.GnssNavigationMessage);
- method @Deprecated public void onStatusChanged(int);
- field @Deprecated public static final int STATUS_LOCATION_DISABLED = 2; // 0x2
- field @Deprecated public static final int STATUS_NOT_SUPPORTED = 0; // 0x0
- field @Deprecated public static final int STATUS_READY = 1; // 0x1
- }
-
- public final class GnssSignalType implements android.os.Parcelable {
- method @NonNull public static android.location.GnssSignalType create(int, @FloatRange(from=0.0f, fromInclusive=false) double, @NonNull String);
- method public int describeContents();
- method @FloatRange(from=0.0f, fromInclusive=false) public double getCarrierFrequencyHz();
- method @NonNull public String getCodeType();
- method public int getConstellationType();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.location.GnssSignalType> CREATOR;
- }
-
- public final class GnssStatus implements android.os.Parcelable {
- method public int describeContents();
- method @FloatRange(from=0, to=360) public float getAzimuthDegrees(@IntRange(from=0) int);
- method @FloatRange(from=0, to=63) public float getBasebandCn0DbHz(@IntRange(from=0) int);
- method @FloatRange(from=0) public float getCarrierFrequencyHz(@IntRange(from=0) int);
- method @FloatRange(from=0, to=63) public float getCn0DbHz(@IntRange(from=0) int);
- method public int getConstellationType(@IntRange(from=0) int);
- method @FloatRange(from=0xffffffa6, to=90) public float getElevationDegrees(@IntRange(from=0) int);
- method @IntRange(from=0) public int getSatelliteCount();
- method @IntRange(from=1, to=206) public int getSvid(@IntRange(from=0) int);
- method public boolean hasAlmanacData(@IntRange(from=0) int);
- method public boolean hasBasebandCn0DbHz(@IntRange(from=0) int);
- method public boolean hasCarrierFrequencyHz(@IntRange(from=0) int);
- method public boolean hasEphemerisData(@IntRange(from=0) int);
- method public boolean usedInFix(@IntRange(from=0) int);
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field public static final int CONSTELLATION_BEIDOU = 5; // 0x5
- field public static final int CONSTELLATION_GALILEO = 6; // 0x6
- field public static final int CONSTELLATION_GLONASS = 3; // 0x3
- field public static final int CONSTELLATION_GPS = 1; // 0x1
- field public static final int CONSTELLATION_IRNSS = 7; // 0x7
- field public static final int CONSTELLATION_QZSS = 4; // 0x4
- field public static final int CONSTELLATION_SBAS = 2; // 0x2
- field public static final int CONSTELLATION_UNKNOWN = 0; // 0x0
- field @NonNull public static final android.os.Parcelable.Creator<android.location.GnssStatus> CREATOR;
- }
-
- public static final class GnssStatus.Builder {
- ctor public GnssStatus.Builder();
- method @NonNull public android.location.GnssStatus.Builder addSatellite(int, @IntRange(from=1, to=200) int, @FloatRange(from=0, to=63) float, @FloatRange(from=0xffffffa6, to=90) float, @FloatRange(from=0, to=360) float, boolean, boolean, boolean, boolean, @FloatRange(from=0) float, boolean, @FloatRange(from=0, to=63) float);
- method @NonNull public android.location.GnssStatus build();
- method @NonNull public android.location.GnssStatus.Builder clearSatellites();
- }
-
- public abstract static class GnssStatus.Callback {
- ctor public GnssStatus.Callback();
- method public void onFirstFix(int);
- method public void onSatelliteStatusChanged(@NonNull android.location.GnssStatus);
- method public void onStarted();
- method public void onStopped();
- }
-
- @Deprecated public final class GpsSatellite {
- method @Deprecated public float getAzimuth();
- method @Deprecated public float getElevation();
- method @Deprecated public int getPrn();
- method @Deprecated public float getSnr();
- method @Deprecated public boolean hasAlmanac();
- method @Deprecated public boolean hasEphemeris();
- method @Deprecated public boolean usedInFix();
- }
-
- @Deprecated public final class GpsStatus {
- method @Deprecated @NonNull public static android.location.GpsStatus create(@NonNull android.location.GnssStatus, int);
- method @Deprecated public int getMaxSatellites();
- method @Deprecated public Iterable<android.location.GpsSatellite> getSatellites();
- method @Deprecated public int getTimeToFirstFix();
- field @Deprecated public static final int GPS_EVENT_FIRST_FIX = 3; // 0x3
- field @Deprecated public static final int GPS_EVENT_SATELLITE_STATUS = 4; // 0x4
- field @Deprecated public static final int GPS_EVENT_STARTED = 1; // 0x1
- field @Deprecated public static final int GPS_EVENT_STOPPED = 2; // 0x2
- }
-
- @Deprecated public static interface GpsStatus.Listener {
- method @Deprecated public void onGpsStatusChanged(int);
- }
-
- @Deprecated public static interface GpsStatus.NmeaListener {
- method @Deprecated public void onNmeaReceived(long, String);
- }
-
public class Location implements android.os.Parcelable {
ctor public Location(@Nullable String);
ctor public Location(@NonNull android.location.Location);
@@ -21000,219 +20493,6 @@ package android.location {
field public static final int FORMAT_SECONDS = 2; // 0x2
}
- public interface LocationListener {
- method public default void onFlushComplete(int);
- method public void onLocationChanged(@NonNull android.location.Location);
- method public default void onLocationChanged(@NonNull java.util.List<android.location.Location>);
- method public default void onProviderDisabled(@NonNull String);
- method public default void onProviderEnabled(@NonNull String);
- method @Deprecated public default void onStatusChanged(String, int, android.os.Bundle);
- }
-
- public class LocationManager {
- method @Deprecated @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean addGpsStatusListener(android.location.GpsStatus.Listener);
- method @Deprecated @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean addNmeaListener(@NonNull android.location.GpsStatus.NmeaListener);
- method @Deprecated @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean addNmeaListener(@NonNull android.location.OnNmeaMessageListener);
- method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean addNmeaListener(@NonNull android.location.OnNmeaMessageListener, @Nullable android.os.Handler);
- method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean addNmeaListener(@NonNull java.util.concurrent.Executor, @NonNull android.location.OnNmeaMessageListener);
- method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void addProximityAlert(double, double, float, long, @NonNull android.app.PendingIntent);
- method public void addTestProvider(@NonNull String, boolean, boolean, boolean, boolean, boolean, boolean, boolean, int, int);
- method public void addTestProvider(@NonNull String, @NonNull android.location.provider.ProviderProperties);
- method public void addTestProvider(@NonNull String, @NonNull android.location.provider.ProviderProperties, @NonNull java.util.Set<java.lang.String>);
- method @Deprecated public void clearTestProviderEnabled(@NonNull String);
- method @Deprecated public void clearTestProviderLocation(@NonNull String);
- method @Deprecated public void clearTestProviderStatus(@NonNull String);
- method @NonNull public java.util.List<java.lang.String> getAllProviders();
- method @Deprecated @Nullable public String getBestProvider(@NonNull android.location.Criteria, boolean);
- method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void getCurrentLocation(@NonNull String, @Nullable android.os.CancellationSignal, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.location.Location>);
- method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void getCurrentLocation(@NonNull String, @NonNull android.location.LocationRequest, @Nullable android.os.CancellationSignal, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.location.Location>);
- method @Nullable public java.util.List<android.location.GnssAntennaInfo> getGnssAntennaInfos();
- method @NonNull public android.location.GnssCapabilities getGnssCapabilities();
- method @Nullable public String getGnssHardwareModelName();
- method public int getGnssYearOfHardware();
- method @Deprecated @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public android.location.GpsStatus getGpsStatus(@Nullable android.location.GpsStatus);
- method @Nullable @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public android.location.Location getLastKnownLocation(@NonNull String);
- method @Deprecated @Nullable public android.location.LocationProvider getProvider(@NonNull String);
- method @Nullable public android.location.provider.ProviderProperties getProviderProperties(@NonNull String);
- method @NonNull public java.util.List<java.lang.String> getProviders(boolean);
- method @Deprecated @NonNull public java.util.List<java.lang.String> getProviders(@NonNull android.location.Criteria, boolean);
- method public boolean hasProvider(@NonNull String);
- method public boolean isLocationEnabled();
- method public boolean isProviderEnabled(@NonNull String);
- method public boolean registerAntennaInfoListener(@NonNull java.util.concurrent.Executor, @NonNull android.location.GnssAntennaInfo.Listener);
- method @Deprecated @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean registerGnssMeasurementsCallback(@NonNull android.location.GnssMeasurementsEvent.Callback);
- method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean registerGnssMeasurementsCallback(@NonNull android.location.GnssMeasurementsEvent.Callback, @Nullable android.os.Handler);
- method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean registerGnssMeasurementsCallback(@NonNull java.util.concurrent.Executor, @NonNull android.location.GnssMeasurementsEvent.Callback);
- method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean registerGnssMeasurementsCallback(@NonNull android.location.GnssMeasurementRequest, @NonNull java.util.concurrent.Executor, @NonNull android.location.GnssMeasurementsEvent.Callback);
- method @Deprecated public boolean registerGnssNavigationMessageCallback(@NonNull android.location.GnssNavigationMessage.Callback);
- method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean registerGnssNavigationMessageCallback(@NonNull android.location.GnssNavigationMessage.Callback, @Nullable android.os.Handler);
- method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean registerGnssNavigationMessageCallback(@NonNull java.util.concurrent.Executor, @NonNull android.location.GnssNavigationMessage.Callback);
- method @Deprecated @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean registerGnssStatusCallback(@NonNull android.location.GnssStatus.Callback);
- method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean registerGnssStatusCallback(@NonNull android.location.GnssStatus.Callback, @Nullable android.os.Handler);
- method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean registerGnssStatusCallback(@NonNull java.util.concurrent.Executor, @NonNull android.location.GnssStatus.Callback);
- method @Deprecated public void removeGpsStatusListener(android.location.GpsStatus.Listener);
- method @Deprecated public void removeNmeaListener(@NonNull android.location.GpsStatus.NmeaListener);
- method public void removeNmeaListener(@NonNull android.location.OnNmeaMessageListener);
- method @RequiresPermission(anyOf={"android.permission.ACCESS_COARSE_LOCATION", "android.permission.ACCESS_FINE_LOCATION"}, apis="..22") public void removeProximityAlert(@NonNull android.app.PendingIntent);
- method public void removeTestProvider(@NonNull String);
- method @RequiresPermission(anyOf={"android.permission.ACCESS_COARSE_LOCATION", "android.permission.ACCESS_FINE_LOCATION"}, apis="..22") public void removeUpdates(@NonNull android.location.LocationListener);
- method public void removeUpdates(@NonNull android.app.PendingIntent);
- method public void requestFlush(@NonNull String, @NonNull android.location.LocationListener, int);
- method public void requestFlush(@NonNull String, @NonNull android.app.PendingIntent, int);
- method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@NonNull String, long, float, @NonNull android.location.LocationListener);
- method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@NonNull String, long, float, @NonNull android.location.LocationListener, @Nullable android.os.Looper);
- method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@NonNull String, long, float, @NonNull java.util.concurrent.Executor, @NonNull android.location.LocationListener);
- method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(long, float, @NonNull android.location.Criteria, @NonNull android.location.LocationListener, @Nullable android.os.Looper);
- method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(long, float, @NonNull android.location.Criteria, @NonNull java.util.concurrent.Executor, @NonNull android.location.LocationListener);
- method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@NonNull String, long, float, @NonNull android.app.PendingIntent);
- method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(long, float, @NonNull android.location.Criteria, @NonNull android.app.PendingIntent);
- method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@NonNull String, @NonNull android.location.LocationRequest, @NonNull java.util.concurrent.Executor, @NonNull android.location.LocationListener);
- method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@NonNull String, @NonNull android.location.LocationRequest, @NonNull android.app.PendingIntent);
- method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestSingleUpdate(@NonNull String, @NonNull android.location.LocationListener, @Nullable android.os.Looper);
- method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestSingleUpdate(@NonNull android.location.Criteria, @NonNull android.location.LocationListener, @Nullable android.os.Looper);
- method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestSingleUpdate(@NonNull String, @NonNull android.app.PendingIntent);
- method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestSingleUpdate(@NonNull android.location.Criteria, @NonNull android.app.PendingIntent);
- method public boolean sendExtraCommand(@NonNull String, @NonNull String, @Nullable android.os.Bundle);
- method public void setTestProviderEnabled(@NonNull String, boolean);
- method public void setTestProviderLocation(@NonNull String, @NonNull android.location.Location);
- method @Deprecated public void setTestProviderStatus(@NonNull String, int, @Nullable android.os.Bundle, long);
- method public void unregisterAntennaInfoListener(@NonNull android.location.GnssAntennaInfo.Listener);
- method public void unregisterGnssMeasurementsCallback(@NonNull android.location.GnssMeasurementsEvent.Callback);
- method public void unregisterGnssNavigationMessageCallback(@NonNull android.location.GnssNavigationMessage.Callback);
- method public void unregisterGnssStatusCallback(@NonNull android.location.GnssStatus.Callback);
- field public static final String ACTION_GNSS_CAPABILITIES_CHANGED = "android.location.action.GNSS_CAPABILITIES_CHANGED";
- field public static final String EXTRA_GNSS_CAPABILITIES = "android.location.extra.GNSS_CAPABILITIES";
- field public static final String EXTRA_LOCATION_ENABLED = "android.location.extra.LOCATION_ENABLED";
- field public static final String EXTRA_PROVIDER_ENABLED = "android.location.extra.PROVIDER_ENABLED";
- field public static final String EXTRA_PROVIDER_NAME = "android.location.extra.PROVIDER_NAME";
- field public static final String FUSED_PROVIDER = "fused";
- field public static final String GPS_PROVIDER = "gps";
- field public static final String KEY_FLUSH_COMPLETE = "flushComplete";
- field public static final String KEY_LOCATIONS = "locations";
- field public static final String KEY_LOCATION_CHANGED = "location";
- field public static final String KEY_PROVIDER_ENABLED = "providerEnabled";
- field public static final String KEY_PROXIMITY_ENTERING = "entering";
- field @Deprecated public static final String KEY_STATUS_CHANGED = "status";
- field public static final String MODE_CHANGED_ACTION = "android.location.MODE_CHANGED";
- field public static final String NETWORK_PROVIDER = "network";
- field public static final String PASSIVE_PROVIDER = "passive";
- field public static final String PROVIDERS_CHANGED_ACTION = "android.location.PROVIDERS_CHANGED";
- }
-
- @Deprecated public class LocationProvider {
- method @Deprecated public int getAccuracy();
- method @Deprecated public String getName();
- method @Deprecated public int getPowerRequirement();
- method @Deprecated public boolean hasMonetaryCost();
- method @Deprecated public boolean meetsCriteria(android.location.Criteria);
- method @Deprecated public boolean requiresCell();
- method @Deprecated public boolean requiresNetwork();
- method @Deprecated public boolean requiresSatellite();
- method @Deprecated public boolean supportsAltitude();
- method @Deprecated public boolean supportsBearing();
- method @Deprecated public boolean supportsSpeed();
- field @Deprecated public static final int AVAILABLE = 2; // 0x2
- field @Deprecated public static final int OUT_OF_SERVICE = 0; // 0x0
- field @Deprecated public static final int TEMPORARILY_UNAVAILABLE = 1; // 0x1
- }
-
- public final class LocationRequest implements android.os.Parcelable {
- method public int describeContents();
- method @IntRange(from=1) public long getDurationMillis();
- method @IntRange(from=0) public long getIntervalMillis();
- method @IntRange(from=0) public long getMaxUpdateDelayMillis();
- method @IntRange(from=1, to=java.lang.Integer.MAX_VALUE) public int getMaxUpdates();
- method @FloatRange(from=0, to=java.lang.Float.MAX_VALUE) public float getMinUpdateDistanceMeters();
- method @IntRange(from=0) public long getMinUpdateIntervalMillis();
- method public int getQuality();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.location.LocationRequest> CREATOR;
- field public static final long PASSIVE_INTERVAL = 9223372036854775807L; // 0x7fffffffffffffffL
- field public static final int QUALITY_BALANCED_POWER_ACCURACY = 102; // 0x66
- field public static final int QUALITY_HIGH_ACCURACY = 100; // 0x64
- field public static final int QUALITY_LOW_POWER = 104; // 0x68
- }
-
- public static final class LocationRequest.Builder {
- ctor public LocationRequest.Builder(long);
- ctor public LocationRequest.Builder(@NonNull android.location.LocationRequest);
- method @NonNull public android.location.LocationRequest build();
- method @NonNull public android.location.LocationRequest.Builder clearMinUpdateIntervalMillis();
- method @NonNull public android.location.LocationRequest.Builder setDurationMillis(@IntRange(from=1) long);
- method @NonNull public android.location.LocationRequest.Builder setIntervalMillis(@IntRange(from=0) long);
- method @NonNull public android.location.LocationRequest.Builder setMaxUpdateDelayMillis(@IntRange(from=0) long);
- method @NonNull public android.location.LocationRequest.Builder setMaxUpdates(@IntRange(from=1, to=java.lang.Integer.MAX_VALUE) int);
- method @NonNull public android.location.LocationRequest.Builder setMinUpdateDistanceMeters(@FloatRange(from=0, to=java.lang.Float.MAX_VALUE) float);
- method @NonNull public android.location.LocationRequest.Builder setMinUpdateIntervalMillis(@IntRange(from=0) long);
- method @NonNull public android.location.LocationRequest.Builder setQuality(int);
- }
-
- public interface OnNmeaMessageListener {
- method public void onNmeaMessage(String, long);
- }
-
- public abstract class SettingInjectorService extends android.app.Service {
- ctor public SettingInjectorService(String);
- method public final android.os.IBinder onBind(android.content.Intent);
- method protected abstract boolean onGetEnabled();
- method protected abstract String onGetSummary();
- method public final void onStart(android.content.Intent, int);
- method public final int onStartCommand(android.content.Intent, int, int);
- method public static final void refreshSettings(@NonNull android.content.Context);
- field public static final String ACTION_INJECTED_SETTING_CHANGED = "android.location.InjectedSettingChanged";
- field public static final String ACTION_SERVICE_INTENT = "android.location.SettingInjectorService";
- field public static final String ATTRIBUTES_NAME = "injected-location-setting";
- field public static final String META_DATA_NAME = "android.location.SettingInjectorService";
- }
-
-}
-
-package android.location.altitude {
-
- public final class AltitudeConverter {
- ctor public AltitudeConverter();
- method @WorkerThread public void addMslAltitudeToLocation(@NonNull android.content.Context, @NonNull android.location.Location) throws java.io.IOException;
- }
-
-}
-
-package android.location.provider {
-
- public final class ProviderProperties implements android.os.Parcelable {
- method public int describeContents();
- method public int getAccuracy();
- method public int getPowerUsage();
- method public boolean hasAltitudeSupport();
- method public boolean hasBearingSupport();
- method public boolean hasCellRequirement();
- method public boolean hasMonetaryCost();
- method public boolean hasNetworkRequirement();
- method public boolean hasSatelliteRequirement();
- method public boolean hasSpeedSupport();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field public static final int ACCURACY_COARSE = 2; // 0x2
- field public static final int ACCURACY_FINE = 1; // 0x1
- field @NonNull public static final android.os.Parcelable.Creator<android.location.provider.ProviderProperties> CREATOR;
- field public static final int POWER_USAGE_HIGH = 3; // 0x3
- field public static final int POWER_USAGE_LOW = 1; // 0x1
- field public static final int POWER_USAGE_MEDIUM = 2; // 0x2
- }
-
- public static final class ProviderProperties.Builder {
- ctor public ProviderProperties.Builder();
- ctor public ProviderProperties.Builder(@NonNull android.location.provider.ProviderProperties);
- method @NonNull public android.location.provider.ProviderProperties build();
- method @NonNull public android.location.provider.ProviderProperties.Builder setAccuracy(int);
- method @NonNull public android.location.provider.ProviderProperties.Builder setHasAltitudeSupport(boolean);
- method @NonNull public android.location.provider.ProviderProperties.Builder setHasBearingSupport(boolean);
- method @NonNull public android.location.provider.ProviderProperties.Builder setHasCellRequirement(boolean);
- method @NonNull public android.location.provider.ProviderProperties.Builder setHasMonetaryCost(boolean);
- method @NonNull public android.location.provider.ProviderProperties.Builder setHasNetworkRequirement(boolean);
- method @NonNull public android.location.provider.ProviderProperties.Builder setHasSatelliteRequirement(boolean);
- method @NonNull public android.location.provider.ProviderProperties.Builder setHasSpeedSupport(boolean);
- method @NonNull public android.location.provider.ProviderProperties.Builder setPowerUsage(int);
- }
-
}
package android.media {
diff --git a/core/api/module-lib-current.txt b/core/api/module-lib-current.txt
index e4846b8affd4..3de774868bb7 100644
--- a/core/api/module-lib-current.txt
+++ b/core/api/module-lib-current.txt
@@ -186,16 +186,6 @@ package android.hardware.usb {
}
-package android.location {
-
- public class LocationManager {
- method @RequiresPermission(allOf={android.Manifest.permission.LOCATION_HARDWARE, android.Manifest.permission.ACCESS_FINE_LOCATION}) public boolean injectLocation(@NonNull android.location.Location);
- method @RequiresPermission(android.Manifest.permission.CONTROL_AUTOMOTIVE_GNSS) public boolean isAutomotiveGnssSuspended();
- method @RequiresPermission(android.Manifest.permission.CONTROL_AUTOMOTIVE_GNSS) public void setAutomotiveGnssSuspended(boolean);
- }
-
-}
-
package android.media {
public class AudioManager {
diff --git a/core/api/module-lib-lint-baseline.txt b/core/api/module-lib-lint-baseline.txt
index 27436ce35867..471745ae0c50 100644
--- a/core/api/module-lib-lint-baseline.txt
+++ b/core/api/module-lib-lint-baseline.txt
@@ -17,18 +17,6 @@ SamShouldBeLast: android.content.pm.PackageItemInfo#dumpBack(android.util.Printe
SAM-compatible parameters (such as parameter 1, "pw", in android.content.pm.PackageItemInfo.dumpBack) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
SamShouldBeLast: android.content.pm.PackageItemInfo#dumpFront(android.util.Printer, String):
SAM-compatible parameters (such as parameter 1, "pw", in android.content.pm.PackageItemInfo.dumpFront) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
-SamShouldBeLast: android.location.LocationManager#addNmeaListener(android.location.OnNmeaMessageListener, android.os.Handler):
- SAM-compatible parameters (such as parameter 1, "listener", in android.location.LocationManager.addNmeaListener) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
-SamShouldBeLast: android.location.LocationManager#requestLocationUpdates(String, long, float, android.location.LocationListener, android.os.Looper):
- SAM-compatible parameters (such as parameter 4, "listener", in android.location.LocationManager.requestLocationUpdates) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
-SamShouldBeLast: android.location.LocationManager#requestLocationUpdates(android.location.LocationRequest, android.location.LocationListener, android.os.Looper):
- SAM-compatible parameters (such as parameter 2, "listener", in android.location.LocationManager.requestLocationUpdates) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
-SamShouldBeLast: android.location.LocationManager#requestLocationUpdates(long, float, android.location.Criteria, android.location.LocationListener, android.os.Looper):
- SAM-compatible parameters (such as parameter 4, "listener", in android.location.LocationManager.requestLocationUpdates) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
-SamShouldBeLast: android.location.LocationManager#requestSingleUpdate(String, android.location.LocationListener, android.os.Looper):
- SAM-compatible parameters (such as parameter 2, "listener", in android.location.LocationManager.requestSingleUpdate) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
-SamShouldBeLast: android.location.LocationManager#requestSingleUpdate(android.location.Criteria, android.location.LocationListener, android.os.Looper):
- SAM-compatible parameters (such as parameter 2, "listener", in android.location.LocationManager.requestSingleUpdate) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
SamShouldBeLast: android.media.AudioManager#abandonAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener, android.media.AudioAttributes):
SAM-compatible parameters (such as parameter 1, "l", in android.media.AudioManager.abandonAudioFocus) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
SamShouldBeLast: android.media.AudioManager#requestAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener, android.media.AudioAttributes, int, int):
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index 35a736dc076b..ff44a1b87e18 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -3547,6 +3547,7 @@ package android.content {
field public static final String ACTION_SHOW_SUSPENDED_APP_DETAILS = "android.intent.action.SHOW_SUSPENDED_APP_DETAILS";
field @Deprecated public static final String ACTION_SIM_STATE_CHANGED = "android.intent.action.SIM_STATE_CHANGED";
field public static final String ACTION_SPLIT_CONFIGURATION_CHANGED = "android.intent.action.SPLIT_CONFIGURATION_CHANGED";
+ field public static final String ACTION_UNARCHIVE_PACKAGE = "android.intent.action.UNARCHIVE_PACKAGE";
field public static final String ACTION_UPGRADE_SETUP = "android.intent.action.UPGRADE_SETUP";
field public static final String ACTION_USER_ADDED = "android.intent.action.USER_ADDED";
field public static final String ACTION_USER_REMOVED = "android.intent.action.USER_REMOVED";
@@ -3796,6 +3797,9 @@ package android.content.pm {
public class PackageArchiver {
method @RequiresPermission(anyOf={android.Manifest.permission.DELETE_PACKAGES, android.Manifest.permission.REQUEST_DELETE_PACKAGES}) public void requestArchive(@NonNull String, @NonNull android.content.IntentSender) throws android.content.pm.PackageManager.NameNotFoundException;
+ method @RequiresPermission(anyOf={android.Manifest.permission.INSTALL_PACKAGES, android.Manifest.permission.REQUEST_INSTALL_PACKAGES}) public void requestUnarchive(@NonNull String) throws android.content.pm.PackageManager.NameNotFoundException;
+ field public static final String EXTRA_UNARCHIVE_ALL_USERS = "android.content.pm.extra.UNARCHIVE_ALL_USERS";
+ field public static final String EXTRA_UNARCHIVE_PACKAGE_NAME = "android.content.pm.extra.UNARCHIVE_PACKAGE_NAME";
}
public class PackageInfo implements android.os.Parcelable {
@@ -6178,653 +6182,12 @@ package android.hardware.usb {
package android.location {
- public abstract class BatchedLocationCallback {
- ctor public BatchedLocationCallback();
- method public void onLocationBatch(java.util.List<android.location.Location>);
- }
-
- public final class CorrelationVector implements android.os.Parcelable {
- method public int describeContents();
- method @FloatRange(from=0.0f) public double getFrequencyOffsetMetersPerSecond();
- method @NonNull public int[] getMagnitude();
- method @FloatRange(from=0.0f) public double getSamplingStartMeters();
- method @FloatRange(from=0.0f, fromInclusive=false) public double getSamplingWidthMeters();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.location.CorrelationVector> CREATOR;
- }
-
- public static final class CorrelationVector.Builder {
- ctor public CorrelationVector.Builder();
- method @NonNull public android.location.CorrelationVector build();
- method @NonNull public android.location.CorrelationVector.Builder setFrequencyOffsetMetersPerSecond(@FloatRange(from=0.0f) double);
- method @NonNull public android.location.CorrelationVector.Builder setMagnitude(@NonNull int[]);
- method @NonNull public android.location.CorrelationVector.Builder setSamplingStartMeters(@FloatRange(from=0.0f) double);
- method @NonNull public android.location.CorrelationVector.Builder setSamplingWidthMeters(@FloatRange(from=0.0f, fromInclusive=false) double);
- }
-
- public final class Country implements android.os.Parcelable {
- ctor public Country(@NonNull String, int);
- method public int describeContents();
- method @NonNull public String getCountryCode();
- method public int getSource();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field public static final int COUNTRY_SOURCE_LOCALE = 3; // 0x3
- field public static final int COUNTRY_SOURCE_LOCATION = 1; // 0x1
- field public static final int COUNTRY_SOURCE_NETWORK = 0; // 0x0
- field public static final int COUNTRY_SOURCE_SIM = 2; // 0x2
- field @NonNull public static final android.os.Parcelable.Creator<android.location.Country> CREATOR;
- }
-
- public class CountryDetector {
- method public void registerCountryDetectorCallback(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.location.Country>);
- method public void unregisterCountryDetectorCallback(@NonNull java.util.function.Consumer<android.location.Country>);
- }
-
- public final class GnssCapabilities implements android.os.Parcelable {
- method @Deprecated public boolean hasMeasurementCorrectionsReflectingPane();
- method @Deprecated public boolean hasNavMessages();
- method @Deprecated public boolean hasSatelliteBlacklist();
- }
-
- public final class GnssExcessPathInfo implements android.os.Parcelable {
- method public int describeContents();
- method @FloatRange(from=0.0f) public float getAttenuationDb();
- method @FloatRange(from=0.0f) public float getExcessPathLengthMeters();
- method @FloatRange(from=0.0f) public float getExcessPathLengthUncertaintyMeters();
- method @NonNull public android.location.GnssReflectingPlane getReflectingPlane();
- method public boolean hasAttenuation();
- method public boolean hasExcessPathLength();
- method public boolean hasExcessPathLengthUncertainty();
- method public boolean hasReflectingPlane();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.location.GnssExcessPathInfo> CREATOR;
- }
-
- public static final class GnssExcessPathInfo.Builder {
- ctor public GnssExcessPathInfo.Builder();
- method @NonNull public android.location.GnssExcessPathInfo build();
- method @NonNull public android.location.GnssExcessPathInfo.Builder clearAttenuationDb();
- method @NonNull public android.location.GnssExcessPathInfo.Builder clearExcessPathLengthMeters();
- method @NonNull public android.location.GnssExcessPathInfo.Builder clearExcessPathLengthUncertaintyMeters();
- method @NonNull public android.location.GnssExcessPathInfo.Builder setAttenuationDb(@FloatRange(from=0.0f) float);
- method @NonNull public android.location.GnssExcessPathInfo.Builder setExcessPathLengthMeters(@FloatRange(from=0.0f) float);
- method @NonNull public android.location.GnssExcessPathInfo.Builder setExcessPathLengthUncertaintyMeters(@FloatRange(from=0.0f) float);
- method @NonNull public android.location.GnssExcessPathInfo.Builder setReflectingPlane(@Nullable android.location.GnssReflectingPlane);
- }
-
- public final class GnssMeasurement implements android.os.Parcelable {
- method @Nullable public java.util.Collection<android.location.CorrelationVector> getCorrelationVectors();
- method @Nullable public android.location.SatellitePvt getSatellitePvt();
- method public boolean hasCorrelationVectors();
- method public boolean hasSatellitePvt();
- }
-
- public final class GnssMeasurementCorrections implements android.os.Parcelable {
- method public int describeContents();
- method @FloatRange(from=-1000.0F, to=10000.0f) public double getAltitudeMeters();
- method @FloatRange(from=0.0f, to=360.0f) public float getEnvironmentBearingDegrees();
- method @FloatRange(from=0.0f, to=180.0f) public float getEnvironmentBearingUncertaintyDegrees();
- method @FloatRange(from=0.0f) public double getHorizontalPositionUncertaintyMeters();
- method @FloatRange(from=-90.0F, to=90.0f) public double getLatitudeDegrees();
- method @FloatRange(from=-180.0F, to=180.0f) public double getLongitudeDegrees();
- method @NonNull public java.util.List<android.location.GnssSingleSatCorrection> getSingleSatelliteCorrectionList();
- method @IntRange(from=0) public long getToaGpsNanosecondsOfWeek();
- method @FloatRange(from=0.0f) public double getVerticalPositionUncertaintyMeters();
- method public boolean hasEnvironmentBearing();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.location.GnssMeasurementCorrections> CREATOR;
- }
-
- public static final class GnssMeasurementCorrections.Builder {
- ctor public GnssMeasurementCorrections.Builder();
- method @NonNull public android.location.GnssMeasurementCorrections build();
- method @NonNull public android.location.GnssMeasurementCorrections.Builder setAltitudeMeters(@FloatRange(from=-1000.0F, to=10000.0f) double);
- method @NonNull public android.location.GnssMeasurementCorrections.Builder setEnvironmentBearingDegrees(@FloatRange(from=0.0f, to=360.0f) float);
- method @NonNull public android.location.GnssMeasurementCorrections.Builder setEnvironmentBearingUncertaintyDegrees(@FloatRange(from=0.0f, to=180.0f) float);
- method @NonNull public android.location.GnssMeasurementCorrections.Builder setHorizontalPositionUncertaintyMeters(@FloatRange(from=0.0f) double);
- method @NonNull public android.location.GnssMeasurementCorrections.Builder setLatitudeDegrees(@FloatRange(from=-90.0F, to=90.0f) double);
- method @NonNull public android.location.GnssMeasurementCorrections.Builder setLongitudeDegrees(@FloatRange(from=-180.0F, to=180.0f) double);
- method @NonNull public android.location.GnssMeasurementCorrections.Builder setSingleSatelliteCorrectionList(@NonNull java.util.List<android.location.GnssSingleSatCorrection>);
- method @NonNull public android.location.GnssMeasurementCorrections.Builder setToaGpsNanosecondsOfWeek(@IntRange(from=0) long);
- method @NonNull public android.location.GnssMeasurementCorrections.Builder setVerticalPositionUncertaintyMeters(@FloatRange(from=0.0f) double);
- }
-
- public final class GnssMeasurementRequest implements android.os.Parcelable {
- method @NonNull public android.os.WorkSource getWorkSource();
- method public boolean isCorrelationVectorOutputsEnabled();
- }
-
- public static final class GnssMeasurementRequest.Builder {
- method @NonNull public android.location.GnssMeasurementRequest.Builder setCorrelationVectorOutputsEnabled(boolean);
- method @NonNull @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public android.location.GnssMeasurementRequest.Builder setWorkSource(@Nullable android.os.WorkSource);
- }
-
- public final class GnssReflectingPlane implements android.os.Parcelable {
- method public int describeContents();
- method @FloatRange(from=-1000.0F, to=10000.0f) public double getAltitudeMeters();
- method @FloatRange(from=0.0f, to=360.0f) public double getAzimuthDegrees();
- method @FloatRange(from=-90.0F, to=90.0f) public double getLatitudeDegrees();
- method @FloatRange(from=-180.0F, to=180.0f) public double getLongitudeDegrees();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.location.GnssReflectingPlane> CREATOR;
- }
-
- public static final class GnssReflectingPlane.Builder {
- ctor public GnssReflectingPlane.Builder();
- method @NonNull public android.location.GnssReflectingPlane build();
- method @NonNull public android.location.GnssReflectingPlane.Builder setAltitudeMeters(@FloatRange(from=-1000.0F, to=10000.0f) double);
- method @NonNull public android.location.GnssReflectingPlane.Builder setAzimuthDegrees(@FloatRange(from=0.0f, to=360.0f) double);
- method @NonNull public android.location.GnssReflectingPlane.Builder setLatitudeDegrees(@FloatRange(from=-90.0F, to=90.0f) double);
- method @NonNull public android.location.GnssReflectingPlane.Builder setLongitudeDegrees(@FloatRange(from=-180.0F, to=180.0f) double);
- }
-
- public final class GnssRequest implements android.os.Parcelable {
- method public int describeContents();
- method public boolean isFullTracking();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.location.GnssRequest> CREATOR;
- }
-
- public static final class GnssRequest.Builder {
- ctor public GnssRequest.Builder();
- ctor public GnssRequest.Builder(@NonNull android.location.GnssRequest);
- method @NonNull public android.location.GnssRequest build();
- method @NonNull public android.location.GnssRequest.Builder setFullTracking(boolean);
- }
-
- public final class GnssSingleSatCorrection implements android.os.Parcelable {
- method public int describeContents();
- method @FloatRange(from=0.0f, fromInclusive=false) public float getCarrierFrequencyHz();
- method @FloatRange(from=0.0f) public float getCombinedAttenuationDb();
- method public int getConstellationType();
- method @FloatRange(from=0.0f) public float getExcessPathLengthMeters();
- method @FloatRange(from=0.0f) public float getExcessPathLengthUncertaintyMeters();
- method @NonNull public java.util.List<android.location.GnssExcessPathInfo> getGnssExcessPathInfoList();
- method @FloatRange(from=0.0f, to=1.0f) public float getProbabilityLineOfSight();
- method @Deprecated @Nullable public android.location.GnssReflectingPlane getReflectingPlane();
- method @IntRange(from=0) public int getSatelliteId();
- method public boolean hasCombinedAttenuation();
- method public boolean hasExcessPathLength();
- method public boolean hasExcessPathLengthUncertainty();
- method @Deprecated public boolean hasReflectingPlane();
- method public boolean hasValidSatelliteLineOfSight();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.location.GnssSingleSatCorrection> CREATOR;
- }
-
- public static final class GnssSingleSatCorrection.Builder {
- ctor public GnssSingleSatCorrection.Builder();
- method @NonNull public android.location.GnssSingleSatCorrection build();
- method @NonNull public android.location.GnssSingleSatCorrection.Builder clearCombinedAttenuationDb();
- method @NonNull public android.location.GnssSingleSatCorrection.Builder clearExcessPathLengthMeters();
- method @NonNull public android.location.GnssSingleSatCorrection.Builder clearExcessPathLengthUncertaintyMeters();
- method @NonNull public android.location.GnssSingleSatCorrection.Builder clearProbabilityLineOfSight();
- method @NonNull public android.location.GnssSingleSatCorrection.Builder setCarrierFrequencyHz(@FloatRange(from=0.0f, fromInclusive=false) float);
- method @NonNull public android.location.GnssSingleSatCorrection.Builder setCombinedAttenuationDb(@FloatRange(from=0.0f) float);
- method @NonNull public android.location.GnssSingleSatCorrection.Builder setConstellationType(int);
- method @NonNull public android.location.GnssSingleSatCorrection.Builder setExcessPathLengthMeters(@FloatRange(from=0.0f) float);
- method @NonNull public android.location.GnssSingleSatCorrection.Builder setExcessPathLengthUncertaintyMeters(@FloatRange(from=0.0f) float);
- method @NonNull public android.location.GnssSingleSatCorrection.Builder setGnssExcessPathInfoList(@NonNull java.util.List<android.location.GnssExcessPathInfo>);
- method @NonNull public android.location.GnssSingleSatCorrection.Builder setProbabilityLineOfSight(@FloatRange(from=0.0f, to=1.0f) float);
- method @Deprecated @NonNull public android.location.GnssSingleSatCorrection.Builder setReflectingPlane(@Nullable android.location.GnssReflectingPlane);
- method @NonNull public android.location.GnssSingleSatCorrection.Builder setSatelliteId(@IntRange(from=0) int);
- }
-
- @Deprecated public class GpsClock implements android.os.Parcelable {
- method @Deprecated public int describeContents();
- method @Deprecated public double getBiasInNs();
- method @Deprecated public double getBiasUncertaintyInNs();
- method @Deprecated public double getDriftInNsPerSec();
- method @Deprecated public double getDriftUncertaintyInNsPerSec();
- method @Deprecated public long getFullBiasInNs();
- method @Deprecated public short getLeapSecond();
- method @Deprecated public long getTimeInNs();
- method @Deprecated public double getTimeUncertaintyInNs();
- method @Deprecated public byte getType();
- method @Deprecated public boolean hasBiasInNs();
- method @Deprecated public boolean hasBiasUncertaintyInNs();
- method @Deprecated public boolean hasDriftInNsPerSec();
- method @Deprecated public boolean hasDriftUncertaintyInNsPerSec();
- method @Deprecated public boolean hasFullBiasInNs();
- method @Deprecated public boolean hasLeapSecond();
- method @Deprecated public boolean hasTimeUncertaintyInNs();
- method @Deprecated public void reset();
- method @Deprecated public void resetBiasInNs();
- method @Deprecated public void resetBiasUncertaintyInNs();
- method @Deprecated public void resetDriftInNsPerSec();
- method @Deprecated public void resetDriftUncertaintyInNsPerSec();
- method @Deprecated public void resetFullBiasInNs();
- method @Deprecated public void resetLeapSecond();
- method @Deprecated public void resetTimeUncertaintyInNs();
- method @Deprecated public void set(android.location.GpsClock);
- method @Deprecated public void setBiasInNs(double);
- method @Deprecated public void setBiasUncertaintyInNs(double);
- method @Deprecated public void setDriftInNsPerSec(double);
- method @Deprecated public void setDriftUncertaintyInNsPerSec(double);
- method @Deprecated public void setFullBiasInNs(long);
- method @Deprecated public void setLeapSecond(short);
- method @Deprecated public void setTimeInNs(long);
- method @Deprecated public void setTimeUncertaintyInNs(double);
- method @Deprecated public void setType(byte);
- method @Deprecated public void writeToParcel(android.os.Parcel, int);
- field @Deprecated @NonNull public static final android.os.Parcelable.Creator<android.location.GpsClock> CREATOR;
- field @Deprecated public static final byte TYPE_GPS_TIME = 2; // 0x2
- field @Deprecated public static final byte TYPE_LOCAL_HW_TIME = 1; // 0x1
- field @Deprecated public static final byte TYPE_UNKNOWN = 0; // 0x0
- }
-
- @Deprecated public class GpsMeasurement implements android.os.Parcelable {
- method @Deprecated public int describeContents();
- method @Deprecated public double getAccumulatedDeltaRangeInMeters();
- method @Deprecated public short getAccumulatedDeltaRangeState();
- method @Deprecated public double getAccumulatedDeltaRangeUncertaintyInMeters();
- method @Deprecated public double getAzimuthInDeg();
- method @Deprecated public double getAzimuthUncertaintyInDeg();
- method @Deprecated public int getBitNumber();
- method @Deprecated public long getCarrierCycles();
- method @Deprecated public float getCarrierFrequencyInHz();
- method @Deprecated public double getCarrierPhase();
- method @Deprecated public double getCarrierPhaseUncertainty();
- method @Deprecated public double getCn0InDbHz();
- method @Deprecated public double getCodePhaseInChips();
- method @Deprecated public double getCodePhaseUncertaintyInChips();
- method @Deprecated public double getDopplerShiftInHz();
- method @Deprecated public double getDopplerShiftUncertaintyInHz();
- method @Deprecated public double getElevationInDeg();
- method @Deprecated public double getElevationUncertaintyInDeg();
- method @Deprecated public byte getLossOfLock();
- method @Deprecated public byte getMultipathIndicator();
- method @Deprecated public byte getPrn();
- method @Deprecated public double getPseudorangeInMeters();
- method @Deprecated public double getPseudorangeRateInMetersPerSec();
- method @Deprecated public double getPseudorangeRateUncertaintyInMetersPerSec();
- method @Deprecated public double getPseudorangeUncertaintyInMeters();
- method @Deprecated public long getReceivedGpsTowInNs();
- method @Deprecated public long getReceivedGpsTowUncertaintyInNs();
- method @Deprecated public double getSnrInDb();
- method @Deprecated public short getState();
- method @Deprecated public short getTimeFromLastBitInMs();
- method @Deprecated public double getTimeOffsetInNs();
- method @Deprecated public boolean hasAzimuthInDeg();
- method @Deprecated public boolean hasAzimuthUncertaintyInDeg();
- method @Deprecated public boolean hasBitNumber();
- method @Deprecated public boolean hasCarrierCycles();
- method @Deprecated public boolean hasCarrierFrequencyInHz();
- method @Deprecated public boolean hasCarrierPhase();
- method @Deprecated public boolean hasCarrierPhaseUncertainty();
- method @Deprecated public boolean hasCodePhaseInChips();
- method @Deprecated public boolean hasCodePhaseUncertaintyInChips();
- method @Deprecated public boolean hasDopplerShiftInHz();
- method @Deprecated public boolean hasDopplerShiftUncertaintyInHz();
- method @Deprecated public boolean hasElevationInDeg();
- method @Deprecated public boolean hasElevationUncertaintyInDeg();
- method @Deprecated public boolean hasPseudorangeInMeters();
- method @Deprecated public boolean hasPseudorangeUncertaintyInMeters();
- method @Deprecated public boolean hasSnrInDb();
- method @Deprecated public boolean hasTimeFromLastBitInMs();
- method @Deprecated public boolean isPseudorangeRateCorrected();
- method @Deprecated public boolean isUsedInFix();
- method @Deprecated public void reset();
- method @Deprecated public void resetAzimuthInDeg();
- method @Deprecated public void resetAzimuthUncertaintyInDeg();
- method @Deprecated public void resetBitNumber();
- method @Deprecated public void resetCarrierCycles();
- method @Deprecated public void resetCarrierFrequencyInHz();
- method @Deprecated public void resetCarrierPhase();
- method @Deprecated public void resetCarrierPhaseUncertainty();
- method @Deprecated public void resetCodePhaseInChips();
- method @Deprecated public void resetCodePhaseUncertaintyInChips();
- method @Deprecated public void resetDopplerShiftInHz();
- method @Deprecated public void resetDopplerShiftUncertaintyInHz();
- method @Deprecated public void resetElevationInDeg();
- method @Deprecated public void resetElevationUncertaintyInDeg();
- method @Deprecated public void resetPseudorangeInMeters();
- method @Deprecated public void resetPseudorangeUncertaintyInMeters();
- method @Deprecated public void resetSnrInDb();
- method @Deprecated public void resetTimeFromLastBitInMs();
- method @Deprecated public void set(android.location.GpsMeasurement);
- method @Deprecated public void setAccumulatedDeltaRangeInMeters(double);
- method @Deprecated public void setAccumulatedDeltaRangeState(short);
- method @Deprecated public void setAccumulatedDeltaRangeUncertaintyInMeters(double);
- method @Deprecated public void setAzimuthInDeg(double);
- method @Deprecated public void setAzimuthUncertaintyInDeg(double);
- method @Deprecated public void setBitNumber(int);
- method @Deprecated public void setCarrierCycles(long);
- method @Deprecated public void setCarrierFrequencyInHz(float);
- method @Deprecated public void setCarrierPhase(double);
- method @Deprecated public void setCarrierPhaseUncertainty(double);
- method @Deprecated public void setCn0InDbHz(double);
- method @Deprecated public void setCodePhaseInChips(double);
- method @Deprecated public void setCodePhaseUncertaintyInChips(double);
- method @Deprecated public void setDopplerShiftInHz(double);
- method @Deprecated public void setDopplerShiftUncertaintyInHz(double);
- method @Deprecated public void setElevationInDeg(double);
- method @Deprecated public void setElevationUncertaintyInDeg(double);
- method @Deprecated public void setLossOfLock(byte);
- method @Deprecated public void setMultipathIndicator(byte);
- method @Deprecated public void setPrn(byte);
- method @Deprecated public void setPseudorangeInMeters(double);
- method @Deprecated public void setPseudorangeRateInMetersPerSec(double);
- method @Deprecated public void setPseudorangeRateUncertaintyInMetersPerSec(double);
- method @Deprecated public void setPseudorangeUncertaintyInMeters(double);
- method @Deprecated public void setReceivedGpsTowInNs(long);
- method @Deprecated public void setReceivedGpsTowUncertaintyInNs(long);
- method @Deprecated public void setSnrInDb(double);
- method @Deprecated public void setState(short);
- method @Deprecated public void setTimeFromLastBitInMs(short);
- method @Deprecated public void setTimeOffsetInNs(double);
- method @Deprecated public void setUsedInFix(boolean);
- method @Deprecated public void writeToParcel(android.os.Parcel, int);
- field @Deprecated public static final short ADR_STATE_CYCLE_SLIP = 4; // 0x4
- field @Deprecated public static final short ADR_STATE_RESET = 2; // 0x2
- field @Deprecated public static final short ADR_STATE_UNKNOWN = 0; // 0x0
- field @Deprecated public static final short ADR_STATE_VALID = 1; // 0x1
- field @Deprecated @NonNull public static final android.os.Parcelable.Creator<android.location.GpsMeasurement> CREATOR;
- field @Deprecated public static final byte LOSS_OF_LOCK_CYCLE_SLIP = 2; // 0x2
- field @Deprecated public static final byte LOSS_OF_LOCK_OK = 1; // 0x1
- field @Deprecated public static final byte LOSS_OF_LOCK_UNKNOWN = 0; // 0x0
- field @Deprecated public static final byte MULTIPATH_INDICATOR_DETECTED = 1; // 0x1
- field @Deprecated public static final byte MULTIPATH_INDICATOR_NOT_USED = 2; // 0x2
- field @Deprecated public static final byte MULTIPATH_INDICATOR_UNKNOWN = 0; // 0x0
- field @Deprecated public static final short STATE_BIT_SYNC = 2; // 0x2
- field @Deprecated public static final short STATE_CODE_LOCK = 1; // 0x1
- field @Deprecated public static final short STATE_MSEC_AMBIGUOUS = 16; // 0x10
- field @Deprecated public static final short STATE_SUBFRAME_SYNC = 4; // 0x4
- field @Deprecated public static final short STATE_TOW_DECODED = 8; // 0x8
- field @Deprecated public static final short STATE_UNKNOWN = 0; // 0x0
- }
-
- @Deprecated public class GpsMeasurementsEvent implements android.os.Parcelable {
- ctor @Deprecated public GpsMeasurementsEvent(android.location.GpsClock, android.location.GpsMeasurement[]);
- method @Deprecated public int describeContents();
- method @Deprecated @NonNull public android.location.GpsClock getClock();
- method @Deprecated @NonNull public java.util.Collection<android.location.GpsMeasurement> getMeasurements();
- method @Deprecated public void writeToParcel(android.os.Parcel, int);
- field @Deprecated @NonNull public static final android.os.Parcelable.Creator<android.location.GpsMeasurementsEvent> CREATOR;
- field @Deprecated public static final int STATUS_GPS_LOCATION_DISABLED = 2; // 0x2
- field @Deprecated public static final int STATUS_NOT_SUPPORTED = 0; // 0x0
- field @Deprecated public static final int STATUS_READY = 1; // 0x1
- }
-
- @Deprecated public static interface GpsMeasurementsEvent.Listener {
- method @Deprecated public void onGpsMeasurementsReceived(android.location.GpsMeasurementsEvent);
- method @Deprecated public void onStatusChanged(int);
- }
-
- @Deprecated public class GpsNavigationMessage implements android.os.Parcelable {
- method @Deprecated public int describeContents();
- method @Deprecated @NonNull public byte[] getData();
- method @Deprecated public short getMessageId();
- method @Deprecated public byte getPrn();
- method @Deprecated public short getStatus();
- method @Deprecated public short getSubmessageId();
- method @Deprecated public byte getType();
- method @Deprecated public void reset();
- method @Deprecated public void set(android.location.GpsNavigationMessage);
- method @Deprecated public void setData(byte[]);
- method @Deprecated public void setMessageId(short);
- method @Deprecated public void setPrn(byte);
- method @Deprecated public void setStatus(short);
- method @Deprecated public void setSubmessageId(short);
- method @Deprecated public void setType(byte);
- method @Deprecated public void writeToParcel(android.os.Parcel, int);
- field @Deprecated @NonNull public static final android.os.Parcelable.Creator<android.location.GpsNavigationMessage> CREATOR;
- field @Deprecated public static final short STATUS_PARITY_PASSED = 1; // 0x1
- field @Deprecated public static final short STATUS_PARITY_REBUILT = 2; // 0x2
- field @Deprecated public static final short STATUS_UNKNOWN = 0; // 0x0
- field @Deprecated public static final byte TYPE_CNAV2 = 4; // 0x4
- field @Deprecated public static final byte TYPE_L1CA = 1; // 0x1
- field @Deprecated public static final byte TYPE_L2CNAV = 2; // 0x2
- field @Deprecated public static final byte TYPE_L5CNAV = 3; // 0x3
- field @Deprecated public static final byte TYPE_UNKNOWN = 0; // 0x0
- }
-
- @Deprecated public class GpsNavigationMessageEvent implements android.os.Parcelable {
- ctor @Deprecated public GpsNavigationMessageEvent(android.location.GpsNavigationMessage);
- method @Deprecated public int describeContents();
- method @Deprecated @NonNull public android.location.GpsNavigationMessage getNavigationMessage();
- method @Deprecated public void writeToParcel(android.os.Parcel, int);
- field @Deprecated @NonNull public static final android.os.Parcelable.Creator<android.location.GpsNavigationMessageEvent> CREATOR;
- field @Deprecated public static int STATUS_GPS_LOCATION_DISABLED;
- field @Deprecated public static int STATUS_NOT_SUPPORTED;
- field @Deprecated public static int STATUS_READY;
- }
-
- @Deprecated public static interface GpsNavigationMessageEvent.Listener {
- method @Deprecated public void onGpsNavigationMessageReceived(android.location.GpsNavigationMessageEvent);
- method @Deprecated public void onStatusChanged(int);
- }
-
- public final class LastLocationRequest implements android.os.Parcelable {
- method public int describeContents();
- method public boolean isAdasGnssBypass();
- method public boolean isHiddenFromAppOps();
- method public boolean isLocationSettingsIgnored();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.location.LastLocationRequest> CREATOR;
- }
-
- public static final class LastLocationRequest.Builder {
- ctor public LastLocationRequest.Builder();
- ctor public LastLocationRequest.Builder(@NonNull android.location.LastLocationRequest);
- method @NonNull public android.location.LastLocationRequest build();
- method @NonNull @RequiresPermission(android.Manifest.permission.LOCATION_BYPASS) public android.location.LastLocationRequest.Builder setAdasGnssBypass(boolean);
- method @NonNull @RequiresPermission(android.Manifest.permission.UPDATE_APP_OPS_STATS) public android.location.LastLocationRequest.Builder setHiddenFromAppOps(boolean);
- method @NonNull @RequiresPermission(android.Manifest.permission.LOCATION_BYPASS) public android.location.LastLocationRequest.Builder setLocationSettingsIgnored(boolean);
- }
-
public class Location implements android.os.Parcelable {
method public void makeComplete();
method @Deprecated public void setIsFromMockProvider(boolean);
field @Deprecated public static final String EXTRA_NO_GPS_LOCATION = "noGPSLocation";
}
- public class LocationManager {
- method @RequiresPermission(allOf={android.Manifest.permission.LOCATION_HARDWARE, android.Manifest.permission.INTERACT_ACROSS_USERS}) public void addProviderRequestChangedListener(@NonNull java.util.concurrent.Executor, @NonNull android.location.provider.ProviderRequest.ChangedListener);
- method @Deprecated @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public void flushGnssBatch();
- method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void getCurrentLocation(@NonNull android.location.LocationRequest, @Nullable android.os.CancellationSignal, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.location.Location>);
- method @Nullable public String getExtraLocationControllerPackage();
- method @Deprecated public int getGnssBatchSize();
- method @Nullable @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public android.location.Location getLastKnownLocation(@NonNull String, @NonNull android.location.LastLocationRequest);
- method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public void injectGnssMeasurementCorrections(@NonNull android.location.GnssMeasurementCorrections);
- method public boolean isAdasGnssLocationEnabled();
- method public boolean isExtraLocationControllerPackageEnabled();
- method public boolean isLocationEnabledForUser(@NonNull android.os.UserHandle);
- method public boolean isProviderEnabledForUser(@NonNull String, @NonNull android.os.UserHandle);
- method @Deprecated @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public boolean isProviderPackage(@NonNull String);
- method @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public boolean isProviderPackage(@Nullable String, @NonNull String, @Nullable String);
- method @Deprecated @RequiresPermission(allOf={android.Manifest.permission.LOCATION_HARDWARE, android.Manifest.permission.UPDATE_APP_OPS_STATS}) public boolean registerGnssBatchedLocationCallback(long, boolean, @NonNull android.location.BatchedLocationCallback, @Nullable android.os.Handler);
- method @Deprecated @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean registerGnssMeasurementsCallback(@NonNull android.location.GnssRequest, @NonNull java.util.concurrent.Executor, @NonNull android.location.GnssMeasurementsEvent.Callback);
- method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public void removeProviderRequestChangedListener(@NonNull android.location.provider.ProviderRequest.ChangedListener);
- method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@Nullable android.location.LocationRequest, @NonNull android.location.LocationListener, @Nullable android.os.Looper);
- method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@Nullable android.location.LocationRequest, @NonNull java.util.concurrent.Executor, @NonNull android.location.LocationListener);
- method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@Nullable android.location.LocationRequest, @NonNull android.app.PendingIntent);
- method @RequiresPermission(android.Manifest.permission.LOCATION_BYPASS) public void setAdasGnssLocationEnabled(boolean);
- method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public void setExtraLocationControllerPackage(@Nullable String);
- method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public void setExtraLocationControllerPackageEnabled(boolean);
- method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void setLocationEnabledForUser(boolean, @NonNull android.os.UserHandle);
- method @Deprecated @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean setProviderEnabledForUser(@NonNull String, boolean, @NonNull android.os.UserHandle);
- method @Deprecated @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public boolean unregisterGnssBatchedLocationCallback(@NonNull android.location.BatchedLocationCallback);
- field public static final String ACTION_ADAS_GNSS_ENABLED_CHANGED = "android.location.action.ADAS_GNSS_ENABLED_CHANGED";
- field public static final String EXTRA_ADAS_GNSS_ENABLED = "android.location.extra.ADAS_GNSS_ENABLED";
- field @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public static final String GPS_HARDWARE_PROVIDER = "gps_hardware";
- }
-
- public final class LocationRequest implements android.os.Parcelable {
- method @Deprecated @NonNull public static android.location.LocationRequest create();
- method @Deprecated @NonNull public static android.location.LocationRequest createFromDeprecatedCriteria(@NonNull android.location.Criteria, long, float, boolean);
- method @Deprecated @NonNull public static android.location.LocationRequest createFromDeprecatedProvider(@NonNull String, long, float, boolean);
- method @Deprecated public long getExpireAt();
- method @Deprecated public long getExpireIn();
- method @Deprecated public long getFastestInterval();
- method @Deprecated public boolean getHideFromAppOps();
- method @Deprecated public long getInterval();
- method @Deprecated public int getNumUpdates();
- method @Deprecated @NonNull public String getProvider();
- method @Deprecated public float getSmallestDisplacement();
- method @NonNull public android.os.WorkSource getWorkSource();
- method public boolean isAdasGnssBypass();
- method public boolean isHiddenFromAppOps();
- method public boolean isLocationSettingsIgnored();
- method public boolean isLowPower();
- method @Deprecated public boolean isLowPowerMode();
- method @Deprecated @NonNull public android.location.LocationRequest setExpireAt(long);
- method @Deprecated @NonNull public android.location.LocationRequest setExpireIn(long);
- method @Deprecated @NonNull public android.location.LocationRequest setFastestInterval(long);
- method @Deprecated public void setHideFromAppOps(boolean);
- method @Deprecated @NonNull public android.location.LocationRequest setInterval(long);
- method @Deprecated @NonNull @RequiresPermission(android.Manifest.permission.LOCATION_BYPASS) public android.location.LocationRequest setLocationSettingsIgnored(boolean);
- method @Deprecated @NonNull public android.location.LocationRequest setLowPowerMode(boolean);
- method @Deprecated @NonNull public android.location.LocationRequest setNumUpdates(int);
- method @Deprecated @NonNull public android.location.LocationRequest setProvider(@NonNull String);
- method @Deprecated @NonNull public android.location.LocationRequest setQuality(int);
- method @Deprecated @NonNull public android.location.LocationRequest setSmallestDisplacement(float);
- method @Deprecated public void setWorkSource(@Nullable android.os.WorkSource);
- field @Deprecated public static final int ACCURACY_BLOCK = 102; // 0x66
- field @Deprecated public static final int ACCURACY_CITY = 104; // 0x68
- field @Deprecated public static final int ACCURACY_FINE = 100; // 0x64
- field @Deprecated public static final int POWER_HIGH = 203; // 0xcb
- field @Deprecated public static final int POWER_LOW = 201; // 0xc9
- field @Deprecated public static final int POWER_NONE = 200; // 0xc8
- }
-
- public static final class LocationRequest.Builder {
- method @NonNull @RequiresPermission(android.Manifest.permission.LOCATION_BYPASS) public android.location.LocationRequest.Builder setAdasGnssBypass(boolean);
- method @NonNull @RequiresPermission(android.Manifest.permission.UPDATE_APP_OPS_STATS) public android.location.LocationRequest.Builder setHiddenFromAppOps(boolean);
- method @NonNull @RequiresPermission(android.Manifest.permission.LOCATION_BYPASS) public android.location.LocationRequest.Builder setLocationSettingsIgnored(boolean);
- method @NonNull @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public android.location.LocationRequest.Builder setLowPower(boolean);
- method @NonNull @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public android.location.LocationRequest.Builder setWorkSource(@Nullable android.os.WorkSource);
- }
-
- public final class SatellitePvt implements android.os.Parcelable {
- method public int describeContents();
- method @Nullable public android.location.SatellitePvt.ClockInfo getClockInfo();
- method public int getEphemerisSource();
- method @FloatRange public double getIonoDelayMeters();
- method @IntRange(from=0, to=1023) public int getIssueOfDataClock();
- method @IntRange(from=0, to=1023) public int getIssueOfDataEphemeris();
- method @Nullable public android.location.SatellitePvt.PositionEcef getPositionEcef();
- method @IntRange(from=0) public long getTimeOfClockSeconds();
- method @IntRange(from=0) public long getTimeOfEphemerisSeconds();
- method @FloatRange public double getTropoDelayMeters();
- method @Nullable public android.location.SatellitePvt.VelocityEcef getVelocityEcef();
- method public boolean hasIono();
- method public boolean hasIssueOfDataClock();
- method public boolean hasIssueOfDataEphemeris();
- method public boolean hasPositionVelocityClockInfo();
- method public boolean hasTimeOfClockSeconds();
- method public boolean hasTimeOfEphemerisSeconds();
- method public boolean hasTropo();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.location.SatellitePvt> CREATOR;
- field public static final int EPHEMERIS_SOURCE_DEMODULATED = 0; // 0x0
- field public static final int EPHEMERIS_SOURCE_OTHER = 3; // 0x3
- field public static final int EPHEMERIS_SOURCE_SERVER_LONG_TERM = 2; // 0x2
- field public static final int EPHEMERIS_SOURCE_SERVER_NORMAL = 1; // 0x1
- }
-
- public static final class SatellitePvt.Builder {
- ctor public SatellitePvt.Builder();
- method @NonNull public android.location.SatellitePvt build();
- method @NonNull public android.location.SatellitePvt.Builder setClockInfo(@NonNull android.location.SatellitePvt.ClockInfo);
- method @NonNull public android.location.SatellitePvt.Builder setEphemerisSource(int);
- method @NonNull public android.location.SatellitePvt.Builder setIonoDelayMeters(@FloatRange(from=0.0f, to=100.0f) double);
- method @NonNull public android.location.SatellitePvt.Builder setIssueOfDataClock(@IntRange(from=0, to=1023) int);
- method @NonNull public android.location.SatellitePvt.Builder setIssueOfDataEphemeris(@IntRange(from=0, to=1023) int);
- method @NonNull public android.location.SatellitePvt.Builder setPositionEcef(@NonNull android.location.SatellitePvt.PositionEcef);
- method @NonNull public android.location.SatellitePvt.Builder setTimeOfClockSeconds(@IntRange(from=0) long);
- method @NonNull public android.location.SatellitePvt.Builder setTimeOfEphemerisSeconds(@IntRange(from=0) long);
- method @NonNull public android.location.SatellitePvt.Builder setTropoDelayMeters(@FloatRange(from=0.0f, to=100.0f) double);
- method @NonNull public android.location.SatellitePvt.Builder setVelocityEcef(@NonNull android.location.SatellitePvt.VelocityEcef);
- }
-
- public static final class SatellitePvt.ClockInfo implements android.os.Parcelable {
- ctor public SatellitePvt.ClockInfo(double, double, double);
- method public int describeContents();
- method @FloatRange public double getClockDriftMetersPerSecond();
- method @FloatRange public double getHardwareCodeBiasMeters();
- method @FloatRange public double getTimeCorrectionMeters();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.location.SatellitePvt.ClockInfo> CREATOR;
- }
-
- public static final class SatellitePvt.PositionEcef implements android.os.Parcelable {
- ctor public SatellitePvt.PositionEcef(double, double, double, double);
- method public int describeContents();
- method @FloatRange(from=0.0f, fromInclusive=false) public double getUreMeters();
- method @FloatRange public double getXMeters();
- method @FloatRange public double getYMeters();
- method @FloatRange public double getZMeters();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.location.SatellitePvt.PositionEcef> CREATOR;
- }
-
- public static final class SatellitePvt.VelocityEcef implements android.os.Parcelable {
- ctor public SatellitePvt.VelocityEcef(double, double, double, double);
- method public int describeContents();
- method @FloatRange(from=0.0f, fromInclusive=false) public double getUreRateMetersPerSecond();
- method @FloatRange public double getXMetersPerSecond();
- method @FloatRange public double getYMetersPerSecond();
- method @FloatRange public double getZMetersPerSecond();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.location.SatellitePvt.VelocityEcef> CREATOR;
- }
-
-}
-
-package android.location.provider {
-
- public abstract class LocationProviderBase {
- ctor public LocationProviderBase(@NonNull android.content.Context, @NonNull String, @NonNull android.location.provider.ProviderProperties);
- method @Nullable public final android.os.IBinder getBinder();
- method @NonNull public android.location.provider.ProviderProperties getProperties();
- method public boolean isAllowed();
- method public abstract void onFlush(@NonNull android.location.provider.LocationProviderBase.OnFlushCompleteCallback);
- method public abstract void onSendExtraCommand(@NonNull String, @Nullable android.os.Bundle);
- method public abstract void onSetRequest(@NonNull android.location.provider.ProviderRequest);
- method public void reportLocation(@NonNull android.location.Location);
- method public void reportLocations(@NonNull java.util.List<android.location.Location>);
- method public void setAllowed(boolean);
- method public void setProperties(@NonNull android.location.provider.ProviderProperties);
- field public static final String ACTION_FUSED_PROVIDER = "com.android.location.service.FusedLocationProvider";
- field public static final String ACTION_GNSS_PROVIDER = "android.location.provider.action.GNSS_PROVIDER";
- field public static final String ACTION_NETWORK_PROVIDER = "com.android.location.service.v3.NetworkLocationProvider";
- }
-
- public static interface LocationProviderBase.OnFlushCompleteCallback {
- method public void onFlushComplete();
- }
-
- public final class ProviderRequest implements android.os.Parcelable {
- method public int describeContents();
- method @IntRange(from=0) public long getIntervalMillis();
- method @IntRange(from=0) public long getMaxUpdateDelayMillis();
- method public int getQuality();
- method @NonNull public android.os.WorkSource getWorkSource();
- method public boolean isActive();
- method public boolean isLocationSettingsIgnored();
- method public boolean isLowPower();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.location.provider.ProviderRequest> CREATOR;
- field @NonNull public static final android.location.provider.ProviderRequest EMPTY_REQUEST;
- field public static final long INTERVAL_DISABLED = 9223372036854775807L; // 0x7fffffffffffffffL
- }
-
- public static final class ProviderRequest.Builder {
- ctor public ProviderRequest.Builder();
- method @NonNull public android.location.provider.ProviderRequest build();
- method @NonNull public android.location.provider.ProviderRequest.Builder setIntervalMillis(@IntRange(from=0) long);
- method @NonNull public android.location.provider.ProviderRequest.Builder setLocationSettingsIgnored(boolean);
- method @NonNull public android.location.provider.ProviderRequest.Builder setLowPower(boolean);
- method @NonNull public android.location.provider.ProviderRequest.Builder setMaxUpdateDelayMillis(@IntRange(from=0) long);
- method @NonNull public android.location.provider.ProviderRequest.Builder setQuality(int);
- method @NonNull public android.location.provider.ProviderRequest.Builder setWorkSource(@NonNull android.os.WorkSource);
- }
-
- public static interface ProviderRequest.ChangedListener {
- method public void onProviderRequestChanged(@NonNull String, @NonNull android.location.provider.ProviderRequest);
- }
-
}
package android.media {
diff --git a/core/api/system-lint-baseline.txt b/core/api/system-lint-baseline.txt
index 6c233270bad5..e7c0a912383f 100644
--- a/core/api/system-lint-baseline.txt
+++ b/core/api/system-lint-baseline.txt
@@ -135,16 +135,6 @@ SamShouldBeLast: android.content.pm.ResolveInfo#dump(android.util.Printer, Strin
SAM-compatible parameters (such as parameter 1, "pw", in android.content.pm.ResolveInfo.dump) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
SamShouldBeLast: android.location.Location#dump(android.util.Printer, String):
SAM-compatible parameters (such as parameter 1, "pw", in android.location.Location.dump) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
-SamShouldBeLast: android.location.LocationManager#addNmeaListener(android.location.OnNmeaMessageListener, android.os.Handler):
- SAM-compatible parameters (such as parameter 1, "listener", in android.location.LocationManager.addNmeaListener) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
-SamShouldBeLast: android.location.LocationManager#requestLocationUpdates(String, long, float, android.location.LocationListener, android.os.Looper):
- SAM-compatible parameters (such as parameter 4, "listener", in android.location.LocationManager.requestLocationUpdates) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
-SamShouldBeLast: android.location.LocationManager#requestLocationUpdates(long, float, android.location.Criteria, android.location.LocationListener, android.os.Looper):
- SAM-compatible parameters (such as parameter 4, "listener", in android.location.LocationManager.requestLocationUpdates) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
-SamShouldBeLast: android.location.LocationManager#requestSingleUpdate(String, android.location.LocationListener, android.os.Looper):
- SAM-compatible parameters (such as parameter 2, "listener", in android.location.LocationManager.requestSingleUpdate) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
-SamShouldBeLast: android.location.LocationManager#requestSingleUpdate(android.location.Criteria, android.location.LocationListener, android.os.Looper):
- SAM-compatible parameters (such as parameter 2, "listener", in android.location.LocationManager.requestSingleUpdate) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
SamShouldBeLast: android.media.AudioFocusRequest.Builder#setOnAudioFocusChangeListener(android.media.AudioManager.OnAudioFocusChangeListener, android.os.Handler):
SAM-compatible parameters (such as parameter 1, "listener", in android.media.AudioFocusRequest.Builder.setOnAudioFocusChangeListener) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
SamShouldBeLast: android.media.AudioManager#requestAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener, int, int):
diff --git a/core/api/system-removed.txt b/core/api/system-removed.txt
index 1c10356c6b03..aa17df3471d7 100644
--- a/core/api/system-removed.txt
+++ b/core/api/system-removed.txt
@@ -114,20 +114,6 @@ package android.hardware.hdmi {
}
-package android.location {
-
- public class LocationManager {
- method @Deprecated public boolean addGpsMeasurementListener(android.location.GpsMeasurementsEvent.Listener);
- method @Deprecated public boolean addGpsNavigationMessageListener(android.location.GpsNavigationMessageEvent.Listener);
- method @Deprecated @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public boolean isProviderPackage(@Nullable String, @NonNull String);
- method @Deprecated public void removeGpsMeasurementListener(android.location.GpsMeasurementsEvent.Listener);
- method @Deprecated public void removeGpsNavigationMessageListener(android.location.GpsNavigationMessageEvent.Listener);
- method @Deprecated @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public void setLocationControllerExtraPackage(String);
- method @Deprecated @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public void setLocationControllerExtraPackageEnabled(boolean);
- }
-
-}
-
package android.media.tv {
public final class TvInputManager {
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index 29b52132be75..642813f36a58 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -499,14 +499,14 @@ package android.app {
method public int describeContents();
method public int getActivityType();
method @Nullable public android.graphics.Rect getAppBounds();
- method public android.graphics.Rect getBounds();
+ method @NonNull public android.graphics.Rect getBounds();
method @NonNull public android.graphics.Rect getMaxBounds();
method public int getRotation();
method public int getWindowingMode();
method public static boolean isFloating(int);
method public void setActivityType(int);
method public void setAppBounds(@Nullable android.graphics.Rect);
- method public void setBounds(android.graphics.Rect);
+ method public void setBounds(@Nullable android.graphics.Rect);
method public void setMaxBounds(@Nullable android.graphics.Rect);
method public void setRotation(int);
method public void setTo(android.app.WindowConfiguration);
@@ -1748,109 +1748,6 @@ package android.inputmethodservice {
}
-package android.location {
-
- public final class GnssClock implements android.os.Parcelable {
- ctor public GnssClock();
- method public void reset();
- method public void resetBiasNanos();
- method public void resetBiasUncertaintyNanos();
- method public void resetDriftNanosPerSecond();
- method public void resetDriftUncertaintyNanosPerSecond();
- method public void resetElapsedRealtimeNanos();
- method public void resetElapsedRealtimeUncertaintyNanos();
- method public void resetFullBiasNanos();
- method public void resetLeapSecond();
- method public void resetReferenceCarrierFrequencyHzForIsb();
- method public void resetReferenceCodeTypeForIsb();
- method public void resetReferenceConstellationTypeForIsb();
- method public void resetTimeUncertaintyNanos();
- method public void set(android.location.GnssClock);
- method public void setBiasNanos(double);
- method public void setBiasUncertaintyNanos(@FloatRange(from=0.0f) double);
- method public void setDriftNanosPerSecond(double);
- method public void setDriftUncertaintyNanosPerSecond(@FloatRange(from=0.0f) double);
- method public void setElapsedRealtimeNanos(long);
- method public void setElapsedRealtimeUncertaintyNanos(@FloatRange(from=0.0f) double);
- method public void setFullBiasNanos(long);
- method public void setHardwareClockDiscontinuityCount(int);
- method public void setLeapSecond(int);
- method public void setReferenceCarrierFrequencyHzForIsb(@FloatRange(from=0.0) double);
- method public void setReferenceCodeTypeForIsb(@NonNull String);
- method public void setReferenceConstellationTypeForIsb(int);
- method public void setTimeNanos(long);
- method public void setTimeUncertaintyNanos(@FloatRange(from=0.0f) double);
- }
-
- public final class GnssMeasurement implements android.os.Parcelable {
- ctor public GnssMeasurement();
- method public void reset();
- method public void resetAutomaticGainControlLevel();
- method public void resetBasebandCn0DbHz();
- method @Deprecated public void resetCarrierCycles();
- method public void resetCarrierFrequencyHz();
- method @Deprecated public void resetCarrierPhase();
- method @Deprecated public void resetCarrierPhaseUncertainty();
- method public void resetCodeType();
- method public void resetCorrelationVectors();
- method public void resetFullInterSignalBiasNanos();
- method public void resetFullInterSignalBiasUncertaintyNanos();
- method public void resetSatelliteInterSignalBiasNanos();
- method public void resetSatelliteInterSignalBiasUncertaintyNanos();
- method public void resetSatellitePvt();
- method public void resetSnrInDb();
- method public void set(android.location.GnssMeasurement);
- method public void setAccumulatedDeltaRangeMeters(double);
- method public void setAccumulatedDeltaRangeState(int);
- method public void setAccumulatedDeltaRangeUncertaintyMeters(double);
- method @Deprecated public void setAutomaticGainControlLevelInDb(double);
- method public void setBasebandCn0DbHz(double);
- method @Deprecated public void setCarrierCycles(long);
- method public void setCarrierFrequencyHz(float);
- method @Deprecated public void setCarrierPhase(double);
- method @Deprecated public void setCarrierPhaseUncertainty(double);
- method public void setCn0DbHz(double);
- method public void setCodeType(@NonNull String);
- method public void setConstellationType(int);
- method public void setCorrelationVectors(@Nullable java.util.Collection<android.location.CorrelationVector>);
- method public void setFullInterSignalBiasNanos(double);
- method public void setFullInterSignalBiasUncertaintyNanos(@FloatRange(from=0.0) double);
- method public void setMultipathIndicator(int);
- method public void setPseudorangeRateMetersPerSecond(double);
- method public void setPseudorangeRateUncertaintyMetersPerSecond(double);
- method public void setReceivedSvTimeNanos(long);
- method public void setReceivedSvTimeUncertaintyNanos(long);
- method public void setSatelliteInterSignalBiasNanos(double);
- method public void setSatelliteInterSignalBiasUncertaintyNanos(@FloatRange(from=0.0) double);
- method public void setSatellitePvt(@Nullable android.location.SatellitePvt);
- method public void setSnrInDb(double);
- method public void setState(int);
- method public void setSvid(int);
- method public void setTimeOffsetNanos(double);
- field public static final int ADR_STATE_ALL = 31; // 0x1f
- }
-
- public final class GnssNavigationMessage implements android.os.Parcelable {
- ctor public GnssNavigationMessage();
- method public void reset();
- method public void set(android.location.GnssNavigationMessage);
- method public void setData(byte[]);
- method public void setMessageId(@IntRange(from=0xffffffff, to=120) int);
- method public void setStatus(int);
- method public void setSubmessageId(@IntRange(from=1) int);
- method public void setSvid(@IntRange(from=1, to=200) int);
- method public void setType(int);
- }
-
- public class LocationManager {
- method @NonNull public String[] getBackgroundThrottlingWhitelist();
- method @NonNull public android.os.PackageTagsList getIgnoreSettingsAllowlist();
- method @Deprecated @NonNull public String[] getIgnoreSettingsWhitelist();
- method @Deprecated @Nullable @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public java.util.List<java.lang.String> getProviderPackages(@NonNull String);
- }
-
-}
-
package android.media {
public final class AudioAttributes implements android.os.Parcelable {
diff --git a/core/api/test-lint-baseline.txt b/core/api/test-lint-baseline.txt
index 4a972806b314..1aaedaba3f79 100644
--- a/core/api/test-lint-baseline.txt
+++ b/core/api/test-lint-baseline.txt
@@ -87,50 +87,6 @@ GenericException: android.service.autofill.ImageTransformation#apply(android.ser
Methods must not throw generic exceptions (`java.lang.Exception`)
-GetterSetterNames: android.location.GnssClock#setBiasNanos(double):
- Symmetric method for `hasBiasNanos` must be named `setHasBiasNanos`; was `setBiasNanos`
-GetterSetterNames: android.location.GnssClock#setBiasUncertaintyNanos(double):
- Symmetric method for `hasBiasUncertaintyNanos` must be named `setHasBiasUncertaintyNanos`; was `setBiasUncertaintyNanos`
-GetterSetterNames: android.location.GnssClock#setDriftNanosPerSecond(double):
- Symmetric method for `hasDriftNanosPerSecond` must be named `setHasDriftNanosPerSecond`; was `setDriftNanosPerSecond`
-GetterSetterNames: android.location.GnssClock#setDriftUncertaintyNanosPerSecond(double):
- Symmetric method for `hasDriftUncertaintyNanosPerSecond` must be named `setHasDriftUncertaintyNanosPerSecond`; was `setDriftUncertaintyNanosPerSecond`
-GetterSetterNames: android.location.GnssClock#setElapsedRealtimeNanos(long):
- Symmetric method for `hasElapsedRealtimeNanos` must be named `setHasElapsedRealtimeNanos`; was `setElapsedRealtimeNanos`
-GetterSetterNames: android.location.GnssClock#setElapsedRealtimeUncertaintyNanos(double):
- Symmetric method for `hasElapsedRealtimeUncertaintyNanos` must be named `setHasElapsedRealtimeUncertaintyNanos`; was `setElapsedRealtimeUncertaintyNanos`
-GetterSetterNames: android.location.GnssClock#setFullBiasNanos(long):
- Symmetric method for `hasFullBiasNanos` must be named `setHasFullBiasNanos`; was `setFullBiasNanos`
-GetterSetterNames: android.location.GnssClock#setLeapSecond(int):
- Symmetric method for `hasLeapSecond` must be named `setHasLeapSecond`; was `setLeapSecond`
-GetterSetterNames: android.location.GnssClock#setReferenceCarrierFrequencyHzForIsb(double):
- Symmetric method for `hasReferenceCarrierFrequencyHzForIsb` must be named `setHasReferenceCarrierFrequencyHzForIsb`; was `setReferenceCarrierFrequencyHzForIsb`
-GetterSetterNames: android.location.GnssClock#setReferenceCodeTypeForIsb(String):
- Symmetric method for `hasReferenceCodeTypeForIsb` must be named `setHasReferenceCodeTypeForIsb`; was `setReferenceCodeTypeForIsb`
-GetterSetterNames: android.location.GnssClock#setReferenceConstellationTypeForIsb(int):
- Symmetric method for `hasReferenceConstellationTypeForIsb` must be named `setHasReferenceConstellationTypeForIsb`; was `setReferenceConstellationTypeForIsb`
-GetterSetterNames: android.location.GnssClock#setTimeUncertaintyNanos(double):
- Symmetric method for `hasTimeUncertaintyNanos` must be named `setHasTimeUncertaintyNanos`; was `setTimeUncertaintyNanos`
-GetterSetterNames: android.location.GnssMeasurement#setBasebandCn0DbHz(double):
- Symmetric method for `hasBasebandCn0DbHz` must be named `setHasBasebandCn0DbHz`; was `setBasebandCn0DbHz`
-GetterSetterNames: android.location.GnssMeasurement#setCarrierFrequencyHz(float):
- Symmetric method for `hasCarrierFrequencyHz` must be named `setHasCarrierFrequencyHz`; was `setCarrierFrequencyHz`
-GetterSetterNames: android.location.GnssMeasurement#setCodeType(String):
- Symmetric method for `hasCodeType` must be named `setHasCodeType`; was `setCodeType`
-GetterSetterNames: android.location.GnssMeasurement#setCorrelationVectors(java.util.Collection<android.location.CorrelationVector>):
- Symmetric method for `hasCorrelationVectors` must be named `setHasCorrelationVectors`; was `setCorrelationVectors`
-GetterSetterNames: android.location.GnssMeasurement#setFullInterSignalBiasNanos(double):
- Symmetric method for `hasFullInterSignalBiasNanos` must be named `setHasFullInterSignalBiasNanos`; was `setFullInterSignalBiasNanos`
-GetterSetterNames: android.location.GnssMeasurement#setFullInterSignalBiasUncertaintyNanos(double):
- Symmetric method for `hasFullInterSignalBiasUncertaintyNanos` must be named `setHasFullInterSignalBiasUncertaintyNanos`; was `setFullInterSignalBiasUncertaintyNanos`
-GetterSetterNames: android.location.GnssMeasurement#setSatelliteInterSignalBiasNanos(double):
- Symmetric method for `hasSatelliteInterSignalBiasNanos` must be named `setHasSatelliteInterSignalBiasNanos`; was `setSatelliteInterSignalBiasNanos`
-GetterSetterNames: android.location.GnssMeasurement#setSatelliteInterSignalBiasUncertaintyNanos(double):
- Symmetric method for `hasSatelliteInterSignalBiasUncertaintyNanos` must be named `setHasSatelliteInterSignalBiasUncertaintyNanos`; was `setSatelliteInterSignalBiasUncertaintyNanos`
-GetterSetterNames: android.location.GnssMeasurement#setSatellitePvt(android.location.SatellitePvt):
- Symmetric method for `hasSatellitePvt` must be named `setHasSatellitePvt`; was `setSatellitePvt`
-GetterSetterNames: android.location.GnssMeasurement#setSnrInDb(double):
- Symmetric method for `hasSnrInDb` must be named `setHasSnrInDb`; was `setSnrInDb`
GetterSetterNames: android.net.NetworkPolicyManager#getRestrictBackground():
Symmetric method for `setRestrictBackground` must be named `isRestrictBackground`; was `getRestrictBackground`
@@ -343,14 +299,6 @@ MissingNullability: android.hardware.camera2.CameraManager#getCameraIdListNoLazy
Missing nullability on method `getCameraIdListNoLazy` return
MissingNullability: android.hardware.display.AmbientDisplayConfiguration#AmbientDisplayConfiguration(android.content.Context) parameter #0:
Missing nullability on parameter `context` in method `AmbientDisplayConfiguration`
-MissingNullability: android.location.GnssClock#set(android.location.GnssClock) parameter #0:
- Missing nullability on parameter `clock` in method `set`
-MissingNullability: android.location.GnssMeasurement#set(android.location.GnssMeasurement) parameter #0:
- Missing nullability on parameter `measurement` in method `set`
-MissingNullability: android.location.GnssNavigationMessage#set(android.location.GnssNavigationMessage) parameter #0:
- Missing nullability on parameter `navigationMessage` in method `set`
-MissingNullability: android.location.GnssNavigationMessage#setData(byte[]) parameter #0:
- Missing nullability on parameter `value` in method `setData`
MissingNullability: android.media.AudioAttributes#getSdkUsages():
Missing nullability on method `getSdkUsages` return
MissingNullability: android.media.AudioManager#getPublicStreamTypes():
diff --git a/core/java/android/app/IUriGrantsManager.aidl b/core/java/android/app/IUriGrantsManager.aidl
index 9e7f2fecfea0..b630d034dca9 100644
--- a/core/java/android/app/IUriGrantsManager.aidl
+++ b/core/java/android/app/IUriGrantsManager.aidl
@@ -39,4 +39,7 @@ interface IUriGrantsManager {
void clearGrantedUriPermissions(in String packageName, int userId);
ParceledListSlice getUriPermissions(in String packageName, boolean incoming,
boolean persistedOnly);
+
+ int checkGrantUriPermission_ignoreNonSystem(
+ int sourceUid, String targetPkg, in Uri uri, int modeFlags, int userId);
}
diff --git a/core/java/android/app/WindowConfiguration.java b/core/java/android/app/WindowConfiguration.java
index bf238c399ad3..019a1a8cb2a6 100644
--- a/core/java/android/app/WindowConfiguration.java
+++ b/core/java/android/app/WindowConfiguration.java
@@ -267,12 +267,13 @@ public class WindowConfiguration implements Parcelable, Comparable<WindowConfigu
}
};
- // TODO(b/297672475): make this take @Nullable
/**
* Sets the bounds to the provided {@link Rect}.
+ * Passing {@code null} sets the bounds {@link Rect} to empty.
+ *
* @param rect the new bounds value.
*/
- public void setBounds(Rect rect) {
+ public void setBounds(@Nullable Rect rect) {
if (rect == null) {
mBounds.setEmpty();
return;
@@ -282,8 +283,10 @@ public class WindowConfiguration implements Parcelable, Comparable<WindowConfigu
}
/**
- * Set {@link #mAppBounds} to the input Rect.
- * @param rect The rect value to set {@link #mAppBounds} to.
+ * Sets the app bounds to the provided {@link Rect}.
+ * Passing {@code null} sets the bounds to {@code null}.
+ *
+ * @param rect the new app bounds value.
* @see #getAppBounds()
*/
public void setAppBounds(@Nullable Rect rect) {
@@ -297,7 +300,9 @@ public class WindowConfiguration implements Parcelable, Comparable<WindowConfigu
/**
* Sets the maximum bounds to the provided {@link Rect}.
- * @param rect the new bounds value.
+ * Passing {@code null} sets the bounds {@link Rect} to empty.
+ *
+ * @param rect the new max bounds value.
* @see #getMaxBounds()
*/
public void setMaxBounds(@Nullable Rect rect) {
@@ -364,8 +369,8 @@ public class WindowConfiguration implements Parcelable, Comparable<WindowConfigu
return mAppBounds;
}
- // TODO(b/297672475): make this return @NonNull
/** @see #setBounds(Rect) */
+ @NonNull
public Rect getBounds() {
return mBounds;
}
diff --git a/core/java/android/app/usage/flags.aconfig b/core/java/android/app/usage/flags.aconfig
new file mode 100644
index 000000000000..afe87de1dbf5
--- /dev/null
+++ b/core/java/android/app/usage/flags.aconfig
@@ -0,0 +1,9 @@
+package: "android.app.usage"
+
+flag {
+ name: "user_interaction_type_api"
+ namespace: "power_optimization"
+ description: "Feature flag for user interaction event report/query API"
+ bug: "296061232"
+}
+
diff --git a/core/java/android/companion/virtual/VirtualDeviceParams.java b/core/java/android/companion/virtual/VirtualDeviceParams.java
index 037e814a722d..51df25723ef6 100644
--- a/core/java/android/companion/virtual/VirtualDeviceParams.java
+++ b/core/java/android/companion/virtual/VirtualDeviceParams.java
@@ -202,14 +202,12 @@ public final class VirtualDeviceParams implements Parcelable {
private final int mLockState;
@NonNull private final ArraySet<UserHandle> mUsersWithMatchingAccounts;
- @NonNull private final ArraySet<ComponentName> mAllowedCrossTaskNavigations;
- @NonNull private final ArraySet<ComponentName> mBlockedCrossTaskNavigations;
@NavigationPolicy
private final int mDefaultNavigationPolicy;
- @NonNull private final ArraySet<ComponentName> mAllowedActivities;
- @NonNull private final ArraySet<ComponentName> mBlockedActivities;
+ @NonNull private final ArraySet<ComponentName> mCrossTaskNavigationExceptions;
@ActivityPolicy
private final int mDefaultActivityPolicy;
+ @NonNull private final ArraySet<ComponentName> mActivityPolicyExceptions;
@Nullable private final String mName;
// Mapping of @PolicyType to @DevicePolicy
@NonNull private final SparseIntArray mDevicePolicies;
@@ -221,12 +219,10 @@ public final class VirtualDeviceParams implements Parcelable {
private VirtualDeviceParams(
@LockState int lockState,
@NonNull Set<UserHandle> usersWithMatchingAccounts,
- @NonNull Set<ComponentName> allowedCrossTaskNavigations,
- @NonNull Set<ComponentName> blockedCrossTaskNavigations,
@NavigationPolicy int defaultNavigationPolicy,
- @NonNull Set<ComponentName> allowedActivities,
- @NonNull Set<ComponentName> blockedActivities,
+ @NonNull Set<ComponentName> crossTaskNavigationExceptions,
@ActivityPolicy int defaultActivityPolicy,
+ @NonNull Set<ComponentName> activityPolicyExceptions,
@Nullable String name,
@NonNull SparseIntArray devicePolicies,
@NonNull List<VirtualSensorConfig> virtualSensorConfigs,
@@ -236,14 +232,12 @@ public final class VirtualDeviceParams implements Parcelable {
mLockState = lockState;
mUsersWithMatchingAccounts =
new ArraySet<>(Objects.requireNonNull(usersWithMatchingAccounts));
- mAllowedCrossTaskNavigations =
- new ArraySet<>(Objects.requireNonNull(allowedCrossTaskNavigations));
- mBlockedCrossTaskNavigations =
- new ArraySet<>(Objects.requireNonNull(blockedCrossTaskNavigations));
mDefaultNavigationPolicy = defaultNavigationPolicy;
- mAllowedActivities = new ArraySet<>(Objects.requireNonNull(allowedActivities));
- mBlockedActivities = new ArraySet<>(Objects.requireNonNull(blockedActivities));
+ mCrossTaskNavigationExceptions =
+ new ArraySet<>(Objects.requireNonNull(crossTaskNavigationExceptions));
mDefaultActivityPolicy = defaultActivityPolicy;
+ mActivityPolicyExceptions =
+ new ArraySet<>(Objects.requireNonNull(activityPolicyExceptions));
mName = name;
mDevicePolicies = Objects.requireNonNull(devicePolicies);
mVirtualSensorConfigs = Objects.requireNonNull(virtualSensorConfigs);
@@ -256,12 +250,10 @@ public final class VirtualDeviceParams implements Parcelable {
private VirtualDeviceParams(Parcel parcel) {
mLockState = parcel.readInt();
mUsersWithMatchingAccounts = (ArraySet<UserHandle>) parcel.readArraySet(null);
- mAllowedCrossTaskNavigations = (ArraySet<ComponentName>) parcel.readArraySet(null);
- mBlockedCrossTaskNavigations = (ArraySet<ComponentName>) parcel.readArraySet(null);
mDefaultNavigationPolicy = parcel.readInt();
- mAllowedActivities = (ArraySet<ComponentName>) parcel.readArraySet(null);
- mBlockedActivities = (ArraySet<ComponentName>) parcel.readArraySet(null);
+ mCrossTaskNavigationExceptions = (ArraySet<ComponentName>) parcel.readArraySet(null);
mDefaultActivityPolicy = parcel.readInt();
+ mActivityPolicyExceptions = (ArraySet<ComponentName>) parcel.readArraySet(null);
mName = parcel.readString8();
mDevicePolicies = parcel.readSparseIntArray();
mVirtualSensorConfigs = new ArrayList<>();
@@ -301,7 +293,9 @@ public final class VirtualDeviceParams implements Parcelable {
*/
@NonNull
public Set<ComponentName> getAllowedCrossTaskNavigations() {
- return Collections.unmodifiableSet(mAllowedCrossTaskNavigations);
+ return mDefaultNavigationPolicy == NAVIGATION_POLICY_DEFAULT_ALLOWED
+ ? Collections.emptySet()
+ : Collections.unmodifiableSet(mCrossTaskNavigationExceptions);
}
/**
@@ -314,7 +308,9 @@ public final class VirtualDeviceParams implements Parcelable {
*/
@NonNull
public Set<ComponentName> getBlockedCrossTaskNavigations() {
- return Collections.unmodifiableSet(mBlockedCrossTaskNavigations);
+ return mDefaultNavigationPolicy == NAVIGATION_POLICY_DEFAULT_BLOCKED
+ ? Collections.emptySet()
+ : Collections.unmodifiableSet(mCrossTaskNavigationExceptions);
}
/**
@@ -338,7 +334,9 @@ public final class VirtualDeviceParams implements Parcelable {
*/
@NonNull
public Set<ComponentName> getAllowedActivities() {
- return Collections.unmodifiableSet(mAllowedActivities);
+ return mDefaultActivityPolicy == ACTIVITY_POLICY_DEFAULT_ALLOWED
+ ? Collections.emptySet()
+ : Collections.unmodifiableSet(mActivityPolicyExceptions);
}
/**
@@ -349,7 +347,9 @@ public final class VirtualDeviceParams implements Parcelable {
*/
@NonNull
public Set<ComponentName> getBlockedActivities() {
- return Collections.unmodifiableSet(mBlockedActivities);
+ return mDefaultActivityPolicy == ACTIVITY_POLICY_DEFAULT_BLOCKED
+ ? Collections.emptySet()
+ : Collections.unmodifiableSet(mActivityPolicyExceptions);
}
/**
@@ -439,12 +439,10 @@ public final class VirtualDeviceParams implements Parcelable {
public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeInt(mLockState);
dest.writeArraySet(mUsersWithMatchingAccounts);
- dest.writeArraySet(mAllowedCrossTaskNavigations);
- dest.writeArraySet(mBlockedCrossTaskNavigations);
dest.writeInt(mDefaultNavigationPolicy);
- dest.writeArraySet(mAllowedActivities);
- dest.writeArraySet(mBlockedActivities);
+ dest.writeArraySet(mCrossTaskNavigationExceptions);
dest.writeInt(mDefaultActivityPolicy);
+ dest.writeArraySet(mActivityPolicyExceptions);
dest.writeString8(mName);
dest.writeSparseIntArray(mDevicePolicies);
dest.writeTypedList(mVirtualSensorConfigs);
@@ -477,11 +475,10 @@ public final class VirtualDeviceParams implements Parcelable {
}
return mLockState == that.mLockState
&& mUsersWithMatchingAccounts.equals(that.mUsersWithMatchingAccounts)
- && Objects.equals(mAllowedCrossTaskNavigations, that.mAllowedCrossTaskNavigations)
- && Objects.equals(mBlockedCrossTaskNavigations, that.mBlockedCrossTaskNavigations)
+ && Objects.equals(
+ mCrossTaskNavigationExceptions, that.mCrossTaskNavigationExceptions)
&& mDefaultNavigationPolicy == that.mDefaultNavigationPolicy
- && Objects.equals(mAllowedActivities, that.mAllowedActivities)
- && Objects.equals(mBlockedActivities, that.mBlockedActivities)
+ && Objects.equals(mActivityPolicyExceptions, that.mActivityPolicyExceptions)
&& mDefaultActivityPolicy == that.mDefaultActivityPolicy
&& Objects.equals(mName, that.mName)
&& mAudioPlaybackSessionId == that.mAudioPlaybackSessionId
@@ -491,10 +488,9 @@ public final class VirtualDeviceParams implements Parcelable {
@Override
public int hashCode() {
int hashCode = Objects.hash(
- mLockState, mUsersWithMatchingAccounts, mAllowedCrossTaskNavigations,
- mBlockedCrossTaskNavigations, mDefaultNavigationPolicy, mAllowedActivities,
- mBlockedActivities, mDefaultActivityPolicy, mName, mDevicePolicies,
- mAudioPlaybackSessionId, mAudioRecordingSessionId);
+ mLockState, mUsersWithMatchingAccounts, mCrossTaskNavigationExceptions,
+ mDefaultNavigationPolicy, mActivityPolicyExceptions, mDefaultActivityPolicy, mName,
+ mDevicePolicies, mAudioPlaybackSessionId, mAudioRecordingSessionId);
for (int i = 0; i < mDevicePolicies.size(); i++) {
hashCode = 31 * hashCode + mDevicePolicies.keyAt(i);
hashCode = 31 * hashCode + mDevicePolicies.valueAt(i);
@@ -508,12 +504,10 @@ public final class VirtualDeviceParams implements Parcelable {
return "VirtualDeviceParams("
+ " mLockState=" + mLockState
+ " mUsersWithMatchingAccounts=" + mUsersWithMatchingAccounts
- + " mAllowedCrossTaskNavigations=" + mAllowedCrossTaskNavigations
- + " mBlockedCrossTaskNavigations=" + mBlockedCrossTaskNavigations
+ " mDefaultNavigationPolicy=" + mDefaultNavigationPolicy
- + " mAllowedActivities=" + mAllowedActivities
- + " mBlockedActivities=" + mBlockedActivities
+ + " mCrossTaskNavigationExceptions=" + mCrossTaskNavigationExceptions
+ " mDefaultActivityPolicy=" + mDefaultActivityPolicy
+ + " mActivityPolicyExceptions=" + mActivityPolicyExceptions
+ " mName=" + mName
+ " mDevicePolicies=" + mDevicePolicies
+ " mAudioPlaybackSessionId=" + mAudioPlaybackSessionId
@@ -529,13 +523,11 @@ public final class VirtualDeviceParams implements Parcelable {
pw.println(prefix + "mName=" + mName);
pw.println(prefix + "mLockState=" + mLockState);
pw.println(prefix + "mUsersWithMatchingAccounts=" + mUsersWithMatchingAccounts);
- pw.println(prefix + "mAllowedCrossTaskNavigations=" + mAllowedCrossTaskNavigations);
- pw.println(prefix + "mBlockedCrossTaskNavigations=" + mBlockedCrossTaskNavigations);
- pw.println(prefix + "mAllowedActivities=" + mAllowedActivities);
- pw.println(prefix + "mBlockedActivities=" + mBlockedActivities);
- pw.println(prefix + "mDevicePolicies=" + mDevicePolicies);
pw.println(prefix + "mDefaultNavigationPolicy=" + mDefaultNavigationPolicy);
+ pw.println(prefix + "mCrossTaskNavigationExceptions=" + mCrossTaskNavigationExceptions);
pw.println(prefix + "mDefaultActivityPolicy=" + mDefaultActivityPolicy);
+ pw.println(prefix + "mActivityPolicyExceptions=" + mActivityPolicyExceptions);
+ pw.println(prefix + "mDevicePolicies=" + mDevicePolicies);
pw.println(prefix + "mVirtualSensorConfigs=" + mVirtualSensorConfigs);
pw.println(prefix + "mAudioPlaybackSessionId=" + mAudioPlaybackSessionId);
pw.println(prefix + "mAudioRecordingSessionId=" + mAudioRecordingSessionId);
@@ -560,13 +552,11 @@ public final class VirtualDeviceParams implements Parcelable {
private @LockState int mLockState = LOCK_STATE_DEFAULT;
@NonNull private Set<UserHandle> mUsersWithMatchingAccounts = Collections.emptySet();
- @NonNull private Set<ComponentName> mAllowedCrossTaskNavigations = Collections.emptySet();
- @NonNull private Set<ComponentName> mBlockedCrossTaskNavigations = Collections.emptySet();
+ @NonNull private Set<ComponentName> mCrossTaskNavigationExceptions = Collections.emptySet();
@NavigationPolicy
private int mDefaultNavigationPolicy = NAVIGATION_POLICY_DEFAULT_ALLOWED;
private boolean mDefaultNavigationPolicyConfigured = false;
- @NonNull private Set<ComponentName> mBlockedActivities = Collections.emptySet();
- @NonNull private Set<ComponentName> mAllowedActivities = Collections.emptySet();
+ @NonNull private Set<ComponentName> mActivityPolicyExceptions = Collections.emptySet();
@ActivityPolicy
private int mDefaultActivityPolicy = ACTIVITY_POLICY_DEFAULT_ALLOWED;
private boolean mDefaultActivityPolicyConfigured = false;
@@ -705,12 +695,12 @@ public final class VirtualDeviceParams implements Parcelable {
if (mDefaultNavigationPolicyConfigured
&& mDefaultNavigationPolicy != NAVIGATION_POLICY_DEFAULT_BLOCKED) {
throw new IllegalArgumentException(
- "Allowed cross task navigation and blocked task navigation cannot "
+ "Allowed cross task navigations and blocked cross task navigations cannot "
+ " both be set.");
}
mDefaultNavigationPolicy = NAVIGATION_POLICY_DEFAULT_BLOCKED;
mDefaultNavigationPolicyConfigured = true;
- mAllowedCrossTaskNavigations = Objects.requireNonNull(allowedCrossTaskNavigations);
+ mCrossTaskNavigationExceptions = Objects.requireNonNull(allowedCrossTaskNavigations);
return this;
}
@@ -741,7 +731,7 @@ public final class VirtualDeviceParams implements Parcelable {
}
mDefaultNavigationPolicy = NAVIGATION_POLICY_DEFAULT_ALLOWED;
mDefaultNavigationPolicyConfigured = true;
- mBlockedCrossTaskNavigations = Objects.requireNonNull(blockedCrossTaskNavigations);
+ mCrossTaskNavigationExceptions = Objects.requireNonNull(blockedCrossTaskNavigations);
return this;
}
@@ -767,7 +757,7 @@ public final class VirtualDeviceParams implements Parcelable {
}
mDefaultActivityPolicy = ACTIVITY_POLICY_DEFAULT_BLOCKED;
mDefaultActivityPolicyConfigured = true;
- mAllowedActivities = Objects.requireNonNull(allowedActivities);
+ mActivityPolicyExceptions = Objects.requireNonNull(allowedActivities);
return this;
}
@@ -793,7 +783,7 @@ public final class VirtualDeviceParams implements Parcelable {
}
mDefaultActivityPolicy = ACTIVITY_POLICY_DEFAULT_ALLOWED;
mDefaultActivityPolicyConfigured = true;
- mBlockedActivities = Objects.requireNonNull(blockedActivities);
+ mActivityPolicyExceptions = Objects.requireNonNull(blockedActivities);
return this;
}
@@ -988,12 +978,10 @@ public final class VirtualDeviceParams implements Parcelable {
return new VirtualDeviceParams(
mLockState,
mUsersWithMatchingAccounts,
- mAllowedCrossTaskNavigations,
- mBlockedCrossTaskNavigations,
mDefaultNavigationPolicy,
- mAllowedActivities,
- mBlockedActivities,
+ mCrossTaskNavigationExceptions,
mDefaultActivityPolicy,
+ mActivityPolicyExceptions,
mName,
mDevicePolicies,
mVirtualSensorConfigs,
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 31f6418ac3d0..fe7d1e6fb232 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -5270,6 +5270,16 @@ public class Intent implements Parcelable, Cloneable {
public static final String ACTION_SHOW_FOREGROUND_SERVICE_MANAGER =
"android.intent.action.SHOW_FOREGROUND_SERVICE_MANAGER";
+ /**
+ * Broadcast Action: Sent to the responsible installer of an archived package when unarchival
+ * is requested.
+ *
+ * @see android.content.pm.PackageArchiver
+ * @hide
+ */
+ @SystemApi
+ public static final String ACTION_UNARCHIVE_PACKAGE = "android.intent.action.UNARCHIVE_PACKAGE";
+
// ---------------------------------------------------------------------
// ---------------------------------------------------------------------
// Standard intent categories (see addCategory()).
diff --git a/core/java/android/content/pm/ArchivedPackageParcel.aidl b/core/java/android/content/pm/ArchivedPackageParcel.aidl
index b34b708aa2c5..6aeee895301a 100644
--- a/core/java/android/content/pm/ArchivedPackageParcel.aidl
+++ b/core/java/android/content/pm/ArchivedPackageParcel.aidl
@@ -29,7 +29,6 @@ parcelable ArchivedPackageParcel {
int versionCode;
int versionCodeMajor;
int targetSdkVersion;
- boolean clearUserDataAllowed;
boolean backupAllowed;
boolean defaultToDeviceProtectedStorage;
boolean requestLegacyExternalStorage;
diff --git a/core/java/android/content/pm/IPackageArchiverService.aidl b/core/java/android/content/pm/IPackageArchiverService.aidl
index fc471c451370..dc6491d6d97e 100644
--- a/core/java/android/content/pm/IPackageArchiverService.aidl
+++ b/core/java/android/content/pm/IPackageArchiverService.aidl
@@ -23,4 +23,7 @@ interface IPackageArchiverService {
@JavaPassthrough(annotation="@android.annotation.RequiresPermission(anyOf={android.Manifest.permission.DELETE_PACKAGES,android.Manifest.permission.REQUEST_DELETE_PACKAGES})")
void requestArchive(String packageName, String callerPackageName, in IntentSender statusReceiver, in UserHandle userHandle);
+
+ @JavaPassthrough(annotation="@android.annotation.RequiresPermission(anyOf={android.Manifest.permission.INSTALL_PACKAGES,android.Manifest.permission.REQUEST_INSTALL_PACKAGES})")
+ void requestUnarchive(String packageName, String callerPackageName, in UserHandle userHandle);
} \ No newline at end of file
diff --git a/core/java/android/content/pm/PackageArchiver.java b/core/java/android/content/pm/PackageArchiver.java
index d739d5054800..b06523160b92 100644
--- a/core/java/android/content/pm/PackageArchiver.java
+++ b/core/java/android/content/pm/PackageArchiver.java
@@ -42,6 +42,26 @@ import android.os.RemoteException;
@SystemApi
public class PackageArchiver {
+ /**
+ * Extra field for the package name of a package that is requested to be unarchived. Sent as
+ * part of the {@link android.content.Intent#ACTION_UNARCHIVE_PACKAGE} intent.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final String EXTRA_UNARCHIVE_PACKAGE_NAME =
+ "android.content.pm.extra.UNARCHIVE_PACKAGE_NAME";
+
+ /**
+ * If true, the requestor of the unarchival has specified that the app should be unarchived
+ * for {@link android.os.UserHandle#ALL}.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final String EXTRA_UNARCHIVE_ALL_USERS =
+ "android.content.pm.extra.UNARCHIVE_ALL_USERS";
+
private final Context mContext;
private final IPackageArchiverService mService;
@@ -58,7 +78,7 @@ public class PackageArchiver {
*
* @param statusReceiver Callback used to notify when the operation is completed.
* @throws NameNotFoundException If {@code packageName} isn't found or not available to the
- * caller.
+ * caller or isn't archived.
* @hide
*/
@RequiresPermission(anyOf = {
@@ -76,4 +96,34 @@ public class PackageArchiver {
throw e.rethrowFromSystemServer();
}
}
+
+ /**
+ * Requests to unarchive a currently archived package.
+ *
+ * <p> Sends a request to unarchive an app to the responsible installer. The installer is
+ * determined by {@link InstallSourceInfo#getUpdateOwnerPackageName()}, or
+ * {@link InstallSourceInfo#getInstallingPackageName()} if the former value is null.
+ *
+ * <p> The installation will happen asynchronously and can be observed through
+ * {@link android.content.Intent#ACTION_PACKAGE_ADDED}.
+ *
+ * @throws NameNotFoundException If {@code packageName} isn't found or not visible to the
+ * caller or if the package has no installer on the device
+ * anymore to unarchive it.
+ * @hide
+ */
+ @RequiresPermission(anyOf = {
+ Manifest.permission.INSTALL_PACKAGES,
+ Manifest.permission.REQUEST_INSTALL_PACKAGES})
+ @SystemApi
+ public void requestUnarchive(@NonNull String packageName)
+ throws NameNotFoundException {
+ try {
+ mService.requestUnarchive(packageName, mContext.getPackageName(), mContext.getUser());
+ } catch (ParcelableException e) {
+ e.maybeRethrow(NameNotFoundException.class);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
}
diff --git a/core/java/android/content/pm/parsing/ApkLite.java b/core/java/android/content/pm/parsing/ApkLite.java
index 71cfd1b1e1cb..8e7592a1eb73 100644
--- a/core/java/android/content/pm/parsing/ApkLite.java
+++ b/core/java/android/content/pm/parsing/ApkLite.java
@@ -140,11 +140,6 @@ public class ApkLite {
private final boolean mIsSdkLibrary;
/**
- * Indicates whether this application's data will be cleared on a failed restore.
- */
- private final boolean mClearUserDataAllowed;
-
- /**
* Set to <code>false</code> if the application does not wish to permit any OS-driven
* backups of its data; <code>true</code> otherwise.
*/
@@ -219,7 +214,6 @@ public class ApkLite {
mRollbackDataPolicy = rollbackDataPolicy;
mHasDeviceAdminReceiver = hasDeviceAdminReceiver;
mIsSdkLibrary = isSdkLibrary;
- mClearUserDataAllowed = clearUserDataAllowed;
mBackupAllowed = backupAllowed;
mDefaultToDeviceProtectedStorage = defaultToDeviceProtectedStorage;
mRequestLegacyExternalStorage = requestLegacyExternalStorage;
@@ -261,7 +255,6 @@ public class ApkLite {
mRollbackDataPolicy = 0;
mHasDeviceAdminReceiver = false;
mIsSdkLibrary = false;
- mClearUserDataAllowed = archivedPackage.clearUserDataAllowed;
mBackupAllowed = archivedPackage.backupAllowed;
mDefaultToDeviceProtectedStorage = archivedPackage.defaultToDeviceProtectedStorage;
mRequestLegacyExternalStorage = archivedPackage.requestLegacyExternalStorage;
@@ -576,14 +569,6 @@ public class ApkLite {
}
/**
- * Indicates whether this application's data will be cleared on a failed restore.
- */
- @DataClass.Generated.Member
- public boolean isClearUserDataAllowed() {
- return mClearUserDataAllowed;
- }
-
- /**
* Set to <code>false</code> if the application does not wish to permit any OS-driven
* backups of its data; <code>true</code> otherwise.
*/
@@ -627,10 +612,10 @@ public class ApkLite {
}
@DataClass.Generated(
- time = 1693422809896L,
+ time = 1693513509013L,
codegenVersion = "1.0.23",
sourceFile = "frameworks/base/core/java/android/content/pm/parsing/ApkLite.java",
- inputSignatures = "private final @android.annotation.NonNull java.lang.String mPackageName\nprivate final @android.annotation.NonNull java.lang.String mPath\nprivate final @android.annotation.Nullable java.lang.String mSplitName\nprivate final @android.annotation.Nullable java.lang.String mUsesSplitName\nprivate final @android.annotation.Nullable java.lang.String mConfigForSplit\nprivate final @android.annotation.Nullable java.util.Set<java.lang.String> mRequiredSplitTypes\nprivate final @android.annotation.Nullable java.util.Set<java.lang.String> mSplitTypes\nprivate final int mVersionCodeMajor\nprivate final int mVersionCode\nprivate final int mRevisionCode\nprivate final int mInstallLocation\nprivate final int mMinSdkVersion\nprivate final int mTargetSdkVersion\nprivate final @android.annotation.NonNull android.content.pm.VerifierInfo[] mVerifiers\nprivate final @android.annotation.NonNull android.content.pm.SigningDetails mSigningDetails\nprivate final boolean mFeatureSplit\nprivate final boolean mIsolatedSplits\nprivate final boolean mSplitRequired\nprivate final boolean mCoreApp\nprivate final boolean mDebuggable\nprivate final boolean mProfileableByShell\nprivate final boolean mMultiArch\nprivate final boolean mUse32bitAbi\nprivate final boolean mExtractNativeLibs\nprivate final boolean mUseEmbeddedDex\nprivate final @android.annotation.Nullable java.lang.String mTargetPackageName\nprivate final boolean mOverlayIsStatic\nprivate final int mOverlayPriority\nprivate final @android.annotation.Nullable java.lang.String mRequiredSystemPropertyName\nprivate final @android.annotation.Nullable java.lang.String mRequiredSystemPropertyValue\nprivate final int mRollbackDataPolicy\nprivate final boolean mHasDeviceAdminReceiver\nprivate final boolean mIsSdkLibrary\nprivate final boolean mClearUserDataAllowed\nprivate final boolean mBackupAllowed\nprivate final boolean mDefaultToDeviceProtectedStorage\nprivate final boolean mRequestLegacyExternalStorage\nprivate final boolean mUserDataFragile\nprivate final boolean mClearUserDataOnFailedRestoreAllowed\npublic long getLongVersionCode()\nprivate boolean hasAnyRequiredSplitTypes()\nclass ApkLite extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genConstructor=false, genConstDefs=false)")
+ inputSignatures = "private final @android.annotation.NonNull java.lang.String mPackageName\nprivate final @android.annotation.NonNull java.lang.String mPath\nprivate final @android.annotation.Nullable java.lang.String mSplitName\nprivate final @android.annotation.Nullable java.lang.String mUsesSplitName\nprivate final @android.annotation.Nullable java.lang.String mConfigForSplit\nprivate final @android.annotation.Nullable java.util.Set<java.lang.String> mRequiredSplitTypes\nprivate final @android.annotation.Nullable java.util.Set<java.lang.String> mSplitTypes\nprivate final int mVersionCodeMajor\nprivate final int mVersionCode\nprivate final int mRevisionCode\nprivate final int mInstallLocation\nprivate final int mMinSdkVersion\nprivate final int mTargetSdkVersion\nprivate final @android.annotation.NonNull android.content.pm.VerifierInfo[] mVerifiers\nprivate final @android.annotation.NonNull android.content.pm.SigningDetails mSigningDetails\nprivate final boolean mFeatureSplit\nprivate final boolean mIsolatedSplits\nprivate final boolean mSplitRequired\nprivate final boolean mCoreApp\nprivate final boolean mDebuggable\nprivate final boolean mProfileableByShell\nprivate final boolean mMultiArch\nprivate final boolean mUse32bitAbi\nprivate final boolean mExtractNativeLibs\nprivate final boolean mUseEmbeddedDex\nprivate final @android.annotation.Nullable java.lang.String mTargetPackageName\nprivate final boolean mOverlayIsStatic\nprivate final int mOverlayPriority\nprivate final @android.annotation.Nullable java.lang.String mRequiredSystemPropertyName\nprivate final @android.annotation.Nullable java.lang.String mRequiredSystemPropertyValue\nprivate final int mRollbackDataPolicy\nprivate final boolean mHasDeviceAdminReceiver\nprivate final boolean mIsSdkLibrary\nprivate final boolean mBackupAllowed\nprivate final boolean mDefaultToDeviceProtectedStorage\nprivate final boolean mRequestLegacyExternalStorage\nprivate final boolean mUserDataFragile\nprivate final boolean mClearUserDataOnFailedRestoreAllowed\npublic long getLongVersionCode()\nprivate boolean hasAnyRequiredSplitTypes()\nclass ApkLite extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genConstructor=false, genConstDefs=false)")
@Deprecated
private void __metadata() {}
diff --git a/core/java/android/content/pm/parsing/PackageLite.java b/core/java/android/content/pm/parsing/PackageLite.java
index 4638af752d33..ccef9def609e 100644
--- a/core/java/android/content/pm/parsing/PackageLite.java
+++ b/core/java/android/content/pm/parsing/PackageLite.java
@@ -113,10 +113,6 @@ public class PackageLite {
*/
private final boolean mIsSdkLibrary;
/**
- * Indicates whether this application's data will be cleared on a failed restore.
- */
- private final boolean mClearUserDataAllowed;
- /**
* Set to <code>false</code> if the application does not wish to permit any OS-driven
* backups of its data; <code>true</code> otherwise.
*/
@@ -175,7 +171,6 @@ public class PackageLite {
mSplitApkPaths = splitApkPaths;
mSplitRevisionCodes = splitRevisionCodes;
mTargetSdk = targetSdk;
- mClearUserDataAllowed = baseApk.isClearUserDataAllowed();
mBackupAllowed = baseApk.isBackupAllowed();
mDefaultToDeviceProtectedStorage = baseApk.isDefaultToDeviceProtectedStorage();
mRequestLegacyExternalStorage = baseApk.isRequestLegacyExternalStorage();
@@ -460,14 +455,6 @@ public class PackageLite {
}
/**
- * Indicates whether this application's data will be cleared on a failed restore.
- */
- @DataClass.Generated.Member
- public boolean isClearUserDataAllowed() {
- return mClearUserDataAllowed;
- }
-
- /**
* Set to <code>false</code> if the application does not wish to permit any OS-driven
* backups of its data; <code>true</code> otherwise.
*/
@@ -511,10 +498,10 @@ public class PackageLite {
}
@DataClass.Generated(
- time = 1693423910860L,
+ time = 1693513525097L,
codegenVersion = "1.0.23",
sourceFile = "frameworks/base/core/java/android/content/pm/parsing/PackageLite.java",
- inputSignatures = "private final @android.annotation.NonNull java.lang.String mPackageName\nprivate final @android.annotation.NonNull java.lang.String mPath\nprivate final @android.annotation.NonNull java.lang.String mBaseApkPath\nprivate final @android.annotation.Nullable java.lang.String[] mSplitApkPaths\nprivate final @android.annotation.Nullable java.lang.String[] mSplitNames\nprivate final @android.annotation.Nullable java.lang.String[] mUsesSplitNames\nprivate final @android.annotation.Nullable java.lang.String[] mConfigForSplit\nprivate final @android.annotation.Nullable java.util.Set<java.lang.String> mBaseRequiredSplitTypes\nprivate final @android.annotation.Nullable java.util.Set<java.lang.String>[] mRequiredSplitTypes\nprivate final @android.annotation.Nullable java.util.Set<java.lang.String>[] mSplitTypes\nprivate final int mVersionCodeMajor\nprivate final int mVersionCode\nprivate final int mTargetSdk\nprivate final int mBaseRevisionCode\nprivate final @android.annotation.Nullable int[] mSplitRevisionCodes\nprivate final int mInstallLocation\nprivate final @android.annotation.NonNull android.content.pm.VerifierInfo[] mVerifiers\nprivate final @android.annotation.NonNull android.content.pm.SigningDetails mSigningDetails\nprivate final @android.annotation.Nullable boolean[] mIsFeatureSplits\nprivate final boolean mIsolatedSplits\nprivate final boolean mSplitRequired\nprivate final boolean mCoreApp\nprivate final boolean mDebuggable\nprivate final boolean mMultiArch\nprivate final boolean mUse32bitAbi\nprivate final boolean mExtractNativeLibs\nprivate final boolean mProfileableByShell\nprivate final boolean mUseEmbeddedDex\nprivate final boolean mIsSdkLibrary\nprivate final boolean mClearUserDataAllowed\nprivate final boolean mBackupAllowed\nprivate final boolean mDefaultToDeviceProtectedStorage\nprivate final boolean mRequestLegacyExternalStorage\nprivate final boolean mUserDataFragile\nprivate final boolean mClearUserDataOnFailedRestoreAllowed\npublic java.util.List<java.lang.String> getAllApkPaths()\npublic long getLongVersionCode()\nprivate boolean hasAnyRequiredSplitTypes()\nclass PackageLite extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genConstructor=false, genConstDefs=false)")
+ inputSignatures = "private final @android.annotation.NonNull java.lang.String mPackageName\nprivate final @android.annotation.NonNull java.lang.String mPath\nprivate final @android.annotation.NonNull java.lang.String mBaseApkPath\nprivate final @android.annotation.Nullable java.lang.String[] mSplitApkPaths\nprivate final @android.annotation.Nullable java.lang.String[] mSplitNames\nprivate final @android.annotation.Nullable java.lang.String[] mUsesSplitNames\nprivate final @android.annotation.Nullable java.lang.String[] mConfigForSplit\nprivate final @android.annotation.Nullable java.util.Set<java.lang.String> mBaseRequiredSplitTypes\nprivate final @android.annotation.Nullable java.util.Set<java.lang.String>[] mRequiredSplitTypes\nprivate final @android.annotation.Nullable java.util.Set<java.lang.String>[] mSplitTypes\nprivate final int mVersionCodeMajor\nprivate final int mVersionCode\nprivate final int mTargetSdk\nprivate final int mBaseRevisionCode\nprivate final @android.annotation.Nullable int[] mSplitRevisionCodes\nprivate final int mInstallLocation\nprivate final @android.annotation.NonNull android.content.pm.VerifierInfo[] mVerifiers\nprivate final @android.annotation.NonNull android.content.pm.SigningDetails mSigningDetails\nprivate final @android.annotation.Nullable boolean[] mIsFeatureSplits\nprivate final boolean mIsolatedSplits\nprivate final boolean mSplitRequired\nprivate final boolean mCoreApp\nprivate final boolean mDebuggable\nprivate final boolean mMultiArch\nprivate final boolean mUse32bitAbi\nprivate final boolean mExtractNativeLibs\nprivate final boolean mProfileableByShell\nprivate final boolean mUseEmbeddedDex\nprivate final boolean mIsSdkLibrary\nprivate final boolean mBackupAllowed\nprivate final boolean mDefaultToDeviceProtectedStorage\nprivate final boolean mRequestLegacyExternalStorage\nprivate final boolean mUserDataFragile\nprivate final boolean mClearUserDataOnFailedRestoreAllowed\npublic java.util.List<java.lang.String> getAllApkPaths()\npublic long getLongVersionCode()\nprivate boolean hasAnyRequiredSplitTypes()\nclass PackageLite extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genConstructor=false, genConstDefs=false)")
@Deprecated
private void __metadata() {}
diff --git a/core/java/android/hardware/camera2/CameraCharacteristics.java b/core/java/android/hardware/camera2/CameraCharacteristics.java
index d352be16ae0c..943f0c4bba0a 100644
--- a/core/java/android/hardware/camera2/CameraCharacteristics.java
+++ b/core/java/android/hardware/camera2/CameraCharacteristics.java
@@ -16,6 +16,7 @@
package android.hardware.camera2;
+import android.annotation.FlaggedApi;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.compat.annotation.UnsupportedAppUsage;
@@ -31,6 +32,7 @@ import android.util.Log;
import android.util.Rational;
import com.android.internal.annotations.GuardedBy;
+import com.android.internal.camera.flags.Flags;
import java.util.ArrayList;
import java.util.Collections;
diff --git a/core/java/android/hardware/camera2/CameraDevice.java b/core/java/android/hardware/camera2/CameraDevice.java
index 082a3361be4e..f4d783a7c2b7 100644
--- a/core/java/android/hardware/camera2/CameraDevice.java
+++ b/core/java/android/hardware/camera2/CameraDevice.java
@@ -625,12 +625,13 @@ public abstract class CameraDevice implements AutoCloseable {
* <style scoped>
* #rb { border-right-width: thick; }
* </style>
+ *
+ * <h5>LEGACY-level guaranteed configurations</h5>
+ *
* <p>Legacy devices ({@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL}
* {@code == }{@link CameraMetadata#INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY LEGACY}) support at
* least the following stream combinations:
*
- * <h5>LEGACY-level guaranteed configurations</h5>
- *
* <table>
* <tr> <th colspan="2" id="rb">Target 1</th> <th colspan="2" id="rb">Target 2</th> <th colspan="2" id="rb">Target 3</th> <th rowspan="2">Sample use case(s)</th> </tr>
* <tr> <th>Type</th><th id="rb">Max size</th> <th>Type</th><th id="rb">Max size</th> <th>Type</th><th id="rb">Max size</th></tr>
@@ -645,13 +646,13 @@ public abstract class CameraDevice implements AutoCloseable {
* </table><br>
* </p>
*
+ * <h5>LIMITED-level additional guaranteed configurations</h5>
+ *
* <p>Limited-level ({@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL}
* {@code == }{@link CameraMetadata#INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED LIMITED}) devices
* support at least the following stream combinations in addition to those for
* {@link CameraMetadata#INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY LEGACY} devices:
*
- * <h5>LIMITED-level additional guaranteed configurations</h5>
- *
* <table>
* <tr><th colspan="2" id="rb">Target 1</th><th colspan="2" id="rb">Target 2</th><th colspan="2" id="rb">Target 3</th> <th rowspan="2">Sample use case(s)</th> </tr>
* <tr><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th></tr>
@@ -664,13 +665,13 @@ public abstract class CameraDevice implements AutoCloseable {
* </table><br>
* </p>
*
+ * <h5>FULL-level additional guaranteed configurations</h5>
+ *
* <p>FULL-level ({@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL}
* {@code == }{@link CameraMetadata#INFO_SUPPORTED_HARDWARE_LEVEL_FULL FULL}) devices
* support at least the following stream combinations in addition to those for
* {@link CameraMetadata#INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED LIMITED} devices:
*
- * <h5>FULL-level additional guaranteed configurations</h5>
- *
* <table>
* <tr><th colspan="2" id="rb">Target 1</th><th colspan="2" id="rb">Target 2</th><th colspan="2" id="rb">Target 3</th> <th rowspan="2">Sample use case(s)</th> </tr>
* <tr><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th> </tr>
@@ -683,14 +684,14 @@ public abstract class CameraDevice implements AutoCloseable {
* </table><br>
* </p>
*
+ * <h5>RAW-capability additional guaranteed configurations</h5>
+ *
* <p>RAW-capability ({@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES} includes
* {@link CameraMetadata#REQUEST_AVAILABLE_CAPABILITIES_RAW RAW}) devices additionally support
* at least the following stream combinations on both
* {@link CameraMetadata#INFO_SUPPORTED_HARDWARE_LEVEL_FULL FULL} and
* {@link CameraMetadata#INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED LIMITED} devices:
*
- * <h5>RAW-capability additional guaranteed configurations</h5>
- *
* <table>
* <tr><th colspan="2" id="rb">Target 1</th><th colspan="2" id="rb">Target 2</th><th colspan="2" id="rb">Target 3</th> <th rowspan="2">Sample use case(s)</th> </tr>
* <tr><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th> </tr>
@@ -705,6 +706,8 @@ public abstract class CameraDevice implements AutoCloseable {
* </table><br>
* </p>
*
+ * <h5>BURST-capability additional guaranteed configurations</h5>
+ *
* <p>BURST-capability ({@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES} includes
* {@link CameraMetadata#REQUEST_AVAILABLE_CAPABILITIES_BURST_CAPTURE BURST_CAPTURE}) devices
* support at least the below stream combinations in addition to those for
@@ -713,8 +716,6 @@ public abstract class CameraDevice implements AutoCloseable {
* list for FULL-level devices, so this table is only relevant for LIMITED-level devices that
* support the BURST_CAPTURE capability.
*
- * <h5>BURST-capability additional guaranteed configurations</h5>
- *
* <table>
* <tr><th colspan="2" id="rb">Target 1</th><th colspan="2" id="rb">Target 2</th><th rowspan="2">Sample use case(s)</th> </tr>
* <tr><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th> </tr>
@@ -724,6 +725,8 @@ public abstract class CameraDevice implements AutoCloseable {
* </table><br>
* </p>
*
+ * <h5>LEVEL-3 additional guaranteed configurations</h5>
+ *
* <p>LEVEL-3 ({@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL}
* {@code == }{@link CameraMetadata#INFO_SUPPORTED_HARDWARE_LEVEL_3 LEVEL_3})
* support at least the following stream combinations in addition to the combinations for
@@ -731,8 +734,6 @@ public abstract class CameraDevice implements AutoCloseable {
* RAW capability ({@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES} includes
* {@link CameraMetadata#REQUEST_AVAILABLE_CAPABILITIES_RAW RAW}):
*
- * <h5>LEVEL-3 additional guaranteed configurations</h5>
- *
* <table>
* <tr><th colspan="2" id="rb">Target 1</th><th colspan="2" id="rb">Target 2</th><th colspan="2" id="rb">Target 3</th><th colspan="2" id="rb">Target 4</th><th rowspan="2">Sample use case(s)</th> </tr>
* <tr><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th> </tr>
@@ -741,14 +742,16 @@ public abstract class CameraDevice implements AutoCloseable {
* </table><br>
* </p>
*
- *<p>BACKWARD_COMPATIBLE devices capable of streaming concurrently with other devices as described by
- * {@link android.hardware.camera2.CameraManager#getConcurrentCameraIds} have the
+ * <h5>Concurrent stream guaranteed configurations</h5>
+ *
+ * <p>BACKWARD_COMPATIBLE devices capable of streaming concurrently with other devices as
+ * described by {@link android.hardware.camera2.CameraManager#getConcurrentCameraIds} have the
* following guaranteed streams (when streaming concurrently with other devices)</p>
+ *
* <p> Note: The sizes mentioned for these concurrent streams are the maximum sizes guaranteed
* to be supported. Sizes smaller than these, obtained by {@link StreamConfigurationMap#getOutputSizes} for a particular format, are supported as well. </p>
*
- * <h5>Concurrent stream guaranteed configurations</h5>
- *
+ * <p>
* <table>
* <tr><th colspan="2" id="rb">Target 1</th><th colspan="2" id="rb">Target 2</th><th rowspan="2">Sample use case(s)</th> </tr>
* <tr><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th> </tr>
@@ -784,6 +787,8 @@ public abstract class CameraDevice implements AutoCloseable {
* level and capabilities. Calling createCaptureSession with both JPEG and HEIC outputs is not
* supported.</p>
*
+ * <h5>LEGACY-level additional guaranteed combinations with multi-resolution outputs</h5>
+ *
* <p>Devices capable of multi-resolution output for a particular format (
* {@link android.hardware.camera2.params.MultiResolutionStreamConfigurationMap#getOutputInfo}
* returns a non-empty list) support using {@link MultiResolutionImageReader} for MAXIMUM
@@ -794,8 +799,6 @@ public abstract class CameraDevice implements AutoCloseable {
* stream combinations ({@code MULTI_RES} in the Max size column refers to a {@link
* MultiResolutionImageReader} created based on the variable max resolutions supported):
*
- * <h5>LEGACY-level additional guaranteed combinations with MultiResolutionoutputs</h5>
- *
* <table>
* <tr> <th colspan="2" id="rb">Target 1</th> <th colspan="2" id="rb">Target 2</th> <th colspan="2" id="rb">Target 3</th> <th rowspan="2">Sample use case(s)</th> </tr>
* <tr> <th>Type</th><th id="rb">Max size</th> <th>Type</th><th id="rb">Max size</th> <th>Type</th><th id="rb">Max size</th></tr>
@@ -804,8 +807,12 @@ public abstract class CameraDevice implements AutoCloseable {
* <tr> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code JPEG}</td><td id="rb">{@code MULTI_RES}</td> <td colspan="2" id="rb"></td> <td>Standard still imaging.</td> </tr>
* <tr> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code YUV }</td><td id="rb">{@code PREVIEW}</td> <td>{@code JPEG}</td><td id="rb">{@code MULTI_RES}</td> <td>Still capture plus in-app processing.</td> </tr>
* </table><br>
+ * </p>
+ *
+ * <h5>LIMITED-level additional guaranteed configurations with multi-resolution outputs</h5>
+ *
+ * <p>
* <table>
- * <tr><th colspan="7">LIMITED-level additional guaranteed configurations with MultiResolutionoutputs</th></tr>
* <tr><th colspan="2" id="rb">Target 1</th><th colspan="2" id="rb">Target 2</th><th colspan="2" id="rb">Target 3</th> <th rowspan="2">Sample use case(s)</th> </tr>
* <tr><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th></tr>
* <tr> <td>{@code YUV }</td><td id="rb">{@code PREVIEW}</td> <td>{@code YUV }</td><td id="rb">{@code PREVIEW}</td> <td>{@code JPEG}</td><td id="rb">{@code MULTI_RES}</td> <td>Two-input in-app processing with still capture.</td> </tr>
@@ -813,11 +820,11 @@ public abstract class CameraDevice implements AutoCloseable {
* The same logic applies to other hardware levels and capabilities.
* </p>
*
- * <p> Devices with the ULTRA_HIGH_RESOLUTION_SENSOR capability have some additional guarantees
- * which clients can take advantage of : </p>
- *
* <h5>Additional guaranteed combinations for ULTRA_HIGH_RESOLUTION sensors</h5>
*
+ * <p> Devices with the ULTRA_HIGH_RESOLUTION_SENSOR capability have some additional guarantees
+ * which clients can take advantage of:
+ *
* <table>
* <tr> <th colspan="3" id="rb">Target 1</th> <th colspan="3" id="rb">Target 2</th> <th colspan="3" id="rb">Target 3</th> <th rowspan="2">Sample use case(s)</th> </tr>
* <tr> <th>Type</th><th id="rb"> SC Map</th><th id="rb">Max size</th> <th>Type</th><th id="rb"> SC Map</th><th id="rb">Max size</th> <th>Type</th><th id="rb"> SC Map</th><th id="rb">Max size</th></tr>
@@ -825,6 +832,7 @@ public abstract class CameraDevice implements AutoCloseable {
* <tr> <td>{@code YUV / JPEG / RAW}</td><td id="rb">{@code MAX_RES}</td><td id="rb">{@code MAX}</td><td id="rb">{@code PRIV}</td><td id="rb">{@code DEFAULT}</td><td id="rb">{@code PREVIEW}</td><td id="rb">{@code PRIV / YUV}</td><td id="rb">{@code DEFAULT}</td><td id="rb">{@code RECORD}</td> <td>Ultra high res still capture with preview + app based RECORD size analysis</td> </tr>
* <tr> <td>{@code YUV / JPEG / RAW}</td><td id="rb">{@code MAX_RES}</td><td id="rb">{@code MAX}</td><td id="rb">{@code PRIV}</td><td id="rb">{@code DEFAULT}</td><td id="rb">{@code PREVIEW}</td><td id="rb">{@code JPEG / YUV / RAW}</td><td id="rb">{@code DEFAULT}</td><td id="rb">{@code MAX}</td> <td>Ultra high res still image capture with preview + default sensor pixel mode analysis stream</td> </tr>
* </table><br>
+ * </p>
*
* <p> Here, SC Map, refers to the {@link StreamConfigurationMap}, the target stream sizes must
* be chosen from. {@code DEFAULT} refers to the default sensor pixel mode {@link
@@ -834,17 +842,17 @@ public abstract class CameraDevice implements AutoCloseable {
* Note: The same capture request must not mix targets from
* {@link StreamConfigurationMap}s corresponding to different sensor pixel modes. </p>
*
- * <p> 10-bit output capable
- * {@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES_DYNAMIC_RANGE_TEN_BIT}
- * devices support at least the following stream combinations: </p>
- *
* <h5>10-bit output additional guaranteed configurations</h5>
*
+ * <p>10-bit output capable
+ * {@link CameraMetadata#REQUEST_AVAILABLE_CAPABILITIES_DYNAMIC_RANGE_TEN_BIT}
+ * devices support at least the following stream combinations:
+ *
* <table>
* <tr><th colspan="2" id="rb">Target 1</th><th colspan="2" id="rb">Target 2</th><th colspan="2" id="rb">Target 3</th> <th rowspan="2">Sample use case(s)</th> </tr>
* <tr><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th></tr>
- * <tr> <td>{@code PRIV}</td><td id="rb">{@code MAXIMUM}</td> }</td> <td colspan="4" id="rb"></td> <td>Simple preview, GPU video processing, or no-preview video recording.</td> </tr>
- * <tr> <td>{@code YUV}</td><td id="rb">{@code MAXIMUM}</td> }</td> <td colspan="4" id="rb"></td> <td>In-application video/image processing.</td> </tr>
+ * <tr> <td>{@code PRIV}</td><td id="rb">{@code MAXIMUM}</td> </td> <td colspan="4" id="rb"></td> <td>Simple preview, GPU video processing, or no-preview video recording.</td> </tr>
+ * <tr> <td>{@code YUV}</td><td id="rb">{@code MAXIMUM}</td> </td> <td colspan="4" id="rb"></td> <td>In-application video/image processing.</td> </tr>
* <tr> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code JPEG}</td><td id="rb">{@code MAXIMUM }</td> <td colspan="2" id="rb"></td> <td>Standard still imaging.</td> </tr>
* <tr> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code YUV }</td><td id="rb">{@code MAXIMUM }</td> <td colspan="2" id="rb"></td> <td>Maximum-resolution in-app processing with preview.</td> </tr>
* <tr> <td>{@code YUV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code YUV}</td><td id="rb">{@code MAXIMUM }</td> <td colspan="2" id="rb"></td> <td>Maximum-resolution two-input in-app processing.</td> </tr>
@@ -852,6 +860,8 @@ public abstract class CameraDevice implements AutoCloseable {
* <tr> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code PRIV}</td><td id="rb">{@code RECORD }</td> <td>{@code YUV}</td><td id="rb">{@code RECORD }</td> <td>High-resolution recording with in-app snapshot.</td> </tr>
* <tr> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code PRIV }</td><td id="rb">{@code RECORD }</td> <td>{@code JPEG}</td><td id="rb">{@code RECORD }</td> <td>High-resolution recording with video snapshot.</td> </tr>
* </table><br>
+ * </p>
+ *
* <p>Here PRIV can be either 8 or 10-bit {@link android.graphics.ImageFormat#PRIVATE} pixel
* format. YUV can be either {@link android.graphics.ImageFormat#YUV_420_888} or
* {@link android.graphics.ImageFormat#YCBCR_P010}.
@@ -887,13 +897,13 @@ public abstract class CameraDevice implements AutoCloseable {
* {@link CameraDevice#isSessionConfigurationSupported} to ensure that this particular
* configuration is supported.</p>
*
+ * <h5>STREAM_USE_CASE capability additional guaranteed configurations</h5>
+ *
* <p>Devices with the STREAM_USE_CASE capability ({@link
* CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES} includes {@link
* CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES_STREAM_USE_CASE}) support below additional
* stream combinations:
*
- * <h5>STREAM_USE_CASE capability additional guaranteed configurations</h5>
- *
* <table>
* <tr><th colspan="3" id="rb">Target 1</th><th colspan="3" id="rb">Target 2</th><th colspan="3" id="rb">Target 3</th> <th rowspan="2">Sample use case(s)</th> </tr>
* <tr><th>Type</th><th id="rb">Max size</th><th>Usecase</th><th>Type</th><th id="rb">Max size</th><th>Usecase</th><th>Type</th><th id="rb">Max size</th><th>Usecase</th> </tr>
@@ -913,12 +923,12 @@ public abstract class CameraDevice implements AutoCloseable {
* </table><br>
* </p>
*
+ * <h5>STREAM_USE_CASE_CROPPED_RAW capability additional guaranteed configurations</h5>
+ *
* <p>Devices that include the {@link CameraMetadata#SCALER_AVAILABLE_STREAM_USE_CASES_CROPPED_RAW}
* stream use-case in {@link CameraCharacteristics#SCALER_AVAILABLE_STREAM_USE_CASES},
* support the additional stream combinations below:
*
- * <h5>STREAM_USE_CASE_CROPPED_RAW capability additional guaranteed configurations</h5>
- *
* <table>
* <tr><th colspan="3" id="rb">Target 1</th><th colspan="3" id="rb">Target 2</th><th colspan="3" id="rb">Target 3</th> <th rowspan="2">Sample use case(s)</th> </tr>
* <tr><th>Type</th><th id="rb">Max size</th><th>Usecase</th><th>Type</th><th id="rb">Max size</th><th>Usecase</th><th>Type</th><th id="rb">Max size</th><th>Usecase</th> </tr>
@@ -926,15 +936,17 @@ public abstract class CameraDevice implements AutoCloseable {
* <tr> <td>{@code PRIV / YUV}</td><td id="rb">{@code PREVIEW}</td><td id="rb">{@code PREVIEW}</td> <td>{@code RAW}</td><td id="rb">{@code MAXIMUM}</td><td id="rb">{@code CROPPED_RAW}</td> <td colspan="3" id="rb"></td> <td>Preview with cropped RAW still capture</td> </tr>
* <tr> <td>{@code PRIV / YUV}</td><td id="rb">{@code PREVIEW}</td><td id="rb">{@code PREVIEW}</td> <td>{@code YUV / JPEG}</td><td id="rb">{@code MAXIMUM}</td><td id="rb">{@code STILL_CAPTURE}</td> <td>{@code RAW}</td><td id="rb">{@code MAXIMUM}</td><td id="rb">{@code CROPPED_RAW}</td> <td>Preview with YUV / JPEG and cropped RAW still capture</td> </tr>
* <tr> <td>{@code PRIV / YUV}</td><td id="rb">{@code PREVIEW}</td><td id="rb">{@code PREVIEW}</td> <td>{@code PRIV / YUV}</td><td id="rb">{@code PREVIEW}</td><td id="rb">{@code VIDEO_RECORD / PREVIEW}</td> <td>{@code RAW}</td><td id="rb">{@code MAXIMUM}</td><td id="rb">{@code CROPPED_RAW}</td> <td>Video recording with preview and cropped RAW still capture</td> </tr>
+ * </table><br>
+ * </p>
*
+ * <h5>Preview stabilization guaranteed stream configurations</h5>
*
- *<p> For devices where {@link CameraCharacteristics#CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES}
- * includes {@link CameraMetadata#CONTROL_VIDEO_STABILIZATION_MODE_PREVIEW_STABILIZATION},
+ * <p>For devices where
+ * {@link CameraCharacteristics#CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES} includes
+ * {@link CameraMetadata#CONTROL_VIDEO_STABILIZATION_MODE_PREVIEW_STABILIZATION},
* the following stream combinations are guaranteed,
* for CaptureRequests where {@link CaptureRequest#CONTROL_VIDEO_STABILIZATION_MODE} is set to
- * {@link CameraMetadata#CONTROL_VIDEO_STABILIZATION_MODE_PREVIEW_STABILIZATION} <p>
- *
- * <h5>Preview stabilization guaranteed stream configurations</h5>
+ * {@link CameraMetadata#CONTROL_VIDEO_STABILIZATION_MODE_PREVIEW_STABILIZATION}
*
* <table>
* <tr><th colspan="2" id="rb">Target 1</th><th colspan="2" id="rb">Target 2</th><th rowspan="2">Sample use case(s)</th> </tr>
@@ -943,6 +955,8 @@ public abstract class CameraDevice implements AutoCloseable {
* <tr> <td>{@code PRIV / YUV}</td><td id="rb">{@code s1440p}</td> <td>{@code JPEG / YUV}</td><td id="rb">{@code MAXIMUM }</td><td>Standard still imaging with stabilized preview.</td> </tr>
* <tr> <td>{@code PRIV / YUV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code PRIV / YUV}</td><td id="rb">{@code s1440p }</td><td>High-resolution recording with stabilized preview and recording stream.</td> </tr>
* </table><br>
+ * </p>
+ *
* <p>
* For the maximum size column, PREVIEW refers to the best size match to the device's screen
* resolution, or to 1080p (1920x1080), whichever is smaller. RECORD refers to the camera
diff --git a/core/java/android/hardware/camera2/CaptureRequest.java b/core/java/android/hardware/camera2/CaptureRequest.java
index 703f16553ddb..dd3238414030 100644
--- a/core/java/android/hardware/camera2/CaptureRequest.java
+++ b/core/java/android/hardware/camera2/CaptureRequest.java
@@ -16,6 +16,7 @@
package android.hardware.camera2;
+import android.annotation.FlaggedApi;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.compat.annotation.UnsupportedAppUsage;
@@ -34,6 +35,8 @@ import android.util.Log;
import android.util.SparseArray;
import android.view.Surface;
+import com.android.internal.camera.flags.Flags;
+
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
diff --git a/core/java/android/hardware/camera2/CaptureResult.java b/core/java/android/hardware/camera2/CaptureResult.java
index 746648ba7ac5..9a800150ef27 100644
--- a/core/java/android/hardware/camera2/CaptureResult.java
+++ b/core/java/android/hardware/camera2/CaptureResult.java
@@ -16,6 +16,7 @@
package android.hardware.camera2;
+import android.annotation.FlaggedApi;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.compat.annotation.UnsupportedAppUsage;
@@ -28,6 +29,8 @@ import android.os.Build;
import android.util.Log;
import android.util.Rational;
+import com.android.internal.camera.flags.Flags;
+
import java.util.List;
/**
diff --git a/core/java/android/inputmethodservice/NavigationBarController.java b/core/java/android/inputmethodservice/NavigationBarController.java
index c01664e55744..8be4c5858694 100644
--- a/core/java/android/inputmethodservice/NavigationBarController.java
+++ b/core/java/android/inputmethodservice/NavigationBarController.java
@@ -237,7 +237,7 @@ final class NavigationBarController {
mNavigationBarFrame.setOnApplyWindowInsetsListener((view, insets) -> {
if (mNavigationBarFrame != null) {
boolean visible = insets.isVisible(captionBar());
- mNavigationBarFrame.setVisibility(visible ? View.VISIBLE : View.INVISIBLE);
+ mNavigationBarFrame.setVisibility(visible ? View.VISIBLE : View.GONE);
}
return view.onApplyWindowInsets(insets);
});
diff --git a/location/java/android/location/GeocoderParams.java b/core/java/android/location/GeocoderParams.java
index 3ea6364e07c5..3ea6364e07c5 100644
--- a/location/java/android/location/GeocoderParams.java
+++ b/core/java/android/location/GeocoderParams.java
diff --git a/location/java/android/location/Geofence.java b/core/java/android/location/Geofence.java
index 10773f82fa43..10773f82fa43 100644
--- a/location/java/android/location/Geofence.java
+++ b/core/java/android/location/Geofence.java
diff --git a/location/java/android/location/GnssSignalQuality.java b/core/java/android/location/GnssSignalQuality.java
index 7945f3ecf841..7945f3ecf841 100644
--- a/location/java/android/location/GnssSignalQuality.java
+++ b/core/java/android/location/GnssSignalQuality.java
diff --git a/location/java/android/location/IFusedGeofenceHardware.aidl b/core/java/android/location/IFusedGeofenceHardware.aidl
index d8c35851b160..d8c35851b160 100644
--- a/location/java/android/location/IFusedGeofenceHardware.aidl
+++ b/core/java/android/location/IFusedGeofenceHardware.aidl
diff --git a/location/java/android/location/IGpsGeofenceHardware.aidl b/core/java/android/location/IGpsGeofenceHardware.aidl
index 764bf8e86fc2..764bf8e86fc2 100644
--- a/location/java/android/location/IGpsGeofenceHardware.aidl
+++ b/core/java/android/location/IGpsGeofenceHardware.aidl
diff --git a/location/java/android/location/Location.aidl b/core/java/android/location/Location.aidl
index f47b4886e3c0..f47b4886e3c0 100644
--- a/location/java/android/location/Location.aidl
+++ b/core/java/android/location/Location.aidl
diff --git a/location/java/android/location/Location.java b/core/java/android/location/Location.java
index fd3e5a22e969..fd3e5a22e969 100644
--- a/location/java/android/location/Location.java
+++ b/core/java/android/location/Location.java
diff --git a/location/java/android/location/LocationTime.java b/core/java/android/location/LocationTime.java
index 2f03508fbb15..2f03508fbb15 100644
--- a/location/java/android/location/LocationTime.java
+++ b/core/java/android/location/LocationTime.java
diff --git a/core/java/android/os/vibrator/flags.aconfig b/core/java/android/os/vibrator/flags.aconfig
index 361e244ac876..c01ef3d79bb9 100644
--- a/core/java/android/os/vibrator/flags.aconfig
+++ b/core/java/android/os/vibrator/flags.aconfig
@@ -1,8 +1,15 @@
package: "android.os.vibrator"
flag {
- namespace: "vibrator"
+ namespace: "haptics"
name: "use_vibrator_haptic_feedback"
description: "Enables performHapticFeedback to directly use the vibrator service instead of going through the window session"
bug: "295459081"
+}
+
+flag {
+ namespace: "haptics"
+ name: "haptics_customization_enabled"
+ description: "Enables the haptics customization feature"
+ bug: "241918098"
} \ No newline at end of file
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 82756af54c13..f823dbcec7f2 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -4871,13 +4871,13 @@ public final class Settings {
public static final String PEAK_REFRESH_RATE = "peak_refresh_rate";
/**
- * Control whether to stay awake on fold
+ * Control lock behavior on fold
*
* If this isn't set, the system falls back to a device specific default.
* @hide
*/
@Readable
- public static final String STAY_AWAKE_ON_FOLD = "stay_awake_on_fold";
+ public static final String FOLD_LOCK_BEHAVIOR = "fold_lock_behavior_setting";
/**
* The amount of time in milliseconds before the device goes to sleep or begins
diff --git a/core/java/android/util/FeatureFlagUtils.java b/core/java/android/util/FeatureFlagUtils.java
index 5fe2aa1f5295..12527e91a87c 100644
--- a/core/java/android/util/FeatureFlagUtils.java
+++ b/core/java/android/util/FeatureFlagUtils.java
@@ -254,7 +254,6 @@ public class FeatureFlagUtils {
DEFAULT_FLAGS.put(SETTINGS_ENABLE_LOCKSCREEN_TRANSFER_API, "true");
DEFAULT_FLAGS.put(SETTINGS_REMOTE_DEVICE_CREDENTIAL_VALIDATION, "true");
DEFAULT_FLAGS.put(SETTINGS_BIOMETRICS2_FINGERPRINT_SETTINGS, "false");
- DEFAULT_FLAGS.put("settings_press_hold_nav_handle_to_search", "false");
// TODO: b/298454866 Replace with Trunk Stable Feature Flag
DEFAULT_FLAGS.put(SETTINGS_REMOTEAUTH_ENROLLMENT_SETTINGS, "false");
}
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 30fd2cfa5f28..81edd3c5b811 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -2449,7 +2449,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* @see #getId()
*/
@IdRes
- @ViewDebug.ExportedProperty(resolveId = true)
int mID = NO_ID;
/** The ID of this view for autofill purposes.
@@ -4300,71 +4299,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* This view's request for the visibility of the status bar.
* @hide
*/
- @ViewDebug.ExportedProperty(flagMapping = {
- @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LOW_PROFILE,
- equals = SYSTEM_UI_FLAG_LOW_PROFILE,
- name = "LOW_PROFILE"),
- @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
- equals = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
- name = "HIDE_NAVIGATION"),
- @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_FULLSCREEN,
- equals = SYSTEM_UI_FLAG_FULLSCREEN,
- name = "FULLSCREEN"),
- @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LAYOUT_STABLE,
- equals = SYSTEM_UI_FLAG_LAYOUT_STABLE,
- name = "LAYOUT_STABLE"),
- @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION,
- equals = SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION,
- name = "LAYOUT_HIDE_NAVIGATION"),
- @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN,
- equals = SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN,
- name = "LAYOUT_FULLSCREEN"),
- @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_IMMERSIVE,
- equals = SYSTEM_UI_FLAG_IMMERSIVE,
- name = "IMMERSIVE"),
- @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_IMMERSIVE_STICKY,
- equals = SYSTEM_UI_FLAG_IMMERSIVE_STICKY,
- name = "IMMERSIVE_STICKY"),
- @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LIGHT_STATUS_BAR,
- equals = SYSTEM_UI_FLAG_LIGHT_STATUS_BAR,
- name = "LIGHT_STATUS_BAR"),
- @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR,
- equals = SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR,
- name = "LIGHT_NAVIGATION_BAR"),
- @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_EXPAND,
- equals = STATUS_BAR_DISABLE_EXPAND,
- name = "STATUS_BAR_DISABLE_EXPAND"),
- @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_NOTIFICATION_ICONS,
- equals = STATUS_BAR_DISABLE_NOTIFICATION_ICONS,
- name = "STATUS_BAR_DISABLE_NOTIFICATION_ICONS"),
- @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_NOTIFICATION_ALERTS,
- equals = STATUS_BAR_DISABLE_NOTIFICATION_ALERTS,
- name = "STATUS_BAR_DISABLE_NOTIFICATION_ALERTS"),
- @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_NOTIFICATION_TICKER,
- equals = STATUS_BAR_DISABLE_NOTIFICATION_TICKER,
- name = "STATUS_BAR_DISABLE_NOTIFICATION_TICKER"),
- @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_SYSTEM_INFO,
- equals = STATUS_BAR_DISABLE_SYSTEM_INFO,
- name = "STATUS_BAR_DISABLE_SYSTEM_INFO"),
- @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_HOME,
- equals = STATUS_BAR_DISABLE_HOME,
- name = "STATUS_BAR_DISABLE_HOME"),
- @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_BACK,
- equals = STATUS_BAR_DISABLE_BACK,
- name = "STATUS_BAR_DISABLE_BACK"),
- @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_CLOCK,
- equals = STATUS_BAR_DISABLE_CLOCK,
- name = "STATUS_BAR_DISABLE_CLOCK"),
- @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_RECENT,
- equals = STATUS_BAR_DISABLE_RECENT,
- name = "STATUS_BAR_DISABLE_RECENT"),
- @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_SEARCH,
- equals = STATUS_BAR_DISABLE_SEARCH,
- name = "STATUS_BAR_DISABLE_SEARCH"),
- @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_ONGOING_CALL_CHIP,
- equals = STATUS_BAR_DISABLE_ONGOING_CALL_CHIP,
- name = "STATUS_BAR_DISABLE_ONGOING_CALL_CHIP")
- }, formatToHexString = true)
@SystemUiVisibility
int mSystemUiVisibility;
@@ -4483,7 +4417,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* to the left edge of this view.
* {@hide}
*/
- @ViewDebug.ExportedProperty(category = "layout")
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
protected int mLeft;
/**
@@ -4491,7 +4424,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* to the right edge of this view.
* {@hide}
*/
- @ViewDebug.ExportedProperty(category = "layout")
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
protected int mRight;
/**
@@ -4499,7 +4431,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* to the top edge of this view.
* {@hide}
*/
- @ViewDebug.ExportedProperty(category = "layout")
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
protected int mTop;
/**
@@ -4507,7 +4438,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* to the bottom edge of this view.
* {@hide}
*/
- @ViewDebug.ExportedProperty(category = "layout")
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
protected int mBottom;
@@ -4518,7 +4448,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* accessing these directly.
* {@hide}
*/
- @ViewDebug.ExportedProperty(category = "scrolling")
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
protected int mScrollX;
/**
@@ -4528,7 +4457,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* accessing these directly.
* {@hide}
*/
- @ViewDebug.ExportedProperty(category = "scrolling")
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
protected int mScrollY;
@@ -4537,7 +4465,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* pixels between the left edge of this view and the left edge of its content.
* {@hide}
*/
- @ViewDebug.ExportedProperty(category = "padding")
@UnsupportedAppUsage
protected int mPaddingLeft = 0;
/**
@@ -4545,7 +4472,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* pixels between the right edge of this view and the right edge of its content.
* {@hide}
*/
- @ViewDebug.ExportedProperty(category = "padding")
@UnsupportedAppUsage
protected int mPaddingRight = 0;
/**
@@ -4553,7 +4479,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* pixels between the top edge of this view and the top edge of its content.
* {@hide}
*/
- @ViewDebug.ExportedProperty(category = "padding")
@UnsupportedAppUsage
protected int mPaddingTop;
/**
@@ -4561,7 +4486,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* pixels between the bottom edge of this view and the bottom edge of its content.
* {@hide}
*/
- @ViewDebug.ExportedProperty(category = "padding")
@UnsupportedAppUsage
protected int mPaddingBottom;
@@ -17923,6 +17847,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* @return The left edge of the displayed part of your view, in pixels.
*/
@InspectableProperty
+ @ViewDebug.ExportedProperty(category = "scrolling")
public final int getScrollX() {
return mScrollX;
}
@@ -17935,6 +17860,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* @return The top edge of the displayed part of your view, in pixels.
*/
@InspectableProperty
+ @ViewDebug.ExportedProperty(category = "scrolling")
public final int getScrollY() {
return mScrollY;
}
@@ -18725,6 +18651,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* @return The top of this view, in pixels.
*/
@ViewDebug.CapturedViewProperty
+ @ViewDebug.ExportedProperty(category = "layout")
public final int getTop() {
return mTop;
}
@@ -18784,6 +18711,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* @return The bottom of this view, in pixels.
*/
@ViewDebug.CapturedViewProperty
+ @ViewDebug.ExportedProperty(category = "layout")
public final int getBottom() {
return mBottom;
}
@@ -18849,6 +18777,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* @return The left edge of this view, in pixels.
*/
@ViewDebug.CapturedViewProperty
+ @ViewDebug.ExportedProperty(category = "layout")
public final int getLeft() {
return mLeft;
}
@@ -18908,6 +18837,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* @return The right edge of this view, in pixels.
*/
@ViewDebug.CapturedViewProperty
+ @ViewDebug.ExportedProperty(category = "layout")
public final int getRight() {
return mRight;
}
@@ -26135,6 +26065,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* @return the top padding in pixels
*/
@InspectableProperty
+ @ViewDebug.ExportedProperty(category = "padding")
public int getPaddingTop() {
return mPaddingTop;
}
@@ -26147,6 +26078,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* @return the bottom padding in pixels
*/
@InspectableProperty
+ @ViewDebug.ExportedProperty(category = "padding")
public int getPaddingBottom() {
return mPaddingBottom;
}
@@ -26159,6 +26091,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* @return the left padding in pixels
*/
@InspectableProperty
+ @ViewDebug.ExportedProperty(category = "padding")
public int getPaddingLeft() {
if (!isPaddingResolved()) {
resolvePadding();
@@ -26189,6 +26122,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* @return the right padding in pixels
*/
@InspectableProperty
+ @ViewDebug.ExportedProperty(category = "padding")
public int getPaddingRight() {
if (!isPaddingResolved()) {
resolvePadding();
@@ -26874,6 +26808,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
*/
@IdRes
@ViewDebug.CapturedViewProperty
+ @ViewDebug.ExportedProperty(resolveId = true)
@InspectableProperty
public int getId() {
return mID;
@@ -27853,6 +27788,71 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* @deprecated SystemUiVisibility flags are deprecated. Use {@link WindowInsetsController}
* instead.
*/
+ @ViewDebug.ExportedProperty(flagMapping = {
+ @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LOW_PROFILE,
+ equals = SYSTEM_UI_FLAG_LOW_PROFILE,
+ name = "LOW_PROFILE"),
+ @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
+ equals = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
+ name = "HIDE_NAVIGATION"),
+ @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_FULLSCREEN,
+ equals = SYSTEM_UI_FLAG_FULLSCREEN,
+ name = "FULLSCREEN"),
+ @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LAYOUT_STABLE,
+ equals = SYSTEM_UI_FLAG_LAYOUT_STABLE,
+ name = "LAYOUT_STABLE"),
+ @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION,
+ equals = SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION,
+ name = "LAYOUT_HIDE_NAVIGATION"),
+ @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN,
+ equals = SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN,
+ name = "LAYOUT_FULLSCREEN"),
+ @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_IMMERSIVE,
+ equals = SYSTEM_UI_FLAG_IMMERSIVE,
+ name = "IMMERSIVE"),
+ @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_IMMERSIVE_STICKY,
+ equals = SYSTEM_UI_FLAG_IMMERSIVE_STICKY,
+ name = "IMMERSIVE_STICKY"),
+ @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LIGHT_STATUS_BAR,
+ equals = SYSTEM_UI_FLAG_LIGHT_STATUS_BAR,
+ name = "LIGHT_STATUS_BAR"),
+ @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR,
+ equals = SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR,
+ name = "LIGHT_NAVIGATION_BAR"),
+ @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_EXPAND,
+ equals = STATUS_BAR_DISABLE_EXPAND,
+ name = "STATUS_BAR_DISABLE_EXPAND"),
+ @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_NOTIFICATION_ICONS,
+ equals = STATUS_BAR_DISABLE_NOTIFICATION_ICONS,
+ name = "STATUS_BAR_DISABLE_NOTIFICATION_ICONS"),
+ @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_NOTIFICATION_ALERTS,
+ equals = STATUS_BAR_DISABLE_NOTIFICATION_ALERTS,
+ name = "STATUS_BAR_DISABLE_NOTIFICATION_ALERTS"),
+ @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_NOTIFICATION_TICKER,
+ equals = STATUS_BAR_DISABLE_NOTIFICATION_TICKER,
+ name = "STATUS_BAR_DISABLE_NOTIFICATION_TICKER"),
+ @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_SYSTEM_INFO,
+ equals = STATUS_BAR_DISABLE_SYSTEM_INFO,
+ name = "STATUS_BAR_DISABLE_SYSTEM_INFO"),
+ @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_HOME,
+ equals = STATUS_BAR_DISABLE_HOME,
+ name = "STATUS_BAR_DISABLE_HOME"),
+ @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_BACK,
+ equals = STATUS_BAR_DISABLE_BACK,
+ name = "STATUS_BAR_DISABLE_BACK"),
+ @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_CLOCK,
+ equals = STATUS_BAR_DISABLE_CLOCK,
+ name = "STATUS_BAR_DISABLE_CLOCK"),
+ @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_RECENT,
+ equals = STATUS_BAR_DISABLE_RECENT,
+ name = "STATUS_BAR_DISABLE_RECENT"),
+ @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_SEARCH,
+ equals = STATUS_BAR_DISABLE_SEARCH,
+ name = "STATUS_BAR_DISABLE_SEARCH"),
+ @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_ONGOING_CALL_CHIP,
+ equals = STATUS_BAR_DISABLE_ONGOING_CALL_CHIP,
+ name = "STATUS_BAR_DISABLE_ONGOING_CALL_CHIP")
+ }, formatToHexString = true)
@Deprecated
public int getSystemUiVisibility() {
return mSystemUiVisibility;
diff --git a/core/java/android/view/inputmethod/RemoteInputConnectionImpl.java b/core/java/android/view/inputmethod/RemoteInputConnectionImpl.java
index f67a61be5879..61470f2bc71a 100644
--- a/core/java/android/view/inputmethod/RemoteInputConnectionImpl.java
+++ b/core/java/android/view/inputmethod/RemoteInputConnectionImpl.java
@@ -28,7 +28,13 @@ import static java.lang.annotation.RetentionPolicy.SOURCE;
import android.annotation.AnyThread;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.UiThread;
+import android.app.UriGrantsManager;
+import android.content.ContentProvider;
+import android.content.Intent;
import android.graphics.RectF;
+import android.net.Uri;
+import android.os.Binder;
import android.os.Bundle;
import android.os.CancellationSignal;
import android.os.CancellationSignalBeamer;
@@ -37,6 +43,7 @@ import android.os.IBinder;
import android.os.Looper;
import android.os.ResultReceiver;
import android.os.Trace;
+import android.os.UserHandle;
import android.util.Log;
import android.util.proto.ProtoOutputStream;
import android.view.KeyEvent;
@@ -1143,7 +1150,22 @@ final class RemoteInputConnectionImpl extends IRemoteInputConnection.Stub {
public void commitContent(InputConnectionCommandHeader header,
InputContentInfo inputContentInfo, int flags, Bundle opts,
AndroidFuture future /* T=Boolean */) {
+ final int imeUid = Binder.getCallingUid();
dispatchWithTracing("commitContent", future, () -> {
+ // Check if the originator IME has the right permissions
+ try {
+ final int contentUriOwnerUserId = ContentProvider.getUserIdFromUri(
+ inputContentInfo.getContentUri(), UserHandle.getUserId(imeUid));
+ final Uri contentUriWithoutUserId = ContentProvider.getUriWithoutUserId(
+ inputContentInfo.getContentUri());
+ UriGrantsManager.getService().checkGrantUriPermission_ignoreNonSystem(imeUid, null,
+ contentUriWithoutUserId, Intent.FLAG_GRANT_READ_URI_PERMISSION,
+ contentUriOwnerUserId);
+ } catch (Exception e) {
+ Log.w(TAG, "commitContent with invalid Uri permission from IME:", e);
+ return false;
+ }
+
if (header.mSessionId != mCurrentSessionId.get()) {
return false; // cancelled
}
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 6523fffc4b91..f5b81b027134 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -50,6 +50,7 @@ import android.util.SparseArray;
import android.view.DragEvent;
import android.view.KeyEvent;
import android.view.MotionEvent;
+import android.view.PointerIcon;
import android.view.View;
import android.view.ViewDebug;
import android.view.ViewGroup;
@@ -3139,4 +3140,15 @@ public class WebView extends AbsoluteLayout
if (result == null) return super.onApplyWindowInsets(insets);
return result;
}
+
+ @Override
+ @Nullable
+ public PointerIcon onResolvePointerIcon(@NonNull MotionEvent event, int pointerIndex) {
+ PointerIcon icon =
+ mProvider.getViewDelegate().onResolvePointerIcon(event, pointerIndex);
+ if (icon != null) {
+ return icon;
+ }
+ return super.onResolvePointerIcon(event, pointerIndex);
+ }
}
diff --git a/core/java/android/webkit/WebViewProvider.java b/core/java/android/webkit/WebViewProvider.java
index 26579c5dec68..ca423e030044 100644
--- a/core/java/android/webkit/WebViewProvider.java
+++ b/core/java/android/webkit/WebViewProvider.java
@@ -39,6 +39,7 @@ import android.util.SparseArray;
import android.view.DragEvent;
import android.view.KeyEvent;
import android.view.MotionEvent;
+import android.view.PointerIcon;
import android.view.View;
import android.view.ViewGroup.LayoutParams;
import android.view.WindowInsets;
@@ -496,6 +497,15 @@ public interface WebViewProvider {
default WindowInsets onApplyWindowInsets(@Nullable WindowInsets insets) {
return null;
}
+
+ /**
+ * @hide Only used by WebView.
+ */
+ @SuppressWarnings("unused")
+ @Nullable
+ default PointerIcon onResolvePointerIcon(@NonNull MotionEvent event, int pointerIndex) {
+ return null;
+ }
}
interface ScrollDelegate {
diff --git a/core/java/android/widget/SearchView.java b/core/java/android/widget/SearchView.java
index da094893abb9..b4d7a943ff17 100755
--- a/core/java/android/widget/SearchView.java
+++ b/core/java/android/widget/SearchView.java
@@ -2109,7 +2109,7 @@ public class SearchView extends LinearLayout implements CollapsibleActionView {
return;
}
- if (imm.isActive(this)) {
+ if (imm.hasActiveInputConnection(this)) {
// This means that SearchAutoComplete is already connected to the IME.
// InputMethodManager#showSoftInput() is guaranteed to pass client-side focus check.
mHasPendingShowSoftInputRequest = false;
diff --git a/core/java/android/window/flags/windowing_sdk.aconfig b/core/java/android/window/flags/windowing_sdk.aconfig
index 560e41b1aa33..b8d251fc5cc5 100644
--- a/core/java/android/window/flags/windowing_sdk.aconfig
+++ b/core/java/android/window/flags/windowing_sdk.aconfig
@@ -8,3 +8,10 @@ flag {
description: "Whether the feature to sync different window-related config updates is enabled"
bug: "260873529"
}
+
+flag {
+ namespace: "windowing_sdk"
+ name: "activity_embedding_overlay_presentation_flag"
+ description: "Whether the overlay presentation feature is enabled"
+ bug: "243518738"
+}
diff --git a/core/java/com/android/internal/content/InstallLocationUtils.java b/core/java/com/android/internal/content/InstallLocationUtils.java
index a173ce16feea..f3dd0f8f6993 100644
--- a/core/java/com/android/internal/content/InstallLocationUtils.java
+++ b/core/java/com/android/internal/content/InstallLocationUtils.java
@@ -454,8 +454,10 @@ public class InstallLocationUtils {
// Include raw dex metadata files
sizeBytes += DexMetadataHelper.getPackageDexMetadataSize(pkg);
- // Include all relevant native code
- sizeBytes += NativeLibraryHelper.sumNativeBinariesWithOverride(handle, abiOverride);
+ if (pkg.isExtractNativeLibs()) {
+ // Include all relevant native code
+ sizeBytes += NativeLibraryHelper.sumNativeBinariesWithOverride(handle, abiOverride);
+ }
return sizeBytes;
}
diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java
index 86ca077d77d9..3e16df4d7f67 100644
--- a/core/java/com/android/internal/policy/DecorView.java
+++ b/core/java/com/android/internal/policy/DecorView.java
@@ -2624,8 +2624,7 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
@Override
public String toString() {
- return "DecorView@" + Integer.toHexString(this.hashCode()) + "["
- + getTitleSuffix(mWindow.getAttributes()) + "]";
+ return super.toString() + "[" + getTitleSuffix(mWindow.getAttributes()) + "]";
}
private static class ColorViewState {
diff --git a/core/java/com/android/internal/util/SettingsWrapper.java b/core/java/com/android/internal/util/SettingsWrapper.java
new file mode 100644
index 000000000000..8cf6c18adb3a
--- /dev/null
+++ b/core/java/com/android/internal/util/SettingsWrapper.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2023 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.internal.util;
+
+import android.content.ContentResolver;
+import android.provider.Settings;
+
+/**
+ * A wrapper class for accessing and modifying system settings that would help with testing.
+ */
+public class SettingsWrapper {
+
+ /** Retrieves the string value of a system setting */
+ public String getStringForUser(ContentResolver contentResolver, String name, int userHandle) {
+ return Settings.System.getStringForUser(contentResolver, name, userHandle);
+ }
+
+ /** Updates the string value of a system setting */
+ public String putStringForUser(ContentResolver contentResolver, String name, int userHandle) {
+ return Settings.System.getStringForUser(contentResolver, name, userHandle);
+ }
+}
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 03480e42e5ac..367a4f5f050d 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -935,6 +935,9 @@
without impacting power, performance, and app compatibility (e.g. protected content). -->
<bool name="config_reduceBrightColorsAvailable">@bool/config_setColorTransformAccelerated</bool>
+ <!-- Whether to show Fold lock behavior setting feature in Settings App -->
+ <bool name="config_fold_lock_behavior">false</bool>
+
<string-array name="config_reduceBrightColorsCoefficientsNonlinear">
<!-- a-coefficient --> <item>-0.4429953456</item>
<!-- b-coefficient --> <item>-0.2434077725</item>
@@ -5480,6 +5483,13 @@
of known compatibility issues. -->
<string-array name="config_highRefreshRateBlacklist"></string-array>
+ <!-- The list of packages to automatically opt in to refresh rate suppressing by small area
+ detection. Format of this array should be packageName:threshold and threshold value should
+ be between 0 to 1-->
+ <string-array name="config_smallAreaDetectionAllowlist" translatable="false">
+ <!-- Add packages:threshold here -->
+ </string-array>
+
<!-- The list of packages to force slowJpegMode for Apps using Camera API1 -->
<string-array name="config_forceSlowJpegModeList" translatable="false">
<!-- Add packages here -->
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 7ea597420746..1965172c8047 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -343,6 +343,7 @@
<java-symbol type="string" name="config_defaultHealthConnectApp" />
<java-symbol type="bool" name="config_sendAudioBecomingNoisy" />
<java-symbol type="bool" name="config_enableScreenshotChord" />
+ <java-symbol type="bool" name="config_fold_lock_behavior" />
<java-symbol type="bool" name="config_enableWifiDisplay" />
<java-symbol type="bool" name="config_allowAnimationsInLowPowerMode" />
<java-symbol type="bool" name="config_useDevInputEventForAudioJack" />
@@ -4288,6 +4289,8 @@
<java-symbol type="array" name="config_highRefreshRateBlacklist" />
<java-symbol type="array" name="config_forceSlowJpegModeList" />
+ <java-symbol type="array" name="config_smallAreaDetectionAllowlist" />
+
<java-symbol type="layout" name="chooser_dialog" />
<java-symbol type="layout" name="chooser_dialog_item" />
<java-symbol type="drawable" name="chooser_dialog_background" />
diff --git a/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java b/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java
index a41fb64716e2..0778311e98bd 100644
--- a/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java
+++ b/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java
@@ -67,7 +67,6 @@ import android.view.View;
import android.window.WindowContextInfo;
import android.window.WindowTokenClientController;
-import androidx.test.filters.FlakyTest;
import androidx.test.filters.MediumTest;
import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.rule.ActivityTestRule;
@@ -254,15 +253,9 @@ public class ActivityThreadTest {
// Execute a local relaunch item with current scaled config (e.g. simulate recreate),
// the config should not be scaled again.
- final Configuration currentConfig = activity.getResources().getConfiguration();
- final ClientTransaction localTransaction =
- newTransaction(activityThread, activity.getActivityToken());
- localTransaction.addCallback(ActivityRelaunchItem.obtain(
- null /* pendingResults */, null /* pendingIntents */, 0 /* configChanges */,
- new MergedConfiguration(currentConfig, currentConfig),
- true /* preserveWindow */));
InstrumentationRegistry.getInstrumentation().runOnMainSync(
- () -> activityThread.executeTransaction(localTransaction));
+ () -> activityThread.executeTransaction(
+ newRelaunchResumeTransaction(activity)));
assertScreenScale(scale, activity, originalActivityConfig, originalActivityMetrics);
} finally {
@@ -630,7 +623,6 @@ public class ActivityThreadTest {
});
}
- @FlakyTest(bugId = 298331121)
@Test
public void testHandleConfigurationChanged_DoesntOverrideActivityConfig() {
final TestActivity activity = mActivityTestRule.launchActivity(new Intent());
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/util/ExtensionHelper.java b/libs/WindowManager/Jetpack/src/androidx/window/util/ExtensionHelper.java
index 57f83088b2ba..6b193fc53935 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/util/ExtensionHelper.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/util/ExtensionHelper.java
@@ -25,10 +25,12 @@ import android.graphics.Rect;
import android.hardware.display.DisplayManagerGlobal;
import android.util.RotationUtils;
import android.view.DisplayInfo;
+import android.view.Surface;
import android.view.WindowManager;
import androidx.annotation.NonNull;
import androidx.annotation.UiContext;
+import androidx.annotation.VisibleForTesting;
/**
* Util class for both Sidecar and Extensions.
@@ -42,18 +44,41 @@ public final class ExtensionHelper {
/**
* Rotates the input rectangle specified in default display orientation to the current display
* rotation.
+ *
+ * @param displayId the display id.
+ * @param rotation the target rotation relative to the default display orientation.
+ * @param inOutRect the input/output Rect as specified in the default display orientation.
*/
- public static void rotateRectToDisplayRotation(int displayId, int rotation, Rect inOutRect) {
- DisplayManagerGlobal dmGlobal = DisplayManagerGlobal.getInstance();
- DisplayInfo displayInfo = dmGlobal.getDisplayInfo(displayId);
+ public static void rotateRectToDisplayRotation(
+ int displayId, @Surface.Rotation int rotation, @NonNull Rect inOutRect) {
+ final DisplayManagerGlobal dmGlobal = DisplayManagerGlobal.getInstance();
+ final DisplayInfo displayInfo = dmGlobal.getDisplayInfo(displayId);
- boolean isSideRotation = rotation == ROTATION_90 || rotation == ROTATION_270;
- int displayWidth = isSideRotation ? displayInfo.logicalHeight : displayInfo.logicalWidth;
- int displayHeight = isSideRotation ? displayInfo.logicalWidth : displayInfo.logicalHeight;
+ rotateRectToDisplayRotation(displayInfo, rotation, inOutRect);
+ }
+
+ @VisibleForTesting
+ static void rotateRectToDisplayRotation(@NonNull DisplayInfo displayInfo,
+ @Surface.Rotation int rotation, @NonNull Rect inOutRect) {
+ // The inOutRect is specified in the default display orientation, so here we need to get
+ // the display width and height in the default orientation to perform the intersection and
+ // rotation.
+ final boolean isSideRotation =
+ displayInfo.rotation == ROTATION_90 || displayInfo.rotation == ROTATION_270;
+ final int baseDisplayWidth =
+ isSideRotation ? displayInfo.logicalHeight : displayInfo.logicalWidth;
+ final int baseDisplayHeight =
+ isSideRotation ? displayInfo.logicalWidth : displayInfo.logicalHeight;
- inOutRect.intersect(0, 0, displayWidth, displayHeight);
+ final boolean success = inOutRect.intersect(0, 0, baseDisplayWidth, baseDisplayHeight);
+ if (!success) {
+ throw new IllegalArgumentException("inOutRect must intersect with the display."
+ + " inOutRect: " + inOutRect
+ + ", baseDisplayWidth: " + baseDisplayWidth
+ + ", baseDisplayHeight: " + baseDisplayHeight);
+ }
- RotationUtils.rotateBounds(inOutRect, displayWidth, displayHeight, rotation);
+ RotationUtils.rotateBounds(inOutRect, baseDisplayWidth, baseDisplayHeight, rotation);
}
/** Transforms rectangle from absolute coordinate space to the window coordinate space. */
diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/WindowExtensionsTest.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/WindowExtensionsTest.java
index 45564cb46c67..068269297193 100644
--- a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/WindowExtensionsTest.java
+++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/WindowExtensionsTest.java
@@ -32,7 +32,7 @@ import org.junit.Test;
import org.junit.runner.RunWith;
/**
- * Test class for {@link WindowExtensionsTest}.
+ * Test class for {@link WindowExtensions}.
*
* Build/Install/Run:
* atest WMJetpackUnitTests:WindowExtensionsTest
diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/util/ExtensionHelperTest.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/util/ExtensionHelperTest.java
new file mode 100644
index 000000000000..ae783de228fb
--- /dev/null
+++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/util/ExtensionHelperTest.java
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2023 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 androidx.window.util;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThrows;
+
+import android.graphics.Rect;
+import android.platform.test.annotations.Presubmit;
+import android.view.DisplayInfo;
+import android.view.Surface;
+
+import androidx.annotation.NonNull;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Test class for {@link ExtensionHelper}.
+ *
+ * Build/Install/Run:
+ * atest WMJetpackUnitTests:ExtensionHelperTest
+ */
+@Presubmit
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class ExtensionHelperTest {
+
+ private static final int MOCK_DISPLAY_HEIGHT = 1000;
+ private static final int MOCK_DISPLAY_WIDTH = 2000;
+ private static final int MOCK_FEATURE_LEFT = 100;
+ private static final int MOCK_FEATURE_RIGHT = 200;
+
+ private static final int[] ROTATIONS = {
+ Surface.ROTATION_0,
+ Surface.ROTATION_90,
+ Surface.ROTATION_180,
+ Surface.ROTATION_270
+ };
+
+ private static final DisplayInfo[] MOCK_DISPLAY_INFOS = {
+ getMockDisplayInfo(Surface.ROTATION_0),
+ getMockDisplayInfo(Surface.ROTATION_90),
+ getMockDisplayInfo(Surface.ROTATION_180),
+ getMockDisplayInfo(Surface.ROTATION_270),
+ };
+
+ @Test
+ public void testRotateRectToDisplayRotation() {
+ for (int rotation : ROTATIONS) {
+ final Rect expectedResult = getExpectedFeatureRectAfterRotation(rotation);
+ // The method should return correctly rotated Rect even if the requested rotation value
+ // differs from the rotation in DisplayInfo. This is because the WindowConfiguration is
+ // not always synced with DisplayInfo.
+ for (DisplayInfo displayInfo : MOCK_DISPLAY_INFOS) {
+ final Rect rect = getMockFeatureRect();
+ ExtensionHelper.rotateRectToDisplayRotation(displayInfo, rotation, rect);
+ assertEquals(
+ "Result Rect should equal to expected for rotation: " + rotation
+ + "; displayInfo: " + displayInfo,
+ expectedResult, rect);
+ }
+ }
+ }
+
+ @Test
+ public void testRotateRectToDisplayRotation_invalidInputRect() {
+ final Rect invalidRect = new Rect(
+ MOCK_DISPLAY_WIDTH + 10, 0, MOCK_DISPLAY_WIDTH + 10, MOCK_DISPLAY_HEIGHT);
+ assertThrows(IllegalArgumentException.class,
+ () -> ExtensionHelper.rotateRectToDisplayRotation(
+ MOCK_DISPLAY_INFOS[0], ROTATIONS[0], invalidRect));
+ }
+
+
+ @NonNull
+ private static DisplayInfo getMockDisplayInfo(@Surface.Rotation int rotation) {
+ final DisplayInfo displayInfo = new DisplayInfo();
+ displayInfo.rotation = rotation;
+ if (rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_180) {
+ displayInfo.logicalWidth = MOCK_DISPLAY_WIDTH;
+ displayInfo.logicalHeight = MOCK_DISPLAY_HEIGHT;
+ } else {
+ displayInfo.logicalWidth = MOCK_DISPLAY_HEIGHT;
+ displayInfo.logicalHeight = MOCK_DISPLAY_WIDTH;
+ }
+ return displayInfo;
+ }
+
+ @NonNull
+ private static Rect getMockFeatureRect() {
+ return new Rect(MOCK_FEATURE_LEFT, 0, MOCK_FEATURE_RIGHT, MOCK_DISPLAY_HEIGHT);
+ }
+
+ @NonNull
+ private static Rect getExpectedFeatureRectAfterRotation(@Surface.Rotation int rotation) {
+ switch (rotation) {
+ case Surface.ROTATION_0:
+ return new Rect(
+ MOCK_FEATURE_LEFT, 0, MOCK_FEATURE_RIGHT, MOCK_DISPLAY_HEIGHT);
+ case Surface.ROTATION_90:
+ return new Rect(0, MOCK_DISPLAY_WIDTH - MOCK_FEATURE_RIGHT,
+ MOCK_DISPLAY_HEIGHT, MOCK_DISPLAY_WIDTH - MOCK_FEATURE_LEFT);
+ case Surface.ROTATION_180:
+ return new Rect(MOCK_DISPLAY_WIDTH - MOCK_FEATURE_RIGHT, 0,
+ MOCK_DISPLAY_WIDTH - MOCK_FEATURE_LEFT, MOCK_DISPLAY_HEIGHT);
+ case Surface.ROTATION_270:
+ return new Rect(0, MOCK_FEATURE_LEFT, MOCK_DISPLAY_HEIGHT,
+ MOCK_FEATURE_RIGHT);
+ default:
+ throw new IllegalArgumentException("Unknown rotation value: " + rotation);
+ }
+ }
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java
index 9aac694e41bf..04795768aefc 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java
@@ -103,7 +103,7 @@ public class ShellTaskOrganizer extends TaskOrganizer implements
default void onBackPressedOnTaskRoot(RunningTaskInfo taskInfo) {}
/** Whether this task listener supports compat UI. */
default boolean supportCompatUI() {
- // All TaskListeners should support compat UI except PIP.
+ // All TaskListeners should support compat UI except PIP and StageCoordinator.
return true;
}
/** Attaches a child window surface to the task surface. */
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java
index 9a2b81243861..85ea8097a2c1 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java
@@ -973,9 +973,9 @@ public class Bubble implements BubbleViewProvider {
pw.print(" suppressNotif: "); pw.println(shouldSuppressNotification());
pw.print(" autoExpand: "); pw.println(shouldAutoExpand());
pw.print(" isDismissable: "); pw.println(mIsDismissable);
- pw.println(" bubbleMetadataFlagListener null: " + (mBubbleMetadataFlagListener == null));
+ pw.println(" bubbleMetadataFlagListener null?: " + (mBubbleMetadataFlagListener == null));
if (mExpandedView != null) {
- mExpandedView.dump(pw);
+ mExpandedView.dump(pw, " ");
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
index 645a96153080..dfdc79ea7afa 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
@@ -1991,13 +1991,20 @@ public class BubbleController implements ConfigurationChangeListener,
* Description of current bubble state.
*/
private void dump(PrintWriter pw, String prefix) {
- pw.println("BubbleController state:");
+ pw.print(prefix); pw.println("BubbleController state:");
+ pw.print(prefix); pw.println(" currentUserId= " + mCurrentUserId);
+ pw.print(prefix); pw.println(" isStatusBarShade= " + mIsStatusBarShade);
+ pw.print(prefix); pw.println(" isShowingAsBubbleBar= " + isShowingAsBubbleBar());
+ pw.println();
+
mBubbleData.dump(pw);
pw.println();
+
if (mStackView != null) {
mStackView.dump(pw);
}
pw.println();
+
mImpl.mCachedState.dump(pw);
}
@@ -2246,8 +2253,7 @@ public class BubbleController implements ConfigurationChangeListener,
pw.println("mIsStackExpanded: " + mIsStackExpanded);
pw.println("mSelectedBubbleKey: " + mSelectedBubbleKey);
- pw.print("mSuppressedBubbleKeys: ");
- pw.println(mSuppressedBubbleKeys.size());
+ pw.println("mSuppressedBubbleKeys: " + mSuppressedBubbleKeys.size());
for (String key : mSuppressedBubbleKeys) {
pw.println(" suppressing: " + key);
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleData.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleData.java
index cc8f50e09fcb..c6f74af0284b 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleData.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleData.java
@@ -1231,29 +1231,30 @@ public class BubbleData {
* Description of current bubble data state.
*/
public void dump(PrintWriter pw) {
- pw.print("selected: ");
+ pw.println("BubbleData state:");
+ pw.print(" selected: ");
pw.println(mSelectedBubble != null
? mSelectedBubble.getKey()
: "null");
- pw.print("expanded: ");
+ pw.print(" expanded: ");
pw.println(mExpanded);
- pw.print("stack bubble count: ");
+ pw.print("Stack bubble count: ");
pw.println(mBubbles.size());
for (Bubble bubble : mBubbles) {
bubble.dump(pw);
}
- pw.print("overflow bubble count: ");
+ pw.print("Overflow bubble count: ");
pw.println(mOverflowBubbles.size());
for (Bubble bubble : mOverflowBubbles) {
bubble.dump(pw);
}
- pw.print("summaryKeys: ");
+ pw.print("SummaryKeys: ");
pw.println(mSuppressedGroupKeys.size());
for (String key : mSuppressedGroupKeys.keySet()) {
- pw.println(" suppressing: " + key);
+ pw.println(" suppressing: " + key);
}
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleDebugConfig.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleDebugConfig.java
index 76662c47238f..1c0e0522d359 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleDebugConfig.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleDebugConfig.java
@@ -77,20 +77,25 @@ public class BubbleDebugConfig {
static String formatBubblesString(List<Bubble> bubbles, BubbleViewProvider selected) {
StringBuilder sb = new StringBuilder();
- for (Bubble bubble : bubbles) {
+ for (int i = 0; i < bubbles.size(); i++) {
+ Bubble bubble = bubbles.get(i);
if (bubble == null) {
- sb.append(" <null> !!!!!\n");
+ sb.append(" <null> !!!!!");
} else {
boolean isSelected = (selected != null
- && selected.getKey() != BubbleOverflow.KEY
+ && !BubbleOverflow.KEY.equals(selected.getKey())
&& bubble == selected);
String arrow = isSelected ? "=>" : " ";
- sb.append(String.format("%s Bubble{act=%12d, showInShade=%d, key=%s}\n",
+
+ sb.append(String.format("%s Bubble{act=%12d, showInShade=%d, key=%s}",
arrow,
bubble.getLastActivity(),
(bubble.showInShade() ? 1 : 0),
bubble.getKey()));
}
+ if (i != bubbles.size() - 1) {
+ sb.append("\n");
+ }
}
return sb.toString();
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java
index e6986012dd88..37bcf1ddeac5 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java
@@ -1094,9 +1094,9 @@ public class BubbleExpandedView extends LinearLayout {
/**
* Description of current expanded view state.
*/
- public void dump(@NonNull PrintWriter pw) {
- pw.print("BubbleExpandedView");
- pw.print(" taskId: "); pw.println(mTaskId);
- pw.print(" stackView: "); pw.println(mStackView);
+ public void dump(@NonNull PrintWriter pw, @NonNull String prefix) {
+ pw.print(prefix); pw.println("BubbleExpandedView:");
+ pw.print(prefix); pw.print(" taskId: "); pw.println(mTaskId);
+ pw.print(prefix); pw.print(" stackView: "); pw.println(mStackView);
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java
index 52c9bf8462ec..093ecb1e3ade 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java
@@ -305,8 +305,7 @@ public class BubbleStackView extends FrameLayout
String bubblesOnScreen = BubbleDebugConfig.formatBubblesString(
getBubblesOnScreen(), getExpandedBubble());
- pw.print(" stack visibility : "); pw.println(getVisibility());
- pw.print(" bubbles on screen: "); pw.println(bubblesOnScreen);
+ pw.println(" bubbles on screen: "); pw.println(bubblesOnScreen);
pw.print(" gestureInProgress: "); pw.println(mIsGestureInProgress);
pw.print(" showingDismiss: "); pw.println(mDismissView.isShowing());
pw.print(" isExpansionAnimating: "); pw.println(mIsExpansionAnimating);
@@ -314,7 +313,8 @@ public class BubbleStackView extends FrameLayout
pw.print(" expandedContainerAlpha: "); pw.println(mExpandedViewContainer.getAlpha());
pw.print(" expandedContainerMatrix: ");
pw.println(mExpandedViewContainer.getAnimationMatrix());
-
+ pw.print(" stack visibility : "); pw.println(getVisibility());
+ pw.print(" temporarilyInvisible: "); pw.println(mTemporarilyInvisible);
mStackAnimationController.dump(pw);
mExpandedAnimationController.dump(pw);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/UserAspectRatioSettingsWindowManager.java b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/UserAspectRatioSettingsWindowManager.java
index cbff4640239e..77aefc8f7e4a 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/UserAspectRatioSettingsWindowManager.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/UserAspectRatioSettingsWindowManager.java
@@ -208,7 +208,7 @@ class UserAspectRatioSettingsWindowManager extends CompatUIWindowManagerAbstract
}
private boolean getHasUserAspectRatioSettingsButton(@NonNull TaskInfo taskInfo) {
- return taskInfo.topActivityEligibleForUserAspectRatioButton
+ return taskInfo.topActivityEligibleForUserAspectRatioButton
&& (taskInfo.topActivityBoundsLetterboxed
|| taskInfo.isUserFullscreenOverrideEnabled);
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
index 842b1bf9e8af..94fa485efd5c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
@@ -228,6 +228,15 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
private final Toast mSplitUnsupportedToast;
private SplitRequest mSplitRequest;
+ /**
+ * Since StageCoordinator only coordinates MainStage and SideStage, it shouldn't support
+ * CompatUI layouts. CompatUI is handled separately by MainStage and SideStage.
+ */
+ @Override
+ public boolean supportCompatUI() {
+ return false;
+ }
+
class SplitRequest {
@SplitPosition
int mActivatePosition;
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DragPositioningCallbackUtilityTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DragPositioningCallbackUtilityTest.kt
index de46b31879ed..5c0e04aecf6c 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DragPositioningCallbackUtilityTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DragPositioningCallbackUtilityTest.kt
@@ -76,7 +76,7 @@ class DragPositioningCallbackUtilityTest {
minHeight = MIN_HEIGHT
defaultMinSize = DEFAULT_MIN
displayId = DISPLAY_ID
- configuration.windowConfiguration.bounds = STARTING_BOUNDS
+ configuration.windowConfiguration.setBounds(STARTING_BOUNDS)
}
mockWindowDecoration.mDisplay = mockDisplay
whenever(mockDisplay.displayId).thenAnswer { DISPLAY_ID }
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/FluidResizeTaskPositionerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/FluidResizeTaskPositionerTest.kt
index 6f0599aa8243..c0c4498e3ebf 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/FluidResizeTaskPositionerTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/FluidResizeTaskPositionerTest.kt
@@ -88,7 +88,7 @@ class FluidResizeTaskPositionerTest : ShellTestCase() {
minHeight = MIN_HEIGHT
defaultMinSize = DEFAULT_MIN
displayId = DISPLAY_ID
- configuration.windowConfiguration.bounds = STARTING_BOUNDS
+ configuration.windowConfiguration.setBounds(STARTING_BOUNDS)
}
mockWindowDecoration.mDisplay = mockDisplay
whenever(mockDisplay.displayId).thenAnswer { DISPLAY_ID }
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/VeiledResizeTaskPositionerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/VeiledResizeTaskPositionerTest.kt
index 3465ddd9d101..8913453aa578 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/VeiledResizeTaskPositionerTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/VeiledResizeTaskPositionerTest.kt
@@ -104,7 +104,7 @@ class VeiledResizeTaskPositionerTest : ShellTestCase() {
minHeight = MIN_HEIGHT
defaultMinSize = DEFAULT_MIN
displayId = DISPLAY_ID
- configuration.windowConfiguration.bounds = STARTING_BOUNDS
+ configuration.windowConfiguration.setBounds(STARTING_BOUNDS)
}
mockDesktopWindowDecoration.mDisplay = mockDisplay
whenever(mockDisplay.displayId).thenAnswer { DISPLAY_ID }
diff --git a/libs/androidfw/tests/ConfigDescription_test.cpp b/libs/androidfw/tests/ConfigDescription_test.cpp
index ec478b0900ef..07bd17568993 100644
--- a/libs/androidfw/tests/ConfigDescription_test.cpp
+++ b/libs/androidfw/tests/ConfigDescription_test.cpp
@@ -159,17 +159,17 @@ TEST(ConfigDescriptionTest, TestGrammaticalGenderQualifier) {
EXPECT_TRUE(TestParse("feminine", &config));
EXPECT_EQ(android::ResTable_config::GRAMMATICAL_GENDER_FEMININE, config.grammaticalInflection);
EXPECT_EQ(SDK_U, config.sdkVersion);
- EXPECT_EQ(std::string("feminine-v34"), config.toString().string());
+ EXPECT_EQ(std::string("feminine-v34"), config.toString().c_str());
EXPECT_TRUE(TestParse("masculine", &config));
EXPECT_EQ(android::ResTable_config::GRAMMATICAL_GENDER_MASCULINE, config.grammaticalInflection);
EXPECT_EQ(SDK_U, config.sdkVersion);
- EXPECT_EQ(std::string("masculine-v34"), config.toString().string());
+ EXPECT_EQ(std::string("masculine-v34"), config.toString().c_str());
EXPECT_TRUE(TestParse("neuter", &config));
EXPECT_EQ(android::ResTable_config::GRAMMATICAL_GENDER_NEUTER, config.grammaticalInflection);
EXPECT_EQ(SDK_U, config.sdkVersion);
- EXPECT_EQ(std::string("neuter-v34"), config.toString().string());
+ EXPECT_EQ(std::string("neuter-v34"), config.toString().c_str());
}
} // namespace android
diff --git a/libs/androidfw/tests/ResTable_test.cpp b/libs/androidfw/tests/ResTable_test.cpp
index 945981b981a0..faac51403203 100644
--- a/libs/androidfw/tests/ResTable_test.cpp
+++ b/libs/androidfw/tests/ResTable_test.cpp
@@ -468,7 +468,7 @@ TEST_P(ResTableParameterizedTest, ShouldLoadSparseEntriesSuccessfully) {
String16 name(u"com.android.sparse:integer/foo_9");
uint32_t flags;
uint32_t resid =
- table.identifierForName(name.string(), name.size(), nullptr, 0, nullptr, 0, &flags);
+ table.identifierForName(name.c_str(), name.size(), nullptr, 0, nullptr, 0, &flags);
ASSERT_NE(0u, resid);
Res_value val;
diff --git a/libs/input/PointerController.cpp b/libs/input/PointerController.cpp
index c41cd0467ed3..abd928486607 100644
--- a/libs/input/PointerController.cpp
+++ b/libs/input/PointerController.cpp
@@ -354,13 +354,12 @@ const ui::Transform& PointerController::getTransformForDisplayLocked(int display
return it != di.end() ? it->transform : kIdentityTransform;
}
-void PointerController::dump(std::string& dump) {
+std::string PointerController::dump() {
if (!mEnabled) {
- dump += INDENT "PointerController: DISABLED due to ongoing PointerChoreographer refactor\n";
- return;
+ return INDENT "PointerController: DISABLED due to ongoing PointerChoreographer refactor\n";
}
- dump += INDENT "PointerController:\n";
+ std::string dump = INDENT "PointerController:\n";
std::scoped_lock lock(getLock());
dump += StringPrintf(INDENT2 "Presentation: %s\n",
ftl::enum_string(mLocked.presentation).c_str());
@@ -373,6 +372,7 @@ void PointerController::dump(std::string& dump) {
for (const auto& [_, spotController] : mLocked.spotControllers) {
spotController.dump(dump, INDENT3);
}
+ return dump;
}
} // namespace android
diff --git a/libs/input/PointerController.h b/libs/input/PointerController.h
index de39eda75210..aa7ca3c52ecf 100644
--- a/libs/input/PointerController.h
+++ b/libs/input/PointerController.h
@@ -75,7 +75,7 @@ public:
void onDisplayInfosChangedLocked(const std::vector<gui::DisplayInfo>& displayInfos)
REQUIRES(getLock());
- void dump(std::string& dump);
+ std::string dump();
protected:
using WindowListenerConsumer =
diff --git a/location/Android.bp b/location/Android.bp
index 46dca74e7e40..cfe0e494432c 100644
--- a/location/Android.bp
+++ b/location/Android.bp
@@ -7,18 +7,18 @@ package {
default_applicable_licenses: ["frameworks_base_license"],
}
-//location sources that will populate the new module
filegroup {
- name: "framework-location-nonupdatable-sources",
+ name: "framework-location-sources",
srcs: [
- "placeholder_java/android/location/Placeholder.java",
+ "java/**/*.java",
+ "java/**/*.aidl",
],
}
java_sdk_library {
name: "framework-location",
srcs: [
- ":framework-location-nonupdatable-sources",
+ ":framework-location-sources",
],
defaults: ["framework-non-updatable-unbundled-defaults"],
permitted_packages: [
diff --git a/location/api/current.txt b/location/api/current.txt
index d802177e249b..33effdd6cd6c 100644
--- a/location/api/current.txt
+++ b/location/api/current.txt
@@ -1 +1,725 @@
// Signature format: 2.0
+package android.location {
+
+ public class Address implements android.os.Parcelable {
+ ctor public Address(java.util.Locale);
+ method public void clearLatitude();
+ method public void clearLongitude();
+ method public int describeContents();
+ method public String getAddressLine(int);
+ method public String getAdminArea();
+ method public String getCountryCode();
+ method public String getCountryName();
+ method public android.os.Bundle getExtras();
+ method public String getFeatureName();
+ method public double getLatitude();
+ method public java.util.Locale getLocale();
+ method public String getLocality();
+ method public double getLongitude();
+ method public int getMaxAddressLineIndex();
+ method public String getPhone();
+ method public String getPostalCode();
+ method public String getPremises();
+ method public String getSubAdminArea();
+ method public String getSubLocality();
+ method public String getSubThoroughfare();
+ method public String getThoroughfare();
+ method public String getUrl();
+ method public boolean hasLatitude();
+ method public boolean hasLongitude();
+ method public void setAddressLine(int, String);
+ method public void setAdminArea(String);
+ method public void setCountryCode(String);
+ method public void setCountryName(String);
+ method public void setExtras(android.os.Bundle);
+ method public void setFeatureName(String);
+ method public void setLatitude(double);
+ method public void setLocality(String);
+ method public void setLongitude(double);
+ method public void setPhone(String);
+ method public void setPostalCode(String);
+ method public void setPremises(String);
+ method public void setSubAdminArea(String);
+ method public void setSubLocality(String);
+ method public void setSubThoroughfare(String);
+ method public void setThoroughfare(String);
+ method public void setUrl(String);
+ method public void writeToParcel(android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.location.Address> CREATOR;
+ }
+
+ @Deprecated public class Criteria implements android.os.Parcelable {
+ ctor @Deprecated public Criteria();
+ ctor @Deprecated public Criteria(android.location.Criteria);
+ method @Deprecated public int describeContents();
+ method @Deprecated public int getAccuracy();
+ method @Deprecated public int getBearingAccuracy();
+ method @Deprecated public int getHorizontalAccuracy();
+ method @Deprecated public int getPowerRequirement();
+ method @Deprecated public int getSpeedAccuracy();
+ method @Deprecated public int getVerticalAccuracy();
+ method @Deprecated public boolean isAltitudeRequired();
+ method @Deprecated public boolean isBearingRequired();
+ method @Deprecated public boolean isCostAllowed();
+ method @Deprecated public boolean isSpeedRequired();
+ method @Deprecated public void setAccuracy(int);
+ method @Deprecated public void setAltitudeRequired(boolean);
+ method @Deprecated public void setBearingAccuracy(int);
+ method @Deprecated public void setBearingRequired(boolean);
+ method @Deprecated public void setCostAllowed(boolean);
+ method @Deprecated public void setHorizontalAccuracy(int);
+ method @Deprecated public void setPowerRequirement(int);
+ method @Deprecated public void setSpeedAccuracy(int);
+ method @Deprecated public void setSpeedRequired(boolean);
+ method @Deprecated public void setVerticalAccuracy(int);
+ method @Deprecated public void writeToParcel(android.os.Parcel, int);
+ field @Deprecated public static final int ACCURACY_COARSE = 2; // 0x2
+ field @Deprecated public static final int ACCURACY_FINE = 1; // 0x1
+ field @Deprecated public static final int ACCURACY_HIGH = 3; // 0x3
+ field @Deprecated public static final int ACCURACY_LOW = 1; // 0x1
+ field @Deprecated public static final int ACCURACY_MEDIUM = 2; // 0x2
+ field @Deprecated @NonNull public static final android.os.Parcelable.Creator<android.location.Criteria> CREATOR;
+ field @Deprecated public static final int NO_REQUIREMENT = 0; // 0x0
+ field @Deprecated public static final int POWER_HIGH = 3; // 0x3
+ field @Deprecated public static final int POWER_LOW = 1; // 0x1
+ field @Deprecated public static final int POWER_MEDIUM = 2; // 0x2
+ }
+
+ public final class Geocoder {
+ ctor public Geocoder(@NonNull android.content.Context);
+ ctor public Geocoder(@NonNull android.content.Context, @NonNull java.util.Locale);
+ method @Deprecated @Nullable public java.util.List<android.location.Address> getFromLocation(@FloatRange(from=-90.0, to=90.0) double, @FloatRange(from=-180.0, to=180.0) double, @IntRange int) throws java.io.IOException;
+ method public void getFromLocation(@FloatRange(from=-90.0, to=90.0) double, @FloatRange(from=-180.0, to=180.0) double, @IntRange int, @NonNull android.location.Geocoder.GeocodeListener);
+ method @Deprecated @Nullable public java.util.List<android.location.Address> getFromLocationName(@NonNull String, @IntRange int) throws java.io.IOException;
+ method public void getFromLocationName(@NonNull String, @IntRange int, @NonNull android.location.Geocoder.GeocodeListener);
+ method @Deprecated @Nullable public java.util.List<android.location.Address> getFromLocationName(@NonNull String, @IntRange int, @FloatRange(from=-90.0, to=90.0) double, @FloatRange(from=-180.0, to=180.0) double, @FloatRange(from=-90.0, to=90.0) double, @FloatRange(from=-180.0, to=180.0) double) throws java.io.IOException;
+ method public void getFromLocationName(@NonNull String, @IntRange int, @FloatRange(from=-90.0, to=90.0) double, @FloatRange(from=-180.0, to=180.0) double, @FloatRange(from=-90.0, to=90.0) double, @FloatRange(from=-180.0, to=180.0) double, @NonNull android.location.Geocoder.GeocodeListener);
+ method public static boolean isPresent();
+ }
+
+ public static interface Geocoder.GeocodeListener {
+ method public default void onError(@Nullable String);
+ method public void onGeocode(@NonNull java.util.List<android.location.Address>);
+ }
+
+ public final class GnssAntennaInfo implements android.os.Parcelable {
+ method public int describeContents();
+ method @FloatRange(from=0.0f) public double getCarrierFrequencyMHz();
+ method @NonNull public android.location.GnssAntennaInfo.PhaseCenterOffset getPhaseCenterOffset();
+ method @Nullable public android.location.GnssAntennaInfo.SphericalCorrections getPhaseCenterVariationCorrections();
+ method @Nullable public android.location.GnssAntennaInfo.SphericalCorrections getSignalGainCorrections();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.location.GnssAntennaInfo> CREATOR;
+ }
+
+ public static class GnssAntennaInfo.Builder {
+ ctor @Deprecated public GnssAntennaInfo.Builder();
+ ctor public GnssAntennaInfo.Builder(double, @NonNull android.location.GnssAntennaInfo.PhaseCenterOffset);
+ ctor public GnssAntennaInfo.Builder(@NonNull android.location.GnssAntennaInfo);
+ method @NonNull public android.location.GnssAntennaInfo build();
+ method @NonNull public android.location.GnssAntennaInfo.Builder setCarrierFrequencyMHz(@FloatRange(from=0.0f) double);
+ method @NonNull public android.location.GnssAntennaInfo.Builder setPhaseCenterOffset(@NonNull android.location.GnssAntennaInfo.PhaseCenterOffset);
+ method @NonNull public android.location.GnssAntennaInfo.Builder setPhaseCenterVariationCorrections(@Nullable android.location.GnssAntennaInfo.SphericalCorrections);
+ method @NonNull public android.location.GnssAntennaInfo.Builder setSignalGainCorrections(@Nullable android.location.GnssAntennaInfo.SphericalCorrections);
+ }
+
+ public static interface GnssAntennaInfo.Listener {
+ method public void onGnssAntennaInfoReceived(@NonNull java.util.List<android.location.GnssAntennaInfo>);
+ }
+
+ public static final class GnssAntennaInfo.PhaseCenterOffset implements android.os.Parcelable {
+ ctor public GnssAntennaInfo.PhaseCenterOffset(double, double, double, double, double, double);
+ method public int describeContents();
+ method @FloatRange public double getXOffsetMm();
+ method @FloatRange public double getXOffsetUncertaintyMm();
+ method @FloatRange public double getYOffsetMm();
+ method @FloatRange public double getYOffsetUncertaintyMm();
+ method @FloatRange public double getZOffsetMm();
+ method @FloatRange public double getZOffsetUncertaintyMm();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.location.GnssAntennaInfo.PhaseCenterOffset> CREATOR;
+ }
+
+ public static final class GnssAntennaInfo.SphericalCorrections implements android.os.Parcelable {
+ ctor public GnssAntennaInfo.SphericalCorrections(@NonNull double[][], @NonNull double[][]);
+ method public int describeContents();
+ method @NonNull public double[][] getCorrectionUncertaintiesArray();
+ method @NonNull public double[][] getCorrectionsArray();
+ method @FloatRange(from=0.0f, to=180.0f) public double getDeltaPhi();
+ method @FloatRange(from=0.0f, to=360.0f) public double getDeltaTheta();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.location.GnssAntennaInfo.SphericalCorrections> CREATOR;
+ }
+
+ public final class GnssAutomaticGainControl implements android.os.Parcelable {
+ method public int describeContents();
+ method @IntRange(from=0) public long getCarrierFrequencyHz();
+ method public int getConstellationType();
+ method @FloatRange(from=0xffffd8f0, to=10000) public double getLevelDb();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.location.GnssAutomaticGainControl> CREATOR;
+ }
+
+ public static final class GnssAutomaticGainControl.Builder {
+ ctor public GnssAutomaticGainControl.Builder();
+ ctor public GnssAutomaticGainControl.Builder(@NonNull android.location.GnssAutomaticGainControl);
+ method @NonNull public android.location.GnssAutomaticGainControl build();
+ method @NonNull public android.location.GnssAutomaticGainControl.Builder setCarrierFrequencyHz(@IntRange(from=0) long);
+ method @NonNull public android.location.GnssAutomaticGainControl.Builder setConstellationType(int);
+ method @NonNull public android.location.GnssAutomaticGainControl.Builder setLevelDb(@FloatRange(from=0xffffd8f0, to=10000) double);
+ }
+
+ public final class GnssCapabilities implements android.os.Parcelable {
+ method public int describeContents();
+ method @NonNull public java.util.List<android.location.GnssSignalType> getGnssSignalTypes();
+ method public int hasAccumulatedDeltaRange();
+ method public boolean hasAntennaInfo();
+ method public boolean hasGeofencing();
+ method @Deprecated public boolean hasGnssAntennaInfo();
+ method public boolean hasLowPowerMode();
+ method public boolean hasMeasurementCorrections();
+ method public boolean hasMeasurementCorrectionsExcessPathLength();
+ method public boolean hasMeasurementCorrectionsForDriving();
+ method public boolean hasMeasurementCorrectionsLosSats();
+ method public boolean hasMeasurementCorrectionsReflectingPlane();
+ method public boolean hasMeasurementCorrelationVectors();
+ method public boolean hasMeasurements();
+ method public boolean hasMsa();
+ method public boolean hasMsb();
+ method public boolean hasNavigationMessages();
+ method public boolean hasOnDemandTime();
+ method public boolean hasPowerMultibandAcquisition();
+ method public boolean hasPowerMultibandTracking();
+ method public boolean hasPowerOtherModes();
+ method public boolean hasPowerSinglebandAcquisition();
+ method public boolean hasPowerSinglebandTracking();
+ method public boolean hasPowerTotal();
+ method public boolean hasSatelliteBlocklist();
+ method public boolean hasSatellitePvt();
+ method public boolean hasScheduling();
+ method public boolean hasSingleShotFix();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field public static final int CAPABILITY_SUPPORTED = 1; // 0x1
+ field public static final int CAPABILITY_UNKNOWN = 0; // 0x0
+ field public static final int CAPABILITY_UNSUPPORTED = 2; // 0x2
+ field @NonNull public static final android.os.Parcelable.Creator<android.location.GnssCapabilities> CREATOR;
+ }
+
+ public static final class GnssCapabilities.Builder {
+ ctor public GnssCapabilities.Builder();
+ ctor public GnssCapabilities.Builder(@NonNull android.location.GnssCapabilities);
+ method @NonNull public android.location.GnssCapabilities build();
+ method @NonNull public android.location.GnssCapabilities.Builder setGnssSignalTypes(@NonNull java.util.List<android.location.GnssSignalType>);
+ method @NonNull public android.location.GnssCapabilities.Builder setHasAccumulatedDeltaRange(int);
+ method @NonNull public android.location.GnssCapabilities.Builder setHasAntennaInfo(boolean);
+ method @NonNull public android.location.GnssCapabilities.Builder setHasGeofencing(boolean);
+ method @NonNull public android.location.GnssCapabilities.Builder setHasLowPowerMode(boolean);
+ method @NonNull public android.location.GnssCapabilities.Builder setHasMeasurementCorrections(boolean);
+ method @NonNull public android.location.GnssCapabilities.Builder setHasMeasurementCorrectionsExcessPathLength(boolean);
+ method @NonNull public android.location.GnssCapabilities.Builder setHasMeasurementCorrectionsForDriving(boolean);
+ method @NonNull public android.location.GnssCapabilities.Builder setHasMeasurementCorrectionsLosSats(boolean);
+ method @NonNull public android.location.GnssCapabilities.Builder setHasMeasurementCorrectionsReflectingPlane(boolean);
+ method @NonNull public android.location.GnssCapabilities.Builder setHasMeasurementCorrelationVectors(boolean);
+ method @NonNull public android.location.GnssCapabilities.Builder setHasMeasurements(boolean);
+ method @NonNull public android.location.GnssCapabilities.Builder setHasMsa(boolean);
+ method @NonNull public android.location.GnssCapabilities.Builder setHasMsb(boolean);
+ method @NonNull public android.location.GnssCapabilities.Builder setHasNavigationMessages(boolean);
+ method @NonNull public android.location.GnssCapabilities.Builder setHasOnDemandTime(boolean);
+ method @NonNull public android.location.GnssCapabilities.Builder setHasPowerMultibandAcquisition(boolean);
+ method @NonNull public android.location.GnssCapabilities.Builder setHasPowerMultibandTracking(boolean);
+ method @NonNull public android.location.GnssCapabilities.Builder setHasPowerOtherModes(boolean);
+ method @NonNull public android.location.GnssCapabilities.Builder setHasPowerSinglebandAcquisition(boolean);
+ method @NonNull public android.location.GnssCapabilities.Builder setHasPowerSinglebandTracking(boolean);
+ method @NonNull public android.location.GnssCapabilities.Builder setHasPowerTotal(boolean);
+ method @NonNull public android.location.GnssCapabilities.Builder setHasSatelliteBlocklist(boolean);
+ method @NonNull public android.location.GnssCapabilities.Builder setHasSatellitePvt(boolean);
+ method @NonNull public android.location.GnssCapabilities.Builder setHasScheduling(boolean);
+ method @NonNull public android.location.GnssCapabilities.Builder setHasSingleShotFix(boolean);
+ }
+
+ public final class GnssClock implements android.os.Parcelable {
+ method public int describeContents();
+ method public double getBiasNanos();
+ method @FloatRange(from=0.0f) public double getBiasUncertaintyNanos();
+ method public double getDriftNanosPerSecond();
+ method @FloatRange(from=0.0f) public double getDriftUncertaintyNanosPerSecond();
+ method public long getElapsedRealtimeNanos();
+ method @FloatRange(from=0.0f) public double getElapsedRealtimeUncertaintyNanos();
+ method public long getFullBiasNanos();
+ method public int getHardwareClockDiscontinuityCount();
+ method public int getLeapSecond();
+ method @FloatRange(from=0.0) public double getReferenceCarrierFrequencyHzForIsb();
+ method @NonNull public String getReferenceCodeTypeForIsb();
+ method public int getReferenceConstellationTypeForIsb();
+ method public long getTimeNanos();
+ method @FloatRange(from=0.0f) public double getTimeUncertaintyNanos();
+ method public boolean hasBiasNanos();
+ method public boolean hasBiasUncertaintyNanos();
+ method public boolean hasDriftNanosPerSecond();
+ method public boolean hasDriftUncertaintyNanosPerSecond();
+ method public boolean hasElapsedRealtimeNanos();
+ method public boolean hasElapsedRealtimeUncertaintyNanos();
+ method public boolean hasFullBiasNanos();
+ method public boolean hasLeapSecond();
+ method public boolean hasReferenceCarrierFrequencyHzForIsb();
+ method public boolean hasReferenceCodeTypeForIsb();
+ method public boolean hasReferenceConstellationTypeForIsb();
+ method public boolean hasTimeUncertaintyNanos();
+ method public void writeToParcel(android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.location.GnssClock> CREATOR;
+ }
+
+ public final class GnssMeasurement implements android.os.Parcelable {
+ method public int describeContents();
+ method public double getAccumulatedDeltaRangeMeters();
+ method public int getAccumulatedDeltaRangeState();
+ method public double getAccumulatedDeltaRangeUncertaintyMeters();
+ method @Deprecated public double getAutomaticGainControlLevelDb();
+ method @FloatRange(from=0, to=63) public double getBasebandCn0DbHz();
+ method @Deprecated public long getCarrierCycles();
+ method public float getCarrierFrequencyHz();
+ method @Deprecated public double getCarrierPhase();
+ method @Deprecated public double getCarrierPhaseUncertainty();
+ method @FloatRange(from=0, to=63) public double getCn0DbHz();
+ method @NonNull public String getCodeType();
+ method public int getConstellationType();
+ method public double getFullInterSignalBiasNanos();
+ method @FloatRange(from=0.0) public double getFullInterSignalBiasUncertaintyNanos();
+ method public int getMultipathIndicator();
+ method public double getPseudorangeRateMetersPerSecond();
+ method public double getPseudorangeRateUncertaintyMetersPerSecond();
+ method public long getReceivedSvTimeNanos();
+ method public long getReceivedSvTimeUncertaintyNanos();
+ method public double getSatelliteInterSignalBiasNanos();
+ method @FloatRange(from=0.0) public double getSatelliteInterSignalBiasUncertaintyNanos();
+ method public double getSnrInDb();
+ method public int getState();
+ method public int getSvid();
+ method public double getTimeOffsetNanos();
+ method @Deprecated public boolean hasAutomaticGainControlLevelDb();
+ method public boolean hasBasebandCn0DbHz();
+ method @Deprecated public boolean hasCarrierCycles();
+ method public boolean hasCarrierFrequencyHz();
+ method @Deprecated public boolean hasCarrierPhase();
+ method @Deprecated public boolean hasCarrierPhaseUncertainty();
+ method public boolean hasCodeType();
+ method public boolean hasFullInterSignalBiasNanos();
+ method public boolean hasFullInterSignalBiasUncertaintyNanos();
+ method public boolean hasSatelliteInterSignalBiasNanos();
+ method public boolean hasSatelliteInterSignalBiasUncertaintyNanos();
+ method public boolean hasSnrInDb();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final int ADR_STATE_CYCLE_SLIP = 4; // 0x4
+ field public static final int ADR_STATE_HALF_CYCLE_REPORTED = 16; // 0x10
+ field public static final int ADR_STATE_HALF_CYCLE_RESOLVED = 8; // 0x8
+ field public static final int ADR_STATE_RESET = 2; // 0x2
+ field public static final int ADR_STATE_UNKNOWN = 0; // 0x0
+ field public static final int ADR_STATE_VALID = 1; // 0x1
+ field @NonNull public static final android.os.Parcelable.Creator<android.location.GnssMeasurement> CREATOR;
+ field public static final int MULTIPATH_INDICATOR_DETECTED = 1; // 0x1
+ field public static final int MULTIPATH_INDICATOR_NOT_DETECTED = 2; // 0x2
+ field public static final int MULTIPATH_INDICATOR_UNKNOWN = 0; // 0x0
+ field public static final int STATE_2ND_CODE_LOCK = 65536; // 0x10000
+ field public static final int STATE_BDS_D2_BIT_SYNC = 256; // 0x100
+ field public static final int STATE_BDS_D2_SUBFRAME_SYNC = 512; // 0x200
+ field public static final int STATE_BIT_SYNC = 2; // 0x2
+ field public static final int STATE_CODE_LOCK = 1; // 0x1
+ field public static final int STATE_GAL_E1BC_CODE_LOCK = 1024; // 0x400
+ field public static final int STATE_GAL_E1B_PAGE_SYNC = 4096; // 0x1000
+ field public static final int STATE_GAL_E1C_2ND_CODE_LOCK = 2048; // 0x800
+ field public static final int STATE_GLO_STRING_SYNC = 64; // 0x40
+ field public static final int STATE_GLO_TOD_DECODED = 128; // 0x80
+ field public static final int STATE_GLO_TOD_KNOWN = 32768; // 0x8000
+ field public static final int STATE_MSEC_AMBIGUOUS = 16; // 0x10
+ field public static final int STATE_SBAS_SYNC = 8192; // 0x2000
+ field public static final int STATE_SUBFRAME_SYNC = 4; // 0x4
+ field public static final int STATE_SYMBOL_SYNC = 32; // 0x20
+ field public static final int STATE_TOW_DECODED = 8; // 0x8
+ field public static final int STATE_TOW_KNOWN = 16384; // 0x4000
+ field public static final int STATE_UNKNOWN = 0; // 0x0
+ }
+
+ public final class GnssMeasurementRequest implements android.os.Parcelable {
+ method public int describeContents();
+ method @IntRange(from=0) public int getIntervalMillis();
+ method public boolean isFullTracking();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.location.GnssMeasurementRequest> CREATOR;
+ field public static final int PASSIVE_INTERVAL = 2147483647; // 0x7fffffff
+ }
+
+ public static final class GnssMeasurementRequest.Builder {
+ ctor public GnssMeasurementRequest.Builder();
+ ctor public GnssMeasurementRequest.Builder(@NonNull android.location.GnssMeasurementRequest);
+ method @NonNull public android.location.GnssMeasurementRequest build();
+ method @NonNull public android.location.GnssMeasurementRequest.Builder setFullTracking(boolean);
+ method @NonNull public android.location.GnssMeasurementRequest.Builder setIntervalMillis(@IntRange(from=0) int);
+ }
+
+ public final class GnssMeasurementsEvent implements android.os.Parcelable {
+ method public int describeContents();
+ method @NonNull public android.location.GnssClock getClock();
+ method @NonNull public java.util.Collection<android.location.GnssAutomaticGainControl> getGnssAutomaticGainControls();
+ method @NonNull public java.util.Collection<android.location.GnssMeasurement> getMeasurements();
+ method public boolean hasIsFullTracking();
+ method public boolean isFullTracking();
+ method public void writeToParcel(android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.location.GnssMeasurementsEvent> CREATOR;
+ }
+
+ public static final class GnssMeasurementsEvent.Builder {
+ ctor public GnssMeasurementsEvent.Builder();
+ ctor public GnssMeasurementsEvent.Builder(@NonNull android.location.GnssMeasurementsEvent);
+ method @NonNull public android.location.GnssMeasurementsEvent build();
+ method @NonNull public android.location.GnssMeasurementsEvent.Builder clearIsFullTracking();
+ method @NonNull public android.location.GnssMeasurementsEvent.Builder setClock(@NonNull android.location.GnssClock);
+ method @NonNull public android.location.GnssMeasurementsEvent.Builder setGnssAutomaticGainControls(@NonNull java.util.Collection<android.location.GnssAutomaticGainControl>);
+ method @NonNull public android.location.GnssMeasurementsEvent.Builder setIsFullTracking(boolean);
+ method @NonNull public android.location.GnssMeasurementsEvent.Builder setMeasurements(@NonNull java.util.Collection<android.location.GnssMeasurement>);
+ }
+
+ public abstract static class GnssMeasurementsEvent.Callback {
+ ctor public GnssMeasurementsEvent.Callback();
+ method public void onGnssMeasurementsReceived(android.location.GnssMeasurementsEvent);
+ method @Deprecated public void onStatusChanged(int);
+ field @Deprecated public static final int STATUS_LOCATION_DISABLED = 2; // 0x2
+ field @Deprecated public static final int STATUS_NOT_ALLOWED = 3; // 0x3
+ field @Deprecated public static final int STATUS_NOT_SUPPORTED = 0; // 0x0
+ field @Deprecated public static final int STATUS_READY = 1; // 0x1
+ }
+
+ public final class GnssNavigationMessage implements android.os.Parcelable {
+ method public int describeContents();
+ method @NonNull public byte[] getData();
+ method @IntRange(from=0xffffffff, to=120) public int getMessageId();
+ method public int getStatus();
+ method @IntRange(from=1) public int getSubmessageId();
+ method @IntRange(from=1, to=200) public int getSvid();
+ method public int getType();
+ method public void writeToParcel(android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.location.GnssNavigationMessage> CREATOR;
+ field public static final int STATUS_PARITY_PASSED = 1; // 0x1
+ field public static final int STATUS_PARITY_REBUILT = 2; // 0x2
+ field public static final int STATUS_UNKNOWN = 0; // 0x0
+ field public static final int TYPE_BDS_CNAV1 = 1283; // 0x503
+ field public static final int TYPE_BDS_CNAV2 = 1284; // 0x504
+ field public static final int TYPE_BDS_D1 = 1281; // 0x501
+ field public static final int TYPE_BDS_D2 = 1282; // 0x502
+ field public static final int TYPE_GAL_F = 1538; // 0x602
+ field public static final int TYPE_GAL_I = 1537; // 0x601
+ field public static final int TYPE_GLO_L1CA = 769; // 0x301
+ field public static final int TYPE_GPS_CNAV2 = 260; // 0x104
+ field public static final int TYPE_GPS_L1CA = 257; // 0x101
+ field public static final int TYPE_GPS_L2CNAV = 258; // 0x102
+ field public static final int TYPE_GPS_L5CNAV = 259; // 0x103
+ field public static final int TYPE_IRN_L5CA = 1793; // 0x701
+ field public static final int TYPE_QZS_L1CA = 1025; // 0x401
+ field public static final int TYPE_SBS = 513; // 0x201
+ field public static final int TYPE_UNKNOWN = 0; // 0x0
+ }
+
+ public abstract static class GnssNavigationMessage.Callback {
+ ctor public GnssNavigationMessage.Callback();
+ method public void onGnssNavigationMessageReceived(android.location.GnssNavigationMessage);
+ method @Deprecated public void onStatusChanged(int);
+ field @Deprecated public static final int STATUS_LOCATION_DISABLED = 2; // 0x2
+ field @Deprecated public static final int STATUS_NOT_SUPPORTED = 0; // 0x0
+ field @Deprecated public static final int STATUS_READY = 1; // 0x1
+ }
+
+ public final class GnssSignalType implements android.os.Parcelable {
+ method @NonNull public static android.location.GnssSignalType create(int, @FloatRange(from=0.0f, fromInclusive=false) double, @NonNull String);
+ method public int describeContents();
+ method @FloatRange(from=0.0f, fromInclusive=false) public double getCarrierFrequencyHz();
+ method @NonNull public String getCodeType();
+ method public int getConstellationType();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.location.GnssSignalType> CREATOR;
+ }
+
+ public final class GnssStatus implements android.os.Parcelable {
+ method public int describeContents();
+ method @FloatRange(from=0, to=360) public float getAzimuthDegrees(@IntRange(from=0) int);
+ method @FloatRange(from=0, to=63) public float getBasebandCn0DbHz(@IntRange(from=0) int);
+ method @FloatRange(from=0) public float getCarrierFrequencyHz(@IntRange(from=0) int);
+ method @FloatRange(from=0, to=63) public float getCn0DbHz(@IntRange(from=0) int);
+ method public int getConstellationType(@IntRange(from=0) int);
+ method @FloatRange(from=0xffffffa6, to=90) public float getElevationDegrees(@IntRange(from=0) int);
+ method @IntRange(from=0) public int getSatelliteCount();
+ method @IntRange(from=1, to=206) public int getSvid(@IntRange(from=0) int);
+ method public boolean hasAlmanacData(@IntRange(from=0) int);
+ method public boolean hasBasebandCn0DbHz(@IntRange(from=0) int);
+ method public boolean hasCarrierFrequencyHz(@IntRange(from=0) int);
+ method public boolean hasEphemerisData(@IntRange(from=0) int);
+ method public boolean usedInFix(@IntRange(from=0) int);
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field public static final int CONSTELLATION_BEIDOU = 5; // 0x5
+ field public static final int CONSTELLATION_GALILEO = 6; // 0x6
+ field public static final int CONSTELLATION_GLONASS = 3; // 0x3
+ field public static final int CONSTELLATION_GPS = 1; // 0x1
+ field public static final int CONSTELLATION_IRNSS = 7; // 0x7
+ field public static final int CONSTELLATION_QZSS = 4; // 0x4
+ field public static final int CONSTELLATION_SBAS = 2; // 0x2
+ field public static final int CONSTELLATION_UNKNOWN = 0; // 0x0
+ field @NonNull public static final android.os.Parcelable.Creator<android.location.GnssStatus> CREATOR;
+ }
+
+ public static final class GnssStatus.Builder {
+ ctor public GnssStatus.Builder();
+ method @NonNull public android.location.GnssStatus.Builder addSatellite(int, @IntRange(from=1, to=200) int, @FloatRange(from=0, to=63) float, @FloatRange(from=0xffffffa6, to=90) float, @FloatRange(from=0, to=360) float, boolean, boolean, boolean, boolean, @FloatRange(from=0) float, boolean, @FloatRange(from=0, to=63) float);
+ method @NonNull public android.location.GnssStatus build();
+ method @NonNull public android.location.GnssStatus.Builder clearSatellites();
+ }
+
+ public abstract static class GnssStatus.Callback {
+ ctor public GnssStatus.Callback();
+ method public void onFirstFix(int);
+ method public void onSatelliteStatusChanged(@NonNull android.location.GnssStatus);
+ method public void onStarted();
+ method public void onStopped();
+ }
+
+ @Deprecated public final class GpsSatellite {
+ method @Deprecated public float getAzimuth();
+ method @Deprecated public float getElevation();
+ method @Deprecated public int getPrn();
+ method @Deprecated public float getSnr();
+ method @Deprecated public boolean hasAlmanac();
+ method @Deprecated public boolean hasEphemeris();
+ method @Deprecated public boolean usedInFix();
+ }
+
+ @Deprecated public final class GpsStatus {
+ method @Deprecated @NonNull public static android.location.GpsStatus create(@NonNull android.location.GnssStatus, int);
+ method @Deprecated public int getMaxSatellites();
+ method @Deprecated public Iterable<android.location.GpsSatellite> getSatellites();
+ method @Deprecated public int getTimeToFirstFix();
+ field @Deprecated public static final int GPS_EVENT_FIRST_FIX = 3; // 0x3
+ field @Deprecated public static final int GPS_EVENT_SATELLITE_STATUS = 4; // 0x4
+ field @Deprecated public static final int GPS_EVENT_STARTED = 1; // 0x1
+ field @Deprecated public static final int GPS_EVENT_STOPPED = 2; // 0x2
+ }
+
+ @Deprecated public static interface GpsStatus.Listener {
+ method @Deprecated public void onGpsStatusChanged(int);
+ }
+
+ @Deprecated public static interface GpsStatus.NmeaListener {
+ method @Deprecated public void onNmeaReceived(long, String);
+ }
+
+ public interface LocationListener {
+ method public default void onFlushComplete(int);
+ method public void onLocationChanged(@NonNull android.location.Location);
+ method public default void onLocationChanged(@NonNull java.util.List<android.location.Location>);
+ method public default void onProviderDisabled(@NonNull String);
+ method public default void onProviderEnabled(@NonNull String);
+ method @Deprecated public default void onStatusChanged(String, int, android.os.Bundle);
+ }
+
+ public class LocationManager {
+ method @Deprecated @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean addGpsStatusListener(android.location.GpsStatus.Listener);
+ method @Deprecated @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean addNmeaListener(@NonNull android.location.GpsStatus.NmeaListener);
+ method @Deprecated @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean addNmeaListener(@NonNull android.location.OnNmeaMessageListener);
+ method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean addNmeaListener(@NonNull android.location.OnNmeaMessageListener, @Nullable android.os.Handler);
+ method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean addNmeaListener(@NonNull java.util.concurrent.Executor, @NonNull android.location.OnNmeaMessageListener);
+ method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void addProximityAlert(double, double, float, long, @NonNull android.app.PendingIntent);
+ method public void addTestProvider(@NonNull String, boolean, boolean, boolean, boolean, boolean, boolean, boolean, int, int);
+ method public void addTestProvider(@NonNull String, @NonNull android.location.provider.ProviderProperties);
+ method public void addTestProvider(@NonNull String, @NonNull android.location.provider.ProviderProperties, @NonNull java.util.Set<java.lang.String>);
+ method @Deprecated public void clearTestProviderEnabled(@NonNull String);
+ method @Deprecated public void clearTestProviderLocation(@NonNull String);
+ method @Deprecated public void clearTestProviderStatus(@NonNull String);
+ method @NonNull public java.util.List<java.lang.String> getAllProviders();
+ method @Deprecated @Nullable public String getBestProvider(@NonNull android.location.Criteria, boolean);
+ method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void getCurrentLocation(@NonNull String, @Nullable android.os.CancellationSignal, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.location.Location>);
+ method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void getCurrentLocation(@NonNull String, @NonNull android.location.LocationRequest, @Nullable android.os.CancellationSignal, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.location.Location>);
+ method @Nullable public java.util.List<android.location.GnssAntennaInfo> getGnssAntennaInfos();
+ method @NonNull public android.location.GnssCapabilities getGnssCapabilities();
+ method @Nullable public String getGnssHardwareModelName();
+ method public int getGnssYearOfHardware();
+ method @Deprecated @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public android.location.GpsStatus getGpsStatus(@Nullable android.location.GpsStatus);
+ method @Nullable @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public android.location.Location getLastKnownLocation(@NonNull String);
+ method @Deprecated @Nullable public android.location.LocationProvider getProvider(@NonNull String);
+ method @Nullable public android.location.provider.ProviderProperties getProviderProperties(@NonNull String);
+ method @NonNull public java.util.List<java.lang.String> getProviders(boolean);
+ method @Deprecated @NonNull public java.util.List<java.lang.String> getProviders(@NonNull android.location.Criteria, boolean);
+ method public boolean hasProvider(@NonNull String);
+ method public boolean isLocationEnabled();
+ method public boolean isProviderEnabled(@NonNull String);
+ method public boolean registerAntennaInfoListener(@NonNull java.util.concurrent.Executor, @NonNull android.location.GnssAntennaInfo.Listener);
+ method @Deprecated @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean registerGnssMeasurementsCallback(@NonNull android.location.GnssMeasurementsEvent.Callback);
+ method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean registerGnssMeasurementsCallback(@NonNull android.location.GnssMeasurementsEvent.Callback, @Nullable android.os.Handler);
+ method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean registerGnssMeasurementsCallback(@NonNull java.util.concurrent.Executor, @NonNull android.location.GnssMeasurementsEvent.Callback);
+ method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean registerGnssMeasurementsCallback(@NonNull android.location.GnssMeasurementRequest, @NonNull java.util.concurrent.Executor, @NonNull android.location.GnssMeasurementsEvent.Callback);
+ method @Deprecated public boolean registerGnssNavigationMessageCallback(@NonNull android.location.GnssNavigationMessage.Callback);
+ method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean registerGnssNavigationMessageCallback(@NonNull android.location.GnssNavigationMessage.Callback, @Nullable android.os.Handler);
+ method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean registerGnssNavigationMessageCallback(@NonNull java.util.concurrent.Executor, @NonNull android.location.GnssNavigationMessage.Callback);
+ method @Deprecated @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean registerGnssStatusCallback(@NonNull android.location.GnssStatus.Callback);
+ method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean registerGnssStatusCallback(@NonNull android.location.GnssStatus.Callback, @Nullable android.os.Handler);
+ method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean registerGnssStatusCallback(@NonNull java.util.concurrent.Executor, @NonNull android.location.GnssStatus.Callback);
+ method @Deprecated public void removeGpsStatusListener(android.location.GpsStatus.Listener);
+ method @Deprecated public void removeNmeaListener(@NonNull android.location.GpsStatus.NmeaListener);
+ method public void removeNmeaListener(@NonNull android.location.OnNmeaMessageListener);
+ method @RequiresPermission(anyOf={"android.permission.ACCESS_COARSE_LOCATION", "android.permission.ACCESS_FINE_LOCATION"}, apis="..22") public void removeProximityAlert(@NonNull android.app.PendingIntent);
+ method public void removeTestProvider(@NonNull String);
+ method @RequiresPermission(anyOf={"android.permission.ACCESS_COARSE_LOCATION", "android.permission.ACCESS_FINE_LOCATION"}, apis="..22") public void removeUpdates(@NonNull android.location.LocationListener);
+ method public void removeUpdates(@NonNull android.app.PendingIntent);
+ method public void requestFlush(@NonNull String, @NonNull android.location.LocationListener, int);
+ method public void requestFlush(@NonNull String, @NonNull android.app.PendingIntent, int);
+ method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@NonNull String, long, float, @NonNull android.location.LocationListener);
+ method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@NonNull String, long, float, @NonNull android.location.LocationListener, @Nullable android.os.Looper);
+ method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@NonNull String, long, float, @NonNull java.util.concurrent.Executor, @NonNull android.location.LocationListener);
+ method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(long, float, @NonNull android.location.Criteria, @NonNull android.location.LocationListener, @Nullable android.os.Looper);
+ method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(long, float, @NonNull android.location.Criteria, @NonNull java.util.concurrent.Executor, @NonNull android.location.LocationListener);
+ method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@NonNull String, long, float, @NonNull android.app.PendingIntent);
+ method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(long, float, @NonNull android.location.Criteria, @NonNull android.app.PendingIntent);
+ method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@NonNull String, @NonNull android.location.LocationRequest, @NonNull java.util.concurrent.Executor, @NonNull android.location.LocationListener);
+ method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@NonNull String, @NonNull android.location.LocationRequest, @NonNull android.app.PendingIntent);
+ method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestSingleUpdate(@NonNull String, @NonNull android.location.LocationListener, @Nullable android.os.Looper);
+ method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestSingleUpdate(@NonNull android.location.Criteria, @NonNull android.location.LocationListener, @Nullable android.os.Looper);
+ method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestSingleUpdate(@NonNull String, @NonNull android.app.PendingIntent);
+ method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestSingleUpdate(@NonNull android.location.Criteria, @NonNull android.app.PendingIntent);
+ method public boolean sendExtraCommand(@NonNull String, @NonNull String, @Nullable android.os.Bundle);
+ method public void setTestProviderEnabled(@NonNull String, boolean);
+ method public void setTestProviderLocation(@NonNull String, @NonNull android.location.Location);
+ method @Deprecated public void setTestProviderStatus(@NonNull String, int, @Nullable android.os.Bundle, long);
+ method public void unregisterAntennaInfoListener(@NonNull android.location.GnssAntennaInfo.Listener);
+ method public void unregisterGnssMeasurementsCallback(@NonNull android.location.GnssMeasurementsEvent.Callback);
+ method public void unregisterGnssNavigationMessageCallback(@NonNull android.location.GnssNavigationMessage.Callback);
+ method public void unregisterGnssStatusCallback(@NonNull android.location.GnssStatus.Callback);
+ field public static final String ACTION_GNSS_CAPABILITIES_CHANGED = "android.location.action.GNSS_CAPABILITIES_CHANGED";
+ field public static final String EXTRA_GNSS_CAPABILITIES = "android.location.extra.GNSS_CAPABILITIES";
+ field public static final String EXTRA_LOCATION_ENABLED = "android.location.extra.LOCATION_ENABLED";
+ field public static final String EXTRA_PROVIDER_ENABLED = "android.location.extra.PROVIDER_ENABLED";
+ field public static final String EXTRA_PROVIDER_NAME = "android.location.extra.PROVIDER_NAME";
+ field public static final String FUSED_PROVIDER = "fused";
+ field public static final String GPS_PROVIDER = "gps";
+ field public static final String KEY_FLUSH_COMPLETE = "flushComplete";
+ field public static final String KEY_LOCATIONS = "locations";
+ field public static final String KEY_LOCATION_CHANGED = "location";
+ field public static final String KEY_PROVIDER_ENABLED = "providerEnabled";
+ field public static final String KEY_PROXIMITY_ENTERING = "entering";
+ field @Deprecated public static final String KEY_STATUS_CHANGED = "status";
+ field public static final String MODE_CHANGED_ACTION = "android.location.MODE_CHANGED";
+ field public static final String NETWORK_PROVIDER = "network";
+ field public static final String PASSIVE_PROVIDER = "passive";
+ field public static final String PROVIDERS_CHANGED_ACTION = "android.location.PROVIDERS_CHANGED";
+ }
+
+ @Deprecated public class LocationProvider {
+ method @Deprecated public int getAccuracy();
+ method @Deprecated public String getName();
+ method @Deprecated public int getPowerRequirement();
+ method @Deprecated public boolean hasMonetaryCost();
+ method @Deprecated public boolean meetsCriteria(android.location.Criteria);
+ method @Deprecated public boolean requiresCell();
+ method @Deprecated public boolean requiresNetwork();
+ method @Deprecated public boolean requiresSatellite();
+ method @Deprecated public boolean supportsAltitude();
+ method @Deprecated public boolean supportsBearing();
+ method @Deprecated public boolean supportsSpeed();
+ field @Deprecated public static final int AVAILABLE = 2; // 0x2
+ field @Deprecated public static final int OUT_OF_SERVICE = 0; // 0x0
+ field @Deprecated public static final int TEMPORARILY_UNAVAILABLE = 1; // 0x1
+ }
+
+ public final class LocationRequest implements android.os.Parcelable {
+ method public int describeContents();
+ method @IntRange(from=1) public long getDurationMillis();
+ method @IntRange(from=0) public long getIntervalMillis();
+ method @IntRange(from=0) public long getMaxUpdateDelayMillis();
+ method @IntRange(from=1, to=java.lang.Integer.MAX_VALUE) public int getMaxUpdates();
+ method @FloatRange(from=0, to=java.lang.Float.MAX_VALUE) public float getMinUpdateDistanceMeters();
+ method @IntRange(from=0) public long getMinUpdateIntervalMillis();
+ method public int getQuality();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.location.LocationRequest> CREATOR;
+ field public static final long PASSIVE_INTERVAL = 9223372036854775807L; // 0x7fffffffffffffffL
+ field public static final int QUALITY_BALANCED_POWER_ACCURACY = 102; // 0x66
+ field public static final int QUALITY_HIGH_ACCURACY = 100; // 0x64
+ field public static final int QUALITY_LOW_POWER = 104; // 0x68
+ }
+
+ public static final class LocationRequest.Builder {
+ ctor public LocationRequest.Builder(long);
+ ctor public LocationRequest.Builder(@NonNull android.location.LocationRequest);
+ method @NonNull public android.location.LocationRequest build();
+ method @NonNull public android.location.LocationRequest.Builder clearMinUpdateIntervalMillis();
+ method @NonNull public android.location.LocationRequest.Builder setDurationMillis(@IntRange(from=1) long);
+ method @NonNull public android.location.LocationRequest.Builder setIntervalMillis(@IntRange(from=0) long);
+ method @NonNull public android.location.LocationRequest.Builder setMaxUpdateDelayMillis(@IntRange(from=0) long);
+ method @NonNull public android.location.LocationRequest.Builder setMaxUpdates(@IntRange(from=1, to=java.lang.Integer.MAX_VALUE) int);
+ method @NonNull public android.location.LocationRequest.Builder setMinUpdateDistanceMeters(@FloatRange(from=0, to=java.lang.Float.MAX_VALUE) float);
+ method @NonNull public android.location.LocationRequest.Builder setMinUpdateIntervalMillis(@IntRange(from=0) long);
+ method @NonNull public android.location.LocationRequest.Builder setQuality(int);
+ }
+
+ public interface OnNmeaMessageListener {
+ method public void onNmeaMessage(String, long);
+ }
+
+ public abstract class SettingInjectorService extends android.app.Service {
+ ctor public SettingInjectorService(String);
+ method public final android.os.IBinder onBind(android.content.Intent);
+ method protected abstract boolean onGetEnabled();
+ method protected abstract String onGetSummary();
+ method public final void onStart(android.content.Intent, int);
+ method public final int onStartCommand(android.content.Intent, int, int);
+ method public static final void refreshSettings(@NonNull android.content.Context);
+ field public static final String ACTION_INJECTED_SETTING_CHANGED = "android.location.InjectedSettingChanged";
+ field public static final String ACTION_SERVICE_INTENT = "android.location.SettingInjectorService";
+ field public static final String ATTRIBUTES_NAME = "injected-location-setting";
+ field public static final String META_DATA_NAME = "android.location.SettingInjectorService";
+ }
+
+}
+
+package android.location.altitude {
+
+ public final class AltitudeConverter {
+ ctor public AltitudeConverter();
+ method @WorkerThread public void addMslAltitudeToLocation(@NonNull android.content.Context, @NonNull android.location.Location) throws java.io.IOException;
+ }
+
+}
+
+package android.location.provider {
+
+ public final class ProviderProperties implements android.os.Parcelable {
+ method public int describeContents();
+ method public int getAccuracy();
+ method public int getPowerUsage();
+ method public boolean hasAltitudeSupport();
+ method public boolean hasBearingSupport();
+ method public boolean hasCellRequirement();
+ method public boolean hasMonetaryCost();
+ method public boolean hasNetworkRequirement();
+ method public boolean hasSatelliteRequirement();
+ method public boolean hasSpeedSupport();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field public static final int ACCURACY_COARSE = 2; // 0x2
+ field public static final int ACCURACY_FINE = 1; // 0x1
+ field @NonNull public static final android.os.Parcelable.Creator<android.location.provider.ProviderProperties> CREATOR;
+ field public static final int POWER_USAGE_HIGH = 3; // 0x3
+ field public static final int POWER_USAGE_LOW = 1; // 0x1
+ field public static final int POWER_USAGE_MEDIUM = 2; // 0x2
+ }
+
+ public static final class ProviderProperties.Builder {
+ ctor public ProviderProperties.Builder();
+ ctor public ProviderProperties.Builder(@NonNull android.location.provider.ProviderProperties);
+ method @NonNull public android.location.provider.ProviderProperties build();
+ method @NonNull public android.location.provider.ProviderProperties.Builder setAccuracy(int);
+ method @NonNull public android.location.provider.ProviderProperties.Builder setHasAltitudeSupport(boolean);
+ method @NonNull public android.location.provider.ProviderProperties.Builder setHasBearingSupport(boolean);
+ method @NonNull public android.location.provider.ProviderProperties.Builder setHasCellRequirement(boolean);
+ method @NonNull public android.location.provider.ProviderProperties.Builder setHasMonetaryCost(boolean);
+ method @NonNull public android.location.provider.ProviderProperties.Builder setHasNetworkRequirement(boolean);
+ method @NonNull public android.location.provider.ProviderProperties.Builder setHasSatelliteRequirement(boolean);
+ method @NonNull public android.location.provider.ProviderProperties.Builder setHasSpeedSupport(boolean);
+ method @NonNull public android.location.provider.ProviderProperties.Builder setPowerUsage(int);
+ }
+
+}
+
diff --git a/location/api/module-lib-current.txt b/location/api/module-lib-current.txt
index d802177e249b..8c14b864005d 100644
--- a/location/api/module-lib-current.txt
+++ b/location/api/module-lib-current.txt
@@ -1 +1,11 @@
// Signature format: 2.0
+package android.location {
+
+ public class LocationManager {
+ method @RequiresPermission(allOf={android.Manifest.permission.LOCATION_HARDWARE, android.Manifest.permission.ACCESS_FINE_LOCATION}) public boolean injectLocation(@NonNull android.location.Location);
+ method @RequiresPermission(android.Manifest.permission.CONTROL_AUTOMOTIVE_GNSS) public boolean isAutomotiveGnssSuspended();
+ method @RequiresPermission(android.Manifest.permission.CONTROL_AUTOMOTIVE_GNSS) public void setAutomotiveGnssSuspended(boolean);
+ }
+
+}
+
diff --git a/location/api/module-lib-lint-baseline.txt b/location/api/module-lib-lint-baseline.txt
new file mode 100644
index 000000000000..7cd6a86853a4
--- /dev/null
+++ b/location/api/module-lib-lint-baseline.txt
@@ -0,0 +1,13 @@
+// Baseline format: 1.0
+SamShouldBeLast: android.location.LocationManager#addNmeaListener(android.location.OnNmeaMessageListener, android.os.Handler):
+ SAM-compatible parameters (such as parameter 1, "listener", in android.location.LocationManager.addNmeaListener) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.location.LocationManager#requestLocationUpdates(String, long, float, android.location.LocationListener, android.os.Looper):
+ SAM-compatible parameters (such as parameter 4, "listener", in android.location.LocationManager.requestLocationUpdates) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.location.LocationManager#requestLocationUpdates(android.location.LocationRequest, android.location.LocationListener, android.os.Looper):
+ SAM-compatible parameters (such as parameter 2, "listener", in android.location.LocationManager.requestLocationUpdates) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.location.LocationManager#requestLocationUpdates(long, float, android.location.Criteria, android.location.LocationListener, android.os.Looper):
+ SAM-compatible parameters (such as parameter 4, "listener", in android.location.LocationManager.requestLocationUpdates) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.location.LocationManager#requestSingleUpdate(String, android.location.LocationListener, android.os.Looper):
+ SAM-compatible parameters (such as parameter 2, "listener", in android.location.LocationManager.requestSingleUpdate) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.location.LocationManager#requestSingleUpdate(android.location.Criteria, android.location.LocationListener, android.os.Looper):
+ SAM-compatible parameters (such as parameter 2, "listener", in android.location.LocationManager.requestSingleUpdate) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
diff --git a/location/api/system-current.txt b/location/api/system-current.txt
index d802177e249b..a1d6ab5798e1 100644
--- a/location/api/system-current.txt
+++ b/location/api/system-current.txt
@@ -1 +1,646 @@
// Signature format: 2.0
+package android.location {
+
+ public abstract class BatchedLocationCallback {
+ ctor public BatchedLocationCallback();
+ method public void onLocationBatch(java.util.List<android.location.Location>);
+ }
+
+ public final class CorrelationVector implements android.os.Parcelable {
+ method public int describeContents();
+ method @FloatRange(from=0.0f) public double getFrequencyOffsetMetersPerSecond();
+ method @NonNull public int[] getMagnitude();
+ method @FloatRange(from=0.0f) public double getSamplingStartMeters();
+ method @FloatRange(from=0.0f, fromInclusive=false) public double getSamplingWidthMeters();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.location.CorrelationVector> CREATOR;
+ }
+
+ public static final class CorrelationVector.Builder {
+ ctor public CorrelationVector.Builder();
+ method @NonNull public android.location.CorrelationVector build();
+ method @NonNull public android.location.CorrelationVector.Builder setFrequencyOffsetMetersPerSecond(@FloatRange(from=0.0f) double);
+ method @NonNull public android.location.CorrelationVector.Builder setMagnitude(@NonNull int[]);
+ method @NonNull public android.location.CorrelationVector.Builder setSamplingStartMeters(@FloatRange(from=0.0f) double);
+ method @NonNull public android.location.CorrelationVector.Builder setSamplingWidthMeters(@FloatRange(from=0.0f, fromInclusive=false) double);
+ }
+
+ public final class Country implements android.os.Parcelable {
+ ctor public Country(@NonNull String, int);
+ method public int describeContents();
+ method @NonNull public String getCountryCode();
+ method public int getSource();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field public static final int COUNTRY_SOURCE_LOCALE = 3; // 0x3
+ field public static final int COUNTRY_SOURCE_LOCATION = 1; // 0x1
+ field public static final int COUNTRY_SOURCE_NETWORK = 0; // 0x0
+ field public static final int COUNTRY_SOURCE_SIM = 2; // 0x2
+ field @NonNull public static final android.os.Parcelable.Creator<android.location.Country> CREATOR;
+ }
+
+ public class CountryDetector {
+ method public void registerCountryDetectorCallback(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.location.Country>);
+ method public void unregisterCountryDetectorCallback(@NonNull java.util.function.Consumer<android.location.Country>);
+ }
+
+ public final class GnssCapabilities implements android.os.Parcelable {
+ method @Deprecated public boolean hasMeasurementCorrectionsReflectingPane();
+ method @Deprecated public boolean hasNavMessages();
+ method @Deprecated public boolean hasSatelliteBlacklist();
+ }
+
+ public final class GnssExcessPathInfo implements android.os.Parcelable {
+ method public int describeContents();
+ method @FloatRange(from=0.0f) public float getAttenuationDb();
+ method @FloatRange(from=0.0f) public float getExcessPathLengthMeters();
+ method @FloatRange(from=0.0f) public float getExcessPathLengthUncertaintyMeters();
+ method @NonNull public android.location.GnssReflectingPlane getReflectingPlane();
+ method public boolean hasAttenuation();
+ method public boolean hasExcessPathLength();
+ method public boolean hasExcessPathLengthUncertainty();
+ method public boolean hasReflectingPlane();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.location.GnssExcessPathInfo> CREATOR;
+ }
+
+ public static final class GnssExcessPathInfo.Builder {
+ ctor public GnssExcessPathInfo.Builder();
+ method @NonNull public android.location.GnssExcessPathInfo build();
+ method @NonNull public android.location.GnssExcessPathInfo.Builder clearAttenuationDb();
+ method @NonNull public android.location.GnssExcessPathInfo.Builder clearExcessPathLengthMeters();
+ method @NonNull public android.location.GnssExcessPathInfo.Builder clearExcessPathLengthUncertaintyMeters();
+ method @NonNull public android.location.GnssExcessPathInfo.Builder setAttenuationDb(@FloatRange(from=0.0f) float);
+ method @NonNull public android.location.GnssExcessPathInfo.Builder setExcessPathLengthMeters(@FloatRange(from=0.0f) float);
+ method @NonNull public android.location.GnssExcessPathInfo.Builder setExcessPathLengthUncertaintyMeters(@FloatRange(from=0.0f) float);
+ method @NonNull public android.location.GnssExcessPathInfo.Builder setReflectingPlane(@Nullable android.location.GnssReflectingPlane);
+ }
+
+ public final class GnssMeasurement implements android.os.Parcelable {
+ method @Nullable public java.util.Collection<android.location.CorrelationVector> getCorrelationVectors();
+ method @Nullable public android.location.SatellitePvt getSatellitePvt();
+ method public boolean hasCorrelationVectors();
+ method public boolean hasSatellitePvt();
+ }
+
+ public final class GnssMeasurementCorrections implements android.os.Parcelable {
+ method public int describeContents();
+ method @FloatRange(from=-1000.0F, to=10000.0f) public double getAltitudeMeters();
+ method @FloatRange(from=0.0f, to=360.0f) public float getEnvironmentBearingDegrees();
+ method @FloatRange(from=0.0f, to=180.0f) public float getEnvironmentBearingUncertaintyDegrees();
+ method @FloatRange(from=0.0f) public double getHorizontalPositionUncertaintyMeters();
+ method @FloatRange(from=-90.0F, to=90.0f) public double getLatitudeDegrees();
+ method @FloatRange(from=-180.0F, to=180.0f) public double getLongitudeDegrees();
+ method @NonNull public java.util.List<android.location.GnssSingleSatCorrection> getSingleSatelliteCorrectionList();
+ method @IntRange(from=0) public long getToaGpsNanosecondsOfWeek();
+ method @FloatRange(from=0.0f) public double getVerticalPositionUncertaintyMeters();
+ method public boolean hasEnvironmentBearing();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.location.GnssMeasurementCorrections> CREATOR;
+ }
+
+ public static final class GnssMeasurementCorrections.Builder {
+ ctor public GnssMeasurementCorrections.Builder();
+ method @NonNull public android.location.GnssMeasurementCorrections build();
+ method @NonNull public android.location.GnssMeasurementCorrections.Builder setAltitudeMeters(@FloatRange(from=-1000.0F, to=10000.0f) double);
+ method @NonNull public android.location.GnssMeasurementCorrections.Builder setEnvironmentBearingDegrees(@FloatRange(from=0.0f, to=360.0f) float);
+ method @NonNull public android.location.GnssMeasurementCorrections.Builder setEnvironmentBearingUncertaintyDegrees(@FloatRange(from=0.0f, to=180.0f) float);
+ method @NonNull public android.location.GnssMeasurementCorrections.Builder setHorizontalPositionUncertaintyMeters(@FloatRange(from=0.0f) double);
+ method @NonNull public android.location.GnssMeasurementCorrections.Builder setLatitudeDegrees(@FloatRange(from=-90.0F, to=90.0f) double);
+ method @NonNull public android.location.GnssMeasurementCorrections.Builder setLongitudeDegrees(@FloatRange(from=-180.0F, to=180.0f) double);
+ method @NonNull public android.location.GnssMeasurementCorrections.Builder setSingleSatelliteCorrectionList(@NonNull java.util.List<android.location.GnssSingleSatCorrection>);
+ method @NonNull public android.location.GnssMeasurementCorrections.Builder setToaGpsNanosecondsOfWeek(@IntRange(from=0) long);
+ method @NonNull public android.location.GnssMeasurementCorrections.Builder setVerticalPositionUncertaintyMeters(@FloatRange(from=0.0f) double);
+ }
+
+ public final class GnssMeasurementRequest implements android.os.Parcelable {
+ method @NonNull public android.os.WorkSource getWorkSource();
+ method public boolean isCorrelationVectorOutputsEnabled();
+ }
+
+ public static final class GnssMeasurementRequest.Builder {
+ method @NonNull public android.location.GnssMeasurementRequest.Builder setCorrelationVectorOutputsEnabled(boolean);
+ method @NonNull @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public android.location.GnssMeasurementRequest.Builder setWorkSource(@Nullable android.os.WorkSource);
+ }
+
+ public final class GnssReflectingPlane implements android.os.Parcelable {
+ method public int describeContents();
+ method @FloatRange(from=-1000.0F, to=10000.0f) public double getAltitudeMeters();
+ method @FloatRange(from=0.0f, to=360.0f) public double getAzimuthDegrees();
+ method @FloatRange(from=-90.0F, to=90.0f) public double getLatitudeDegrees();
+ method @FloatRange(from=-180.0F, to=180.0f) public double getLongitudeDegrees();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.location.GnssReflectingPlane> CREATOR;
+ }
+
+ public static final class GnssReflectingPlane.Builder {
+ ctor public GnssReflectingPlane.Builder();
+ method @NonNull public android.location.GnssReflectingPlane build();
+ method @NonNull public android.location.GnssReflectingPlane.Builder setAltitudeMeters(@FloatRange(from=-1000.0F, to=10000.0f) double);
+ method @NonNull public android.location.GnssReflectingPlane.Builder setAzimuthDegrees(@FloatRange(from=0.0f, to=360.0f) double);
+ method @NonNull public android.location.GnssReflectingPlane.Builder setLatitudeDegrees(@FloatRange(from=-90.0F, to=90.0f) double);
+ method @NonNull public android.location.GnssReflectingPlane.Builder setLongitudeDegrees(@FloatRange(from=-180.0F, to=180.0f) double);
+ }
+
+ public final class GnssRequest implements android.os.Parcelable {
+ method public int describeContents();
+ method public boolean isFullTracking();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.location.GnssRequest> CREATOR;
+ }
+
+ public static final class GnssRequest.Builder {
+ ctor public GnssRequest.Builder();
+ ctor public GnssRequest.Builder(@NonNull android.location.GnssRequest);
+ method @NonNull public android.location.GnssRequest build();
+ method @NonNull public android.location.GnssRequest.Builder setFullTracking(boolean);
+ }
+
+ public final class GnssSingleSatCorrection implements android.os.Parcelable {
+ method public int describeContents();
+ method @FloatRange(from=0.0f, fromInclusive=false) public float getCarrierFrequencyHz();
+ method @FloatRange(from=0.0f) public float getCombinedAttenuationDb();
+ method public int getConstellationType();
+ method @FloatRange(from=0.0f) public float getExcessPathLengthMeters();
+ method @FloatRange(from=0.0f) public float getExcessPathLengthUncertaintyMeters();
+ method @NonNull public java.util.List<android.location.GnssExcessPathInfo> getGnssExcessPathInfoList();
+ method @FloatRange(from=0.0f, to=1.0f) public float getProbabilityLineOfSight();
+ method @Deprecated @Nullable public android.location.GnssReflectingPlane getReflectingPlane();
+ method @IntRange(from=0) public int getSatelliteId();
+ method public boolean hasCombinedAttenuation();
+ method public boolean hasExcessPathLength();
+ method public boolean hasExcessPathLengthUncertainty();
+ method @Deprecated public boolean hasReflectingPlane();
+ method public boolean hasValidSatelliteLineOfSight();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.location.GnssSingleSatCorrection> CREATOR;
+ }
+
+ public static final class GnssSingleSatCorrection.Builder {
+ ctor public GnssSingleSatCorrection.Builder();
+ method @NonNull public android.location.GnssSingleSatCorrection build();
+ method @NonNull public android.location.GnssSingleSatCorrection.Builder clearCombinedAttenuationDb();
+ method @NonNull public android.location.GnssSingleSatCorrection.Builder clearExcessPathLengthMeters();
+ method @NonNull public android.location.GnssSingleSatCorrection.Builder clearExcessPathLengthUncertaintyMeters();
+ method @NonNull public android.location.GnssSingleSatCorrection.Builder clearProbabilityLineOfSight();
+ method @NonNull public android.location.GnssSingleSatCorrection.Builder setCarrierFrequencyHz(@FloatRange(from=0.0f, fromInclusive=false) float);
+ method @NonNull public android.location.GnssSingleSatCorrection.Builder setCombinedAttenuationDb(@FloatRange(from=0.0f) float);
+ method @NonNull public android.location.GnssSingleSatCorrection.Builder setConstellationType(int);
+ method @NonNull public android.location.GnssSingleSatCorrection.Builder setExcessPathLengthMeters(@FloatRange(from=0.0f) float);
+ method @NonNull public android.location.GnssSingleSatCorrection.Builder setExcessPathLengthUncertaintyMeters(@FloatRange(from=0.0f) float);
+ method @NonNull public android.location.GnssSingleSatCorrection.Builder setGnssExcessPathInfoList(@NonNull java.util.List<android.location.GnssExcessPathInfo>);
+ method @NonNull public android.location.GnssSingleSatCorrection.Builder setProbabilityLineOfSight(@FloatRange(from=0.0f, to=1.0f) float);
+ method @Deprecated @NonNull public android.location.GnssSingleSatCorrection.Builder setReflectingPlane(@Nullable android.location.GnssReflectingPlane);
+ method @NonNull public android.location.GnssSingleSatCorrection.Builder setSatelliteId(@IntRange(from=0) int);
+ }
+
+ @Deprecated public class GpsClock implements android.os.Parcelable {
+ method @Deprecated public int describeContents();
+ method @Deprecated public double getBiasInNs();
+ method @Deprecated public double getBiasUncertaintyInNs();
+ method @Deprecated public double getDriftInNsPerSec();
+ method @Deprecated public double getDriftUncertaintyInNsPerSec();
+ method @Deprecated public long getFullBiasInNs();
+ method @Deprecated public short getLeapSecond();
+ method @Deprecated public long getTimeInNs();
+ method @Deprecated public double getTimeUncertaintyInNs();
+ method @Deprecated public byte getType();
+ method @Deprecated public boolean hasBiasInNs();
+ method @Deprecated public boolean hasBiasUncertaintyInNs();
+ method @Deprecated public boolean hasDriftInNsPerSec();
+ method @Deprecated public boolean hasDriftUncertaintyInNsPerSec();
+ method @Deprecated public boolean hasFullBiasInNs();
+ method @Deprecated public boolean hasLeapSecond();
+ method @Deprecated public boolean hasTimeUncertaintyInNs();
+ method @Deprecated public void reset();
+ method @Deprecated public void resetBiasInNs();
+ method @Deprecated public void resetBiasUncertaintyInNs();
+ method @Deprecated public void resetDriftInNsPerSec();
+ method @Deprecated public void resetDriftUncertaintyInNsPerSec();
+ method @Deprecated public void resetFullBiasInNs();
+ method @Deprecated public void resetLeapSecond();
+ method @Deprecated public void resetTimeUncertaintyInNs();
+ method @Deprecated public void set(android.location.GpsClock);
+ method @Deprecated public void setBiasInNs(double);
+ method @Deprecated public void setBiasUncertaintyInNs(double);
+ method @Deprecated public void setDriftInNsPerSec(double);
+ method @Deprecated public void setDriftUncertaintyInNsPerSec(double);
+ method @Deprecated public void setFullBiasInNs(long);
+ method @Deprecated public void setLeapSecond(short);
+ method @Deprecated public void setTimeInNs(long);
+ method @Deprecated public void setTimeUncertaintyInNs(double);
+ method @Deprecated public void setType(byte);
+ method @Deprecated public void writeToParcel(android.os.Parcel, int);
+ field @Deprecated @NonNull public static final android.os.Parcelable.Creator<android.location.GpsClock> CREATOR;
+ field @Deprecated public static final byte TYPE_GPS_TIME = 2; // 0x2
+ field @Deprecated public static final byte TYPE_LOCAL_HW_TIME = 1; // 0x1
+ field @Deprecated public static final byte TYPE_UNKNOWN = 0; // 0x0
+ }
+
+ @Deprecated public class GpsMeasurement implements android.os.Parcelable {
+ method @Deprecated public int describeContents();
+ method @Deprecated public double getAccumulatedDeltaRangeInMeters();
+ method @Deprecated public short getAccumulatedDeltaRangeState();
+ method @Deprecated public double getAccumulatedDeltaRangeUncertaintyInMeters();
+ method @Deprecated public double getAzimuthInDeg();
+ method @Deprecated public double getAzimuthUncertaintyInDeg();
+ method @Deprecated public int getBitNumber();
+ method @Deprecated public long getCarrierCycles();
+ method @Deprecated public float getCarrierFrequencyInHz();
+ method @Deprecated public double getCarrierPhase();
+ method @Deprecated public double getCarrierPhaseUncertainty();
+ method @Deprecated public double getCn0InDbHz();
+ method @Deprecated public double getCodePhaseInChips();
+ method @Deprecated public double getCodePhaseUncertaintyInChips();
+ method @Deprecated public double getDopplerShiftInHz();
+ method @Deprecated public double getDopplerShiftUncertaintyInHz();
+ method @Deprecated public double getElevationInDeg();
+ method @Deprecated public double getElevationUncertaintyInDeg();
+ method @Deprecated public byte getLossOfLock();
+ method @Deprecated public byte getMultipathIndicator();
+ method @Deprecated public byte getPrn();
+ method @Deprecated public double getPseudorangeInMeters();
+ method @Deprecated public double getPseudorangeRateInMetersPerSec();
+ method @Deprecated public double getPseudorangeRateUncertaintyInMetersPerSec();
+ method @Deprecated public double getPseudorangeUncertaintyInMeters();
+ method @Deprecated public long getReceivedGpsTowInNs();
+ method @Deprecated public long getReceivedGpsTowUncertaintyInNs();
+ method @Deprecated public double getSnrInDb();
+ method @Deprecated public short getState();
+ method @Deprecated public short getTimeFromLastBitInMs();
+ method @Deprecated public double getTimeOffsetInNs();
+ method @Deprecated public boolean hasAzimuthInDeg();
+ method @Deprecated public boolean hasAzimuthUncertaintyInDeg();
+ method @Deprecated public boolean hasBitNumber();
+ method @Deprecated public boolean hasCarrierCycles();
+ method @Deprecated public boolean hasCarrierFrequencyInHz();
+ method @Deprecated public boolean hasCarrierPhase();
+ method @Deprecated public boolean hasCarrierPhaseUncertainty();
+ method @Deprecated public boolean hasCodePhaseInChips();
+ method @Deprecated public boolean hasCodePhaseUncertaintyInChips();
+ method @Deprecated public boolean hasDopplerShiftInHz();
+ method @Deprecated public boolean hasDopplerShiftUncertaintyInHz();
+ method @Deprecated public boolean hasElevationInDeg();
+ method @Deprecated public boolean hasElevationUncertaintyInDeg();
+ method @Deprecated public boolean hasPseudorangeInMeters();
+ method @Deprecated public boolean hasPseudorangeUncertaintyInMeters();
+ method @Deprecated public boolean hasSnrInDb();
+ method @Deprecated public boolean hasTimeFromLastBitInMs();
+ method @Deprecated public boolean isPseudorangeRateCorrected();
+ method @Deprecated public boolean isUsedInFix();
+ method @Deprecated public void reset();
+ method @Deprecated public void resetAzimuthInDeg();
+ method @Deprecated public void resetAzimuthUncertaintyInDeg();
+ method @Deprecated public void resetBitNumber();
+ method @Deprecated public void resetCarrierCycles();
+ method @Deprecated public void resetCarrierFrequencyInHz();
+ method @Deprecated public void resetCarrierPhase();
+ method @Deprecated public void resetCarrierPhaseUncertainty();
+ method @Deprecated public void resetCodePhaseInChips();
+ method @Deprecated public void resetCodePhaseUncertaintyInChips();
+ method @Deprecated public void resetDopplerShiftInHz();
+ method @Deprecated public void resetDopplerShiftUncertaintyInHz();
+ method @Deprecated public void resetElevationInDeg();
+ method @Deprecated public void resetElevationUncertaintyInDeg();
+ method @Deprecated public void resetPseudorangeInMeters();
+ method @Deprecated public void resetPseudorangeUncertaintyInMeters();
+ method @Deprecated public void resetSnrInDb();
+ method @Deprecated public void resetTimeFromLastBitInMs();
+ method @Deprecated public void set(android.location.GpsMeasurement);
+ method @Deprecated public void setAccumulatedDeltaRangeInMeters(double);
+ method @Deprecated public void setAccumulatedDeltaRangeState(short);
+ method @Deprecated public void setAccumulatedDeltaRangeUncertaintyInMeters(double);
+ method @Deprecated public void setAzimuthInDeg(double);
+ method @Deprecated public void setAzimuthUncertaintyInDeg(double);
+ method @Deprecated public void setBitNumber(int);
+ method @Deprecated public void setCarrierCycles(long);
+ method @Deprecated public void setCarrierFrequencyInHz(float);
+ method @Deprecated public void setCarrierPhase(double);
+ method @Deprecated public void setCarrierPhaseUncertainty(double);
+ method @Deprecated public void setCn0InDbHz(double);
+ method @Deprecated public void setCodePhaseInChips(double);
+ method @Deprecated public void setCodePhaseUncertaintyInChips(double);
+ method @Deprecated public void setDopplerShiftInHz(double);
+ method @Deprecated public void setDopplerShiftUncertaintyInHz(double);
+ method @Deprecated public void setElevationInDeg(double);
+ method @Deprecated public void setElevationUncertaintyInDeg(double);
+ method @Deprecated public void setLossOfLock(byte);
+ method @Deprecated public void setMultipathIndicator(byte);
+ method @Deprecated public void setPrn(byte);
+ method @Deprecated public void setPseudorangeInMeters(double);
+ method @Deprecated public void setPseudorangeRateInMetersPerSec(double);
+ method @Deprecated public void setPseudorangeRateUncertaintyInMetersPerSec(double);
+ method @Deprecated public void setPseudorangeUncertaintyInMeters(double);
+ method @Deprecated public void setReceivedGpsTowInNs(long);
+ method @Deprecated public void setReceivedGpsTowUncertaintyInNs(long);
+ method @Deprecated public void setSnrInDb(double);
+ method @Deprecated public void setState(short);
+ method @Deprecated public void setTimeFromLastBitInMs(short);
+ method @Deprecated public void setTimeOffsetInNs(double);
+ method @Deprecated public void setUsedInFix(boolean);
+ method @Deprecated public void writeToParcel(android.os.Parcel, int);
+ field @Deprecated public static final short ADR_STATE_CYCLE_SLIP = 4; // 0x4
+ field @Deprecated public static final short ADR_STATE_RESET = 2; // 0x2
+ field @Deprecated public static final short ADR_STATE_UNKNOWN = 0; // 0x0
+ field @Deprecated public static final short ADR_STATE_VALID = 1; // 0x1
+ field @Deprecated @NonNull public static final android.os.Parcelable.Creator<android.location.GpsMeasurement> CREATOR;
+ field @Deprecated public static final byte LOSS_OF_LOCK_CYCLE_SLIP = 2; // 0x2
+ field @Deprecated public static final byte LOSS_OF_LOCK_OK = 1; // 0x1
+ field @Deprecated public static final byte LOSS_OF_LOCK_UNKNOWN = 0; // 0x0
+ field @Deprecated public static final byte MULTIPATH_INDICATOR_DETECTED = 1; // 0x1
+ field @Deprecated public static final byte MULTIPATH_INDICATOR_NOT_USED = 2; // 0x2
+ field @Deprecated public static final byte MULTIPATH_INDICATOR_UNKNOWN = 0; // 0x0
+ field @Deprecated public static final short STATE_BIT_SYNC = 2; // 0x2
+ field @Deprecated public static final short STATE_CODE_LOCK = 1; // 0x1
+ field @Deprecated public static final short STATE_MSEC_AMBIGUOUS = 16; // 0x10
+ field @Deprecated public static final short STATE_SUBFRAME_SYNC = 4; // 0x4
+ field @Deprecated public static final short STATE_TOW_DECODED = 8; // 0x8
+ field @Deprecated public static final short STATE_UNKNOWN = 0; // 0x0
+ }
+
+ @Deprecated public class GpsMeasurementsEvent implements android.os.Parcelable {
+ ctor @Deprecated public GpsMeasurementsEvent(android.location.GpsClock, android.location.GpsMeasurement[]);
+ method @Deprecated public int describeContents();
+ method @Deprecated @NonNull public android.location.GpsClock getClock();
+ method @Deprecated @NonNull public java.util.Collection<android.location.GpsMeasurement> getMeasurements();
+ method @Deprecated public void writeToParcel(android.os.Parcel, int);
+ field @Deprecated @NonNull public static final android.os.Parcelable.Creator<android.location.GpsMeasurementsEvent> CREATOR;
+ field @Deprecated public static final int STATUS_GPS_LOCATION_DISABLED = 2; // 0x2
+ field @Deprecated public static final int STATUS_NOT_SUPPORTED = 0; // 0x0
+ field @Deprecated public static final int STATUS_READY = 1; // 0x1
+ }
+
+ @Deprecated public static interface GpsMeasurementsEvent.Listener {
+ method @Deprecated public void onGpsMeasurementsReceived(android.location.GpsMeasurementsEvent);
+ method @Deprecated public void onStatusChanged(int);
+ }
+
+ @Deprecated public class GpsNavigationMessage implements android.os.Parcelable {
+ method @Deprecated public int describeContents();
+ method @Deprecated @NonNull public byte[] getData();
+ method @Deprecated public short getMessageId();
+ method @Deprecated public byte getPrn();
+ method @Deprecated public short getStatus();
+ method @Deprecated public short getSubmessageId();
+ method @Deprecated public byte getType();
+ method @Deprecated public void reset();
+ method @Deprecated public void set(android.location.GpsNavigationMessage);
+ method @Deprecated public void setData(byte[]);
+ method @Deprecated public void setMessageId(short);
+ method @Deprecated public void setPrn(byte);
+ method @Deprecated public void setStatus(short);
+ method @Deprecated public void setSubmessageId(short);
+ method @Deprecated public void setType(byte);
+ method @Deprecated public void writeToParcel(android.os.Parcel, int);
+ field @Deprecated @NonNull public static final android.os.Parcelable.Creator<android.location.GpsNavigationMessage> CREATOR;
+ field @Deprecated public static final short STATUS_PARITY_PASSED = 1; // 0x1
+ field @Deprecated public static final short STATUS_PARITY_REBUILT = 2; // 0x2
+ field @Deprecated public static final short STATUS_UNKNOWN = 0; // 0x0
+ field @Deprecated public static final byte TYPE_CNAV2 = 4; // 0x4
+ field @Deprecated public static final byte TYPE_L1CA = 1; // 0x1
+ field @Deprecated public static final byte TYPE_L2CNAV = 2; // 0x2
+ field @Deprecated public static final byte TYPE_L5CNAV = 3; // 0x3
+ field @Deprecated public static final byte TYPE_UNKNOWN = 0; // 0x0
+ }
+
+ @Deprecated public class GpsNavigationMessageEvent implements android.os.Parcelable {
+ ctor @Deprecated public GpsNavigationMessageEvent(android.location.GpsNavigationMessage);
+ method @Deprecated public int describeContents();
+ method @Deprecated @NonNull public android.location.GpsNavigationMessage getNavigationMessage();
+ method @Deprecated public void writeToParcel(android.os.Parcel, int);
+ field @Deprecated @NonNull public static final android.os.Parcelable.Creator<android.location.GpsNavigationMessageEvent> CREATOR;
+ field @Deprecated public static int STATUS_GPS_LOCATION_DISABLED;
+ field @Deprecated public static int STATUS_NOT_SUPPORTED;
+ field @Deprecated public static int STATUS_READY;
+ }
+
+ @Deprecated public static interface GpsNavigationMessageEvent.Listener {
+ method @Deprecated public void onGpsNavigationMessageReceived(android.location.GpsNavigationMessageEvent);
+ method @Deprecated public void onStatusChanged(int);
+ }
+
+ public final class LastLocationRequest implements android.os.Parcelable {
+ method public int describeContents();
+ method public boolean isAdasGnssBypass();
+ method public boolean isHiddenFromAppOps();
+ method public boolean isLocationSettingsIgnored();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.location.LastLocationRequest> CREATOR;
+ }
+
+ public static final class LastLocationRequest.Builder {
+ ctor public LastLocationRequest.Builder();
+ ctor public LastLocationRequest.Builder(@NonNull android.location.LastLocationRequest);
+ method @NonNull public android.location.LastLocationRequest build();
+ method @NonNull @RequiresPermission(android.Manifest.permission.LOCATION_BYPASS) public android.location.LastLocationRequest.Builder setAdasGnssBypass(boolean);
+ method @NonNull @RequiresPermission(android.Manifest.permission.UPDATE_APP_OPS_STATS) public android.location.LastLocationRequest.Builder setHiddenFromAppOps(boolean);
+ method @NonNull @RequiresPermission(android.Manifest.permission.LOCATION_BYPASS) public android.location.LastLocationRequest.Builder setLocationSettingsIgnored(boolean);
+ }
+
+ public class LocationManager {
+ method @RequiresPermission(allOf={android.Manifest.permission.LOCATION_HARDWARE, android.Manifest.permission.INTERACT_ACROSS_USERS}) public void addProviderRequestChangedListener(@NonNull java.util.concurrent.Executor, @NonNull android.location.provider.ProviderRequest.ChangedListener);
+ method @Deprecated @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public void flushGnssBatch();
+ method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void getCurrentLocation(@NonNull android.location.LocationRequest, @Nullable android.os.CancellationSignal, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.location.Location>);
+ method @Nullable public String getExtraLocationControllerPackage();
+ method @Deprecated public int getGnssBatchSize();
+ method @Nullable @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public android.location.Location getLastKnownLocation(@NonNull String, @NonNull android.location.LastLocationRequest);
+ method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public void injectGnssMeasurementCorrections(@NonNull android.location.GnssMeasurementCorrections);
+ method public boolean isAdasGnssLocationEnabled();
+ method public boolean isExtraLocationControllerPackageEnabled();
+ method public boolean isLocationEnabledForUser(@NonNull android.os.UserHandle);
+ method public boolean isProviderEnabledForUser(@NonNull String, @NonNull android.os.UserHandle);
+ method @Deprecated @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public boolean isProviderPackage(@NonNull String);
+ method @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public boolean isProviderPackage(@Nullable String, @NonNull String, @Nullable String);
+ method @Deprecated @RequiresPermission(allOf={android.Manifest.permission.LOCATION_HARDWARE, android.Manifest.permission.UPDATE_APP_OPS_STATS}) public boolean registerGnssBatchedLocationCallback(long, boolean, @NonNull android.location.BatchedLocationCallback, @Nullable android.os.Handler);
+ method @Deprecated @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean registerGnssMeasurementsCallback(@NonNull android.location.GnssRequest, @NonNull java.util.concurrent.Executor, @NonNull android.location.GnssMeasurementsEvent.Callback);
+ method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public void removeProviderRequestChangedListener(@NonNull android.location.provider.ProviderRequest.ChangedListener);
+ method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@Nullable android.location.LocationRequest, @NonNull android.location.LocationListener, @Nullable android.os.Looper);
+ method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@Nullable android.location.LocationRequest, @NonNull java.util.concurrent.Executor, @NonNull android.location.LocationListener);
+ method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@Nullable android.location.LocationRequest, @NonNull android.app.PendingIntent);
+ method @RequiresPermission(android.Manifest.permission.LOCATION_BYPASS) public void setAdasGnssLocationEnabled(boolean);
+ method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public void setExtraLocationControllerPackage(@Nullable String);
+ method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public void setExtraLocationControllerPackageEnabled(boolean);
+ method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void setLocationEnabledForUser(boolean, @NonNull android.os.UserHandle);
+ method @Deprecated @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean setProviderEnabledForUser(@NonNull String, boolean, @NonNull android.os.UserHandle);
+ method @Deprecated @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public boolean unregisterGnssBatchedLocationCallback(@NonNull android.location.BatchedLocationCallback);
+ field public static final String ACTION_ADAS_GNSS_ENABLED_CHANGED = "android.location.action.ADAS_GNSS_ENABLED_CHANGED";
+ field public static final String EXTRA_ADAS_GNSS_ENABLED = "android.location.extra.ADAS_GNSS_ENABLED";
+ field @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public static final String GPS_HARDWARE_PROVIDER = "gps_hardware";
+ }
+
+ public final class LocationRequest implements android.os.Parcelable {
+ method @Deprecated @NonNull public static android.location.LocationRequest create();
+ method @Deprecated @NonNull public static android.location.LocationRequest createFromDeprecatedCriteria(@NonNull android.location.Criteria, long, float, boolean);
+ method @Deprecated @NonNull public static android.location.LocationRequest createFromDeprecatedProvider(@NonNull String, long, float, boolean);
+ method @Deprecated public long getExpireAt();
+ method @Deprecated public long getExpireIn();
+ method @Deprecated public long getFastestInterval();
+ method @Deprecated public boolean getHideFromAppOps();
+ method @Deprecated public long getInterval();
+ method @Deprecated public int getNumUpdates();
+ method @Deprecated @NonNull public String getProvider();
+ method @Deprecated public float getSmallestDisplacement();
+ method @NonNull public android.os.WorkSource getWorkSource();
+ method public boolean isAdasGnssBypass();
+ method public boolean isHiddenFromAppOps();
+ method public boolean isLocationSettingsIgnored();
+ method public boolean isLowPower();
+ method @Deprecated public boolean isLowPowerMode();
+ method @Deprecated @NonNull public android.location.LocationRequest setExpireAt(long);
+ method @Deprecated @NonNull public android.location.LocationRequest setExpireIn(long);
+ method @Deprecated @NonNull public android.location.LocationRequest setFastestInterval(long);
+ method @Deprecated public void setHideFromAppOps(boolean);
+ method @Deprecated @NonNull public android.location.LocationRequest setInterval(long);
+ method @Deprecated @NonNull @RequiresPermission(android.Manifest.permission.LOCATION_BYPASS) public android.location.LocationRequest setLocationSettingsIgnored(boolean);
+ method @Deprecated @NonNull public android.location.LocationRequest setLowPowerMode(boolean);
+ method @Deprecated @NonNull public android.location.LocationRequest setNumUpdates(int);
+ method @Deprecated @NonNull public android.location.LocationRequest setProvider(@NonNull String);
+ method @Deprecated @NonNull public android.location.LocationRequest setQuality(int);
+ method @Deprecated @NonNull public android.location.LocationRequest setSmallestDisplacement(float);
+ method @Deprecated public void setWorkSource(@Nullable android.os.WorkSource);
+ field @Deprecated public static final int ACCURACY_BLOCK = 102; // 0x66
+ field @Deprecated public static final int ACCURACY_CITY = 104; // 0x68
+ field @Deprecated public static final int ACCURACY_FINE = 100; // 0x64
+ field @Deprecated public static final int POWER_HIGH = 203; // 0xcb
+ field @Deprecated public static final int POWER_LOW = 201; // 0xc9
+ field @Deprecated public static final int POWER_NONE = 200; // 0xc8
+ }
+
+ public static final class LocationRequest.Builder {
+ method @NonNull @RequiresPermission(android.Manifest.permission.LOCATION_BYPASS) public android.location.LocationRequest.Builder setAdasGnssBypass(boolean);
+ method @NonNull @RequiresPermission(android.Manifest.permission.UPDATE_APP_OPS_STATS) public android.location.LocationRequest.Builder setHiddenFromAppOps(boolean);
+ method @NonNull @RequiresPermission(android.Manifest.permission.LOCATION_BYPASS) public android.location.LocationRequest.Builder setLocationSettingsIgnored(boolean);
+ method @NonNull @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public android.location.LocationRequest.Builder setLowPower(boolean);
+ method @NonNull @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public android.location.LocationRequest.Builder setWorkSource(@Nullable android.os.WorkSource);
+ }
+
+ public final class SatellitePvt implements android.os.Parcelable {
+ method public int describeContents();
+ method @Nullable public android.location.SatellitePvt.ClockInfo getClockInfo();
+ method public int getEphemerisSource();
+ method @FloatRange public double getIonoDelayMeters();
+ method @IntRange(from=0, to=1023) public int getIssueOfDataClock();
+ method @IntRange(from=0, to=1023) public int getIssueOfDataEphemeris();
+ method @Nullable public android.location.SatellitePvt.PositionEcef getPositionEcef();
+ method @IntRange(from=0) public long getTimeOfClockSeconds();
+ method @IntRange(from=0) public long getTimeOfEphemerisSeconds();
+ method @FloatRange public double getTropoDelayMeters();
+ method @Nullable public android.location.SatellitePvt.VelocityEcef getVelocityEcef();
+ method public boolean hasIono();
+ method public boolean hasIssueOfDataClock();
+ method public boolean hasIssueOfDataEphemeris();
+ method public boolean hasPositionVelocityClockInfo();
+ method public boolean hasTimeOfClockSeconds();
+ method public boolean hasTimeOfEphemerisSeconds();
+ method public boolean hasTropo();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.location.SatellitePvt> CREATOR;
+ field public static final int EPHEMERIS_SOURCE_DEMODULATED = 0; // 0x0
+ field public static final int EPHEMERIS_SOURCE_OTHER = 3; // 0x3
+ field public static final int EPHEMERIS_SOURCE_SERVER_LONG_TERM = 2; // 0x2
+ field public static final int EPHEMERIS_SOURCE_SERVER_NORMAL = 1; // 0x1
+ }
+
+ public static final class SatellitePvt.Builder {
+ ctor public SatellitePvt.Builder();
+ method @NonNull public android.location.SatellitePvt build();
+ method @NonNull public android.location.SatellitePvt.Builder setClockInfo(@NonNull android.location.SatellitePvt.ClockInfo);
+ method @NonNull public android.location.SatellitePvt.Builder setEphemerisSource(int);
+ method @NonNull public android.location.SatellitePvt.Builder setIonoDelayMeters(@FloatRange(from=0.0f, to=100.0f) double);
+ method @NonNull public android.location.SatellitePvt.Builder setIssueOfDataClock(@IntRange(from=0, to=1023) int);
+ method @NonNull public android.location.SatellitePvt.Builder setIssueOfDataEphemeris(@IntRange(from=0, to=1023) int);
+ method @NonNull public android.location.SatellitePvt.Builder setPositionEcef(@NonNull android.location.SatellitePvt.PositionEcef);
+ method @NonNull public android.location.SatellitePvt.Builder setTimeOfClockSeconds(@IntRange(from=0) long);
+ method @NonNull public android.location.SatellitePvt.Builder setTimeOfEphemerisSeconds(@IntRange(from=0) long);
+ method @NonNull public android.location.SatellitePvt.Builder setTropoDelayMeters(@FloatRange(from=0.0f, to=100.0f) double);
+ method @NonNull public android.location.SatellitePvt.Builder setVelocityEcef(@NonNull android.location.SatellitePvt.VelocityEcef);
+ }
+
+ public static final class SatellitePvt.ClockInfo implements android.os.Parcelable {
+ ctor public SatellitePvt.ClockInfo(double, double, double);
+ method public int describeContents();
+ method @FloatRange public double getClockDriftMetersPerSecond();
+ method @FloatRange public double getHardwareCodeBiasMeters();
+ method @FloatRange public double getTimeCorrectionMeters();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.location.SatellitePvt.ClockInfo> CREATOR;
+ }
+
+ public static final class SatellitePvt.PositionEcef implements android.os.Parcelable {
+ ctor public SatellitePvt.PositionEcef(double, double, double, double);
+ method public int describeContents();
+ method @FloatRange(from=0.0f, fromInclusive=false) public double getUreMeters();
+ method @FloatRange public double getXMeters();
+ method @FloatRange public double getYMeters();
+ method @FloatRange public double getZMeters();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.location.SatellitePvt.PositionEcef> CREATOR;
+ }
+
+ public static final class SatellitePvt.VelocityEcef implements android.os.Parcelable {
+ ctor public SatellitePvt.VelocityEcef(double, double, double, double);
+ method public int describeContents();
+ method @FloatRange(from=0.0f, fromInclusive=false) public double getUreRateMetersPerSecond();
+ method @FloatRange public double getXMetersPerSecond();
+ method @FloatRange public double getYMetersPerSecond();
+ method @FloatRange public double getZMetersPerSecond();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.location.SatellitePvt.VelocityEcef> CREATOR;
+ }
+
+}
+
+package android.location.provider {
+
+ public abstract class LocationProviderBase {
+ ctor public LocationProviderBase(@NonNull android.content.Context, @NonNull String, @NonNull android.location.provider.ProviderProperties);
+ method @Nullable public final android.os.IBinder getBinder();
+ method @NonNull public android.location.provider.ProviderProperties getProperties();
+ method public boolean isAllowed();
+ method public abstract void onFlush(@NonNull android.location.provider.LocationProviderBase.OnFlushCompleteCallback);
+ method public abstract void onSendExtraCommand(@NonNull String, @Nullable android.os.Bundle);
+ method public abstract void onSetRequest(@NonNull android.location.provider.ProviderRequest);
+ method public void reportLocation(@NonNull android.location.Location);
+ method public void reportLocations(@NonNull java.util.List<android.location.Location>);
+ method public void setAllowed(boolean);
+ method public void setProperties(@NonNull android.location.provider.ProviderProperties);
+ field public static final String ACTION_FUSED_PROVIDER = "com.android.location.service.FusedLocationProvider";
+ field public static final String ACTION_GNSS_PROVIDER = "android.location.provider.action.GNSS_PROVIDER";
+ field public static final String ACTION_NETWORK_PROVIDER = "com.android.location.service.v3.NetworkLocationProvider";
+ }
+
+ public static interface LocationProviderBase.OnFlushCompleteCallback {
+ method public void onFlushComplete();
+ }
+
+ public final class ProviderRequest implements android.os.Parcelable {
+ method public int describeContents();
+ method @IntRange(from=0) public long getIntervalMillis();
+ method @IntRange(from=0) public long getMaxUpdateDelayMillis();
+ method public int getQuality();
+ method @NonNull public android.os.WorkSource getWorkSource();
+ method public boolean isActive();
+ method public boolean isLocationSettingsIgnored();
+ method public boolean isLowPower();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.location.provider.ProviderRequest> CREATOR;
+ field @NonNull public static final android.location.provider.ProviderRequest EMPTY_REQUEST;
+ field public static final long INTERVAL_DISABLED = 9223372036854775807L; // 0x7fffffffffffffffL
+ }
+
+ public static final class ProviderRequest.Builder {
+ ctor public ProviderRequest.Builder();
+ method @NonNull public android.location.provider.ProviderRequest build();
+ method @NonNull public android.location.provider.ProviderRequest.Builder setIntervalMillis(@IntRange(from=0) long);
+ method @NonNull public android.location.provider.ProviderRequest.Builder setLocationSettingsIgnored(boolean);
+ method @NonNull public android.location.provider.ProviderRequest.Builder setLowPower(boolean);
+ method @NonNull public android.location.provider.ProviderRequest.Builder setMaxUpdateDelayMillis(@IntRange(from=0) long);
+ method @NonNull public android.location.provider.ProviderRequest.Builder setQuality(int);
+ method @NonNull public android.location.provider.ProviderRequest.Builder setWorkSource(@NonNull android.os.WorkSource);
+ }
+
+ public static interface ProviderRequest.ChangedListener {
+ method public void onProviderRequestChanged(@NonNull String, @NonNull android.location.provider.ProviderRequest);
+ }
+
+}
+
diff --git a/location/api/system-lint-baseline.txt b/location/api/system-lint-baseline.txt
new file mode 100644
index 000000000000..a5e5752d7cf5
--- /dev/null
+++ b/location/api/system-lint-baseline.txt
@@ -0,0 +1,11 @@
+// Baseline format: 1.0
+SamShouldBeLast: android.location.LocationManager#addNmeaListener(android.location.OnNmeaMessageListener, android.os.Handler):
+ SAM-compatible parameters (such as parameter 1, "listener", in android.location.LocationManager.addNmeaListener) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.location.LocationManager#requestLocationUpdates(String, long, float, android.location.LocationListener, android.os.Looper):
+ SAM-compatible parameters (such as parameter 4, "listener", in android.location.LocationManager.requestLocationUpdates) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.location.LocationManager#requestLocationUpdates(long, float, android.location.Criteria, android.location.LocationListener, android.os.Looper):
+ SAM-compatible parameters (such as parameter 4, "listener", in android.location.LocationManager.requestLocationUpdates) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.location.LocationManager#requestSingleUpdate(String, android.location.LocationListener, android.os.Looper):
+ SAM-compatible parameters (such as parameter 2, "listener", in android.location.LocationManager.requestSingleUpdate) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.location.LocationManager#requestSingleUpdate(android.location.Criteria, android.location.LocationListener, android.os.Looper):
+ SAM-compatible parameters (such as parameter 2, "listener", in android.location.LocationManager.requestSingleUpdate) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
diff --git a/location/api/system-removed.txt b/location/api/system-removed.txt
index d802177e249b..2755a9ff33c8 100644
--- a/location/api/system-removed.txt
+++ b/location/api/system-removed.txt
@@ -1 +1,15 @@
// Signature format: 2.0
+package android.location {
+
+ public class LocationManager {
+ method @Deprecated public boolean addGpsMeasurementListener(android.location.GpsMeasurementsEvent.Listener);
+ method @Deprecated public boolean addGpsNavigationMessageListener(android.location.GpsNavigationMessageEvent.Listener);
+ method @Deprecated @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public boolean isProviderPackage(@Nullable String, @NonNull String);
+ method @Deprecated public void removeGpsMeasurementListener(android.location.GpsMeasurementsEvent.Listener);
+ method @Deprecated public void removeGpsNavigationMessageListener(android.location.GpsNavigationMessageEvent.Listener);
+ method @Deprecated @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public void setLocationControllerExtraPackage(String);
+ method @Deprecated @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public void setLocationControllerExtraPackageEnabled(boolean);
+ }
+
+}
+
diff --git a/location/api/test-current.txt b/location/api/test-current.txt
index d802177e249b..bdcb00a93b95 100644
--- a/location/api/test-current.txt
+++ b/location/api/test-current.txt
@@ -1 +1,104 @@
// Signature format: 2.0
+package android.location {
+
+ public final class GnssClock implements android.os.Parcelable {
+ ctor public GnssClock();
+ method public void reset();
+ method public void resetBiasNanos();
+ method public void resetBiasUncertaintyNanos();
+ method public void resetDriftNanosPerSecond();
+ method public void resetDriftUncertaintyNanosPerSecond();
+ method public void resetElapsedRealtimeNanos();
+ method public void resetElapsedRealtimeUncertaintyNanos();
+ method public void resetFullBiasNanos();
+ method public void resetLeapSecond();
+ method public void resetReferenceCarrierFrequencyHzForIsb();
+ method public void resetReferenceCodeTypeForIsb();
+ method public void resetReferenceConstellationTypeForIsb();
+ method public void resetTimeUncertaintyNanos();
+ method public void set(android.location.GnssClock);
+ method public void setBiasNanos(double);
+ method public void setBiasUncertaintyNanos(@FloatRange(from=0.0f) double);
+ method public void setDriftNanosPerSecond(double);
+ method public void setDriftUncertaintyNanosPerSecond(@FloatRange(from=0.0f) double);
+ method public void setElapsedRealtimeNanos(long);
+ method public void setElapsedRealtimeUncertaintyNanos(@FloatRange(from=0.0f) double);
+ method public void setFullBiasNanos(long);
+ method public void setHardwareClockDiscontinuityCount(int);
+ method public void setLeapSecond(int);
+ method public void setReferenceCarrierFrequencyHzForIsb(@FloatRange(from=0.0) double);
+ method public void setReferenceCodeTypeForIsb(@NonNull String);
+ method public void setReferenceConstellationTypeForIsb(int);
+ method public void setTimeNanos(long);
+ method public void setTimeUncertaintyNanos(@FloatRange(from=0.0f) double);
+ }
+
+ public final class GnssMeasurement implements android.os.Parcelable {
+ ctor public GnssMeasurement();
+ method public void reset();
+ method public void resetAutomaticGainControlLevel();
+ method public void resetBasebandCn0DbHz();
+ method @Deprecated public void resetCarrierCycles();
+ method public void resetCarrierFrequencyHz();
+ method @Deprecated public void resetCarrierPhase();
+ method @Deprecated public void resetCarrierPhaseUncertainty();
+ method public void resetCodeType();
+ method public void resetCorrelationVectors();
+ method public void resetFullInterSignalBiasNanos();
+ method public void resetFullInterSignalBiasUncertaintyNanos();
+ method public void resetSatelliteInterSignalBiasNanos();
+ method public void resetSatelliteInterSignalBiasUncertaintyNanos();
+ method public void resetSatellitePvt();
+ method public void resetSnrInDb();
+ method public void set(android.location.GnssMeasurement);
+ method public void setAccumulatedDeltaRangeMeters(double);
+ method public void setAccumulatedDeltaRangeState(int);
+ method public void setAccumulatedDeltaRangeUncertaintyMeters(double);
+ method @Deprecated public void setAutomaticGainControlLevelInDb(double);
+ method public void setBasebandCn0DbHz(double);
+ method @Deprecated public void setCarrierCycles(long);
+ method public void setCarrierFrequencyHz(float);
+ method @Deprecated public void setCarrierPhase(double);
+ method @Deprecated public void setCarrierPhaseUncertainty(double);
+ method public void setCn0DbHz(double);
+ method public void setCodeType(@NonNull String);
+ method public void setConstellationType(int);
+ method public void setCorrelationVectors(@Nullable java.util.Collection<android.location.CorrelationVector>);
+ method public void setFullInterSignalBiasNanos(double);
+ method public void setFullInterSignalBiasUncertaintyNanos(@FloatRange(from=0.0) double);
+ method public void setMultipathIndicator(int);
+ method public void setPseudorangeRateMetersPerSecond(double);
+ method public void setPseudorangeRateUncertaintyMetersPerSecond(double);
+ method public void setReceivedSvTimeNanos(long);
+ method public void setReceivedSvTimeUncertaintyNanos(long);
+ method public void setSatelliteInterSignalBiasNanos(double);
+ method public void setSatelliteInterSignalBiasUncertaintyNanos(@FloatRange(from=0.0) double);
+ method public void setSatellitePvt(@Nullable android.location.SatellitePvt);
+ method public void setSnrInDb(double);
+ method public void setState(int);
+ method public void setSvid(int);
+ method public void setTimeOffsetNanos(double);
+ field public static final int ADR_STATE_ALL = 31; // 0x1f
+ }
+
+ public final class GnssNavigationMessage implements android.os.Parcelable {
+ ctor public GnssNavigationMessage();
+ method public void reset();
+ method public void set(android.location.GnssNavigationMessage);
+ method public void setData(byte[]);
+ method public void setMessageId(@IntRange(from=0xffffffff, to=120) int);
+ method public void setStatus(int);
+ method public void setSubmessageId(@IntRange(from=1) int);
+ method public void setSvid(@IntRange(from=1, to=200) int);
+ method public void setType(int);
+ }
+
+ public class LocationManager {
+ method @NonNull public String[] getBackgroundThrottlingWhitelist();
+ method @NonNull public android.os.PackageTagsList getIgnoreSettingsAllowlist();
+ method @Deprecated @NonNull public String[] getIgnoreSettingsWhitelist();
+ method @Deprecated @Nullable @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public java.util.List<java.lang.String> getProviderPackages(@NonNull String);
+ }
+
+}
+
diff --git a/location/api/test-lint-baseline.txt b/location/api/test-lint-baseline.txt
new file mode 100644
index 000000000000..189588e4bafb
--- /dev/null
+++ b/location/api/test-lint-baseline.txt
@@ -0,0 +1,54 @@
+// Baseline format: 1.0
+GetterSetterNames: android.location.GnssClock#setBiasNanos(double):
+ Symmetric method for `hasBiasNanos` must be named `setHasBiasNanos`; was `setBiasNanos`
+GetterSetterNames: android.location.GnssClock#setBiasUncertaintyNanos(double):
+ Symmetric method for `hasBiasUncertaintyNanos` must be named `setHasBiasUncertaintyNanos`; was `setBiasUncertaintyNanos`
+GetterSetterNames: android.location.GnssClock#setDriftNanosPerSecond(double):
+ Symmetric method for `hasDriftNanosPerSecond` must be named `setHasDriftNanosPerSecond`; was `setDriftNanosPerSecond`
+GetterSetterNames: android.location.GnssClock#setDriftUncertaintyNanosPerSecond(double):
+ Symmetric method for `hasDriftUncertaintyNanosPerSecond` must be named `setHasDriftUncertaintyNanosPerSecond`; was `setDriftUncertaintyNanosPerSecond`
+GetterSetterNames: android.location.GnssClock#setElapsedRealtimeNanos(long):
+ Symmetric method for `hasElapsedRealtimeNanos` must be named `setHasElapsedRealtimeNanos`; was `setElapsedRealtimeNanos`
+GetterSetterNames: android.location.GnssClock#setElapsedRealtimeUncertaintyNanos(double):
+ Symmetric method for `hasElapsedRealtimeUncertaintyNanos` must be named `setHasElapsedRealtimeUncertaintyNanos`; was `setElapsedRealtimeUncertaintyNanos`
+GetterSetterNames: android.location.GnssClock#setFullBiasNanos(long):
+ Symmetric method for `hasFullBiasNanos` must be named `setHasFullBiasNanos`; was `setFullBiasNanos`
+GetterSetterNames: android.location.GnssClock#setLeapSecond(int):
+ Symmetric method for `hasLeapSecond` must be named `setHasLeapSecond`; was `setLeapSecond`
+GetterSetterNames: android.location.GnssClock#setReferenceCarrierFrequencyHzForIsb(double):
+ Symmetric method for `hasReferenceCarrierFrequencyHzForIsb` must be named `setHasReferenceCarrierFrequencyHzForIsb`; was `setReferenceCarrierFrequencyHzForIsb`
+GetterSetterNames: android.location.GnssClock#setReferenceCodeTypeForIsb(String):
+ Symmetric method for `hasReferenceCodeTypeForIsb` must be named `setHasReferenceCodeTypeForIsb`; was `setReferenceCodeTypeForIsb`
+GetterSetterNames: android.location.GnssClock#setReferenceConstellationTypeForIsb(int):
+ Symmetric method for `hasReferenceConstellationTypeForIsb` must be named `setHasReferenceConstellationTypeForIsb`; was `setReferenceConstellationTypeForIsb`
+GetterSetterNames: android.location.GnssClock#setTimeUncertaintyNanos(double):
+ Symmetric method for `hasTimeUncertaintyNanos` must be named `setHasTimeUncertaintyNanos`; was `setTimeUncertaintyNanos`
+GetterSetterNames: android.location.GnssMeasurement#setBasebandCn0DbHz(double):
+ Symmetric method for `hasBasebandCn0DbHz` must be named `setHasBasebandCn0DbHz`; was `setBasebandCn0DbHz`
+GetterSetterNames: android.location.GnssMeasurement#setCarrierFrequencyHz(float):
+ Symmetric method for `hasCarrierFrequencyHz` must be named `setHasCarrierFrequencyHz`; was `setCarrierFrequencyHz`
+GetterSetterNames: android.location.GnssMeasurement#setCodeType(String):
+ Symmetric method for `hasCodeType` must be named `setHasCodeType`; was `setCodeType`
+GetterSetterNames: android.location.GnssMeasurement#setCorrelationVectors(java.util.Collection<android.location.CorrelationVector>):
+ Symmetric method for `hasCorrelationVectors` must be named `setHasCorrelationVectors`; was `setCorrelationVectors`
+GetterSetterNames: android.location.GnssMeasurement#setFullInterSignalBiasNanos(double):
+ Symmetric method for `hasFullInterSignalBiasNanos` must be named `setHasFullInterSignalBiasNanos`; was `setFullInterSignalBiasNanos`
+GetterSetterNames: android.location.GnssMeasurement#setFullInterSignalBiasUncertaintyNanos(double):
+ Symmetric method for `hasFullInterSignalBiasUncertaintyNanos` must be named `setHasFullInterSignalBiasUncertaintyNanos`; was `setFullInterSignalBiasUncertaintyNanos`
+GetterSetterNames: android.location.GnssMeasurement#setSatelliteInterSignalBiasNanos(double):
+ Symmetric method for `hasSatelliteInterSignalBiasNanos` must be named `setHasSatelliteInterSignalBiasNanos`; was `setSatelliteInterSignalBiasNanos`
+GetterSetterNames: android.location.GnssMeasurement#setSatelliteInterSignalBiasUncertaintyNanos(double):
+ Symmetric method for `hasSatelliteInterSignalBiasUncertaintyNanos` must be named `setHasSatelliteInterSignalBiasUncertaintyNanos`; was `setSatelliteInterSignalBiasUncertaintyNanos`
+GetterSetterNames: android.location.GnssMeasurement#setSatellitePvt(android.location.SatellitePvt):
+ Symmetric method for `hasSatellitePvt` must be named `setHasSatellitePvt`; was `setSatellitePvt`
+GetterSetterNames: android.location.GnssMeasurement#setSnrInDb(double):
+ Symmetric method for `hasSnrInDb` must be named `setHasSnrInDb`; was `setSnrInDb`
+
+MissingNullability: android.location.GnssClock#set(android.location.GnssClock) parameter #0:
+ Missing nullability on parameter `clock` in method `set`
+MissingNullability: android.location.GnssMeasurement#set(android.location.GnssMeasurement) parameter #0:
+ Missing nullability on parameter `measurement` in method `set`
+MissingNullability: android.location.GnssNavigationMessage#set(android.location.GnssNavigationMessage) parameter #0:
+ Missing nullability on parameter `navigationMessage` in method `set`
+MissingNullability: android.location.GnssNavigationMessage#setData(byte[]) parameter #0:
+ Missing nullability on parameter `value` in method `setData`
diff --git a/location/java/Android.bp b/location/java/Android.bp
deleted file mode 100644
index 543f2b1ab4a8..000000000000
--- a/location/java/Android.bp
+++ /dev/null
@@ -1,17 +0,0 @@
-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"],
-}
-
-filegroup {
- name: "framework-location-sources",
- srcs: [
- "**/*.java",
- "**/*.aidl",
- ],
- visibility: ["//frameworks/base"],
-}
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index e2f407294458..842542f4f43b 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -4945,7 +4945,9 @@ public class AudioManager {
synchronized (this) {
while (!mQuit) {
final long timeToWait = timeOutTime - java.lang.System.currentTimeMillis();
- if (timeToWait < 0) { break; }
+ if (timeToWait <= 0) {
+ break;
+ }
this.wait(timeToWait);
}
}
diff --git a/media/java/android/media/RingtoneManager.java b/media/java/android/media/RingtoneManager.java
index c4f2159a23dc..12db8c0824db 100644
--- a/media/java/android/media/RingtoneManager.java
+++ b/media/java/android/media/RingtoneManager.java
@@ -30,6 +30,7 @@ import android.content.ContentProvider;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.Context;
+import android.content.Intent;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.UserInfo;
import android.content.res.AssetFileDescriptor;
@@ -120,6 +121,53 @@ public class RingtoneManager {
public static final String ACTION_RINGTONE_PICKER = "android.intent.action.RINGTONE_PICKER";
/**
+ * Given to the ringtone picker as a string that represents the category of ringtone picker that
+ * should be used. This value should also be returned once a ringtone is selected.
+ * <p>
+ * The categories are:
+ * <li>{@link #CATEGORY_RINGTONE_PICKER_SOUND}
+ * <li>{@link #CATEGORY_RINGTONE_PICKER_VIBRATION}
+ * <li>{@link #CATEGORY_RINGTONE_PICKER_RINGTONE}
+ * <li>{@link Intent#CATEGORY_DEFAULT}
+ *
+ * <p> If the category is {@link Intent#CATEGORY_DEFAULT} or absent, then the picker will
+ * default to a sound-only ringtone picker.
+ *
+ * <p> If the selected category was not supported, then the returned category will be null.
+ *
+ * @hide
+ */
+ public static final String EXTRA_RINGTONE_PICKER_CATEGORY =
+ "android.intent.extra.ringtone.RINGTONE_PICKER_CATEGORY";
+
+ /**
+ * A sound-only ringtone picker.
+ *
+ * @hide
+ * @see #EXTRA_RINGTONE_PICKER_CATEGORY
+ */
+ public static final String CATEGORY_RINGTONE_PICKER_SOUND =
+ "android.net.category.RINGTONE_PICKER_SOUND";
+
+ /**
+ * A vibration-only ringtone picker.
+ *
+ * @hide
+ * @see #EXTRA_RINGTONE_PICKER_CATEGORY
+ */
+ public static final String CATEGORY_RINGTONE_PICKER_VIBRATION =
+ "android.net.category.RINGTONE_PICKER_VIBRATION";
+
+ /**
+ * A combined sound and vibration ringtone picker.
+ *
+ * @hide
+ * @see #EXTRA_RINGTONE_PICKER_CATEGORY
+ */
+ public static final String CATEGORY_RINGTONE_PICKER_RINGTONE =
+ "android.net.category.RINGTONE_PICKER_RINGTONE";
+
+ /**
* Given to the ringtone picker as a boolean. Whether to show an item for
* "Default".
*
@@ -160,6 +208,18 @@ public class RingtoneManager {
*/
public static final String EXTRA_RINGTONE_EXISTING_URI =
"android.intent.extra.ringtone.EXISTING_URI";
+
+ /**
+ * Similar to #EXTRA_RINGTONE_EXISTING_URI but the {@link Uri} can include both sound and
+ * vibration.
+ * <p>This can include silent sound/vibration explicitly by setting that part of the URI to
+ * null.
+ *
+ * @hide
+ * @see #ACTION_RINGTONE_PICKER
+ */
+ public static final String EXTRA_RINGTONE_EXISTING_RINGTONE_URI =
+ "android.intent.extra.ringtone.RINGTONE_EXISTING_RINGTONE_URI";
/**
* Given to the ringtone picker as a {@link Uri}. The {@link Uri} of the
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/CustomizedAppBar.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/CustomizedAppBar.kt
index 90a723f707da..b77368a429ae 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/CustomizedAppBar.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/CustomizedAppBar.kt
@@ -253,6 +253,7 @@ private fun SingleRowTopAppBar(
hideTitleSemantics = false,
navigationIcon = navigationIcon,
actions = actionsRow,
+ titleScaleDisabled = false,
)
}
}
@@ -426,6 +427,7 @@ private fun TwoRowsTopAppBar(
* accessibility services at the same time, when animating between collapsed / expanded states.
* @param navigationIcon a navigation icon [Composable]
* @param actions actions [Composable]
+ * @param titleScaleDisabled whether the title font scaling is disabled. Default is disabled.
*/
@Composable
private fun TopAppBarLayout(
@@ -443,6 +445,7 @@ private fun TopAppBarLayout(
hideTitleSemantics: Boolean,
navigationIcon: @Composable () -> Unit,
actions: @Composable () -> Unit,
+ titleScaleDisabled: Boolean = true,
) {
Layout(
{
@@ -466,9 +469,12 @@ private fun TopAppBarLayout(
ProvideTextStyle(value = titleTextStyle) {
CompositionLocalProvider(
LocalContentColor provides titleContentColor,
- // Disable the title font scaling by only passing the density but not the
- // font scale.
- LocalDensity provides Density(density = LocalDensity.current.density),
+ LocalDensity provides with(LocalDensity.current) {
+ Density(
+ density = density,
+ fontScale = if (titleScaleDisabled) 1f else fontScale,
+ )
+ },
content = title
)
}
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/SearchScaffold.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/SearchScaffold.kt
index d437e3579354..696e8776ccd7 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/SearchScaffold.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/SearchScaffold.kt
@@ -18,6 +18,7 @@ package com.android.settingslib.spa.widget.scaffold
import androidx.activity.compose.BackHandler
import androidx.appcompat.R
+import androidx.compose.foundation.focusable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.RowScope
@@ -96,7 +97,8 @@ fun SearchScaffold(
Modifier
.padding(paddingValues.horizontalValues())
.padding(top = paddingValues.calculateTopPadding())
- .fillMaxSize(),
+ .focusable()
+ .fillMaxSize()
) {
content(
paddingValues.calculateBottomPadding(),
diff --git a/packages/SettingsProvider/src/android/provider/settings/backup/SystemSettings.java b/packages/SettingsProvider/src/android/provider/settings/backup/SystemSettings.java
index 6b0a9060d782..248c60cb4fe9 100644
--- a/packages/SettingsProvider/src/android/provider/settings/backup/SystemSettings.java
+++ b/packages/SettingsProvider/src/android/provider/settings/backup/SystemSettings.java
@@ -61,7 +61,7 @@ public class SystemSettings {
Settings.System.TTY_MODE,
Settings.System.MASTER_MONO,
Settings.System.MASTER_BALANCE,
- Settings.System.STAY_AWAKE_ON_FOLD,
+ Settings.System.FOLD_LOCK_BEHAVIOR,
Settings.System.SOUND_EFFECTS_ENABLED,
Settings.System.HAPTIC_FEEDBACK_ENABLED,
Settings.System.POWER_SOUNDS_ENABLED, // moved to global
diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/SystemSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/SystemSettingsValidators.java
index 20740dcedf95..17ce7c7cc435 100644
--- a/packages/SettingsProvider/src/android/provider/settings/validators/SystemSettingsValidators.java
+++ b/packages/SettingsProvider/src/android/provider/settings/validators/SystemSettingsValidators.java
@@ -134,6 +134,7 @@ public class SystemSettingsValidators {
VALIDATORS.put(System.HAPTIC_FEEDBACK_ENABLED, BOOLEAN_VALIDATOR);
VALIDATORS.put(System.RINGTONE, URI_VALIDATOR);
VALIDATORS.put(System.NOTIFICATION_SOUND, URI_VALIDATOR);
+ VALIDATORS.put(System.FOLD_LOCK_BEHAVIOR, ANY_STRING_VALIDATOR);
VALIDATORS.put(System.ALARM_ALERT, URI_VALIDATOR);
VALIDATORS.put(System.TEXT_AUTO_REPLACE, BOOLEAN_VALIDATOR);
VALIDATORS.put(System.TEXT_AUTO_CAPS, BOOLEAN_VALIDATOR);
@@ -219,7 +220,6 @@ public class SystemSettingsValidators {
VALIDATORS.put(System.WIFI_STATIC_DNS1, LENIENT_IP_ADDRESS_VALIDATOR);
VALIDATORS.put(System.WIFI_STATIC_DNS2, LENIENT_IP_ADDRESS_VALIDATOR);
VALIDATORS.put(System.SHOW_BATTERY_PERCENT, BOOLEAN_VALIDATOR);
- VALIDATORS.put(System.STAY_AWAKE_ON_FOLD, BOOLEAN_VALIDATOR);
VALIDATORS.put(System.NOTIFICATION_LIGHT_PULSE, BOOLEAN_VALIDATOR);
VALIDATORS.put(System.WEAR_ACCESSIBILITY_GESTURE_ENABLED, BOOLEAN_VALIDATOR);
VALIDATORS.put(System.WEAR_ACCESSIBILITY_GESTURE_ENABLED_DURING_OOBE, BOOLEAN_VALIDATOR);
diff --git a/packages/SystemUI/Android.bp b/packages/SystemUI/Android.bp
index 089ddbeda53b..bba79bbcab5b 100644
--- a/packages/SystemUI/Android.bp
+++ b/packages/SystemUI/Android.bp
@@ -552,10 +552,12 @@ systemui_optimized_java_defaults {
optimize: true,
shrink: true,
shrink_resources: true,
+ ignore_warnings: false,
proguard_compatibility: false,
},
conditions_default: {
optimize: {
+ ignore_warnings: false,
proguard_compatibility: false,
},
},
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/qs/footer/ui/compose/FooterActions.kt b/packages/SystemUI/compose/features/src/com/android/systemui/qs/footer/ui/compose/FooterActions.kt
index 13acde206247..482220013e32 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/qs/footer/ui/compose/FooterActions.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/qs/footer/ui/compose/FooterActions.kt
@@ -137,6 +137,7 @@ fun FooterActions(
)
}
+ val horizontalPadding = dimensionResource(R.dimen.qs_content_horizontal_padding)
Row(
modifier
.fillMaxWidth()
@@ -150,6 +151,8 @@ fun FooterActions(
.padding(
top = dimensionResource(R.dimen.qs_footer_actions_top_padding),
bottom = dimensionResource(R.dimen.qs_footer_actions_bottom_padding),
+ start = horizontalPadding,
+ end = horizontalPadding,
)
.layout { measurable, constraints ->
// All buttons have a 4dp padding to increase their touch size. To be consistent
diff --git a/packages/SystemUI/res-keyguard/layout-land/keyguard_pin_view.xml b/packages/SystemUI/res-keyguard/layout-land/keyguard_pin_view.xml
deleted file mode 100644
index cd7ab986844c..000000000000
--- a/packages/SystemUI/res-keyguard/layout-land/keyguard_pin_view.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?><!--
-**
-** Copyright 2023, 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.
-*/
--->
-
-<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent">
-
- <include layout="@layout/keyguard_pin_view_landscape" />
-
-</FrameLayout>
diff --git a/packages/SystemUI/res-keyguard/layout-sw600dp-land/keyguard_pin_view.xml b/packages/SystemUI/res-keyguard/layout-sw600dp-land/keyguard_pin_view.xml
deleted file mode 100644
index 80cc8c06680a..000000000000
--- a/packages/SystemUI/res-keyguard/layout-sw600dp-land/keyguard_pin_view.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?><!--
-**
-** Copyright 2023, 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.
-*/
--->
-
-<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent">
-
- <include layout="@layout/keyguard_pin_view_portrait" />
-
-</FrameLayout>
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_pin_view.xml b/packages/SystemUI/res-keyguard/layout/keyguard_pin_view.xml
index 29e14c57a047..f3cd9e49b49c 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_pin_view.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_pin_view.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
**
-** Copyright 2012, The Android Open Source Project
+** Copyright 2023, 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.
@@ -16,10 +16,203 @@
** limitations under the License.
*/
-->
-<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+
+<com.android.keyguard.KeyguardPINView xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:androidprv="http://schemas.android.com/apk/res-auto"
+ android:id="@+id/keyguard_pin_view"
android:layout_width="match_parent"
- android:layout_height="match_parent">
+ android:layout_height="match_parent"
+ android:layout_gravity="center_horizontal|bottom"
+ android:clipChildren="false"
+ android:clipToPadding="false"
+ android:orientation="vertical"
+ androidprv:layout_maxWidth="@dimen/keyguard_security_width">
+
+ <include layout="@layout/keyguard_bouncer_message_area"/>
+
+ <com.android.systemui.bouncer.ui.BouncerMessageView
+ android:id="@+id/bouncer_message_view"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical" />
+
+ <androidx.constraintlayout.widget.ConstraintLayout
+ android:id="@+id/pin_container"
+ android:layout_width="match_parent"
+ android:layout_height="0dp"
+ android:layout_marginBottom="8dp"
+ android:clipChildren="false"
+ android:clipToPadding="false"
+ android:layout_weight="1"
+ android:layoutDirection="ltr"
+ android:orientation="vertical">
+
+ <!-- Set this to be just above key1. It would be better to introduce a barrier above
+ key1/key2/key3, then place this View above that. Sadly, that doesn't work (the Barrier
+ drops to the bottom of the page, and key1/2/3 all shoot up to the top-left). In any
+ case, the Flow should ensure that key1/2/3 all have the same top, so this should be
+ fine. -->
+ <com.android.keyguard.AlphaOptimizedRelativeLayout
+ android:id="@+id/row0"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingBottom="@dimen/num_pad_entry_row_margin_bottom"
+ androidprv:layout_constraintTop_toTopOf="parent"
+ androidprv:layout_constraintEnd_toEndOf="parent"
+ androidprv:layout_constraintStart_toStartOf="parent"
+ androidprv:layout_constraintBottom_toTopOf="@id/key1"
+ androidprv:layout_constraintVertical_bias="0.5">
+
+ <com.android.keyguard.PasswordTextView
+ android:id="@+id/pinEntry"
+ style="@style/Widget.TextView.Password"
+ android:layout_width="@dimen/keyguard_security_width"
+ android:layout_height="@dimen/keyguard_password_height"
+ android:layout_centerHorizontal="true"
+ android:layout_marginRight="72dp"
+ android:contentDescription="@string/keyguard_accessibility_pin_area"
+ androidprv:scaledTextSize="@integer/scaled_password_text_size" />
+ </com.android.keyguard.AlphaOptimizedRelativeLayout>
+
+ <!-- Guideline used to place the top row of keys relative to the screen height. This will be
+ updated in KeyguardPINView to reduce the height of the PIN pad. -->
+ <androidx.constraintlayout.widget.Guideline
+ android:id="@+id/pin_pad_top_guideline"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ androidprv:layout_constraintGuide_percent="0"
+ android:orientation="horizontal" />
+
+ <com.android.keyguard.KeyguardPinFlowView
+ android:id="@+id/flow1"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:orientation="horizontal"
+ android:clipChildren="false"
+ android:clipToPadding="false"
+
+ androidprv:constraint_referenced_ids="key1,key2,key3,key4,key5,key6,key7,key8,key9,delete_button,key0,key_enter"
+
+ androidprv:flow_horizontalGap="@dimen/num_pad_key_margin_end"
+
+ androidprv:flow_horizontalStyle="packed"
+ androidprv:flow_maxElementsWrap="3"
+
+ androidprv:flow_verticalBias="1.0"
+ androidprv:flow_verticalGap="@dimen/num_pad_entry_row_margin_bottom"
+ androidprv:flow_verticalStyle="packed"
+
+ androidprv:flow_wrapMode="aligned"
+ androidprv:layout_constraintBottom_toBottomOf="parent"
+ androidprv:layout_constraintEnd_toEndOf="parent"
+ androidprv:layout_constraintStart_toStartOf="parent"
+ androidprv:layout_constraintTop_toBottomOf="@id/pin_pad_top_guideline" />
+
+ <com.android.keyguard.NumPadKey
+ android:id="@+id/key1"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:accessibilityTraversalBefore="@id/key2"
+ androidprv:digit="1"
+ androidprv:textView="@+id/pinEntry" />
+
+ <com.android.keyguard.NumPadKey
+ android:id="@+id/key2"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:accessibilityTraversalBefore="@id/key3"
+ androidprv:digit="2"
+ androidprv:textView="@+id/pinEntry" />
+
+ <com.android.keyguard.NumPadKey
+ android:id="@+id/key3"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:accessibilityTraversalBefore="@id/key4"
+ androidprv:digit="3"
+ androidprv:textView="@+id/pinEntry" />
+
+ <com.android.keyguard.NumPadKey
+ android:id="@+id/key4"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:accessibilityTraversalBefore="@id/key5"
+ androidprv:digit="4"
+ androidprv:textView="@+id/pinEntry" />
+
+ <com.android.keyguard.NumPadKey
+ android:id="@+id/key5"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:accessibilityTraversalBefore="@id/key6"
+ androidprv:digit="5"
+ androidprv:textView="@+id/pinEntry" />
+
+ <com.android.keyguard.NumPadKey
+ android:id="@+id/key6"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:accessibilityTraversalBefore="@id/key7"
+ androidprv:digit="6"
+ androidprv:textView="@+id/pinEntry" />
+
+ <com.android.keyguard.NumPadKey
+ android:id="@+id/key7"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:accessibilityTraversalBefore="@id/key8"
+ androidprv:digit="7"
+ androidprv:textView="@+id/pinEntry" />
+
+
+ <com.android.keyguard.NumPadKey
+ android:id="@+id/key8"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:accessibilityTraversalBefore="@id/key9"
+ androidprv:digit="8"
+ androidprv:textView="@+id/pinEntry" />
+
+ <com.android.keyguard.NumPadKey
+ android:id="@+id/key9"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:accessibilityTraversalBefore="@id/delete_button"
+ androidprv:digit="9"
+ androidprv:textView="@+id/pinEntry" />
+
+ <com.android.keyguard.NumPadButton
+ android:id="@+id/delete_button"
+ style="@style/NumPadKey.Delete"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:accessibilityTraversalBefore="@id/key0"
+ android:contentDescription="@string/keyboardview_keycode_delete" />
+
+ <com.android.keyguard.NumPadKey
+ android:id="@+id/key0"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:accessibilityTraversalBefore="@id/key_enter"
+ androidprv:digit="0"
+ androidprv:textView="@+id/pinEntry" />
+
+ <com.android.keyguard.NumPadButton
+ android:id="@+id/key_enter"
+ style="@style/NumPadKey.Enter"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:contentDescription="@string/keyboardview_keycode_enter" />
+ </androidx.constraintlayout.widget.ConstraintLayout>
- <include layout="@layout/keyguard_pin_view_portrait" />
+ <include layout="@layout/keyguard_eca"
+ android:id="@+id/keyguard_selector_fade_container"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:layout_gravity="bottom|center_horizontal"
+ android:layout_marginTop="@dimen/keyguard_eca_top_margin"
+ android:layout_marginBottom="@dimen/keyguard_eca_bottom_margin"
+ android:gravity="center_horizontal"/>
-</FrameLayout>
+</com.android.keyguard.KeyguardPINView>
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_pin_view_landscape.xml b/packages/SystemUI/res-keyguard/layout/keyguard_pin_view_landscape.xml
deleted file mode 100644
index e00742d80017..000000000000
--- a/packages/SystemUI/res-keyguard/layout/keyguard_pin_view_landscape.xml
+++ /dev/null
@@ -1,231 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?><!--
-**
-** Copyright 2023, 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.
-*/
--->
-
-<com.android.keyguard.KeyguardPINView xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:androidprv="http://schemas.android.com/apk/res-auto"
- xmlns:tools="http://schemas.android.com/tools"
- android:id="@+id/keyguard_pin_view"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:layout_gravity="center_horizontal|bottom"
- android:clipChildren="false"
- android:clipToPadding="false"
- android:orientation="horizontal">
-
- <androidx.constraintlayout.widget.ConstraintLayout
- android:layout_width="0dp"
- android:layout_height="match_parent"
- android:layout_weight="2"
- android:clipChildren="false"
- android:clipToPadding="false"
- android:layoutDirection="ltr"
- android:orientation="vertical">
-
- <include layout="@layout/keyguard_bouncer_message_area" />
-
- <com.android.systemui.bouncer.ui.BouncerMessageView
- android:id="@+id/bouncer_message_view"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="vertical"
- androidprv:layout_constraintBottom_toTopOf="@+id/row0"
- androidprv:layout_constraintTop_toTopOf="parent"
- androidprv:layout_constraintVertical_chainStyle="packed" />
-
- <!-- Set this to be just above key1. It would be better to introduce a barrier above
- key1/key2/key3, then place this View above that. Sadly, that doesn't work (the Barrier
- drops to the bottom of the page, and key1/2/3 all shoot up to the top-left). In any
- case, the Flow should ensure that key1/2/3 all have the same top, so this should be
- fine. -->
- <com.android.keyguard.AlphaOptimizedRelativeLayout
- android:id="@+id/row0"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:paddingBottom="@dimen/num_pad_entry_row_margin_bottom"
- androidprv:layout_constraintBottom_toTopOf="@+id/keyguard_selector_fade_container"
- androidprv:layout_constraintTop_toBottomOf="@+id/bouncer_message_view"
- tools:layout_editor_absoluteX="-16dp">
-
- <com.android.keyguard.PasswordTextView
- android:id="@+id/pinEntry"
- style="@style/Widget.TextView.Password"
- android:layout_width="@dimen/keyguard_security_width"
- android:layout_height="@dimen/keyguard_password_height"
- android:layout_centerHorizontal="true"
- android:layout_marginRight="72dp"
- android:contentDescription="@string/keyguard_accessibility_pin_area"
- androidprv:scaledTextSize="@integer/scaled_password_text_size" />
- </com.android.keyguard.AlphaOptimizedRelativeLayout>
-
- <include
- android:id="@+id/keyguard_selector_fade_container"
- layout="@layout/keyguard_eca"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_gravity="bottom|center_horizontal"
- android:layout_marginBottom="@dimen/keyguard_eca_bottom_margin"
- android:layout_marginTop="@dimen/keyguard_eca_top_margin"
- android:gravity="center_horizontal"
- android:orientation="vertical"
- androidprv:layout_constraintBottom_toBottomOf="parent" />
-
- </androidx.constraintlayout.widget.ConstraintLayout>
-
- <androidx.constraintlayout.widget.ConstraintLayout
- android:id="@+id/pin_container"
- android:layout_width="0dp"
- android:layout_height="match_parent"
- android:layout_weight="3"
- android:clipChildren="false"
- android:clipToPadding="false"
- android:layoutDirection="ltr"
- android:orientation="vertical">
-
- <!-- Guideline used to place the top row of keys relative to the screen height. This will be
- updated in KeyguardPINView to reduce the height of the PIN pad. -->
- <androidx.constraintlayout.widget.Guideline
- android:id="@+id/pin_pad_top_guideline"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:orientation="horizontal"
- androidprv:layout_constraintGuide_percent="0" />
-
- <com.android.keyguard.KeyguardPinFlowView
- android:id="@+id/flow1"
- android:layout_width="0dp"
- android:layout_height="0dp"
- android:clipChildren="false"
- android:clipToPadding="false"
- android:orientation="horizontal"
-
- androidprv:constraint_referenced_ids="key1,key2,key3,key4,key5,key6,key7,key8,key9,delete_button,key0,key_enter"
-
- androidprv:flow_horizontalGap="@dimen/num_pad_key_margin_end"
-
- androidprv:flow_horizontalStyle="packed"
- androidprv:flow_maxElementsWrap="3"
-
- androidprv:flow_verticalBias="0.5"
- androidprv:flow_verticalGap="@dimen/num_pad_entry_row_margin_bottom"
- androidprv:flow_verticalStyle="packed"
-
- androidprv:flow_wrapMode="aligned"
- androidprv:layout_constraintBottom_toBottomOf="parent"
- androidprv:layout_constraintEnd_toEndOf="parent"
- androidprv:layout_constraintStart_toStartOf="parent"
- androidprv:layout_constraintTop_toBottomOf="@id/pin_pad_top_guideline" />
-
- <com.android.keyguard.NumPadButton
- android:id="@+id/delete_button"
- style="@style/NumPadKey.Delete"
- android:layout_width="0dp"
- android:layout_height="0dp"
- android:accessibilityTraversalBefore="@id/key0"
- android:contentDescription="@string/keyboardview_keycode_delete" />
-
- <com.android.keyguard.NumPadButton
- android:id="@+id/key_enter"
- style="@style/NumPadKey.Enter"
- android:layout_width="0dp"
- android:layout_height="0dp"
- android:contentDescription="@string/keyboardview_keycode_enter" />
-
- <com.android.keyguard.NumPadKey
- android:id="@+id/key1"
- android:layout_width="0dp"
- android:layout_height="0dp"
- android:accessibilityTraversalBefore="@id/key2"
- androidprv:digit="1"
- androidprv:textView="@+id/pinEntry" />
-
- <com.android.keyguard.NumPadKey
- android:id="@+id/key2"
- android:layout_width="0dp"
- android:layout_height="0dp"
- android:accessibilityTraversalBefore="@id/key3"
- androidprv:digit="2"
- androidprv:textView="@+id/pinEntry" />
-
- <com.android.keyguard.NumPadKey
- android:id="@+id/key3"
- android:layout_width="0dp"
- android:layout_height="0dp"
- android:accessibilityTraversalBefore="@id/key4"
- androidprv:digit="3"
- androidprv:textView="@+id/pinEntry" />
-
- <com.android.keyguard.NumPadKey
- android:id="@+id/key4"
- android:layout_width="0dp"
- android:layout_height="0dp"
- android:accessibilityTraversalBefore="@id/key5"
- androidprv:digit="4"
- androidprv:textView="@+id/pinEntry" />
-
- <com.android.keyguard.NumPadKey
- android:id="@+id/key5"
- android:layout_width="0dp"
- android:layout_height="0dp"
- android:accessibilityTraversalBefore="@id/key6"
- androidprv:digit="5"
- androidprv:textView="@+id/pinEntry" />
-
-
- <com.android.keyguard.NumPadKey
- android:id="@+id/key6"
- android:layout_width="0dp"
- android:layout_height="0dp"
- android:accessibilityTraversalBefore="@id/key7"
- androidprv:digit="6"
- androidprv:textView="@+id/pinEntry" />
-
- <com.android.keyguard.NumPadKey
- android:id="@+id/key7"
- android:layout_width="0dp"
- android:layout_height="0dp"
- android:accessibilityTraversalBefore="@id/key8"
- androidprv:digit="7"
- androidprv:textView="@+id/pinEntry" />
-
- <com.android.keyguard.NumPadKey
- android:id="@+id/key8"
- android:layout_width="0dp"
- android:layout_height="0dp"
- android:accessibilityTraversalBefore="@id/key9"
- androidprv:digit="8"
- androidprv:textView="@+id/pinEntry" />
-
- <com.android.keyguard.NumPadKey
- android:id="@+id/key9"
- android:layout_width="0dp"
- android:layout_height="0dp"
- android:accessibilityTraversalBefore="@id/delete_button"
- androidprv:digit="9"
- androidprv:textView="@+id/pinEntry" />
-
- <com.android.keyguard.NumPadKey
- android:id="@+id/key0"
- android:layout_width="0dp"
- android:layout_height="0dp"
- android:accessibilityTraversalBefore="@id/key_enter"
- androidprv:digit="0"
- androidprv:textView="@+id/pinEntry" />
-
- </androidx.constraintlayout.widget.ConstraintLayout>
-
-</com.android.keyguard.KeyguardPINView>
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_pin_view_portrait.xml b/packages/SystemUI/res-keyguard/layout/keyguard_pin_view_portrait.xml
deleted file mode 100644
index f3cd9e49b49c..000000000000
--- a/packages/SystemUI/res-keyguard/layout/keyguard_pin_view_portrait.xml
+++ /dev/null
@@ -1,218 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-**
-** Copyright 2023, 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.
-*/
--->
-
-<com.android.keyguard.KeyguardPINView xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:androidprv="http://schemas.android.com/apk/res-auto"
- android:id="@+id/keyguard_pin_view"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:layout_gravity="center_horizontal|bottom"
- android:clipChildren="false"
- android:clipToPadding="false"
- android:orientation="vertical"
- androidprv:layout_maxWidth="@dimen/keyguard_security_width">
-
- <include layout="@layout/keyguard_bouncer_message_area"/>
-
- <com.android.systemui.bouncer.ui.BouncerMessageView
- android:id="@+id/bouncer_message_view"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="vertical" />
-
- <androidx.constraintlayout.widget.ConstraintLayout
- android:id="@+id/pin_container"
- android:layout_width="match_parent"
- android:layout_height="0dp"
- android:layout_marginBottom="8dp"
- android:clipChildren="false"
- android:clipToPadding="false"
- android:layout_weight="1"
- android:layoutDirection="ltr"
- android:orientation="vertical">
-
- <!-- Set this to be just above key1. It would be better to introduce a barrier above
- key1/key2/key3, then place this View above that. Sadly, that doesn't work (the Barrier
- drops to the bottom of the page, and key1/2/3 all shoot up to the top-left). In any
- case, the Flow should ensure that key1/2/3 all have the same top, so this should be
- fine. -->
- <com.android.keyguard.AlphaOptimizedRelativeLayout
- android:id="@+id/row0"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:paddingBottom="@dimen/num_pad_entry_row_margin_bottom"
- androidprv:layout_constraintTop_toTopOf="parent"
- androidprv:layout_constraintEnd_toEndOf="parent"
- androidprv:layout_constraintStart_toStartOf="parent"
- androidprv:layout_constraintBottom_toTopOf="@id/key1"
- androidprv:layout_constraintVertical_bias="0.5">
-
- <com.android.keyguard.PasswordTextView
- android:id="@+id/pinEntry"
- style="@style/Widget.TextView.Password"
- android:layout_width="@dimen/keyguard_security_width"
- android:layout_height="@dimen/keyguard_password_height"
- android:layout_centerHorizontal="true"
- android:layout_marginRight="72dp"
- android:contentDescription="@string/keyguard_accessibility_pin_area"
- androidprv:scaledTextSize="@integer/scaled_password_text_size" />
- </com.android.keyguard.AlphaOptimizedRelativeLayout>
-
- <!-- Guideline used to place the top row of keys relative to the screen height. This will be
- updated in KeyguardPINView to reduce the height of the PIN pad. -->
- <androidx.constraintlayout.widget.Guideline
- android:id="@+id/pin_pad_top_guideline"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- androidprv:layout_constraintGuide_percent="0"
- android:orientation="horizontal" />
-
- <com.android.keyguard.KeyguardPinFlowView
- android:id="@+id/flow1"
- android:layout_width="0dp"
- android:layout_height="0dp"
- android:orientation="horizontal"
- android:clipChildren="false"
- android:clipToPadding="false"
-
- androidprv:constraint_referenced_ids="key1,key2,key3,key4,key5,key6,key7,key8,key9,delete_button,key0,key_enter"
-
- androidprv:flow_horizontalGap="@dimen/num_pad_key_margin_end"
-
- androidprv:flow_horizontalStyle="packed"
- androidprv:flow_maxElementsWrap="3"
-
- androidprv:flow_verticalBias="1.0"
- androidprv:flow_verticalGap="@dimen/num_pad_entry_row_margin_bottom"
- androidprv:flow_verticalStyle="packed"
-
- androidprv:flow_wrapMode="aligned"
- androidprv:layout_constraintBottom_toBottomOf="parent"
- androidprv:layout_constraintEnd_toEndOf="parent"
- androidprv:layout_constraintStart_toStartOf="parent"
- androidprv:layout_constraintTop_toBottomOf="@id/pin_pad_top_guideline" />
-
- <com.android.keyguard.NumPadKey
- android:id="@+id/key1"
- android:layout_width="0dp"
- android:layout_height="0dp"
- android:accessibilityTraversalBefore="@id/key2"
- androidprv:digit="1"
- androidprv:textView="@+id/pinEntry" />
-
- <com.android.keyguard.NumPadKey
- android:id="@+id/key2"
- android:layout_width="0dp"
- android:layout_height="0dp"
- android:accessibilityTraversalBefore="@id/key3"
- androidprv:digit="2"
- androidprv:textView="@+id/pinEntry" />
-
- <com.android.keyguard.NumPadKey
- android:id="@+id/key3"
- android:layout_width="0dp"
- android:layout_height="0dp"
- android:accessibilityTraversalBefore="@id/key4"
- androidprv:digit="3"
- androidprv:textView="@+id/pinEntry" />
-
- <com.android.keyguard.NumPadKey
- android:id="@+id/key4"
- android:layout_width="0dp"
- android:layout_height="0dp"
- android:accessibilityTraversalBefore="@id/key5"
- androidprv:digit="4"
- androidprv:textView="@+id/pinEntry" />
-
- <com.android.keyguard.NumPadKey
- android:id="@+id/key5"
- android:layout_width="0dp"
- android:layout_height="0dp"
- android:accessibilityTraversalBefore="@id/key6"
- androidprv:digit="5"
- androidprv:textView="@+id/pinEntry" />
-
- <com.android.keyguard.NumPadKey
- android:id="@+id/key6"
- android:layout_width="0dp"
- android:layout_height="0dp"
- android:accessibilityTraversalBefore="@id/key7"
- androidprv:digit="6"
- androidprv:textView="@+id/pinEntry" />
-
- <com.android.keyguard.NumPadKey
- android:id="@+id/key7"
- android:layout_width="0dp"
- android:layout_height="0dp"
- android:accessibilityTraversalBefore="@id/key8"
- androidprv:digit="7"
- androidprv:textView="@+id/pinEntry" />
-
-
- <com.android.keyguard.NumPadKey
- android:id="@+id/key8"
- android:layout_width="0dp"
- android:layout_height="0dp"
- android:accessibilityTraversalBefore="@id/key9"
- androidprv:digit="8"
- androidprv:textView="@+id/pinEntry" />
-
- <com.android.keyguard.NumPadKey
- android:id="@+id/key9"
- android:layout_width="0dp"
- android:layout_height="0dp"
- android:accessibilityTraversalBefore="@id/delete_button"
- androidprv:digit="9"
- androidprv:textView="@+id/pinEntry" />
-
- <com.android.keyguard.NumPadButton
- android:id="@+id/delete_button"
- style="@style/NumPadKey.Delete"
- android:layout_width="0dp"
- android:layout_height="0dp"
- android:accessibilityTraversalBefore="@id/key0"
- android:contentDescription="@string/keyboardview_keycode_delete" />
-
- <com.android.keyguard.NumPadKey
- android:id="@+id/key0"
- android:layout_width="0dp"
- android:layout_height="0dp"
- android:accessibilityTraversalBefore="@id/key_enter"
- androidprv:digit="0"
- androidprv:textView="@+id/pinEntry" />
-
- <com.android.keyguard.NumPadButton
- android:id="@+id/key_enter"
- style="@style/NumPadKey.Enter"
- android:layout_width="0dp"
- android:layout_height="0dp"
- android:contentDescription="@string/keyboardview_keycode_enter" />
- </androidx.constraintlayout.widget.ConstraintLayout>
-
- <include layout="@layout/keyguard_eca"
- android:id="@+id/keyguard_selector_fade_container"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="vertical"
- android:layout_gravity="bottom|center_horizontal"
- android:layout_marginTop="@dimen/keyguard_eca_top_margin"
- android:layout_marginBottom="@dimen/keyguard_eca_bottom_margin"
- android:gravity="center_horizontal"/>
-
-</com.android.keyguard.KeyguardPINView>
diff --git a/packages/SystemUI/res/values-sw600dp/bools.xml b/packages/SystemUI/res/values-sw600dp/bools.xml
index 05e38bdb8389..d7ddf00f91c2 100644
--- a/packages/SystemUI/res/values-sw600dp/bools.xml
+++ b/packages/SystemUI/res/values-sw600dp/bools.xml
@@ -18,4 +18,12 @@
<resources>
<!-- Whether to show the user switcher in quick settings when only a single user is present. -->
<bool name="qs_show_user_switcher_for_single_user">true</bool>
+
+ <!-- Do update bouncer constraints (port or land) on rotation.
+ Needed for bouncer refactor to use motion layout, because constraints should only be
+ changed on small screens. Only used when flag "lockscreen.enable_landscape" (b/293252410)
+ is enabled
+
+ False here so bouncers constraints are not updated when rotating on large screens -->
+ <bool name="update_bouncer_constraints">false</bool>
</resources>
diff --git a/packages/SystemUI/res/values/bools.xml b/packages/SystemUI/res/values/bools.xml
index 405a59fe1cc7..91d3a88dcc89 100644
--- a/packages/SystemUI/res/values/bools.xml
+++ b/packages/SystemUI/res/values/bools.xml
@@ -51,4 +51,12 @@
This configuration will only apply when config_remoteInsetsControllerControlsSystemBars.
is set to true. -->
<bool name="config_remoteInsetsControllerSystemBarsCanBeShownByUserAction">false</bool>
+
+ <!-- Do update bouncer constraints (port or land) on rotation.
+ Needed for bouncer refactor to use motion layout, because constraints should only be
+ changed on small screens. Only used when flag "lockscreen.enable_landscape" (b/293252410)
+ is enabled
+
+ True here so bouncers constraints are updated when rotating on small screens -->
+ <bool name="update_bouncer_constraints">true</bool>
</resources>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 016936aae956..c13480672102 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -934,4 +934,12 @@
<!-- Flag controlling whether visual query attention detection has been enabled. -->
<bool name="config_enableVisualQueryAttentionDetection">false</bool>
+
+ <!--
+ Whether the scene container framework is enabled.
+
+ The scene container framework is a newer (2023) way to organize the various "scenes" between the
+ bouncer, lockscreen, shade, and quick settings.
+ -->
+ <bool name="config_sceneContainerFrameworkEnabled">true</bool>
</resources>
diff --git a/packages/SystemUI/res/values/ids.xml b/packages/SystemUI/res/values/ids.xml
index 579358fe709b..d8c808054fff 100644
--- a/packages/SystemUI/res/values/ids.xml
+++ b/packages/SystemUI/res/values/ids.xml
@@ -233,4 +233,7 @@
removed later.
-->
<item type="id" name="tag_smartspace_view" />
+
+ <!-- Tag set on the Compose implementation of the QS footer actions. -->
+ <item type="id" name="tag_compose_qs_footer_actions" />
</resources>
diff --git a/packages/SystemUI/res/xml/media_session_expanded.xml b/packages/SystemUI/res/xml/media_session_expanded.xml
index 0cdc0f9505bc..8bf7560d6ddb 100644
--- a/packages/SystemUI/res/xml/media_session_expanded.xml
+++ b/packages/SystemUI/res/xml/media_session_expanded.xml
@@ -54,10 +54,12 @@
android:layout_marginStart="@dimen/qs_media_padding"
android:layout_marginEnd="@dimen/qs_media_padding"
app:layout_constraintEnd_toStartOf="@id/actionPlayPause"
+ app:layout_constraintTop_toBottomOf="@id/media_seamless"
app:layout_constrainedWidth="true"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintBottom_toTopOf="@id/header_artist"
- app:layout_constraintHorizontal_bias="0" />
+ app:layout_constraintHorizontal_bias="0"
+ app:layout_constraintVertical_bias="1" />
<Constraint
android:id="@+id/media_explicit_indicator"
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardInputView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardInputView.java
index c9d906911dbc..a72d8137663b 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardInputView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardInputView.java
@@ -64,6 +64,11 @@ public abstract class KeyguardInputView extends LinearLayout {
return false;
}
+ /** Change motion layout constraint set based on orientation */
+ protected void updateConstraints(int orientation) {
+ //Unless overridden, never update constrains (keeping default portrait constraints)
+ }
+
protected AnimatorListenerAdapter getAnimationListener(int cuj) {
return new AnimatorListenerAdapter() {
private boolean mIsCancel;
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
index d90785dd266d..a2d8c50fdca7 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
@@ -83,6 +83,7 @@ import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInterac
import com.android.systemui.log.SessionTracker;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.FalsingManager;
+import com.android.systemui.scene.shared.flag.SceneContainerFlags;
import com.android.systemui.shared.system.SysUiStatsLog;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
@@ -123,6 +124,7 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
private final UserSwitcherController mUserSwitcherController;
private final GlobalSettings mGlobalSettings;
private final FeatureFlags mFeatureFlags;
+ private final SceneContainerFlags mSceneContainerFlags;
private final SessionTracker mSessionTracker;
private final Optional<SideFpsController> mSideFpsController;
private final FalsingA11yDelegate mFalsingA11yDelegate;
@@ -369,11 +371,9 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
@Override
public void onOrientationChanged(int orientation) {
- if (mFeatureFlags.isEnabled(LOCKSCREEN_ENABLE_LANDSCAPE)) {
- // TODO(b/295603468)
- // Fix reinflation of views when flag is enabled.
- KeyguardSecurityContainerController.this
- .onDensityOrFontScaleOrOrientationChanged();
+ if (mFeatureFlags.isEnabled(LOCKSCREEN_ENABLE_LANDSCAPE)
+ && getResources().getBoolean(R.bool.update_bouncer_constraints)) {
+ mSecurityViewFlipperController.updateConstraints(orientation);
}
}
};
@@ -433,6 +433,7 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
FalsingManager falsingManager,
UserSwitcherController userSwitcherController,
FeatureFlags featureFlags,
+ SceneContainerFlags sceneContainerFlags,
GlobalSettings globalSettings,
SessionTracker sessionTracker,
Optional<SideFpsController> sideFpsController,
@@ -466,6 +467,7 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
mFalsingManager = falsingManager;
mUserSwitcherController = userSwitcherController;
mFeatureFlags = featureFlags;
+ mSceneContainerFlags = sceneContainerFlags;
mGlobalSettings = globalSettings;
mSessionTracker = sessionTracker;
mSideFpsController = sideFpsController;
@@ -503,7 +505,7 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
showPrimarySecurityScreen(false);
- if (mFeatureFlags.isEnabled(Flags.SCENE_CONTAINER)) {
+ if (mSceneContainerFlags.isEnabled()) {
// When the scene framework says that the lockscreen has been dismissed, dismiss the
// keyguard here, revealing the underlying app or launcher:
mSceneTransitionCollectionJob = mJavaAdapter.get().alwaysCollectFlow(
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityViewFlipper.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityViewFlipper.java
index 4d2391ad5596..891eb149427b 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityViewFlipper.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityViewFlipper.java
@@ -83,6 +83,14 @@ public class KeyguardSecurityViewFlipper extends ViewFlipper {
return "";
}
+ /** Updates the keyguard view's constraints based on orientation */
+ public void updateConstraints(int orientation) {
+ KeyguardInputView securityView = getSecurityView();
+ if (securityView != null) {
+ securityView.updateConstraints(orientation);
+ }
+ }
+
@Override
protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
return p instanceof LayoutParams;
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityViewFlipperController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityViewFlipperController.java
index bc5b1ba9a294..74f0beb71eb2 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityViewFlipperController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityViewFlipperController.java
@@ -16,6 +16,8 @@
package com.android.keyguard;
+import static com.android.systemui.flags.Flags.LOCKSCREEN_ENABLE_LANDSCAPE;
+
import android.util.Log;
import android.view.LayoutInflater;
@@ -116,30 +118,38 @@ public class KeyguardSecurityViewFlipperController
public void asynchronouslyInflateView(SecurityMode securityMode,
KeyguardSecurityCallback keyguardSecurityCallback,
@Nullable OnViewInflatedCallback onViewInflatedListener) {
- int layoutId = getLayoutIdFor(securityMode);
- int viewID = getKeyguardInputViewId(securityMode);
- if (layoutId != 0 && viewID != 0) {
+ int layoutId = mFeatureFlags.isEnabled(LOCKSCREEN_ENABLE_LANDSCAPE)
+ ? getLayoutIdFor(securityMode) : getLegacyLayoutIdFor(securityMode);
+ if (layoutId != 0) {
if (DEBUG) {
- Log.v(TAG, "inflating on bg thread id = "
- + layoutId + " . viewID = " + viewID);
+ Log.v(TAG, "inflating on bg thread id = " + layoutId + " .");
}
mAsyncLayoutInflater.inflate(layoutId, mView,
(view, resId, parent) -> {
mView.addView(view);
KeyguardInputViewController<KeyguardInputView> childController =
mKeyguardSecurityViewControllerFactory.create(
- (KeyguardInputView) view.findViewById(viewID),
+ (KeyguardInputView) view,
securityMode, keyguardSecurityCallback);
childController.init();
mChildren.add(childController);
if (onViewInflatedListener != null) {
onViewInflatedListener.onViewInflated(childController);
+
+ // Portrait constrains are default
+ if (mFeatureFlags.isEnabled(LOCKSCREEN_ENABLE_LANDSCAPE)
+ &&
+ getResources().getBoolean(R.bool.update_bouncer_constraints)) {
+ // updateConstraints based on orientation (only on small screens)
+ updateConstraints(getResources().getConfiguration().orientation);
+ }
}
});
}
}
private int getLayoutIdFor(SecurityMode securityMode) {
+ // TODO (b/297863911, b/297864907) - implement motion layout for other bouncers
switch (securityMode) {
case Pattern: return R.layout.keyguard_pattern_view;
case PIN: return R.layout.keyguard_pin_view;
@@ -151,19 +161,23 @@ public class KeyguardSecurityViewFlipperController
}
}
- private int getKeyguardInputViewId(SecurityMode securityMode) {
- //Keyguard Input View is not the root view of the layout, use these IDs for lookup.
+ private int getLegacyLayoutIdFor(SecurityMode securityMode) {
switch (securityMode) {
- case Pattern: return R.id.keyguard_pattern_view;
- case PIN: return R.id.keyguard_pin_view;
- case Password: return R.id.keyguard_password_view;
- case SimPin: return R.id.keyguard_sim_pin_view;
- case SimPuk: return R.id.keyguard_sim_puk_view;
+ case Pattern: return R.layout.keyguard_pattern_view;
+ case PIN: return R.layout.keyguard_pin_view;
+ case Password: return R.layout.keyguard_password_view;
+ case SimPin: return R.layout.keyguard_sim_pin_view;
+ case SimPuk: return R.layout.keyguard_sim_puk_view;
default:
return 0;
}
}
+ /** Updates the keyguard view's constraints based on orientation */
+ public void updateConstraints(int orientation) {
+ mView.updateConstraints(orientation);
+ }
+
/** Makes the supplied child visible if it is contained win this view, */
public void show(KeyguardInputViewController<KeyguardInputView> childController) {
int index = childController.getIndexIn(mView);
diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractor.kt b/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractor.kt
index fc32f4c138d7..9527f327a837 100644
--- a/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractor.kt
@@ -26,9 +26,8 @@ import com.android.systemui.classifier.FalsingClassifier
import com.android.systemui.classifier.domain.interactor.FalsingInteractor
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
-import com.android.systemui.flags.FeatureFlags
-import com.android.systemui.flags.Flags
import com.android.systemui.scene.domain.interactor.SceneInteractor
+import com.android.systemui.scene.shared.flag.SceneContainerFlags
import com.android.systemui.scene.shared.model.SceneKey
import com.android.systemui.scene.shared.model.SceneModel
import com.android.systemui.util.kotlin.pairwise
@@ -51,7 +50,7 @@ constructor(
private val repository: BouncerRepository,
private val authenticationInteractor: AuthenticationInteractor,
private val sceneInteractor: SceneInteractor,
- featureFlags: FeatureFlags,
+ flags: SceneContainerFlags,
private val falsingInteractor: FalsingInteractor,
) {
@@ -94,7 +93,7 @@ constructor(
val isPatternVisible: StateFlow<Boolean> = authenticationInteractor.isPatternVisible
init {
- if (featureFlags.isEnabled(Flags.SCENE_CONTAINER)) {
+ if (flags.isEnabled()) {
// Clear the message if moved from throttling to no-longer throttling.
applicationScope.launch {
isThrottled.pairwise().collect { (wasThrottled, currentlyThrottled) ->
diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModel.kt b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModel.kt
index 5b1998d1e5f6..f6794d4f40b3 100644
--- a/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModel.kt
@@ -23,8 +23,7 @@ import com.android.systemui.authentication.domain.model.AuthenticationMethodMode
import com.android.systemui.bouncer.domain.interactor.BouncerInteractor
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
-import com.android.systemui.flags.FeatureFlags
-import com.android.systemui.flags.Flags
+import com.android.systemui.scene.shared.flag.SceneContainerFlags
import javax.inject.Inject
import kotlin.math.ceil
import kotlinx.coroutines.CoroutineScope
@@ -47,7 +46,7 @@ constructor(
@Application private val applicationScope: CoroutineScope,
private val bouncerInteractor: BouncerInteractor,
private val authenticationInteractor: AuthenticationInteractor,
- featureFlags: FeatureFlags,
+ flags: SceneContainerFlags,
) {
private val isInputEnabled: StateFlow<Boolean> =
bouncerInteractor.isThrottled
@@ -102,7 +101,7 @@ constructor(
)
init {
- if (featureFlags.isEnabled(Flags.SCENE_CONTAINER)) {
+ if (flags.isEnabled()) {
applicationScope.launch {
bouncerInteractor.isThrottled
.map { isThrottled ->
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingModule.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingModule.java
index 3195d093a711..0a1aed65c205 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingModule.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingModule.java
@@ -22,8 +22,7 @@ import android.view.ViewConfiguration;
import com.android.systemui.R;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Main;
-import com.android.systemui.flags.FeatureFlagsClassic;
-import com.android.systemui.flags.Flags;
+import com.android.systemui.scene.shared.flag.SceneContainerFlags;
import com.android.systemui.statusbar.phone.NotificationTapHelper;
import dagger.Binds;
@@ -53,8 +52,8 @@ public interface FalsingModule {
static FalsingCollector providesFalsingCollectorLegacy(
FalsingCollectorImpl impl,
FalsingCollectorNoOp noOp,
- FeatureFlagsClassic featureFlags) {
- return featureFlags.isEnabled(Flags.SCENE_CONTAINER) ? noOp : impl;
+ SceneContainerFlags flags) {
+ return flags.isEnabled() ? noOp : impl;
}
/** Provides the actual {@link FalsingCollector}. */
diff --git a/packages/SystemUI/src/com/android/systemui/communal/ui/view/layout/blueprints/DefaultCommunalBlueprint.kt b/packages/SystemUI/src/com/android/systemui/communal/ui/view/layout/blueprints/DefaultCommunalBlueprint.kt
index 970b475fe702..3ff1f09cc0f1 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/ui/view/layout/blueprints/DefaultCommunalBlueprint.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/ui/view/layout/blueprints/DefaultCommunalBlueprint.kt
@@ -31,7 +31,7 @@ constructor(
defaultCommunalWidgetSection: DefaultCommunalWidgetSection,
) : KeyguardBlueprint {
override val id: String = COMMUNAL
- override val sections: Array<KeyguardSection> = arrayOf(defaultCommunalWidgetSection)
+ override val sections: Set<KeyguardSection> = setOf(defaultCommunalWidgetSection)
companion object {
const val COMMUNAL = "communal"
diff --git a/packages/SystemUI/src/com/android/systemui/communal/ui/view/layout/sections/DefaultCommunalWidgetSection.kt b/packages/SystemUI/src/com/android/systemui/communal/ui/view/layout/sections/DefaultCommunalWidgetSection.kt
index 4fb9384630a5..8640c97bb1e1 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/ui/view/layout/sections/DefaultCommunalWidgetSection.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/ui/view/layout/sections/DefaultCommunalWidgetSection.kt
@@ -42,9 +42,12 @@ constructor(
private val communalWidgetViewModel: CommunalWidgetViewModel,
private val communalWidgetViewAdapter: CommunalWidgetViewAdapter,
private val keyguardBlueprintInteractor: Lazy<KeyguardBlueprintInteractor>,
-) : KeyguardSection {
+) : KeyguardSection() {
private val widgetAreaViewId = R.id.communal_widget_wrapper
- override fun addViews(constraintLayout: ConstraintLayout) {
+
+ override fun addViews(constraintLayout: ConstraintLayout) {}
+
+ override fun bindData(constraintLayout: ConstraintLayout) {
if (!featureFlags.isEnabled(Flags.WIDGET_ON_KEYGUARD)) {
return
}
@@ -65,4 +68,6 @@ constructor(
connect(widgetAreaViewId, END, PARENT_ID, END)
}
}
+
+ override fun removeViews(constraintLayout: ConstraintLayout) {}
}
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ThumbnailBehavior.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ThumbnailBehavior.kt
index 0b57e792f9f7..d011dd421f7f 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/ThumbnailBehavior.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ThumbnailBehavior.kt
@@ -22,6 +22,7 @@ import android.graphics.drawable.ClipDrawable
import android.graphics.drawable.LayerDrawable
import android.view.View
import android.service.controls.Control
+import android.service.controls.templates.TemperatureControlTemplate
import android.service.controls.templates.ThumbnailTemplate
import android.util.TypedValue
@@ -68,7 +69,9 @@ class ThumbnailBehavior(currentUserId: Int) : Behavior {
override fun bind(cws: ControlWithState, colorOffset: Int) {
this.control = cws.control!!
cvh.setStatusText(control.getStatusText())
- template = control.getControlTemplate() as ThumbnailTemplate
+ template = control.controlTemplate as? ThumbnailTemplate
+ ?: (control.controlTemplate as TemperatureControlTemplate).template
+ as ThumbnailTemplate
val ld = cvh.layout.getBackground() as LayerDrawable
val clipLayer = ld.findDrawableByLayerId(R.id.clip_layer) as ClipDrawable
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
index 08d11c2fc4ef..7ee0ff4568be 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
@@ -124,7 +124,6 @@ import com.android.systemui.user.UserModule;
import com.android.systemui.util.concurrency.SysUIConcurrencyModule;
import com.android.systemui.util.dagger.UtilModule;
import com.android.systemui.util.kotlin.CoroutinesModule;
-import com.android.systemui.util.leak.GarbageMonitorModule;
import com.android.systemui.util.sensors.SensorModule;
import com.android.systemui.util.settings.SettingsUtilModule;
import com.android.systemui.util.time.SystemClock;
@@ -177,7 +176,6 @@ import javax.inject.Named;
FlagsModule.class,
SystemPropertiesFlagsModule.class,
FooterActionsModule.class,
- GarbageMonitorModule.class,
KeyboardModule.class,
LetterboxModule.class,
KeyguardBlueprintModule.class,
diff --git a/packages/SystemUI/src/com/android/systemui/display/data/repository/DisplayRepository.kt b/packages/SystemUI/src/com/android/systemui/display/data/repository/DisplayRepository.kt
index f68078a8a340..82b032450938 100644
--- a/packages/SystemUI/src/com/android/systemui/display/data/repository/DisplayRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/display/data/repository/DisplayRepository.kt
@@ -29,6 +29,7 @@ import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCall
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.dagger.qualifiers.Background
+import com.android.systemui.util.Compile
import com.android.systemui.util.traceSection
import javax.inject.Inject
import kotlinx.coroutines.CoroutineDispatcher
@@ -239,7 +240,7 @@ constructor(
private companion object {
const val TAG = "DisplayRepository"
- val DEBUG = Log.isLoggable(TAG, Log.DEBUG)
+ val DEBUG = Log.isLoggable(TAG, Log.DEBUG) || Compile.IS_DEBUG
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
index d8b31a229261..2301e8602d18 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
+++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
@@ -115,7 +115,7 @@ object Flags {
val BUILDER_EXTRAS_OVERRIDE =
sysPropBooleanFlag(
"persist.sysui.notification.builder_extras_override",
- default = true
+ default = false
)
/** Only notify group expansion listeners when a change happens. */
@@ -636,8 +636,29 @@ object Flags {
val CLIPBOARD_SHARED_TRANSITIONS =
unreleasedFlag("clipboard_shared_transitions", teamfood = true)
+ /**
+ * Whether the scene container (Flexiglass) is enabled. Note that [SCENE_CONTAINER] should be
+ * checked and toggled together with [SCENE_CONTAINER_ENABLED] so that ProGuard can remove
+ * unused code from our APK at compile time.
+ */
// TODO(b/283300105): Tracking Bug
- @JvmField val SCENE_CONTAINER = unreleasedFlag("scene_container")
+ @JvmField val SCENE_CONTAINER_ENABLED = false
+ @Deprecated(
+ message = """
+ Do not use this flag directly. Please use
+ [com.android.systemui.scene.shared.flag.SceneContainerFlags#isEnabled].
+
+ (Not really deprecated but using this as a simple way to bring attention to the above).
+ """,
+ replaceWith = ReplaceWith(
+ "com.android.systemui.scene.shared.flag.SceneContainerFlags#isEnabled",
+ ),
+ level = DeprecationLevel.WARNING,
+ )
+ @JvmField val SCENE_CONTAINER = resourceBooleanFlag(
+ R.bool.config_sceneContainerFrameworkEnabled,
+ "scene_container",
+ )
// 1900
@JvmField val NOTE_TASKS = releasedFlag("keycode_flag")
@@ -674,6 +695,10 @@ object Flags {
// TODO:(b/283203305): Tracking bug
@JvmField val TRIM_FONT_CACHES_AT_UNLOCK = unreleasedFlag("trim_font_caches_on_unlock")
+ // TODO(b/298380520): Tracking Bug
+ @JvmField
+ val USER_TRACKER_BACKGROUND_CALLBACKS = unreleasedFlag("user_tracker_background_callbacks")
+
// 2700 - unfold transitions
// TODO(b/265764985): Tracking Bug
@Keep
@@ -698,7 +723,7 @@ object Flags {
@JvmField val KEYBOARD_BACKLIGHT_INDICATOR = releasedFlag("keyboard_backlight_indicator")
// TODO(b/277192623): Tracking Bug
- @JvmField val KEYBOARD_EDUCATION = unreleasedFlag("keyboard_education", teamfood = false)
+ @JvmField val KEYBOARD_EDUCATION = unreleasedFlag("keyboard_education", teamfood = true)
// TODO(b/277201412): Tracking Bug
@JvmField
@@ -764,11 +789,11 @@ object Flags {
/** Enable the Compose implementation of the PeopleSpaceActivity. */
@JvmField
- val COMPOSE_PEOPLE_SPACE = unreleasedFlag("compose_people_space")
+ val COMPOSE_PEOPLE_SPACE = unreleasedFlag("compose_people_space", teamfood = true)
/** Enable the Compose implementation of the Quick Settings footer actions. */
@JvmField
- val COMPOSE_QS_FOOTER_ACTIONS = unreleasedFlag("compose_qs_footer_actions")
+ val COMPOSE_QS_FOOTER_ACTIONS = unreleasedFlag("compose_qs_footer_actions", teamfood = true)
/** Enable the share wifi button in Quick Settings internet dialog. */
@JvmField
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt
index e374549b9101..572785721b4f 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt
@@ -45,6 +45,7 @@ import com.android.systemui.keyguard.shared.model.ScreenModel
import com.android.systemui.keyguard.shared.model.StatusBarState
import com.android.systemui.keyguard.shared.model.WakefulnessModel
import com.android.systemui.scene.domain.interactor.SceneInteractor
+import com.android.systemui.scene.shared.flag.SceneContainerFlags
import com.android.systemui.scene.shared.model.SceneKey
import com.android.systemui.shade.data.repository.ShadeRepository
import com.android.systemui.statusbar.CommandQueue
@@ -77,6 +78,7 @@ constructor(
private val repository: KeyguardRepository,
private val commandQueue: CommandQueue,
featureFlags: FeatureFlags,
+ sceneContainerFlags: SceneContainerFlags,
bouncerRepository: KeyguardBouncerRepository,
configurationRepository: ConfigurationRepository,
shadeRepository: ShadeRepository,
@@ -249,7 +251,7 @@ constructor(
/** Whether to animate the next doze mode transition. */
val animateDozingTransitions: Flow<Boolean> by lazy {
- if (featureFlags.isEnabled(Flags.SCENE_CONTAINER)) {
+ if (sceneContainerFlags.isEnabled()) {
sceneInteractorProvider
.get()
.transitioningTo
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/KeyguardBlueprint.kt b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/KeyguardBlueprint.kt
index 659c5f3007e8..35a9aaecc8cd 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/KeyguardBlueprint.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/KeyguardBlueprint.kt
@@ -22,17 +22,34 @@ import androidx.constraintlayout.widget.ConstraintSet
/** Determines the constraints for the ConstraintSet in the lockscreen root view. */
interface KeyguardBlueprint {
val id: String
- val sections: Array<KeyguardSection>
+ val sections: Set<KeyguardSection>
- fun addViews(constraintLayout: ConstraintLayout) {
- sections.forEach { it.addViews(constraintLayout) }
+ /**
+ * Add views to new blueprint.
+ *
+ * Finds sections that did not exist in the previous blueprint and add the corresponding views.
+ *
+ * @param previousBluePrint: KeyguardBlueprint the blueprint we are transitioning from.
+ */
+ fun addViews(previousBlueprint: KeyguardBlueprint?, constraintLayout: ConstraintLayout) {
+ sections.subtract((previousBlueprint?.sections ?: setOf()).toSet()).forEach {
+ it.addViews(constraintLayout)
+ it.bindData(constraintLayout)
+ }
}
- fun applyConstraints(constraintSet: ConstraintSet) {
- sections.forEach { it.applyConstraints(constraintSet) }
+ /**
+ * Remove views of old blueprint.
+ *
+ * Finds sections that are no longer in the next blueprint and remove the corresponding views.
+ *
+ * @param nextBluePrint: KeyguardBlueprint the blueprint we will transition to.
+ */
+ fun removeViews(nextBlueprint: KeyguardBlueprint, constraintLayout: ConstraintLayout) {
+ sections.subtract(nextBlueprint.sections).forEach { it.removeViews(constraintLayout) }
}
- fun onDestroy() {
- sections.forEach { it.onDestroy() }
+ fun applyConstraints(constraintSet: ConstraintSet) {
+ sections.forEach { it.applyConstraints(constraintSet) }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/KeyguardSection.kt b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/KeyguardSection.kt
index 19f50dec3032..48a214615733 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/KeyguardSection.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/KeyguardSection.kt
@@ -23,8 +23,34 @@ import androidx.constraintlayout.widget.ConstraintSet
* Lower level modules that determine constraints for a particular section in the lockscreen root
* view.
*/
-interface KeyguardSection {
- fun addViews(constraintLayout: ConstraintLayout)
- fun applyConstraints(constraintSet: ConstraintSet)
- fun onDestroy() {}
+abstract class KeyguardSection {
+ /** Adds the views to the root view. */
+ abstract fun addViews(constraintLayout: ConstraintLayout)
+ /** Binds the views to data. */
+ abstract fun bindData(constraintLayout: ConstraintLayout)
+ /** Applies layout constraints to the view in respect to the root view. */
+ abstract fun applyConstraints(constraintSet: ConstraintSet)
+ /** Removes views and does any data binding destruction. */
+ abstract fun removeViews(constraintLayout: ConstraintLayout)
+
+ /**
+ * Defines equality as same class.
+ *
+ * This is to enable set operations to be done as an optimization to blueprint transitions.
+ */
+ override fun equals(other: Any?): Boolean {
+ other?.let { other ->
+ return this::class == other::class
+ }
+ return false
+ }
+
+ /**
+ * Defines hashcode as class.
+ *
+ * This is to enable set operations to be done as an optimization to blueprint transitions.
+ */
+ override fun hashCode(): Int {
+ return this::class.hashCode()
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBlueprintViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBlueprintViewBinder.kt
index c340e5df498b..78b72a9e5e6a 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBlueprintViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBlueprintViewBinder.kt
@@ -21,7 +21,6 @@ import android.os.Trace
import android.util.Log
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.constraintlayout.widget.ConstraintSet
-import androidx.core.view.children
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.repeatOnLifecycle
import com.android.systemui.keyguard.ui.viewmodel.KeyguardBlueprintViewModel
@@ -37,26 +36,20 @@ class KeyguardBlueprintViewBinder {
repeatOnLifecycle(Lifecycle.State.CREATED) {
launch {
viewModel.blueprint.collect { blueprint ->
+ val prevBluePrint = viewModel.currentBluePrint
Trace.beginSection("KeyguardBlueprint#applyBlueprint")
Log.d(TAG, "applying blueprint: $blueprint")
- if (blueprint != viewModel.currentBluePrint) {
- viewModel.currentBluePrint?.onDestroy()
+ // Add and remove views of sections that are not contained by the other.
+ prevBluePrint?.removeViews(blueprint, constraintLayout)
+ blueprint.addViews(prevBluePrint, constraintLayout)
+
+ ConstraintSet().apply {
+ clone(constraintLayout)
+ val emptyLayout = ConstraintSet.Layout()
+ knownIds.forEach { getConstraint(it).layout.copyFrom(emptyLayout) }
+ blueprint.applyConstraints(this)
+ applyTo(constraintLayout)
}
- val constraintSet =
- ConstraintSet().apply {
- clone(constraintLayout)
- val emptyLayout = ConstraintSet.Layout()
- knownIds.forEach {
- getConstraint(it).layout.copyFrom(emptyLayout)
- }
- blueprint.addViews(constraintLayout)
- blueprint.applyConstraints(this)
- applyTo(constraintLayout)
- }
- // Remove all unconstrained views.
- constraintLayout.children
- .filterNot { constraintSet.knownIds.contains(it.id) }
- .forEach { constraintLayout.removeView(it) }
viewModel.currentBluePrint = blueprint
Trace.endSection()
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/blueprints/DefaultKeyguardBlueprint.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/blueprints/DefaultKeyguardBlueprint.kt
index 5a15fc236a0a..85b2b82cd44a 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/blueprints/DefaultKeyguardBlueprint.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/blueprints/DefaultKeyguardBlueprint.kt
@@ -55,7 +55,7 @@ constructor(
override val id: String = DEFAULT
override val sections =
- arrayOf(
+ setOf(
defaultIndicationAreaSection,
defaultLockIconSection,
defaultShortcutsSection,
@@ -66,9 +66,12 @@ constructor(
splitShadeGuidelines,
)
- override fun addViews(constraintLayout: ConstraintLayout) {
+ override fun addViews(
+ previousBlueprint: KeyguardBlueprint?,
+ constraintLayout: ConstraintLayout
+ ) {
if (featureFlags.isEnabled(Flags.LAZY_INFLATE_KEYGUARD)) {
- super.addViews(constraintLayout)
+ super.addViews(previousBlueprint, constraintLayout)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/blueprints/ShortcutsBesideUdfpsKeyguardBlueprint.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/blueprints/ShortcutsBesideUdfpsKeyguardBlueprint.kt
index 5ef625e62d00..bb3af6cc86a2 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/blueprints/ShortcutsBesideUdfpsKeyguardBlueprint.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/blueprints/ShortcutsBesideUdfpsKeyguardBlueprint.kt
@@ -46,7 +46,7 @@ constructor(
override val id: String = SHORTCUTS_BESIDE_UDFPS
override val sections =
- arrayOf(
+ setOf(
defaultIndicationAreaSection,
defaultLockIconSection,
defaultAmbientIndicationAreaSection,
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/AlignShortcutsToUdfpsSection.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/AlignShortcutsToUdfpsSection.kt
index 587c6b7cb4ae..79b715799d31 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/AlignShortcutsToUdfpsSection.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/AlignShortcutsToUdfpsSection.kt
@@ -18,6 +18,8 @@
package com.android.systemui.keyguard.ui.view.layout.sections
import android.content.res.Resources
+import android.view.View
+import android.widget.ImageView
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.constraintlayout.widget.ConstraintSet
import androidx.constraintlayout.widget.ConstraintSet.BOTTOM
@@ -25,7 +27,9 @@ import androidx.constraintlayout.widget.ConstraintSet.LEFT
import androidx.constraintlayout.widget.ConstraintSet.PARENT_ID
import androidx.constraintlayout.widget.ConstraintSet.RIGHT
import androidx.constraintlayout.widget.ConstraintSet.TOP
+import androidx.core.content.res.ResourcesCompat
import com.android.systemui.R
+import com.android.systemui.animation.view.LaunchableImageView
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.flags.FeatureFlags
import com.android.systemui.flags.Flags
@@ -49,12 +53,19 @@ constructor(
private val falsingManager: FalsingManager,
private val indicationController: KeyguardIndicationController,
private val vibratorHelper: VibratorHelper,
-) : BaseShortcutsSection(), KeyguardSection {
+) : KeyguardSection() {
+ private var leftShortcutHandle: KeyguardQuickAffordanceViewBinder.Binding? = null
+ private var rightShortcutHandle: KeyguardQuickAffordanceViewBinder.Binding? = null
override fun addViews(constraintLayout: ConstraintLayout) {
if (featureFlags.isEnabled(Flags.MIGRATE_SPLIT_KEYGUARD_BOTTOM_AREA)) {
addLeftShortcut(constraintLayout)
addRightShortcut(constraintLayout)
+ }
+ }
+
+ override fun bindData(constraintLayout: ConstraintLayout) {
+ if (featureFlags.isEnabled(Flags.MIGRATE_SPLIT_KEYGUARD_BOTTOM_AREA)) {
leftShortcutHandle =
KeyguardQuickAffordanceViewBinder.bind(
constraintLayout.requireViewById(R.id.start_button),
@@ -98,4 +109,67 @@ constructor(
connect(R.id.end_button, BOTTOM, R.id.lock_icon_view, BOTTOM)
}
}
+
+ override fun removeViews(constraintLayout: ConstraintLayout) {
+ leftShortcutHandle?.destroy()
+ rightShortcutHandle?.destroy()
+ constraintLayout.removeView(R.id.start_button)
+ constraintLayout.removeView(R.id.end_button)
+ }
+
+ private fun addLeftShortcut(constraintLayout: ConstraintLayout) {
+ val padding =
+ constraintLayout.resources.getDimensionPixelSize(
+ R.dimen.keyguard_affordance_fixed_padding
+ )
+ val view =
+ LaunchableImageView(constraintLayout.context, null).apply {
+ id = R.id.start_button
+ scaleType = ImageView.ScaleType.FIT_CENTER
+ background =
+ ResourcesCompat.getDrawable(
+ context.resources,
+ R.drawable.keyguard_bottom_affordance_bg,
+ context.theme
+ )
+ foreground =
+ ResourcesCompat.getDrawable(
+ context.resources,
+ R.drawable.keyguard_bottom_affordance_selected_border,
+ context.theme
+ )
+ visibility = View.INVISIBLE
+ setPadding(padding, padding, padding, padding)
+ }
+ constraintLayout.addView(view)
+ }
+
+ private fun addRightShortcut(constraintLayout: ConstraintLayout) {
+ if (constraintLayout.findViewById<View>(R.id.end_button) != null) return
+
+ val padding =
+ constraintLayout.resources.getDimensionPixelSize(
+ R.dimen.keyguard_affordance_fixed_padding
+ )
+ val view =
+ LaunchableImageView(constraintLayout.context, null).apply {
+ id = R.id.end_button
+ scaleType = ImageView.ScaleType.FIT_CENTER
+ background =
+ ResourcesCompat.getDrawable(
+ context.resources,
+ R.drawable.keyguard_bottom_affordance_bg,
+ context.theme
+ )
+ foreground =
+ ResourcesCompat.getDrawable(
+ context.resources,
+ R.drawable.keyguard_bottom_affordance_selected_border,
+ context.theme
+ )
+ visibility = View.INVISIBLE
+ setPadding(padding, padding, padding, padding)
+ }
+ constraintLayout.addView(view)
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/BaseShortcutsSection.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/BaseShortcutsSection.kt
deleted file mode 100644
index db0cf5ad3000..000000000000
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/BaseShortcutsSection.kt
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Copyright (C) 2023 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.systemui.keyguard.ui.view.layout.sections
-
-import android.view.View
-import android.widget.ImageView
-import androidx.constraintlayout.widget.ConstraintLayout
-import androidx.constraintlayout.widget.ConstraintSet
-import androidx.core.content.res.ResourcesCompat
-import com.android.systemui.R
-import com.android.systemui.animation.view.LaunchableImageView
-import com.android.systemui.keyguard.shared.model.KeyguardSection
-import com.android.systemui.keyguard.ui.binder.KeyguardQuickAffordanceViewBinder
-
-/** Base class for sections that add lockscreen shortcuts. */
-abstract class BaseShortcutsSection : KeyguardSection {
- protected open var leftShortcutHandle: KeyguardQuickAffordanceViewBinder.Binding? = null
- protected open var rightShortcutHandle: KeyguardQuickAffordanceViewBinder.Binding? = null
-
- override fun addViews(constraintLayout: ConstraintLayout) {}
-
- override fun applyConstraints(constraintSet: ConstraintSet) {}
-
- override fun onDestroy() {
- leftShortcutHandle?.destroy()
- rightShortcutHandle?.destroy()
- }
-
- protected open fun addLeftShortcut(constraintLayout: ConstraintLayout) {
- if (constraintLayout.findViewById<View>(R.id.start_button) != null) return
-
- val padding =
- constraintLayout.resources.getDimensionPixelSize(
- R.dimen.keyguard_affordance_fixed_padding
- )
- val view =
- LaunchableImageView(constraintLayout.context, null).apply {
- id = R.id.start_button
- scaleType = ImageView.ScaleType.FIT_CENTER
- background =
- ResourcesCompat.getDrawable(
- context.resources,
- R.drawable.keyguard_bottom_affordance_bg,
- context.theme
- )
- foreground =
- ResourcesCompat.getDrawable(
- context.resources,
- R.drawable.keyguard_bottom_affordance_selected_border,
- context.theme
- )
- visibility = View.INVISIBLE
- setPadding(padding, padding, padding, padding)
- }
- constraintLayout.addView(view)
- }
-
- protected open fun addRightShortcut(constraintLayout: ConstraintLayout) {
- if (constraintLayout.findViewById<View>(R.id.end_button) != null) return
-
- val padding =
- constraintLayout.resources.getDimensionPixelSize(
- R.dimen.keyguard_affordance_fixed_padding
- )
- val view =
- LaunchableImageView(constraintLayout.context, null).apply {
- id = R.id.end_button
- scaleType = ImageView.ScaleType.FIT_CENTER
- background =
- ResourcesCompat.getDrawable(
- context.resources,
- R.drawable.keyguard_bottom_affordance_bg,
- context.theme
- )
- foreground =
- ResourcesCompat.getDrawable(
- context.resources,
- R.drawable.keyguard_bottom_affordance_selected_border,
- context.theme
- )
- visibility = View.INVISIBLE
- setPadding(padding, padding, padding, padding)
- }
- constraintLayout.addView(view)
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultAmbientIndicationAreaSection.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultAmbientIndicationAreaSection.kt
index f8455c53a51f..ce86e9784180 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultAmbientIndicationAreaSection.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultAmbientIndicationAreaSection.kt
@@ -18,7 +18,6 @@
package com.android.systemui.keyguard.ui.view.layout.sections
import android.view.LayoutInflater
-import android.view.View
import android.view.ViewGroup.LayoutParams.MATCH_PARENT
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.constraintlayout.widget.ConstraintSet
@@ -46,19 +45,21 @@ constructor(
private val featureFlags: FeatureFlags,
private val keyguardAmbientIndicationViewModel: KeyguardAmbientIndicationViewModel,
private val keyguardRootViewModel: KeyguardRootViewModel,
-) : KeyguardSection {
+) : KeyguardSection() {
private var ambientIndicationAreaHandle: KeyguardAmbientIndicationAreaViewBinder.Binding? = null
override fun addViews(constraintLayout: ConstraintLayout) {
if (featureFlags.isEnabled(Flags.MIGRATE_SPLIT_KEYGUARD_BOTTOM_AREA)) {
- if (constraintLayout.findViewById<View>(R.id.ambient_indication_container) == null) {
- val view =
- LayoutInflater.from(constraintLayout.context)
- .inflate(R.layout.ambient_indication, constraintLayout, false)
+ val view =
+ LayoutInflater.from(constraintLayout.context)
+ .inflate(R.layout.ambient_indication, constraintLayout, false)
- constraintLayout.addView(view)
- }
+ constraintLayout.addView(view)
+ }
+ }
+ override fun bindData(constraintLayout: ConstraintLayout) {
+ if (featureFlags.isEnabled(Flags.MIGRATE_SPLIT_KEYGUARD_BOTTOM_AREA)) {
ambientIndicationAreaHandle =
KeyguardAmbientIndicationAreaViewBinder.bind(
constraintLayout,
@@ -94,7 +95,9 @@ constructor(
}
}
- override fun onDestroy() {
+ override fun removeViews(constraintLayout: ConstraintLayout) {
ambientIndicationAreaHandle?.destroy()
+
+ constraintLayout.removeView(R.id.ambient_indication_container)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultIndicationAreaSection.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultIndicationAreaSection.kt
index f04bfc675f1f..a45223cbd449 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultIndicationAreaSection.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultIndicationAreaSection.kt
@@ -18,7 +18,6 @@
package com.android.systemui.keyguard.ui.view.layout.sections
import android.content.Context
-import android.view.View
import android.view.ViewGroup
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.constraintlayout.widget.ConstraintSet
@@ -42,17 +41,19 @@ constructor(
private val keyguardRootViewModel: KeyguardRootViewModel,
private val indicationController: KeyguardIndicationController,
private val featureFlags: FeatureFlags,
-) : KeyguardSection {
+) : KeyguardSection() {
private val indicationAreaViewId = R.id.keyguard_indication_area
private var indicationAreaHandle: DisposableHandle? = null
override fun addViews(constraintLayout: ConstraintLayout) {
if (featureFlags.isEnabled(Flags.MIGRATE_SPLIT_KEYGUARD_BOTTOM_AREA)) {
- if (constraintLayout.findViewById<View>(indicationAreaViewId) == null) {
- val view = KeyguardIndicationArea(context, null)
- constraintLayout.addView(view)
- }
+ val view = KeyguardIndicationArea(context, null)
+ constraintLayout.addView(view)
+ }
+ }
+ override fun bindData(constraintLayout: ConstraintLayout) {
+ if (featureFlags.isEnabled(Flags.MIGRATE_SPLIT_KEYGUARD_BOTTOM_AREA)) {
indicationAreaHandle =
KeyguardIndicationAreaBinder.bind(
constraintLayout,
@@ -90,7 +91,8 @@ constructor(
}
}
- override fun onDestroy() {
+ override fun removeViews(constraintLayout: ConstraintLayout) {
indicationAreaHandle?.dispose()
+ constraintLayout.removeView(indicationAreaViewId)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultLockIconSection.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultLockIconSection.kt
index 3d62f3f1f985..3e91d9336b13 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultLockIconSection.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultLockIconSection.kt
@@ -47,19 +47,23 @@ constructor(
private val notificationPanelView: NotificationPanelView,
private val featureFlags: FeatureFlags,
private val lockIconViewController: LockIconViewController,
-) : KeyguardSection {
+) : KeyguardSection() {
private val lockIconViewId = R.id.lock_icon_view
override fun addViews(constraintLayout: ConstraintLayout) {
- if (featureFlags.isEnabled(Flags.MIGRATE_LOCK_ICON)) {
- notificationPanelView.findViewById<View>(R.id.lock_icon_view).let {
- notificationPanelView.removeView(it)
- }
- if (constraintLayout.findViewById<View>(R.id.lock_icon_view) == null) {
- val view = LockIconView(context, null).apply { id = R.id.lock_icon_view }
- constraintLayout.addView(view)
- lockIconViewController.setLockIconView(view)
- }
+ if (!featureFlags.isEnabled(Flags.MIGRATE_LOCK_ICON)) {
+ return
+ }
+ notificationPanelView.findViewById<View>(R.id.lock_icon_view).let {
+ notificationPanelView.removeView(it)
+ }
+ val view = LockIconView(context, null).apply { id = R.id.lock_icon_view }
+ constraintLayout.addView(view)
+ }
+
+ override fun bindData(constraintLayout: ConstraintLayout) {
+ constraintLayout.findViewById<LockIconView?>(R.id.lock_icon_view)?.let {
+ lockIconViewController.setLockIconView(it)
}
}
@@ -92,6 +96,10 @@ constructor(
}
}
+ override fun removeViews(constraintLayout: ConstraintLayout) {
+ constraintLayout.removeView(R.id.lock_icon_view)
+ }
+
@VisibleForTesting
internal fun centerLockIcon(center: Point, radius: Float, constraintSet: ConstraintSet) {
val sensorRect =
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultNotificationStackScrollLayoutSection.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultNotificationStackScrollLayoutSection.kt
index a203e41db86e..59c5d78bfce8 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultNotificationStackScrollLayoutSection.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultNotificationStackScrollLayoutSection.kt
@@ -40,22 +40,30 @@ constructor(
private val sharedNotificationContainer: SharedNotificationContainer,
private val sharedNotificationContainerViewModel: SharedNotificationContainerViewModel,
private val controller: NotificationStackScrollLayoutController,
-) : KeyguardSection {
+) : KeyguardSection() {
override fun addViews(constraintLayout: ConstraintLayout) {
+ if (!featureFlags.isEnabled(Flags.MIGRATE_NSSL)) {
+ return
+ }
+ // This moves the existing NSSL view to a different parent, as the controller is a
+ // singleton and recreating it has other bad side effects
+ notificationPanelView.findViewById<View?>(R.id.notification_stack_scroller)?.let {
+ (it.parent as ViewGroup).removeView(it)
+ sharedNotificationContainer.addNotificationStackScrollLayout(it)
+ }
+ }
+
+ override fun bindData(constraintLayout: ConstraintLayout) {
if (featureFlags.isEnabled(Flags.MIGRATE_NSSL)) {
- // This moves the existing NSSL view to a different parent, as the controller is a
- // singleton and recreating it has other bad side effects
- notificationPanelView.findViewById<View?>(R.id.notification_stack_scroller)?.let {
- (it.parent as ViewGroup).removeView(it)
- sharedNotificationContainer.addNotificationStackScrollLayout(it)
- SharedNotificationContainerBinder.bind(
- sharedNotificationContainer,
- sharedNotificationContainerViewModel,
- controller,
- )
- }
+ SharedNotificationContainerBinder.bind(
+ sharedNotificationContainer,
+ sharedNotificationContainerViewModel,
+ controller,
+ )
}
}
override fun applyConstraints(constraintSet: ConstraintSet) {}
+
+ override fun removeViews(constraintLayout: ConstraintLayout) {}
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultSettingsPopupMenuSection.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultSettingsPopupMenuSection.kt
index 660cc96f21e6..b25f9afc0d1e 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultSettingsPopupMenuSection.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultSettingsPopupMenuSection.kt
@@ -49,23 +49,26 @@ constructor(
private val keyguardSettingsMenuViewModel: KeyguardSettingsMenuViewModel,
private val vibratorHelper: VibratorHelper,
private val activityStarter: ActivityStarter,
-) : KeyguardSection {
+) : KeyguardSection() {
private var settingsPopupMenuHandle: DisposableHandle? = null
override fun addViews(constraintLayout: ConstraintLayout) {
- if (featureFlags.isEnabled(Flags.MIGRATE_SPLIT_KEYGUARD_BOTTOM_AREA)) {
- if (constraintLayout.findViewById<View?>(R.id.keyguard_settings_button) == null) {
- val view =
- LayoutInflater.from(constraintLayout.context)
- .inflate(R.layout.keyguard_settings_popup_menu, constraintLayout, false)
- .apply {
- id = R.id.keyguard_settings_button
- isVisible = false
- alpha = 0f
- } as LaunchableLinearLayout
- constraintLayout.addView(view)
- }
+ if (!featureFlags.isEnabled(Flags.MIGRATE_SPLIT_KEYGUARD_BOTTOM_AREA)) {
+ return
+ }
+ val view =
+ LayoutInflater.from(constraintLayout.context)
+ .inflate(R.layout.keyguard_settings_popup_menu, constraintLayout, false)
+ .apply {
+ id = R.id.keyguard_settings_button
+ isVisible = false
+ alpha = 0f
+ } as LaunchableLinearLayout
+ constraintLayout.addView(view)
+ }
+ override fun bindData(constraintLayout: ConstraintLayout) {
+ if (featureFlags.isEnabled(Flags.MIGRATE_SPLIT_KEYGUARD_BOTTOM_AREA)) {
settingsPopupMenuHandle =
KeyguardSettingsViewBinder.bind(
constraintLayout.requireViewById<View>(R.id.keyguard_settings_button),
@@ -100,7 +103,8 @@ constructor(
}
}
- override fun onDestroy() {
+ override fun removeViews(constraintLayout: ConstraintLayout) {
settingsPopupMenuHandle?.dispose()
+ constraintLayout.removeView(R.id.keyguard_settings_button)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultShortcutsSection.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultShortcutsSection.kt
index 965910a1be66..c4980557c454 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultShortcutsSection.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultShortcutsSection.kt
@@ -18,13 +18,17 @@
package com.android.systemui.keyguard.ui.view.layout.sections
import android.content.res.Resources
+import android.view.View
+import android.widget.ImageView
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.constraintlayout.widget.ConstraintSet
import androidx.constraintlayout.widget.ConstraintSet.BOTTOM
import androidx.constraintlayout.widget.ConstraintSet.LEFT
import androidx.constraintlayout.widget.ConstraintSet.PARENT_ID
import androidx.constraintlayout.widget.ConstraintSet.RIGHT
+import androidx.core.content.res.ResourcesCompat
import com.android.systemui.R
+import com.android.systemui.animation.view.LaunchableImageView
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.flags.FeatureFlags
import com.android.systemui.flags.Flags
@@ -48,12 +52,19 @@ constructor(
private val falsingManager: FalsingManager,
private val indicationController: KeyguardIndicationController,
private val vibratorHelper: VibratorHelper,
-) : BaseShortcutsSection(), KeyguardSection {
+) : KeyguardSection() {
+ private var leftShortcutHandle: KeyguardQuickAffordanceViewBinder.Binding? = null
+ private var rightShortcutHandle: KeyguardQuickAffordanceViewBinder.Binding? = null
override fun addViews(constraintLayout: ConstraintLayout) {
if (featureFlags.isEnabled(Flags.MIGRATE_SPLIT_KEYGUARD_BOTTOM_AREA)) {
addLeftShortcut(constraintLayout)
addRightShortcut(constraintLayout)
+ }
+ }
+
+ override fun bindData(constraintLayout: ConstraintLayout) {
+ if (featureFlags.isEnabled(Flags.MIGRATE_SPLIT_KEYGUARD_BOTTOM_AREA)) {
leftShortcutHandle =
KeyguardQuickAffordanceViewBinder.bind(
constraintLayout.requireViewById(R.id.start_button),
@@ -98,6 +109,69 @@ constructor(
}
}
+ override fun removeViews(constraintLayout: ConstraintLayout) {
+ leftShortcutHandle?.destroy()
+ rightShortcutHandle?.destroy()
+ constraintLayout.removeView(R.id.start_button)
+ constraintLayout.removeView(R.id.end_button)
+ }
+
+ private fun addLeftShortcut(constraintLayout: ConstraintLayout) {
+ val padding =
+ constraintLayout.resources.getDimensionPixelSize(
+ R.dimen.keyguard_affordance_fixed_padding
+ )
+ val view =
+ LaunchableImageView(constraintLayout.context, null).apply {
+ id = R.id.start_button
+ scaleType = ImageView.ScaleType.FIT_CENTER
+ background =
+ ResourcesCompat.getDrawable(
+ context.resources,
+ R.drawable.keyguard_bottom_affordance_bg,
+ context.theme
+ )
+ foreground =
+ ResourcesCompat.getDrawable(
+ context.resources,
+ R.drawable.keyguard_bottom_affordance_selected_border,
+ context.theme
+ )
+ visibility = View.INVISIBLE
+ setPadding(padding, padding, padding, padding)
+ }
+ constraintLayout.addView(view)
+ }
+
+ private fun addRightShortcut(constraintLayout: ConstraintLayout) {
+ if (constraintLayout.findViewById<View>(R.id.end_button) != null) return
+
+ val padding =
+ constraintLayout.resources.getDimensionPixelSize(
+ R.dimen.keyguard_affordance_fixed_padding
+ )
+ val view =
+ LaunchableImageView(constraintLayout.context, null).apply {
+ id = R.id.end_button
+ scaleType = ImageView.ScaleType.FIT_CENTER
+ background =
+ ResourcesCompat.getDrawable(
+ context.resources,
+ R.drawable.keyguard_bottom_affordance_bg,
+ context.theme
+ )
+ foreground =
+ ResourcesCompat.getDrawable(
+ context.resources,
+ R.drawable.keyguard_bottom_affordance_selected_border,
+ context.theme
+ )
+ visibility = View.INVISIBLE
+ setPadding(padding, padding, padding, padding)
+ }
+ constraintLayout.addView(view)
+ }
+
/** Method to add shortcuts without applying any data binding. */
fun addShortcutViews(constraintLayout: ConstraintLayout) {
addLeftShortcut(constraintLayout)
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultStatusViewSection.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultStatusViewSection.kt
index 321d7a70b087..b144f7ae6906 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultStatusViewSection.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultStatusViewSection.kt
@@ -55,31 +55,34 @@ constructor(
private val keyguardViewConfigurator: Lazy<KeyguardViewConfigurator>,
private val notificationPanelViewController: Lazy<NotificationPanelViewController>,
private val keyguardMediaController: KeyguardMediaController,
-) : KeyguardSection {
+) : KeyguardSection() {
private val statusViewId = R.id.keyguard_status_view
- @OptIn(ExperimentalCoroutinesApi::class)
override fun addViews(constraintLayout: ConstraintLayout) {
+ if (!featureFlags.isEnabled(Flags.MIGRATE_KEYGUARD_STATUS_VIEW)) {
+ return
+ }
// At startup, 2 views with the ID `R.id.keyguard_status_view` will be available.
// Disable one of them
- if (featureFlags.isEnabled(Flags.MIGRATE_KEYGUARD_STATUS_VIEW)) {
- notificationPanelView.findViewById<View>(statusViewId)?.let {
- notificationPanelView.removeView(it)
- }
- if (constraintLayout.findViewById<View>(statusViewId) == null) {
- val keyguardStatusView =
- (LayoutInflater.from(context)
- .inflate(R.layout.keyguard_status_view, constraintLayout, false)
- as KeyguardStatusView)
- .apply { clipChildren = false }
+ notificationPanelView.findViewById<View>(statusViewId)?.let {
+ notificationPanelView.removeView(it)
+ }
+ val keyguardStatusView =
+ (LayoutInflater.from(context)
+ .inflate(R.layout.keyguard_status_view, constraintLayout, false)
+ as KeyguardStatusView)
+ .apply { clipChildren = false }
+ constraintLayout.addView(keyguardStatusView)
+ }
- val statusViewComponent =
- keyguardStatusViewComponentFactory.build(keyguardStatusView)
+ override fun bindData(constraintLayout: ConstraintLayout) {
+ if (featureFlags.isEnabled(Flags.MIGRATE_KEYGUARD_STATUS_VIEW)) {
+ constraintLayout.findViewById<KeyguardStatusView?>(R.id.keyguard_status_view)?.let {
+ val statusViewComponent = keyguardStatusViewComponentFactory.build(it)
val controller = statusViewComponent.keyguardStatusViewController
controller.init()
- constraintLayout.addView(keyguardStatusView)
keyguardMediaController.attachSplitShadeContainer(
- keyguardStatusView.requireViewById<ViewGroup>(R.id.status_view_media_container)
+ it.requireViewById<ViewGroup>(R.id.status_view_media_container)
)
keyguardViewConfigurator.get().keyguardStatusViewController = controller
notificationPanelViewController.get().updateStatusBarViewController()
@@ -107,7 +110,8 @@ constructor(
}
@OptIn(ExperimentalCoroutinesApi::class)
- override fun onDestroy() {
+ override fun removeViews(constraintLayout: ConstraintLayout) {
+ constraintLayout.removeView(statusViewId)
keyguardViewConfigurator.get().keyguardStatusViewController = null
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/Extensions.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/Extensions.kt
new file mode 100644
index 000000000000..94332d21f499
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/Extensions.kt
@@ -0,0 +1,8 @@
+package com.android.systemui.keyguard.ui.view.layout.sections
+
+import android.view.View
+import androidx.constraintlayout.widget.ConstraintLayout
+
+internal fun ConstraintLayout.removeView(viewId: Int) {
+ findViewById<View?>(viewId)?.let { removeView(it) }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/SplitShadeGuidelines.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/SplitShadeGuidelines.kt
index bd629d512614..5e3ea059ddd5 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/SplitShadeGuidelines.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/SplitShadeGuidelines.kt
@@ -17,7 +17,6 @@
package com.android.systemui.keyguard.ui.view.layout.sections
-import android.content.Context
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.constraintlayout.widget.ConstraintSet
import androidx.constraintlayout.widget.ConstraintSet.VERTICAL
@@ -25,9 +24,11 @@ import com.android.systemui.R
import com.android.systemui.keyguard.shared.model.KeyguardSection
import javax.inject.Inject
-class SplitShadeGuidelines @Inject constructor(private val context: Context) : KeyguardSection {
+class SplitShadeGuidelines @Inject constructor() : KeyguardSection() {
override fun addViews(constraintLayout: ConstraintLayout) {}
+ override fun bindData(constraintLayout: ConstraintLayout) {}
+
override fun applyConstraints(constraintSet: ConstraintSet) {
constraintSet.apply {
// For use on large screens, it will provide a guideline vertically in the center to
@@ -36,4 +37,6 @@ class SplitShadeGuidelines @Inject constructor(private val context: Context) : K
setGuidelinePercent(R.id.split_shade_guideline, 0.5f)
}
}
+
+ override fun removeViews(constraintLayout: ConstraintLayout) {}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
index d2eac45754bd..37e750b86c21 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
@@ -235,11 +235,15 @@ public class QSContainerImpl extends FrameLayout implements Dumpable {
quickStatusBarHeaderController.setContentMargins(mContentHorizontalPadding,
mContentHorizontalPadding);
} else {
- view.setPaddingRelative(
- mContentHorizontalPadding,
- view.getPaddingTop(),
- mContentHorizontalPadding,
- view.getPaddingBottom());
+ // Set the horizontal paddings unless the view is the Compose implementation of the
+ // footer actions.
+ if (view.getTag(R.id.tag_compose_qs_footer_actions) == null) {
+ view.setPaddingRelative(
+ mContentHorizontalPadding,
+ view.getPaddingTop(),
+ mContentHorizontalPadding,
+ view.getPaddingBottom());
+ }
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
index d801faa44b40..596d024958b0 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
@@ -303,6 +303,17 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
// to all views except for qs_footer_actions, so we set it to the Compose view.
composeView.setId(R.id.qs_footer_actions);
+ // Set this tag so that QSContainerImpl does not add horizontal paddings to this Compose
+ // implementation of the footer actions. They will be set in Compose instead so that the
+ // background fills the full screen width.
+ composeView.setTag(R.id.tag_compose_qs_footer_actions, true);
+
+ // Set the same elevation as the View implementation, otherwise the footer actions will be
+ // drawn below the scroll view with QS grid and clicks won't get through on small devices
+ // where there isn't enough vertical space to show all the tiles and the footer actions.
+ composeView.setElevation(
+ composeView.getContext().getResources().getDimension(R.dimen.qs_panel_elevation));
+
// Replace the View by the Compose provided one.
ViewGroup parent = (ViewGroup) footerActionsView.getParent();
ViewGroup.LayoutParams layoutParams = footerActionsView.getLayoutParams();
diff --git a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
index 3a64a6a989f2..d23bedace06f 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
@@ -85,7 +85,6 @@ import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.flags.FeatureFlags;
-import com.android.systemui.flags.Flags;
import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
import com.android.systemui.keyguard.WakefulnessLifecycle;
import com.android.systemui.model.SysUiState;
@@ -96,6 +95,7 @@ import com.android.systemui.navigationbar.NavigationModeController;
import com.android.systemui.navigationbar.buttons.KeyButtonView;
import com.android.systemui.recents.OverviewProxyService.OverviewProxyListener;
import com.android.systemui.scene.domain.interactor.SceneInteractor;
+import com.android.systemui.scene.shared.flag.SceneContainerFlags;
import com.android.systemui.settings.DisplayTracker;
import com.android.systemui.settings.UserTracker;
import com.android.systemui.shade.ShadeViewController;
@@ -143,6 +143,7 @@ public class OverviewProxyService implements CallbackController<OverviewProxyLis
private final Context mContext;
private final FeatureFlags mFeatureFlags;
+ private final SceneContainerFlags mSceneContainerFlags;
private final Executor mMainExecutor;
private final ShellInterface mShellInterface;
private final Lazy<Optional<CentralSurfaces>> mCentralSurfacesOptionalLazy;
@@ -218,7 +219,7 @@ public class OverviewProxyService implements CallbackController<OverviewProxyLis
// If scene framework is enabled, set the scene container window to
// visible and let the touch "slip" into that window.
- if (mFeatureFlags.isEnabled(Flags.SCENE_CONTAINER)) {
+ if (mSceneContainerFlags.isEnabled()) {
mSceneInteractor.get().setVisible(true, "swipe down on launcher");
} else {
centralSurfaces.onInputFocusTransfer(
@@ -229,7 +230,7 @@ public class OverviewProxyService implements CallbackController<OverviewProxyLis
if (action == ACTION_UP || action == ACTION_CANCEL) {
mInputFocusTransferStarted = false;
- if (!mFeatureFlags.isEnabled(Flags.SCENE_CONTAINER)) {
+ if (!mSceneContainerFlags.isEnabled()) {
float velocity = (event.getY() - mInputFocusTransferStartY)
/ (event.getEventTime() - mInputFocusTransferStartMillis);
centralSurfaces.onInputFocusTransfer(mInputFocusTransferStarted,
@@ -582,6 +583,7 @@ public class OverviewProxyService implements CallbackController<OverviewProxyLis
KeyguardUnlockAnimationController sysuiUnlockAnimationController,
AssistUtils assistUtils,
FeatureFlags featureFlags,
+ SceneContainerFlags sceneContainerFlags,
DumpManager dumpManager,
Optional<UnfoldTransitionProgressForwarder> unfoldTransitionProgressForwarder
) {
@@ -592,6 +594,7 @@ public class OverviewProxyService implements CallbackController<OverviewProxyLis
mContext = context;
mFeatureFlags = featureFlags;
+ mSceneContainerFlags = sceneContainerFlags;
mMainExecutor = mainExecutor;
mShellInterface = shellInterface;
mCentralSurfacesOptionalLazy = centralSurfacesOptionalLazy;
diff --git a/packages/SystemUI/src/com/android/systemui/scene/KeyguardlessSceneContainerFrameworkModule.kt b/packages/SystemUI/src/com/android/systemui/scene/KeyguardlessSceneContainerFrameworkModule.kt
index c5fbf7b96fff..fcbe9a6675ab 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/KeyguardlessSceneContainerFrameworkModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/KeyguardlessSceneContainerFrameworkModule.kt
@@ -16,6 +16,7 @@
package com.android.systemui.scene
+import com.android.systemui.scene.shared.flag.SceneContainerFlagsModule
import com.android.systemui.scene.shared.model.SceneContainerConfig
import com.android.systemui.scene.shared.model.SceneKey
import dagger.Module
@@ -28,6 +29,7 @@ import dagger.Provides
EmptySceneModule::class,
GoneSceneModule::class,
QuickSettingsSceneModule::class,
+ SceneContainerFlagsModule::class,
ShadeSceneModule::class,
],
)
diff --git a/packages/SystemUI/src/com/android/systemui/scene/SceneContainerFrameworkModule.kt b/packages/SystemUI/src/com/android/systemui/scene/SceneContainerFrameworkModule.kt
index 85ef21aa9542..b36ec3274083 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/SceneContainerFrameworkModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/SceneContainerFrameworkModule.kt
@@ -19,6 +19,7 @@ package com.android.systemui.scene
import com.android.systemui.CoreStartable
import com.android.systemui.scene.domain.interactor.WindowRootViewVisibilityInteractor
import com.android.systemui.scene.domain.startable.SceneContainerStartable
+import com.android.systemui.scene.shared.flag.SceneContainerFlagsModule
import com.android.systemui.scene.shared.model.SceneContainerConfig
import com.android.systemui.scene.shared.model.SceneKey
import dagger.Binds
@@ -36,6 +37,7 @@ import dagger.multibindings.IntoMap
GoneSceneModule::class,
LockscreenSceneModule::class,
QuickSettingsSceneModule::class,
+ SceneContainerFlagsModule::class,
ShadeSceneModule::class,
],
)
diff --git a/packages/SystemUI/src/com/android/systemui/scene/ShadelessSceneContainerFrameworkModule.kt b/packages/SystemUI/src/com/android/systemui/scene/ShadelessSceneContainerFrameworkModule.kt
index 5fda9b1a323b..c10e51b68ba2 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/ShadelessSceneContainerFrameworkModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/ShadelessSceneContainerFrameworkModule.kt
@@ -16,6 +16,7 @@
package com.android.systemui.scene
+import com.android.systemui.scene.shared.flag.SceneContainerFlagsModule
import com.android.systemui.scene.shared.model.SceneContainerConfig
import com.android.systemui.scene.shared.model.SceneKey
import dagger.Module
@@ -29,6 +30,7 @@ import dagger.Provides
EmptySceneModule::class,
GoneSceneModule::class,
LockscreenSceneModule::class,
+ SceneContainerFlagsModule::class,
],
)
object ShadelessSceneContainerFrameworkModule {
diff --git a/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt b/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt
index 7f77acc1789a..722d3661d0ae 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt
@@ -26,13 +26,12 @@ import com.android.systemui.classifier.FalsingCollectorActual
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.dagger.qualifiers.DisplayId
-import com.android.systemui.flags.FeatureFlags
-import com.android.systemui.flags.Flags
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
import com.android.systemui.keyguard.shared.model.WakefulnessState
import com.android.systemui.model.SysUiState
import com.android.systemui.model.updateFlags
import com.android.systemui.scene.domain.interactor.SceneInteractor
+import com.android.systemui.scene.shared.flag.SceneContainerFlags
import com.android.systemui.scene.shared.logger.SceneLogger
import com.android.systemui.scene.shared.model.ObservableTransitionState
import com.android.systemui.scene.shared.model.SceneKey
@@ -66,7 +65,7 @@ constructor(
private val sceneInteractor: SceneInteractor,
private val authenticationInteractor: AuthenticationInteractor,
private val keyguardInteractor: KeyguardInteractor,
- private val featureFlags: FeatureFlags,
+ private val flags: SceneContainerFlags,
private val sysUiState: SysUiState,
@DisplayId private val displayId: Int,
private val sceneLogger: SceneLogger,
@@ -74,14 +73,17 @@ constructor(
) : CoreStartable {
override fun start() {
- if (featureFlags.isEnabled(Flags.SCENE_CONTAINER)) {
+ if (flags.isEnabled()) {
sceneLogger.logFrameworkEnabled(isEnabled = true)
hydrateVisibility()
automaticallySwitchScenes()
hydrateSystemUiState()
collectFalsingSignals()
} else {
- sceneLogger.logFrameworkEnabled(isEnabled = false)
+ sceneLogger.logFrameworkEnabled(
+ isEnabled = false,
+ reason = flags.requirementDescription(),
+ )
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/scene/shared/flag/SceneContainerFlags.kt b/packages/SystemUI/src/com/android/systemui/scene/shared/flag/SceneContainerFlags.kt
new file mode 100644
index 000000000000..83fb723eda82
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/scene/shared/flag/SceneContainerFlags.kt
@@ -0,0 +1,136 @@
+/*
+ * Copyright 2023 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.systemui.scene.shared.flag
+
+import androidx.annotation.VisibleForTesting
+import com.android.systemui.compose.ComposeFacade
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.flags.FeatureFlagsClassic
+import com.android.systemui.flags.Flag
+import com.android.systemui.flags.Flags
+import com.android.systemui.flags.ReleasedFlag
+import com.android.systemui.flags.ResourceBooleanFlag
+import com.android.systemui.flags.UnreleasedFlag
+import dagger.Module
+import dagger.Provides
+import dagger.assisted.Assisted
+import dagger.assisted.AssistedFactory
+import dagger.assisted.AssistedInject
+
+/**
+ * Defines interface for classes that can check whether the scene container framework feature is
+ * enabled.
+ */
+interface SceneContainerFlags {
+
+ /** Returns `true` if the Scene Container Framework is enabled; `false` otherwise. */
+ fun isEnabled(): Boolean
+
+ /** Returns a developer-readable string that describes the current requirement list. */
+ fun requirementDescription(): String
+}
+
+class SceneContainerFlagsImpl
+@AssistedInject
+constructor(
+ private val featureFlags: FeatureFlagsClassic,
+ @Assisted private val isComposeAvailable: Boolean,
+) : SceneContainerFlags {
+
+ companion object {
+ @VisibleForTesting
+ val flags: List<Flag<Boolean>> =
+ listOf(
+ Flags.SCENE_CONTAINER,
+ Flags.MIGRATE_SPLIT_KEYGUARD_BOTTOM_AREA,
+ Flags.MIGRATE_LOCK_ICON,
+ Flags.MIGRATE_NSSL,
+ Flags.MIGRATE_KEYGUARD_STATUS_VIEW,
+ )
+ }
+
+ /** The list of requirements, all must be met for the feature to be enabled. */
+ private val requirements =
+ flags.map { FlagMustBeEnabled(it) } +
+ listOf(ComposeMustBeAvailable(), CompileTimeFlagMustBeEnabled())
+
+ override fun isEnabled(): Boolean {
+ return requirements.all { it.isMet() }
+ }
+
+ override fun requirementDescription(): String {
+ return buildString {
+ requirements.forEach { requirement ->
+ append('\n')
+ append(if (requirement.isMet()) " [MET]" else "[NOT MET]")
+ append(" ${requirement.name}")
+ }
+ }
+ }
+
+ private interface Requirement {
+ val name: String
+
+ fun isMet(): Boolean
+ }
+
+ private inner class ComposeMustBeAvailable : Requirement {
+ override val name = "Jetpack Compose must be available"
+
+ override fun isMet(): Boolean {
+ return isComposeAvailable
+ }
+ }
+
+ private inner class CompileTimeFlagMustBeEnabled : Requirement {
+ override val name = "Flags.SCENE_CONTAINER_ENABLED must be enabled in code"
+
+ override fun isMet(): Boolean {
+ return Flags.SCENE_CONTAINER_ENABLED
+ }
+ }
+
+ private inner class FlagMustBeEnabled<FlagType : Flag<*>>(
+ private val flag: FlagType,
+ ) : Requirement {
+ override val name = "Flag ${flag.name} must be enabled"
+
+ override fun isMet(): Boolean {
+ return when (flag) {
+ is ResourceBooleanFlag -> featureFlags.isEnabled(flag)
+ is ReleasedFlag -> featureFlags.isEnabled(flag)
+ is UnreleasedFlag -> featureFlags.isEnabled(flag)
+ else -> error("Unsupported flag type ${flag.javaClass}")
+ }
+ }
+ }
+
+ @AssistedFactory
+ interface Factory {
+ fun create(isComposeAvailable: Boolean): SceneContainerFlagsImpl
+ }
+}
+
+@Module
+object SceneContainerFlagsModule {
+
+ @Provides
+ @SysUISingleton
+ fun impl(factory: SceneContainerFlagsImpl.Factory): SceneContainerFlags {
+ return factory.create(ComposeFacade.isComposeAvailable())
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/scene/shared/logger/SceneLogger.kt b/packages/SystemUI/src/com/android/systemui/scene/shared/logger/SceneLogger.kt
index 62136dcd8e1d..c2c2e04990c2 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/shared/logger/SceneLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/shared/logger/SceneLogger.kt
@@ -24,16 +24,21 @@ import javax.inject.Inject
class SceneLogger @Inject constructor(@SceneFrameworkLog private val logBuffer: LogBuffer) {
- fun logFrameworkEnabled(isEnabled: Boolean) {
+ fun logFrameworkEnabled(isEnabled: Boolean, reason: String? = null) {
fun asWord(isEnabled: Boolean): String {
return if (isEnabled) "enabled" else "disabled"
}
logBuffer.log(
tag = TAG,
- level = LogLevel.INFO,
- messageInitializer = { bool1 = isEnabled },
- messagePrinter = { "Scene framework is ${asWord(bool1)}" }
+ level = if (isEnabled) LogLevel.INFO else LogLevel.WARNING,
+ messageInitializer = {
+ bool1 = isEnabled
+ str1 = reason
+ },
+ messagePrinter = {
+ "Scene framework is ${asWord(bool1)}${if (str1 != null) " $str1" else ""}"
+ }
)
}
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
index 8db7abf7347f..c1999043743c 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
@@ -163,6 +163,7 @@ import com.android.systemui.plugins.FalsingManager.FalsingTapListener;
import com.android.systemui.plugins.qs.QS;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener;
+import com.android.systemui.shade.data.repository.ShadeRepository;
import com.android.systemui.shade.transition.ShadeTransitionController;
import com.android.systemui.shared.system.InteractionJankMonitorWrapper;
import com.android.systemui.shared.system.QuickStepContract;
@@ -350,6 +351,7 @@ public final class NotificationPanelViewController implements ShadeSurface, Dump
private final Interpolator mBounceInterpolator;
private final NotificationShadeWindowController mNotificationShadeWindowController;
private final ShadeExpansionStateManager mShadeExpansionStateManager;
+ private final ShadeRepository mShadeRepository;
private final FalsingTapListener mFalsingTapListener = this::falsingAdditionalTapRequired;
private final AccessibilityDelegate mAccessibilityDelegate = new ShadeAccessibilityDelegate();
private final NotificationGutsManager mGutsManager;
@@ -710,7 +712,8 @@ public final class NotificationPanelViewController implements ShadeSurface, Dump
VibratorHelper vibratorHelper,
LatencyTracker latencyTracker,
PowerManager powerManager,
- AccessibilityManager accessibilityManager, @DisplayId int displayId,
+ AccessibilityManager accessibilityManager,
+ @DisplayId int displayId,
KeyguardUpdateMonitor keyguardUpdateMonitor,
MetricsLogger metricsLogger,
ShadeLogger shadeLogger,
@@ -746,6 +749,7 @@ public final class NotificationPanelViewController implements ShadeSurface, Dump
ScreenOffAnimationController screenOffAnimationController,
LockscreenGestureLogger lockscreenGestureLogger,
ShadeExpansionStateManager shadeExpansionStateManager,
+ ShadeRepository shadeRepository,
Optional<SysUIUnfoldComponent> unfoldComponent,
SysUiState sysUiState,
Provider<KeyguardBottomAreaViewController> keyguardBottomAreaViewControllerProvider,
@@ -788,6 +792,7 @@ public final class NotificationPanelViewController implements ShadeSurface, Dump
mStatusBarKeyguardViewManager = statusBarKeyguardViewManager;
mLockscreenGestureLogger = lockscreenGestureLogger;
mShadeExpansionStateManager = shadeExpansionStateManager;
+ mShadeRepository = shadeRepository;
mShadeLog = shadeLogger;
mGutsManager = gutsManager;
mDreamingToLockscreenTransitionViewModel = dreamingToLockscreenTransitionViewModel;
@@ -3952,6 +3957,7 @@ public final class NotificationPanelViewController implements ShadeSurface, Dump
}
mExpandedFraction = Math.min(1f,
maxPanelHeight == 0 ? 0 : mExpandedHeight / maxPanelHeight);
+ mShadeRepository.setLegacyShadeExpansion(mExpandedFraction);
mQsController.setShadeExpansion(mExpandedHeight, mExpandedFraction);
mExpansionDragDownAmountPx = h;
mAmbientState.setExpansionFraction(mExpandedFraction);
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeViewProviderModule.kt b/packages/SystemUI/src/com/android/systemui/shade/ShadeViewProviderModule.kt
index 6585fcb1ae53..3f7512a25732 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ShadeViewProviderModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeViewProviderModule.kt
@@ -26,13 +26,13 @@ import com.android.systemui.R
import com.android.systemui.battery.BatteryMeterView
import com.android.systemui.battery.BatteryMeterViewController
import com.android.systemui.biometrics.AuthRippleView
-import com.android.systemui.compose.ComposeFacade
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.flags.FeatureFlags
import com.android.systemui.flags.Flags
import com.android.systemui.keyguard.ui.view.KeyguardRootView
import com.android.systemui.privacy.OngoingPrivacyChip
+import com.android.systemui.scene.shared.flag.SceneContainerFlags
import com.android.systemui.scene.shared.model.Scene
import com.android.systemui.scene.shared.model.SceneContainerConfig
import com.android.systemui.scene.ui.view.SceneWindowRootView
@@ -70,15 +70,13 @@ abstract class ShadeViewProviderModule {
@SysUISingleton
fun providesWindowRootView(
layoutInflater: LayoutInflater,
- featureFlags: FeatureFlags,
+ sceneContainerFlags: SceneContainerFlags,
viewModelProvider: Provider<SceneContainerViewModel>,
containerConfigProvider: Provider<SceneContainerConfig>,
scenesProvider: Provider<Set<@JvmSuppressWildcards Scene>>,
layoutInsetController: NotificationInsetsController,
): WindowRootView {
- return if (
- featureFlags.isEnabled(Flags.SCENE_CONTAINER) && ComposeFacade.isComposeAvailable()
- ) {
+ return if (sceneContainerFlags.isEnabled()) {
val sceneWindowRootView =
layoutInflater.inflate(R.layout.scene_window_root, null) as SceneWindowRootView
sceneWindowRootView.init(
@@ -102,9 +100,9 @@ abstract class ShadeViewProviderModule {
@SysUISingleton
fun providesNotificationShadeWindowView(
root: WindowRootView,
- featureFlags: FeatureFlags,
+ sceneContainerFlags: SceneContainerFlags,
): NotificationShadeWindowView {
- if (featureFlags.isEnabled(Flags.SCENE_CONTAINER)) {
+ if (sceneContainerFlags.isEnabled()) {
return root.requireViewById(R.id.legacy_window_root)
}
return root as NotificationShadeWindowView?
diff --git a/packages/SystemUI/src/com/android/systemui/shade/data/repository/ShadeRepository.kt b/packages/SystemUI/src/com/android/systemui/shade/data/repository/ShadeRepository.kt
index 5a8be1e328f6..509921fd38e1 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/data/repository/ShadeRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/data/repository/ShadeRepository.kt
@@ -34,21 +34,48 @@ interface ShadeRepository {
/** ShadeModel information regarding shade expansion events */
val shadeModel: Flow<ShadeModel>
- /** Amount qs has expanded. Quick Settings can be expanded without the full shade expansion. */
+ /**
+ * Amount qs has expanded, [0-1]. 0 means fully collapsed, 1 means fully expanded. Quick
+ * Settings can be expanded without the full shade expansion.
+ */
val qsExpansion: StateFlow<Float>
- /** The amount the shade has expanded */
- val shadeExpansion: StateFlow<Float>
+ /**
+ * The amount the lockscreen shade has dragged down by the user, [0-1]. 0 means fully collapsed,
+ * 1 means fully expanded.
+ */
+ val lockscreenShadeExpansion: StateFlow<Float>
+
+ /**
+ * NotificationPanelViewController.mExpandedFraction as a StateFlow. This nominally represents
+ * the amount the shade has expanded 0-1 like many other flows in this repo, but there are cases
+ * where its value will be 1 and no shade will be rendered, e.g. whenever the keyguard is
+ * visible and when quick settings is expanded. The confusing nature and impending deletion of
+ * this makes it unsuitable for future development, so usage is discouraged.
+ */
+ @Deprecated("Use ShadeInteractor.shadeExpansion instead")
+ val legacyShadeExpansion: StateFlow<Float>
/** Amount shade has expanded with regard to the UDFPS location */
val udfpsTransitionToFullShadeProgress: StateFlow<Float>
/** The amount QS has expanded without notifications */
fun setQsExpansion(qsExpansion: Float)
+
fun setUdfpsTransitionToFullShadeProgress(progress: Float)
- /** The amount the shade has expanded, [0-1]. 0 means fully collapsed, 1 means fully expanded */
- fun setShadeExpansion(expansion: Float)
+ /**
+ * Set the amount the shade has dragged down by the user, [0-1]. 0 means fully collapsed, 1
+ * means fully expanded.
+ */
+ fun setLockscreenShadeExpansion(lockscreenShadeExpansion: Float)
+
+ /**
+ * Set the legacy expansion value. This should only be called whenever the value of
+ * NotificationPanelViewController.mExpandedFraction changes or in tests.
+ */
+ @Deprecated("Should only be called by NPVC and tests")
+ fun setLegacyShadeExpansion(expandedFraction: Float)
}
/** Business logic for shade interactions */
@@ -84,18 +111,29 @@ constructor(shadeExpansionStateManager: ShadeExpansionStateManager) : ShadeRepos
private val _qsExpansion = MutableStateFlow(0f)
override val qsExpansion: StateFlow<Float> = _qsExpansion.asStateFlow()
- private val _shadeExpansion = MutableStateFlow(0f)
- override val shadeExpansion: StateFlow<Float> = _shadeExpansion.asStateFlow()
+ private val _lockscreenShadeExpansion = MutableStateFlow(0f)
+ override val lockscreenShadeExpansion: StateFlow<Float> =
+ _lockscreenShadeExpansion.asStateFlow()
private var _udfpsTransitionToFullShadeProgress = MutableStateFlow(0f)
override val udfpsTransitionToFullShadeProgress: StateFlow<Float> =
_udfpsTransitionToFullShadeProgress.asStateFlow()
+
+ private val _legacyShadeExpansion = MutableStateFlow(0f)
+ @Deprecated("Use ShadeInteractor.shadeExpansion instead")
+ override val legacyShadeExpansion: StateFlow<Float> = _legacyShadeExpansion.asStateFlow()
+
override fun setQsExpansion(qsExpansion: Float) {
_qsExpansion.value = qsExpansion
}
- override fun setShadeExpansion(expansion: Float) {
- _shadeExpansion.value = expansion
+ @Deprecated("Should only be called by NPVC and tests")
+ override fun setLegacyShadeExpansion(expandedFraction: Float) {
+ _legacyShadeExpansion.value = expandedFraction
+ }
+
+ override fun setLockscreenShadeExpansion(lockscreenShadeExpansion: Float) {
+ _lockscreenShadeExpansion.value = lockscreenShadeExpansion
}
override fun setUdfpsTransitionToFullShadeProgress(progress: Float) {
diff --git a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractor.kt b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractor.kt
index 288d32e58c7c..fd63b89d1199 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractor.kt
@@ -22,6 +22,7 @@ import com.android.systemui.keyguard.data.repository.KeyguardRepository
import com.android.systemui.keyguard.shared.model.StatusBarState
import com.android.systemui.shade.data.repository.ShadeRepository
import com.android.systemui.statusbar.disableflags.data.repository.DisableFlagsRepository
+import com.android.systemui.statusbar.notification.stack.domain.interactor.SharedNotificationContainerInteractor
import com.android.systemui.statusbar.pipeline.mobile.data.repository.UserSetupRepository
import com.android.systemui.statusbar.policy.DeviceProvisionedController
import com.android.systemui.user.domain.interactor.UserInteractor
@@ -31,6 +32,7 @@ import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.stateIn
@@ -45,6 +47,7 @@ constructor(
userSetupRepository: UserSetupRepository,
deviceProvisionedController: DeviceProvisionedController,
userInteractor: UserInteractor,
+ sharedNotificationContainerInteractor: SharedNotificationContainerInteractor,
repository: ShadeRepository,
) {
/** Emits true if the shade is currently allowed and false otherwise. */
@@ -53,16 +56,31 @@ constructor(
.map { it.isShadeEnabled() }
.stateIn(scope, SharingStarted.Eagerly, initialValue = false)
+ /**
+ * Whether split shade, the combined notifications and quick settings shade used for large
+ * screens, is enabled.
+ */
+ val splitShadeEnabled: Flow<Boolean> =
+ sharedNotificationContainerInteractor.configurationBasedDimensions
+ .map { dimens -> dimens.useSplitShade }
+ .distinctUntilChanged()
+
/** The amount [0-1] that the shade has been opened */
val shadeExpansion: Flow<Float> =
- combine(repository.shadeExpansion, keyguardRepository.statusBarState) {
- shadeExpansion,
- statusBarState ->
- // This is required, as shadeExpansion gets reset to 0f even with the shade open
- if (statusBarState == StatusBarState.SHADE_LOCKED) {
- 1f
- } else {
- shadeExpansion
+ combine(
+ repository.lockscreenShadeExpansion,
+ keyguardRepository.statusBarState,
+ repository.legacyShadeExpansion,
+ repository.qsExpansion,
+ splitShadeEnabled
+ ) { dragDownAmount, statusBarState, legacyShadeExpansion, qsExpansion, splitShadeEnabled ->
+ when (statusBarState) {
+ // legacyShadeExpansion is 1 instead of 0 when QS is expanded
+ StatusBarState.SHADE ->
+ if (!splitShadeEnabled && qsExpansion > 0f) 0f else legacyShadeExpansion
+ StatusBarState.KEYGUARD -> dragDownAmount
+ // This is required, as shadeExpansion gets reset to 0f even with the shade open
+ StatusBarState.SHADE_LOCKED -> 1f
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt
index f004982413e8..73bbbca09fe8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt
@@ -447,7 +447,7 @@ class LockscreenShadeTransitionController @Inject constructor(
if (!nsslController.isInLockedDownShade() || field == 0f || forceApplyAmount) {
fractionToShade =
MathUtils.saturate(dragDownAmount / notificationShelfTransitionDistance)
- shadeRepository.setShadeExpansion(fractionToShade)
+ shadeRepository.setLockscreenShadeExpansion(fractionToShade)
nsslController.setTransitionToFullShadeAmount(fractionToShade)
qsTransitionController.dragDownAmount = value
@@ -857,12 +857,12 @@ class DragDownHelper(
MotionEvent.ACTION_MOVE -> {
val h = y - initialTouchY
// Adjust the touch slop if another gesture may be being performed.
- val touchSlop = if (event.classification
- == MotionEvent.CLASSIFICATION_AMBIGUOUS_GESTURE) {
- touchSlop * slopMultiplier
- } else {
- touchSlop
- }
+ val touchSlop =
+ if (event.classification == MotionEvent.CLASSIFICATION_AMBIGUOUS_GESTURE) {
+ touchSlop * slopMultiplier
+ } else {
+ touchSlop
+ }
if (h > touchSlop && h > Math.abs(x - initialTouchX)) {
isDraggingDown = true
captureStartingChild(initialTouchX, initialTouchY)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
index 0277a36c91ad..b797c6339a34 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
@@ -606,8 +606,8 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces {
private final ActivityLaunchAnimator mActivityLaunchAnimator;
private final NotificationLaunchAnimatorControllerProvider mNotificationAnimationProvider;
- private final NotificationPresenter mPresenter;
- private final NotificationActivityStarter mNotificationActivityStarter;
+ private final Lazy<NotificationPresenter> mPresenterLazy;
+ private final Lazy<NotificationActivityStarter> mNotificationActivityStarterLazy;
private final Lazy<NotificationShadeDepthController> mNotificationShadeDepthControllerLazy;
private final Optional<Bubbles> mBubblesOptional;
private final Lazy<NoteTaskController> mNoteTaskControllerLazy;
@@ -681,8 +681,9 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces {
Lazy<NotificationShadeWindowViewController> notificationShadeWindowViewControllerLazy,
NotificationShelfController notificationShelfController,
NotificationStackScrollLayoutController notificationStackScrollLayoutController,
- NotificationPresenter notificationPresenter,
- NotificationActivityStarter notificationActivityStarter,
+ // Lazys due to b/298099682.
+ Lazy<NotificationPresenter> notificationPresenterLazy,
+ Lazy<NotificationActivityStarter> notificationActivityStarterLazy,
NotificationLaunchAnimatorControllerProvider notifLaunchAnimatorControllerProvider,
NotificationExpansionRepository notificationExpansionRepository,
DozeParameters dozeParameters,
@@ -791,8 +792,8 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces {
mStackScrollerController = notificationStackScrollLayoutController;
mStackScroller = mStackScrollerController.getView();
mNotifListContainer = mStackScrollerController.getNotificationListContainer();
- mPresenter = notificationPresenter;
- mNotificationActivityStarter = notificationActivityStarter;
+ mPresenterLazy = notificationPresenterLazy;
+ mNotificationActivityStarterLazy = notificationActivityStarterLazy;
mNotificationAnimationProvider = notifLaunchAnimatorControllerProvider;
mNotificationExpansionRepository = notificationExpansionRepository;
mDozeServiceHost = dozeServiceHost;
@@ -1509,15 +1510,16 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces {
mActivityLaunchAnimator.setCallback(mActivityLaunchAnimatorCallback);
mActivityLaunchAnimator.addListener(mActivityLaunchAnimatorListener);
mRemoteInputManager.addControllerCallback(mNotificationShadeWindowController);
- mStackScrollerController.setNotificationActivityStarter(mNotificationActivityStarter);
- mGutsManager.setNotificationActivityStarter(mNotificationActivityStarter);
- mShadeController.setNotificationPresenter(mPresenter);
+ mStackScrollerController.setNotificationActivityStarter(
+ mNotificationActivityStarterLazy.get());
+ mGutsManager.setNotificationActivityStarter(mNotificationActivityStarterLazy.get());
+ mShadeController.setNotificationPresenter(mPresenterLazy.get());
mNotificationsController.initialize(
- mPresenter,
+ mPresenterLazy.get(),
mNotifListContainer,
mStackScrollerController.getNotifStackController(),
- mNotificationActivityStarter);
- mWindowRootViewVisibilityInteractor.setUp(mPresenter, mNotificationsController);
+ mNotificationActivityStarterLazy.get());
+ mWindowRootViewVisibilityInteractor.setUp(mPresenterLazy.get(), mNotificationsController);
}
/**
@@ -1710,7 +1712,7 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces {
private void onExpandedInvisible() {
setInteracting(StatusBarManager.WINDOW_STATUS_BAR, false);
- if (!mNotificationActivityStarter.isCollapsingToShowActivityOverLockscreen()) {
+ if (!mNotificationActivityStarterLazy.get().isCollapsingToShowActivityOverLockscreen()) {
showBouncerOrLockScreenIfKeyguard();
} else if (DEBUG) {
Log.d(TAG, "Not showing bouncer due to activity showing over lockscreen");
@@ -2036,7 +2038,7 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces {
String action = intent.getAction();
if (ACTION_FAKE_ARTWORK.equals(action)) {
if (DEBUG_MEDIA_FAKE_ARTWORK) {
- mPresenter.updateMediaMetaData(true, true);
+ mPresenterLazy.get().updateMediaMetaData(true, true);
}
}
}
@@ -2218,7 +2220,7 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces {
releaseGestureWakeLock();
runLaunchTransitionEndRunnable();
mKeyguardStateController.setLaunchTransitionFadingAway(false);
- mPresenter.updateMediaMetaData(true /* metaDataChanged */, true);
+ mPresenterLazy.get().updateMediaMetaData(true /* metaDataChanged */, true);
}
/**
@@ -2242,7 +2244,7 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces {
beforeFading.run();
}
updateScrimController();
- mPresenter.updateMediaMetaData(false, true);
+ mPresenterLazy.get().updateMediaMetaData(false, true);
mShadeSurface.resetAlpha();
mShadeSurface.fadeOut(
FADE_KEYGUARD_START_DELAY, FADE_KEYGUARD_DURATION,
@@ -3343,7 +3345,8 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces {
updateDozingState();
checkBarModes();
updateScrimController();
- mPresenter.updateMediaMetaData(false, mState != StatusBarState.KEYGUARD);
+ mPresenterLazy.get()
+ .updateMediaMetaData(false, mState != StatusBarState.KEYGUARD);
Trace.endSection();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewController.kt
index cc41bf843565..23b0ee0ec9bc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewController.kt
@@ -27,6 +27,7 @@ import com.android.systemui.Gefingerpoken
import com.android.systemui.R
import com.android.systemui.flags.FeatureFlags
import com.android.systemui.flags.Flags
+import com.android.systemui.scene.shared.flag.SceneContainerFlags
import com.android.systemui.scene.ui.view.WindowRootView
import com.android.systemui.shade.ShadeController
import com.android.systemui.shade.ShadeLogger
@@ -48,8 +49,9 @@ import javax.inject.Provider
private const val TAG = "PhoneStatusBarViewController"
-/** Controller for [PhoneStatusBarView]. */
-class PhoneStatusBarViewController private constructor(
+/** Controller for [PhoneStatusBarView]. */
+class PhoneStatusBarViewController
+private constructor(
view: PhoneStatusBarView,
@Named(UNFOLD_STATUS_BAR) private val progressProvider: ScopedUnfoldTransitionProgressProvider?,
private val centralSurfaces: CentralSurfaces,
@@ -61,42 +63,42 @@ class PhoneStatusBarViewController private constructor(
private val moveFromCenterAnimationController: StatusBarMoveFromCenterAnimationController?,
private val userChipViewModel: StatusBarUserChipViewModel,
private val viewUtil: ViewUtil,
- private val featureFlags: FeatureFlags,
+ private val sceneContainerFlags: SceneContainerFlags,
private val configurationController: ConfigurationController,
private val statusOverlayHoverListenerFactory: StatusOverlayHoverListenerFactory,
) : ViewController<PhoneStatusBarView>(view) {
private lateinit var statusContainer: View
- private val configurationListener = object : ConfigurationController.ConfigurationListener {
- override fun onConfigChanged(newConfig: Configuration?) {
- mView.updateResources()
+ private val configurationListener =
+ object : ConfigurationController.ConfigurationListener {
+ override fun onConfigChanged(newConfig: Configuration?) {
+ mView.updateResources()
+ }
}
- }
override fun onViewAttached() {
statusContainer = mView.requireViewById(R.id.system_icons)
statusContainer.setOnHoverListener(
- statusOverlayHoverListenerFactory.createDarkAwareListener(statusContainer))
+ statusOverlayHoverListenerFactory.createDarkAwareListener(statusContainer)
+ )
if (moveFromCenterAnimationController == null) return
val statusBarLeftSide: View =
- mView.requireViewById(R.id.status_bar_start_side_except_heads_up)
+ mView.requireViewById(R.id.status_bar_start_side_except_heads_up)
val systemIconArea: ViewGroup = mView.requireViewById(R.id.status_bar_end_side_content)
- val viewsToAnimate = arrayOf(
- statusBarLeftSide,
- systemIconArea
- )
+ val viewsToAnimate = arrayOf(statusBarLeftSide, systemIconArea)
- mView.viewTreeObserver.addOnPreDrawListener(object :
- ViewTreeObserver.OnPreDrawListener {
- override fun onPreDraw(): Boolean {
- moveFromCenterAnimationController.onViewsReady(viewsToAnimate)
- mView.viewTreeObserver.removeOnPreDrawListener(this)
- return true
+ mView.viewTreeObserver.addOnPreDrawListener(
+ object : ViewTreeObserver.OnPreDrawListener {
+ override fun onPreDraw(): Boolean {
+ moveFromCenterAnimationController.onViewsReady(viewsToAnimate)
+ mView.viewTreeObserver.removeOnPreDrawListener(this)
+ return true
+ }
}
- })
+ )
mView.addOnLayoutChangeListener { _, left, _, right, _, oldLeft, _, oldRight, _ ->
val widthChanged = right - left != oldRight - oldLeft
@@ -121,8 +123,7 @@ class PhoneStatusBarViewController private constructor(
mView.init(userChipViewModel)
}
- override fun onInit() {
- }
+ override fun onInit() {}
fun setImportantForAccessibility(mode: Int) {
mView.importantForAccessibility = mode
@@ -151,10 +152,11 @@ class PhoneStatusBarViewController private constructor(
fun onTouch(event: MotionEvent) {
if (statusBarWindowStateController.windowIsShowing()) {
val upOrCancel =
- event.action == MotionEvent.ACTION_UP ||
- event.action == MotionEvent.ACTION_CANCEL
- centralSurfaces.setInteracting(WINDOW_STATUS_BAR,
- !upOrCancel || shadeController.isExpandedVisible)
+ event.action == MotionEvent.ACTION_UP || event.action == MotionEvent.ACTION_CANCEL
+ centralSurfaces.setInteracting(
+ WINDOW_STATUS_BAR,
+ !upOrCancel || shadeController.isExpandedVisible
+ )
}
}
@@ -171,15 +173,20 @@ class PhoneStatusBarViewController private constructor(
// panel view.
if (!centralSurfaces.commandQueuePanelsEnabled) {
if (event.action == MotionEvent.ACTION_DOWN) {
- Log.v(TAG, String.format("onTouchForwardedFromStatusBar: panel disabled, " +
- "ignoring touch at (${event.x.toInt()},${event.y.toInt()})"))
+ Log.v(
+ TAG,
+ String.format(
+ "onTouchForwardedFromStatusBar: panel disabled, " +
+ "ignoring touch at (${event.x.toInt()},${event.y.toInt()})"
+ )
+ )
}
return false
}
// If scene framework is enabled, route the touch to it and
// ignore the rest of the gesture.
- if (featureFlags.isEnabled(Flags.SCENE_CONTAINER)) {
+ if (sceneContainerFlags.isEnabled()) {
windowRootView.get().dispatchTouchEvent(event)
return true
}
@@ -188,12 +195,13 @@ class PhoneStatusBarViewController private constructor(
// If the view that would receive the touch is disabled, just have status
// bar eat the gesture.
if (!shadeViewController.isViewEnabled) {
- shadeLogger.logMotionEvent(event,
- "onTouchForwardedFromStatusBar: panel view disabled")
+ shadeLogger.logMotionEvent(
+ event,
+ "onTouchForwardedFromStatusBar: panel view disabled"
+ )
return true
}
- if (shadeViewController.isFullyCollapsed &&
- event.y < 1f) {
+ if (shadeViewController.isFullyCollapsed && event.y < 1f) {
// b/235889526 Eat events on the top edge of the phone when collapsed
shadeLogger.logMotionEvent(event, "top edge touch ignored")
return true
@@ -218,9 +226,7 @@ class PhoneStatusBarViewController private constructor(
else -> super.getViewCenter(view, outPoint)
}
- /**
- * Returns start or end (based on [isStart]) center point of the view
- */
+ /** Returns start or end (based on [isStart]) center point of the view */
private fun getViewEdgeCenter(view: View, outPoint: Point, isStart: Boolean) {
val isRtl = view.resources.configuration.layoutDirection == View.LAYOUT_DIRECTION_RTL
val isLeftEdge = isRtl xor isStart
@@ -236,11 +242,14 @@ class PhoneStatusBarViewController private constructor(
}
}
- class Factory @Inject constructor(
+ class Factory
+ @Inject
+ constructor(
private val unfoldComponent: Optional<SysUIUnfoldComponent>,
@Named(UNFOLD_STATUS_BAR)
private val progressProvider: Optional<ScopedUnfoldTransitionProgressProvider>,
private val featureFlags: FeatureFlags,
+ private val sceneContainerFlags: SceneContainerFlags,
private val userChipViewModel: StatusBarUserChipViewModel,
private val centralSurfaces: CentralSurfaces,
private val statusBarWindowStateController: StatusBarWindowStateController,
@@ -252,9 +261,7 @@ class PhoneStatusBarViewController private constructor(
private val configurationController: ConfigurationController,
private val statusOverlayHoverListenerFactory: StatusOverlayHoverListenerFactory,
) {
- fun create(
- view: PhoneStatusBarView
- ): PhoneStatusBarViewController {
+ fun create(view: PhoneStatusBarView): PhoneStatusBarViewController {
val statusBarMoveFromCenterAnimationController =
if (featureFlags.isEnabled(Flags.ENABLE_UNFOLD_STATUS_BAR_ANIMATIONS)) {
unfoldComponent.getOrNull()?.getStatusBarMoveFromCenterAnimationController()
@@ -274,10 +281,10 @@ class PhoneStatusBarViewController private constructor(
statusBarMoveFromCenterAnimationController,
userChipViewModel,
viewUtil,
- featureFlags,
+ sceneContainerFlags,
configurationController,
statusOverlayHoverListenerFactory,
)
}
}
-} \ No newline at end of file
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarTouchableRegionManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarTouchableRegionManager.java
index fa9b9d2c571a..5773612d55c7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarTouchableRegionManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarTouchableRegionManager.java
@@ -34,9 +34,8 @@ import com.android.systemui.Dumpable;
import com.android.systemui.R;
import com.android.systemui.ScreenDecorations;
import com.android.systemui.dagger.SysUISingleton;
-import com.android.systemui.flags.FeatureFlags;
-import com.android.systemui.flags.Flags;
import com.android.systemui.scene.domain.interactor.SceneInteractor;
+import com.android.systemui.scene.shared.flag.SceneContainerFlags;
import com.android.systemui.shade.ShadeExpansionStateManager;
import com.android.systemui.statusbar.NotificationShadeWindowController;
import com.android.systemui.statusbar.policy.ConfigurationController;
@@ -85,7 +84,7 @@ public final class StatusBarTouchableRegionManager implements Dumpable {
ShadeExpansionStateManager shadeExpansionStateManager,
Provider<SceneInteractor> sceneInteractor,
Provider<JavaAdapter> javaAdapter,
- FeatureFlags featureFlags,
+ SceneContainerFlags sceneContainerFlags,
UnlockedScreenOffAnimationController unlockedScreenOffAnimationController
) {
mContext = context;
@@ -123,7 +122,7 @@ public final class StatusBarTouchableRegionManager implements Dumpable {
mUnlockedScreenOffAnimationController = unlockedScreenOffAnimationController;
shadeExpansionStateManager.addFullExpansionListener(this::onShadeExpansionFullyChanged);
- if (featureFlags.isEnabled(Flags.SCENE_CONTAINER)) {
+ if (sceneContainerFlags.isEnabled()) {
javaAdapter.get().alwaysCollectFlow(
sceneInteractor.get().isVisible(),
this::onShadeExpansionFullyChanged);
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.kt
index 6bff4ce4aad9..5da919b22afe 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.kt
@@ -191,7 +191,6 @@ class KeyguardSecurityContainerControllerTest : SysuiTestCase() {
featureFlags = FakeFeatureFlags()
featureFlags.set(Flags.REVAMPED_BOUNCER_MESSAGES, true)
- featureFlags.set(Flags.SCENE_CONTAINER, false)
featureFlags.set(Flags.BOUNCER_USER_SWITCHER, false)
featureFlags.set(Flags.KEYGUARD_WM_STATE_REFACTOR, false)
@@ -244,6 +243,7 @@ class KeyguardSecurityContainerControllerTest : SysuiTestCase() {
falsingManager,
userSwitcherController,
featureFlags,
+ sceneTestUtils.sceneContainerFlags,
globalSettings,
sessionTracker,
Optional.of(sideFpsController),
@@ -622,51 +622,6 @@ class KeyguardSecurityContainerControllerTest : SysuiTestCase() {
configurationListenerArgumentCaptor.value.onUiModeChanged()
verify(view).reloadColors()
}
- @Test
- fun onOrientationChanged_landscapeKeyguardFlagDisabled_blockReinflate() {
- featureFlags.set(Flags.LOCKSCREEN_ENABLE_LANDSCAPE, false)
-
- // Run onOrientationChanged
- val configurationListenerArgumentCaptor =
- ArgumentCaptor.forClass(ConfigurationController.ConfigurationListener::class.java)
- underTest.onViewAttached()
- verify(configurationController).addCallback(configurationListenerArgumentCaptor.capture())
- clearInvocations(viewFlipperController)
- configurationListenerArgumentCaptor.value.onOrientationChanged(
- Configuration.ORIENTATION_LANDSCAPE
- )
- // Verify view is reinflated when flag is on
- verify(viewFlipperController, never()).clearViews()
- verify(viewFlipperController, never())
- .asynchronouslyInflateView(
- eq(SecurityMode.PIN),
- any(),
- onViewInflatedCallbackArgumentCaptor.capture()
- )
- }
-
- @Test
- fun onOrientationChanged_landscapeKeyguardFlagEnabled_doesReinflate() {
- featureFlags.set(Flags.LOCKSCREEN_ENABLE_LANDSCAPE, true)
-
- // Run onOrientationChanged
- val configurationListenerArgumentCaptor =
- ArgumentCaptor.forClass(ConfigurationController.ConfigurationListener::class.java)
- underTest.onViewAttached()
- verify(configurationController).addCallback(configurationListenerArgumentCaptor.capture())
- clearInvocations(viewFlipperController)
- configurationListenerArgumentCaptor.value.onOrientationChanged(
- Configuration.ORIENTATION_LANDSCAPE
- )
- // Verify view is reinflated when flag is on
- verify(viewFlipperController).clearViews()
- verify(viewFlipperController)
- .asynchronouslyInflateView(
- eq(SecurityMode.PIN),
- any(),
- onViewInflatedCallbackArgumentCaptor.capture()
- )
- }
@Test
fun hasDismissActions() {
@@ -802,8 +757,6 @@ class KeyguardSecurityContainerControllerTest : SysuiTestCase() {
@Test
fun dismissesKeyguard_whenSceneChangesToGone() =
sceneTestUtils.testScope.runTest {
- featureFlags.set(Flags.SCENE_CONTAINER, true)
-
// Upon init, we have never dismisses the keyguard.
underTest.onInit()
runCurrent()
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityViewFlipperControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityViewFlipperControllerTest.java
index 68c2f59722ad..19bc8186eee5 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityViewFlipperControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityViewFlipperControllerTest.java
@@ -140,11 +140,6 @@ public class KeyguardSecurityViewFlipperControllerTest extends SysuiTestCase {
@Test
public void asynchronouslyInflateView_setNeedsInput() {
- when(mKeyguardSecurityViewControllerFactory.create(
- any(), any(SecurityMode.class),
- any(KeyguardSecurityCallback.class)))
- .thenReturn(mKeyguardInputViewController);
-
ArgumentCaptor<AsyncLayoutInflater.OnInflateFinishedListener> argumentCaptor =
ArgumentCaptor.forClass(AsyncLayoutInflater.OnInflateFinishedListener.class);
mKeyguardSecurityViewFlipperController.asynchronouslyInflateView(SecurityMode.PIN,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/communal/ui/view/layout/blueprints/DefaultCommunalBlueprintTest.kt b/packages/SystemUI/tests/src/com/android/systemui/communal/ui/view/layout/blueprints/DefaultCommunalBlueprintTest.kt
index be9f6ca0fc33..09cb9291f6b2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/communal/ui/view/layout/blueprints/DefaultCommunalBlueprintTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/communal/ui/view/layout/blueprints/DefaultCommunalBlueprintTest.kt
@@ -33,7 +33,7 @@ class DefaultCommunalBlueprintTest : SysuiTestCase() {
@Test
fun addView() {
val constraintLayout = ConstraintLayout(context, null)
- blueprint.addViews(constraintLayout)
+ blueprint.addViews(null, constraintLayout)
verify(widgetSection).addViews(constraintLayout)
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/ui/TemperatureControlBehaviorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/ui/TemperatureControlBehaviorTest.kt
new file mode 100644
index 000000000000..588e34d3111d
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/controls/ui/TemperatureControlBehaviorTest.kt
@@ -0,0 +1,98 @@
+package com.android.systemui.controls.ui
+
+import android.app.PendingIntent
+import android.content.ComponentName
+import android.content.Intent
+import android.graphics.drawable.Icon
+import android.service.controls.Control
+import android.service.controls.DeviceTypes
+import android.service.controls.templates.TemperatureControlTemplate
+import android.service.controls.templates.ThumbnailTemplate
+import android.view.LayoutInflater
+import android.view.ViewGroup
+import androidx.test.filters.SmallTest
+import com.android.systemui.R
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.controls.ControlsMetricsLogger
+import com.android.systemui.controls.controller.ControlInfo
+import com.android.systemui.controls.controller.ControlsController
+import com.android.systemui.util.concurrency.FakeExecutor
+import com.android.systemui.util.time.FakeSystemClock
+import org.junit.Before
+import org.junit.Test
+import org.mockito.Mock
+import org.mockito.MockitoAnnotations
+
+@SmallTest
+class TemperatureControlBehaviorTest : SysuiTestCase() {
+
+ @Mock lateinit var controlsMetricsLogger: ControlsMetricsLogger
+ @Mock lateinit var controlActionCoordinator: ControlActionCoordinator
+ @Mock lateinit var controlsController: ControlsController
+
+ private val fakeSystemClock = FakeSystemClock()
+ private val underTest = TemperatureControlBehavior()
+
+ private lateinit var viewHolder: ControlViewHolder
+
+ @Before
+ fun setup() {
+ MockitoAnnotations.initMocks(this)
+
+ viewHolder =
+ ControlViewHolder(
+ LayoutInflater.from(mContext).inflate(R.layout.controls_base_item, null, false)
+ as ViewGroup,
+ controlsController,
+ FakeExecutor(fakeSystemClock),
+ FakeExecutor(fakeSystemClock),
+ controlActionCoordinator,
+ controlsMetricsLogger,
+ 0,
+ 0,
+ )
+ }
+
+ @Test
+ fun testBehaviourSupportsThumbnailSubBehaviour() {
+ val controlWithState =
+ ControlWithState(
+ ComponentName("test.pkg", "TestClass"),
+ ControlInfo(
+ "test_id",
+ "test title",
+ "test subtitle",
+ DeviceTypes.TYPE_AC_UNIT,
+ ),
+ Control.StatefulBuilder(
+ "",
+ PendingIntent.getActivity(
+ context,
+ 0,
+ Intent(),
+ PendingIntent.FLAG_IMMUTABLE,
+ ),
+ )
+ .setControlTemplate(
+ TemperatureControlTemplate(
+ "test id",
+ ThumbnailTemplate(
+ "test id",
+ false,
+ Icon.createWithContentUri(""),
+ "test description",
+ ),
+ 0,
+ 0,
+ 0
+ )
+ )
+ .setStatus(Control.STATUS_OK)
+ .build()
+ )
+ viewHolder.bindData(controlWithState, false)
+ underTest.initialize(viewHolder)
+
+ underTest.bind(controlWithState, 0) // no crash
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/CustomizationProviderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/CustomizationProviderTest.kt
index e2362f64b885..f62137c62c65 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/CustomizationProviderTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/CustomizationProviderTest.kt
@@ -175,7 +175,6 @@ class CustomizationProviderTest : SysuiTestCase() {
set(Flags.REVAMPED_WALLPAPER_UI, true)
set(Flags.WALLPAPER_FULLSCREEN_PREVIEW, true)
set(Flags.FACE_AUTH_REFACTOR, true)
- set(Flags.SCENE_CONTAINER, false)
}
underTest.interactor =
KeyguardQuickAffordanceInteractor(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorTest.kt
index ce280d7b221b..14cdf2f58a7d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorTest.kt
@@ -29,7 +29,6 @@ import com.android.systemui.common.ui.data.repository.FakeConfigurationRepositor
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.flags.FakeFeatureFlags
import com.android.systemui.flags.Flags.FACE_AUTH_REFACTOR
-import com.android.systemui.flags.Flags.SCENE_CONTAINER
import com.android.systemui.keyguard.data.repository.FakeCommandQueue
import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
import com.android.systemui.keyguard.shared.model.CameraLaunchSourceModel
@@ -70,11 +69,7 @@ class KeyguardInteractorTest : SysuiTestCase() {
@Before
fun setUp() {
MockitoAnnotations.initMocks(this)
- featureFlags =
- FakeFeatureFlags().apply {
- set(FACE_AUTH_REFACTOR, true)
- set(SCENE_CONTAINER, true)
- }
+ featureFlags = FakeFeatureFlags().apply { set(FACE_AUTH_REFACTOR, true) }
commandQueue = FakeCommandQueue()
val sceneTestUtils = SceneTestUtils(this)
testScope = sceneTestUtils.testScope
@@ -90,6 +85,7 @@ class KeyguardInteractorTest : SysuiTestCase() {
repository = repository,
commandQueue = commandQueue,
featureFlags = featureFlags,
+ sceneContainerFlags = sceneTestUtils.sceneContainerFlags,
bouncerRepository = bouncerRepository,
configurationRepository = configurationRepository,
shadeRepository = shadeRepository,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/OccludingAppDeviceEntryInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/OccludingAppDeviceEntryInteractorTest.kt
index 499a6362ce05..bdcb9abba745 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/OccludingAppDeviceEntryInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/OccludingAppDeviceEntryInteractorTest.kt
@@ -104,7 +104,6 @@ class OccludingAppDeviceEntryInteractorTest : SysuiTestCase() {
FakeFeatureFlags().apply {
set(Flags.FACE_AUTH_REFACTOR, false)
set(Flags.DELAY_BOUNCER, false)
- set(Flags.SCENE_CONTAINER, false)
}
trustRepository = FakeTrustRepository()
powerRepository = FakePowerRepository()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/blueprints/DefaultKeyguardBlueprintTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/blueprints/DefaultKeyguardBlueprintTest.kt
index 3b4eab2a5fe1..bf57ecb41091 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/blueprints/DefaultKeyguardBlueprintTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/blueprints/DefaultKeyguardBlueprintTest.kt
@@ -25,6 +25,7 @@ import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.flags.FakeFeatureFlags
import com.android.systemui.flags.Flags
+import com.android.systemui.keyguard.shared.model.KeyguardBlueprint
import com.android.systemui.keyguard.ui.view.KeyguardRootView
import com.android.systemui.keyguard.ui.view.layout.sections.DefaultAmbientIndicationAreaSection
import com.android.systemui.keyguard.ui.view.layout.sections.DefaultIndicationAreaSection
@@ -34,10 +35,12 @@ import com.android.systemui.keyguard.ui.view.layout.sections.DefaultSettingsPopu
import com.android.systemui.keyguard.ui.view.layout.sections.DefaultShortcutsSection
import com.android.systemui.keyguard.ui.view.layout.sections.DefaultStatusViewSection
import com.android.systemui.keyguard.ui.view.layout.sections.SplitShadeGuidelines
+import com.android.systemui.util.mockito.whenever
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mock
+import org.mockito.Mockito.mock
import org.mockito.Mockito.never
import org.mockito.Mockito.verify
import org.mockito.MockitoAnnotations
@@ -81,7 +84,7 @@ class DefaultKeyguardBlueprintTest : SysuiTestCase() {
@Test
fun addViews() {
val constraintLayout = ConstraintLayout(context, null)
- underTest.addViews(constraintLayout)
+ underTest.addViews(null, constraintLayout)
underTest.sections.forEach { verify(it, never()).addViews(constraintLayout) }
}
@@ -89,11 +92,35 @@ class DefaultKeyguardBlueprintTest : SysuiTestCase() {
fun addViews_lazyInflateFlagOn() {
featureFlags.set(Flags.LAZY_INFLATE_KEYGUARD, true)
val constraintLayout = ConstraintLayout(context, null)
- underTest.addViews(constraintLayout)
+ underTest.addViews(null, constraintLayout)
underTest.sections.forEach { verify(it).addViews(constraintLayout) }
}
@Test
+ fun addViews_withPrevBlueprint() {
+ val prevBlueprint = mock(KeyguardBlueprint::class.java)
+ whenever(prevBlueprint.sections)
+ .thenReturn(underTest.sections.minus(defaultLockIconSection))
+ featureFlags.set(Flags.LAZY_INFLATE_KEYGUARD, true)
+ val constraintLayout = ConstraintLayout(context, null)
+ underTest.addViews(prevBlueprint, constraintLayout)
+ underTest.sections.minus(defaultLockIconSection).forEach {
+ verify(it, never()).addViews(constraintLayout)
+ }
+
+ verify(defaultLockIconSection).addViews(constraintLayout)
+ }
+
+ @Test
+ fun addViews_withNextBlueprint() {
+ val nextBlueprint = mock(KeyguardBlueprint::class.java)
+ whenever(nextBlueprint.sections).thenReturn(setOf())
+ val constraintLayout = ConstraintLayout(context, null)
+ underTest.removeViews(nextBlueprint, constraintLayout)
+ underTest.sections.forEach { verify(it).removeViews(constraintLayout) }
+ }
+
+ @Test
fun applyConstraints() {
val cs = ConstraintSet()
underTest.applyConstraints(cs)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultIndicationAreaSectionTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultIndicationAreaSectionTest.kt
index 798b23e4a074..4e31af22f771 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultIndicationAreaSectionTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultIndicationAreaSectionTest.kt
@@ -18,14 +18,17 @@
package com.android.systemui.keyguard.ui.view.layout.sections
import android.view.ViewGroup
+import androidx.constraintlayout.widget.ConstraintLayout
import androidx.constraintlayout.widget.ConstraintSet
import androidx.test.filters.SmallTest
import com.android.systemui.R
import com.android.systemui.SysuiTestCase
import com.android.systemui.flags.FeatureFlags
+import com.android.systemui.flags.Flags
import com.android.systemui.keyguard.ui.viewmodel.KeyguardIndicationAreaViewModel
import com.android.systemui.keyguard.ui.viewmodel.KeyguardRootViewModel
import com.android.systemui.statusbar.KeyguardIndicationController
+import com.android.systemui.util.mockito.whenever
import com.google.common.truth.Truth.assertThat
import org.junit.Before
import org.junit.Test
@@ -58,7 +61,23 @@ class DefaultIndicationAreaSectionTest : SysuiTestCase() {
}
@Test
- fun apply() {
+ fun addViewsConditionally() {
+ whenever(featureFlags.isEnabled(Flags.MIGRATE_SPLIT_KEYGUARD_BOTTOM_AREA)).thenReturn(true)
+ val constraintLayout = ConstraintLayout(context, null)
+ underTest.addViews(constraintLayout)
+ assertThat(constraintLayout.childCount).isGreaterThan(0)
+ }
+
+ @Test
+ fun addViewsConditionally_migrateFlagOff() {
+ whenever(featureFlags.isEnabled(Flags.MIGRATE_SPLIT_KEYGUARD_BOTTOM_AREA)).thenReturn(false)
+ val constraintLayout = ConstraintLayout(context, null)
+ underTest.addViews(constraintLayout)
+ assertThat(constraintLayout.childCount).isEqualTo(0)
+ }
+
+ @Test
+ fun applyConstraints() {
val cs = ConstraintSet()
underTest.applyConstraints(cs)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultLockIconSectionTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultLockIconSectionTest.kt
index 1192a8017dc4..1c3b5e616ddf 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultLockIconSectionTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultLockIconSectionTest.kt
@@ -19,6 +19,7 @@ package com.android.systemui.keyguard.ui.view.layout.sections
import android.graphics.Point
import android.view.WindowManager
+import androidx.constraintlayout.widget.ConstraintLayout
import androidx.constraintlayout.widget.ConstraintSet
import androidx.test.filters.SmallTest
import com.android.keyguard.KeyguardUpdateMonitor
@@ -27,7 +28,9 @@ import com.android.systemui.R
import com.android.systemui.SysuiTestCase
import com.android.systemui.biometrics.AuthController
import com.android.systemui.flags.FeatureFlags
+import com.android.systemui.flags.Flags
import com.android.systemui.shade.NotificationPanelView
+import com.android.systemui.util.mockito.whenever
import com.google.common.truth.Truth.assertThat
import org.junit.Before
import org.junit.Test
@@ -64,7 +67,23 @@ class DefaultLockIconSectionTest : SysuiTestCase() {
}
@Test
- fun apply() {
+ fun addViewsConditionally() {
+ whenever(featureFlags.isEnabled(Flags.MIGRATE_LOCK_ICON)).thenReturn(true)
+ val constraintLayout = ConstraintLayout(context, null)
+ underTest.addViews(constraintLayout)
+ assertThat(constraintLayout.childCount).isGreaterThan(0)
+ }
+
+ @Test
+ fun addViewsConditionally_migrateFlagOff() {
+ whenever(featureFlags.isEnabled(Flags.MIGRATE_LOCK_ICON)).thenReturn(false)
+ val constraintLayout = ConstraintLayout(context, null)
+ underTest.addViews(constraintLayout)
+ assertThat(constraintLayout.childCount).isEqualTo(0)
+ }
+
+ @Test
+ fun applyConstraints() {
val cs = ConstraintSet()
underTest.applyConstraints(cs)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardQuickAffordancesCombinedViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardQuickAffordancesCombinedViewModelTest.kt
index 7fecfc234392..b935e1d3c65a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardQuickAffordancesCombinedViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardQuickAffordancesCombinedViewModelTest.kt
@@ -129,7 +129,6 @@ class KeyguardQuickAffordancesCombinedViewModelTest : SysuiTestCase() {
set(Flags.FACE_AUTH_REFACTOR, true)
set(Flags.LOCK_SCREEN_LONG_PRESS_ENABLED, false)
set(Flags.LOCK_SCREEN_LONG_PRESS_DIRECT_TO_WPP, false)
- set(Flags.SCENE_CONTAINER, false)
}
val withDeps = KeyguardInteractorFactory.create(featureFlags = featureFlags)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/recents/OverviewProxyServiceTest.kt b/packages/SystemUI/tests/src/com/android/systemui/recents/OverviewProxyServiceTest.kt
index ef07fab70bb0..e353a53af752 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/recents/OverviewProxyServiceTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/recents/OverviewProxyServiceTest.kt
@@ -36,6 +36,7 @@ import com.android.systemui.model.SysUiState
import com.android.systemui.navigationbar.NavigationBarController
import com.android.systemui.navigationbar.NavigationModeController
import com.android.systemui.recents.OverviewProxyService.ACTION_QUICKSTEP
+import com.android.systemui.scene.shared.flag.FakeSceneContainerFlags
import com.android.systemui.settings.FakeDisplayTracker
import com.android.systemui.settings.UserTracker
import com.android.systemui.shade.ShadeViewController
@@ -146,6 +147,7 @@ class OverviewProxyServiceTest : SysuiTestCase() {
sysuiUnlockAnimationController,
assistUtils,
featureFlags,
+ FakeSceneContainerFlags(),
dumpManager,
unfoldTransitionProgressForwarder
)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt b/packages/SystemUI/tests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt
index 6006cd42424a..2f26a53afe7c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt
@@ -25,8 +25,6 @@ import com.android.systemui.authentication.domain.model.AuthenticationMethodMode
import com.android.systemui.authentication.domain.model.AuthenticationMethodModel
import com.android.systemui.bouncer.ui.viewmodel.PinBouncerViewModel
import com.android.systemui.coroutines.collectLastValue
-import com.android.systemui.flags.FakeFeatureFlags
-import com.android.systemui.flags.Flags
import com.android.systemui.keyguard.shared.model.WakefulnessState
import com.android.systemui.keyguard.ui.viewmodel.KeyguardLongPressViewModel
import com.android.systemui.keyguard.ui.viewmodel.LockscreenSceneViewModel
@@ -140,8 +138,6 @@ class SceneFrameworkIntegrationTest : SysuiTestCase() {
@Before
fun setUp() {
- val featureFlags = FakeFeatureFlags().apply { set(Flags.SCENE_CONTAINER, true) }
-
authenticationRepository.setUnlocked(false)
val displayTracker = FakeDisplayTracker(context)
@@ -152,7 +148,7 @@ class SceneFrameworkIntegrationTest : SysuiTestCase() {
sceneInteractor = sceneInteractor,
authenticationInteractor = authenticationInteractor,
keyguardInteractor = keyguardInteractor,
- featureFlags = featureFlags,
+ flags = utils.sceneContainerFlags,
sysUiState = sysUiState,
displayId = displayTracker.defaultDisplayId,
sceneLogger = mock(),
diff --git a/packages/SystemUI/tests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt b/packages/SystemUI/tests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt
index 771c3e330e8a..145629a65f68 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt
@@ -42,6 +42,7 @@ import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
+import org.junit.Assume.assumeTrue
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
@@ -57,7 +58,7 @@ class SceneContainerStartableTest : SysuiTestCase() {
private val utils = SceneTestUtils(this)
private val testScope = utils.testScope
private val sceneInteractor = utils.sceneInteractor()
- private val featureFlags = utils.featureFlags
+ private val sceneContainerFlags = utils.sceneContainerFlags
private val authenticationRepository = utils.authenticationRepository()
private val authenticationInteractor =
utils.authenticationInteractor(
@@ -78,7 +79,7 @@ class SceneContainerStartableTest : SysuiTestCase() {
sceneInteractor = sceneInteractor,
authenticationInteractor = authenticationInteractor,
keyguardInteractor = keyguardInteractor,
- featureFlags = featureFlags,
+ flags = sceneContainerFlags,
sysUiState = sysUiState,
displayId = Display.DEFAULT_DISPLAY,
sceneLogger = mock(),
@@ -516,7 +517,8 @@ class SceneContainerStartableTest : SysuiTestCase() {
initialSceneKey: SceneKey? = null,
authenticationMethod: AuthenticationMethodModel? = null,
): MutableStateFlow<ObservableTransitionState> {
- featureFlags.set(Flags.SCENE_CONTAINER, true)
+ assumeTrue(Flags.SCENE_CONTAINER_ENABLED)
+ sceneContainerFlags.enabled = true
authenticationRepository.setUnlocked(isDeviceUnlocked)
keyguardRepository.setBypassEnabled(isBypassEnabled)
val transitionStateFlow =
diff --git a/packages/SystemUI/tests/src/com/android/systemui/scene/shared/flag/SceneContainerFlagsTest.kt b/packages/SystemUI/tests/src/com/android/systemui/scene/shared/flag/SceneContainerFlagsTest.kt
new file mode 100644
index 000000000000..17ee3a1cc906
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/scene/shared/flag/SceneContainerFlagsTest.kt
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2023 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.systemui.scene.shared.flag
+
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.flags.FakeFeatureFlagsClassic
+import com.android.systemui.flags.Flags
+import com.android.systemui.flags.ReleasedFlag
+import com.android.systemui.flags.ResourceBooleanFlag
+import com.android.systemui.flags.UnreleasedFlag
+import com.google.common.truth.Truth.assertThat
+import org.junit.Assume.assumeTrue
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.Parameterized
+
+@SmallTest
+@RunWith(Parameterized::class)
+internal class SceneContainerFlagsTest(
+ private val testCase: TestCase,
+) : SysuiTestCase() {
+
+ private lateinit var underTest: SceneContainerFlags
+
+ @Before
+ fun setUp() {
+ val featureFlags =
+ FakeFeatureFlagsClassic().apply {
+ SceneContainerFlagsImpl.flags.forEach { flag ->
+ when (flag) {
+ is ResourceBooleanFlag -> set(flag, testCase.areAllFlagsSet)
+ is ReleasedFlag -> set(flag, testCase.areAllFlagsSet)
+ is UnreleasedFlag -> set(flag, testCase.areAllFlagsSet)
+ else -> error("Unsupported flag type ${flag.javaClass}")
+ }
+ }
+ }
+ underTest = SceneContainerFlagsImpl(featureFlags, testCase.isComposeAvailable)
+ }
+
+ @Test
+ fun isEnabled() {
+ assumeTrue(Flags.SCENE_CONTAINER_ENABLED)
+ assertThat(underTest.isEnabled()).isEqualTo(testCase.expectedEnabled)
+ }
+
+ internal data class TestCase(
+ val isComposeAvailable: Boolean,
+ val areAllFlagsSet: Boolean,
+ val expectedEnabled: Boolean,
+ ) {
+ override fun toString(): String {
+ return """
+ (compose=$isComposeAvailable + flags=$areAllFlagsSet) -> expected=$expectedEnabled
+ """
+ .trimIndent()
+ }
+ }
+
+ companion object {
+ @Parameterized.Parameters(name = "{0}")
+ @JvmStatic
+ fun testCases() = buildList {
+ repeat(4) { combination ->
+ val isComposeAvailable = combination and 0b100 != 0
+ val areAllFlagsSet = combination and 0b001 != 0
+
+ val expectedEnabled = isComposeAvailable && areAllFlagsSet
+
+ add(
+ TestCase(
+ isComposeAvailable = isComposeAvailable,
+ areAllFlagsSet = areAllFlagsSet,
+ expectedEnabled = expectedEnabled,
+ )
+ )
+ }
+ }
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotPolicyImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotPolicyImplTest.kt
index ee61f5736263..587da2d5d677 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotPolicyImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotPolicyImplTest.kt
@@ -140,7 +140,7 @@ class ScreenshotPolicyImplTest : SysuiTestCase() {
private val pipTask = RootTaskInfo().apply {
configuration.windowConfiguration.apply {
windowingMode = WINDOWING_MODE_PINNED
- bounds = Rect(628, 1885, 1038, 2295)
+ setBounds(Rect(628, 1885, 1038, 2295))
activityType = ACTIVITY_TYPE_STANDARD
}
displayId = DISPLAY_ID
@@ -164,7 +164,7 @@ class ScreenshotPolicyImplTest : SysuiTestCase() {
private val fullScreenWorkProfileTask = RootTaskInfo().apply {
configuration.windowConfiguration.apply {
windowingMode = WINDOWING_MODE_FULLSCREEN
- bounds = Rect(0, 0, 1080, 2400)
+ setBounds(Rect(0, 0, 1080, 2400))
activityType = ACTIVITY_TYPE_STANDARD
}
displayId = DISPLAY_ID
@@ -188,7 +188,7 @@ class ScreenshotPolicyImplTest : SysuiTestCase() {
private val launcherTask = RootTaskInfo().apply {
configuration.windowConfiguration.apply {
windowingMode = WINDOWING_MODE_FULLSCREEN
- bounds = Rect(0, 0, 1080, 2400)
+ setBounds(Rect(0, 0, 1080, 2400))
activityType = ACTIVITY_TYPE_HOME
}
displayId = DISPLAY_ID
@@ -212,7 +212,7 @@ class ScreenshotPolicyImplTest : SysuiTestCase() {
private val emptyTask = RootTaskInfo().apply {
configuration.windowConfiguration.apply {
windowingMode = WINDOWING_MODE_FULLSCREEN
- bounds = Rect(0, 0, 1080, 2400)
+ setBounds(Rect(0, 0, 1080, 2400))
activityType = ACTIVITY_TYPE_UNDEFINED
}
displayId = DISPLAY_ID
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java
index c573ac638032..1c9ec27c6a1b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java
@@ -626,6 +626,7 @@ public class NotificationPanelViewControllerBaseTest extends SysuiTestCase {
mScreenOffAnimationController,
mLockscreenGestureLogger,
mShadeExpansionStateManager,
+ mShadeRepository,
mSysUIUnfoldComponent,
mSysUiState,
() -> mKeyguardBottomAreaViewController,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerBaseTest.java
index ab0ae05b0e83..e42a7a6f50d7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerBaseTest.java
@@ -37,6 +37,7 @@ import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.TestScopeProvider;
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.common.ui.data.repository.FakeConfigurationRepository;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.fragments.FragmentHostManager;
@@ -61,6 +62,7 @@ import com.android.systemui.statusbar.SysuiStatusBarStateController;
import com.android.systemui.statusbar.disableflags.data.repository.FakeDisableFlagsRepository;
import com.android.systemui.statusbar.notification.stack.AmbientState;
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController;
+import com.android.systemui.statusbar.notification.stack.domain.interactor.SharedNotificationContainerInteractor;
import com.android.systemui.statusbar.phone.KeyguardBottomAreaView;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
import com.android.systemui.statusbar.phone.KeyguardStatusBarView;
@@ -174,6 +176,9 @@ public class QuickSettingsControllerBaseTest extends SysuiTestCase {
new FakeUserSetupRepository(),
mDeviceProvisionedController,
mUserInteractor,
+ new SharedNotificationContainerInteractor(
+ new FakeConfigurationRepository(),
+ mContext),
mShadeRepository
);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/data/repository/ShadeInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/data/repository/ShadeInteractorTest.kt
index e6e7482bdaf9..41ea5b747e06 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/data/repository/ShadeInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/data/repository/ShadeInteractorTest.kt
@@ -25,7 +25,9 @@ import android.os.UserManager
import androidx.test.filters.SmallTest
import com.android.internal.logging.UiEventLogger
import com.android.keyguard.KeyguardUpdateMonitor
+import com.android.systemui.R
import com.android.systemui.SysuiTestCase
+import com.android.systemui.common.ui.data.repository.FakeConfigurationRepository
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.flags.FakeFeatureFlags
import com.android.systemui.flags.Flags
@@ -36,6 +38,7 @@ import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.shade.domain.interactor.ShadeInteractor
import com.android.systemui.statusbar.disableflags.data.model.DisableFlagsModel
import com.android.systemui.statusbar.disableflags.data.repository.FakeDisableFlagsRepository
+import com.android.systemui.statusbar.notification.stack.domain.interactor.SharedNotificationContainerInteractor
import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeUserSetupRepository
import com.android.systemui.statusbar.policy.DeviceProvisionedController
import com.android.systemui.telephony.data.repository.FakeTelephonyRepository
@@ -52,6 +55,7 @@ import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.test.StandardTestDispatcher
import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
import org.junit.Before
import org.junit.Test
@@ -71,6 +75,12 @@ class ShadeInteractorTest : SysuiTestCase() {
private val disableFlagsRepository = FakeDisableFlagsRepository()
private val keyguardRepository = FakeKeyguardRepository()
private val shadeRepository = FakeShadeRepository()
+ private val configurationRepository = FakeConfigurationRepository()
+ private val sharedNotificationContainerInteractor =
+ SharedNotificationContainerInteractor(
+ configurationRepository,
+ mContext,
+ )
@Mock private lateinit var manager: UserManager
@Mock private lateinit var headlessSystemUserMode: HeadlessSystemUserMode
@@ -145,6 +155,7 @@ class ShadeInteractorTest : SysuiTestCase() {
userSetupRepository,
deviceProvisionedController,
userInteractor,
+ sharedNotificationContainerInteractor,
shadeRepository,
)
}
@@ -363,7 +374,7 @@ class ShadeInteractorTest : SysuiTestCase() {
val actual by collectLastValue(underTest.shadeExpansion)
keyguardRepository.setStatusBarState(StatusBarState.SHADE_LOCKED)
- shadeRepository.setShadeExpansion(0.5f)
+ shadeRepository.setLockscreenShadeExpansion(0.5f)
assertThat(actual).isEqualTo(1f)
}
@@ -375,10 +386,52 @@ class ShadeInteractorTest : SysuiTestCase() {
keyguardRepository.setStatusBarState(StatusBarState.KEYGUARD)
- shadeRepository.setShadeExpansion(0.5f)
+ shadeRepository.setLockscreenShadeExpansion(0.5f)
assertThat(actual).isEqualTo(0.5f)
- shadeRepository.setShadeExpansion(0.8f)
+ shadeRepository.setLockscreenShadeExpansion(0.8f)
assertThat(actual).isEqualTo(0.8f)
}
+
+ fun shadeExpansionWhenInSplitShadeAndQsExpanded() =
+ testScope.runTest {
+ val actual by collectLastValue(underTest.shadeExpansion)
+
+ // WHEN split shade is enabled and QS is expanded
+ keyguardRepository.setStatusBarState(StatusBarState.SHADE)
+ overrideResource(R.bool.config_use_split_notification_shade, true)
+ configurationRepository.onAnyConfigurationChange()
+ runCurrent()
+ shadeRepository.setQsExpansion(.5f)
+ shadeRepository.setLegacyShadeExpansion(.7f)
+
+ // THEN legacy shade expansion is passed through
+ assertThat(actual).isEqualTo(.7f)
+ }
+
+ fun shadeExpansionWhenNotInSplitShadeAndQsExpanded() =
+ testScope.runTest {
+ val actual by collectLastValue(underTest.shadeExpansion)
+
+ // WHEN split shade is not enabled and QS is expanded
+ keyguardRepository.setStatusBarState(StatusBarState.SHADE)
+ shadeRepository.setQsExpansion(.5f)
+ shadeRepository.setLegacyShadeExpansion(1f)
+
+ // THEN shade expansion is zero
+ assertThat(actual).isEqualTo(0f)
+ }
+
+ fun shadeExpansionWhenNotInSplitShadeAndQsCollapsed() =
+ testScope.runTest {
+ val actual by collectLastValue(underTest.shadeExpansion)
+
+ // WHEN split shade is not enabled and QS is expanded
+ keyguardRepository.setStatusBarState(StatusBarState.SHADE)
+ shadeRepository.setQsExpansion(0f)
+ shadeRepository.setLegacyShadeExpansion(.6f)
+
+ // THEN shade expansion is zero
+ assertThat(actual).isEqualTo(.6f)
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/data/repository/ShadeRepositoryImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/data/repository/ShadeRepositoryImplTest.kt
index fdaea2220de9..e086712308b6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/data/repository/ShadeRepositoryImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/data/repository/ShadeRepositoryImplTest.kt
@@ -121,18 +121,33 @@ class ShadeRepositoryImplTest : SysuiTestCase() {
}
@Test
- fun updateShadeExpansion() =
+ fun updateDragDownAmount() =
testScope.runTest {
- assertThat(underTest.shadeExpansion.value).isEqualTo(0f)
+ assertThat(underTest.lockscreenShadeExpansion.value).isEqualTo(0f)
- underTest.setShadeExpansion(.5f)
- assertThat(underTest.shadeExpansion.value).isEqualTo(.5f)
+ underTest.setLockscreenShadeExpansion(.5f)
+ assertThat(underTest.lockscreenShadeExpansion.value).isEqualTo(.5f)
- underTest.setShadeExpansion(.82f)
- assertThat(underTest.shadeExpansion.value).isEqualTo(.82f)
+ underTest.setLockscreenShadeExpansion(.82f)
+ assertThat(underTest.lockscreenShadeExpansion.value).isEqualTo(.82f)
- underTest.setShadeExpansion(1f)
- assertThat(underTest.shadeExpansion.value).isEqualTo(1f)
+ underTest.setLockscreenShadeExpansion(1f)
+ assertThat(underTest.lockscreenShadeExpansion.value).isEqualTo(1f)
+ }
+
+ @Test
+ fun updateLegacyShadeExpansion() =
+ testScope.runTest {
+ assertThat(underTest.legacyShadeExpansion.value).isEqualTo(0f)
+
+ underTest.setLegacyShadeExpansion(.5f)
+ assertThat(underTest.legacyShadeExpansion.value).isEqualTo(.5f)
+
+ underTest.setLegacyShadeExpansion(.82f)
+ assertThat(underTest.legacyShadeExpansion.value).isEqualTo(.82f)
+
+ underTest.setLegacyShadeExpansion(1f)
+ assertThat(underTest.legacyShadeExpansion.value).isEqualTo(1f)
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt
index 51e72c615372..6f7588097c70 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt
@@ -10,6 +10,7 @@ import com.android.systemui.R
import com.android.systemui.SysuiTestCase
import com.android.systemui.classifier.FalsingCollector
import com.android.systemui.classifier.FalsingCollectorFake
+import com.android.systemui.common.ui.data.repository.FakeConfigurationRepository
import com.android.systemui.dump.DumpManager
import com.android.systemui.keyguard.WakefulnessLifecycle
import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
@@ -29,6 +30,7 @@ import com.android.systemui.statusbar.notification.row.NotificationTestHelper
import com.android.systemui.statusbar.notification.stack.AmbientState
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController
+import com.android.systemui.statusbar.notification.stack.domain.interactor.SharedNotificationContainerInteractor
import com.android.systemui.statusbar.phone.CentralSurfaces
import com.android.systemui.statusbar.phone.KeyguardBypassController
import com.android.systemui.statusbar.phone.LSShadeTransitionLogger
@@ -102,6 +104,11 @@ class LockscreenShadeTransitionControllerTest : SysuiTestCase() {
@Mock lateinit var transitionControllerCallback: LockscreenShadeTransitionController.Callback
private val disableFlagsRepository = FakeDisableFlagsRepository()
private val keyguardRepository = FakeKeyguardRepository()
+ private val configurationRepository = FakeConfigurationRepository()
+ private val sharedNotificationContainerInteractor = SharedNotificationContainerInteractor(
+ configurationRepository,
+ mContext,
+ )
private val shadeInteractor =
ShadeInteractor(
testScope.backgroundScope,
@@ -110,6 +117,7 @@ class LockscreenShadeTransitionControllerTest : SysuiTestCase() {
userSetupRepository = FakeUserSetupRepository(),
deviceProvisionedController = mock(),
userInteractor = mock(),
+ sharedNotificationContainerInteractor,
repository = FakeShadeRepository(),
)
private val powerInteractor =
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelTest.kt
index 55b52dc21434..75fb22dfddd0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelTest.kt
@@ -30,6 +30,7 @@ import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractorFactory
import com.android.systemui.keyguard.shared.model.KeyguardState
+import com.android.systemui.keyguard.shared.model.StatusBarState
import com.android.systemui.keyguard.shared.model.TransitionState
import com.android.systemui.keyguard.shared.model.TransitionStep
import com.android.systemui.shade.data.repository.FakeShadeRepository
@@ -97,7 +98,11 @@ class SharedNotificationContainerViewModelTest : SysuiTestCase() {
keyguardTransitionInteractor = it.keyguardTransitionInteractor
keyguardTransitionRepository = it.repository
}
-
+ sharedNotificationContainerInteractor =
+ SharedNotificationContainerInteractor(
+ configurationRepository,
+ mContext,
+ )
shadeInteractor =
ShadeInteractor(
testScope.backgroundScope,
@@ -106,14 +111,9 @@ class SharedNotificationContainerViewModelTest : SysuiTestCase() {
userSetupRepository,
deviceProvisionedController,
userInteractor,
+ sharedNotificationContainerInteractor,
shadeRepository,
)
-
- sharedNotificationContainerInteractor =
- SharedNotificationContainerInteractor(
- configurationRepository,
- mContext,
- )
underTest =
SharedNotificationContainerViewModel(
sharedNotificationContainerInteractor,
@@ -228,7 +228,7 @@ class SharedNotificationContainerViewModelTest : SysuiTestCase() {
val isOnLockscreenWithoutShade by collectLastValue(underTest.isOnLockscreenWithoutShade)
// First on AOD
- shadeRepository.setShadeExpansion(0f)
+ shadeRepository.setLockscreenShadeExpansion(0f)
shadeRepository.setQsExpansion(0f)
keyguardTransitionRepository.sendTransitionStep(
TransitionStep(
@@ -242,19 +242,19 @@ class SharedNotificationContainerViewModelTest : SysuiTestCase() {
showLockscreen()
// While state is LOCKSCREEN, validate variations of both shade and qs expansion
- shadeRepository.setShadeExpansion(0.1f)
+ shadeRepository.setLockscreenShadeExpansion(0.1f)
shadeRepository.setQsExpansion(0f)
assertThat(isOnLockscreenWithoutShade).isFalse()
- shadeRepository.setShadeExpansion(0.1f)
+ shadeRepository.setLockscreenShadeExpansion(0.1f)
shadeRepository.setQsExpansion(0.1f)
assertThat(isOnLockscreenWithoutShade).isFalse()
- shadeRepository.setShadeExpansion(0f)
+ shadeRepository.setLockscreenShadeExpansion(0f)
shadeRepository.setQsExpansion(0.1f)
assertThat(isOnLockscreenWithoutShade).isFalse()
- shadeRepository.setShadeExpansion(0f)
+ shadeRepository.setLockscreenShadeExpansion(0f)
shadeRepository.setQsExpansion(0f)
assertThat(isOnLockscreenWithoutShade).isTrue()
}
@@ -366,8 +366,9 @@ class SharedNotificationContainerViewModelTest : SysuiTestCase() {
}
private suspend fun showLockscreen() {
- shadeRepository.setShadeExpansion(0f)
+ shadeRepository.setLockscreenShadeExpansion(0f)
shadeRepository.setQsExpansion(0f)
+ keyguardRepository.setStatusBarState(StatusBarState.KEYGUARD)
keyguardTransitionRepository.sendTransitionStep(
TransitionStep(
to = KeyguardState.LOCKSCREEN,
@@ -377,8 +378,9 @@ class SharedNotificationContainerViewModelTest : SysuiTestCase() {
}
private suspend fun showLockscreenWithShadeExpanded() {
- shadeRepository.setShadeExpansion(1f)
+ shadeRepository.setLockscreenShadeExpansion(1f)
shadeRepository.setQsExpansion(0f)
+ keyguardRepository.setStatusBarState(StatusBarState.SHADE_LOCKED)
keyguardTransitionRepository.sendTransitionStep(
TransitionStep(
to = KeyguardState.LOCKSCREEN,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java
index 4e3690f1d124..137566bf1a2a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java
@@ -136,6 +136,7 @@ import com.android.systemui.statusbar.LockscreenShadeTransitionController;
import com.android.systemui.statusbar.NotificationListener;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.NotificationMediaManager;
+import com.android.systemui.statusbar.NotificationPresenter;
import com.android.systemui.statusbar.NotificationRemoteInputManager;
import com.android.systemui.statusbar.NotificationShadeDepthController;
import com.android.systemui.statusbar.NotificationShadeWindowController;
@@ -491,8 +492,8 @@ public class CentralSurfacesImplTest extends SysuiTestCase {
mNotificationShadeWindowViewControllerLazy,
mNotificationShelfController,
mStackScrollerController,
- mNotificationPresenter,
- mNotificationActivityStarter,
+ (Lazy<NotificationPresenter>) () -> mNotificationPresenter,
+ (Lazy<NotificationActivityStarter>) () -> mNotificationActivityStarter,
mNotifLaunchAnimControllerProvider,
new NotificationExpansionRepository(),
mDozeParameters,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewControllerTest.kt
index 4c3c3f9d8da5..4349d738b0f3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewControllerTest.kt
@@ -31,6 +31,7 @@ import com.android.systemui.R
import com.android.systemui.SysuiTestCase
import com.android.systemui.flags.FeatureFlags
import com.android.systemui.flags.Flags
+import com.android.systemui.scene.shared.flag.FakeSceneContainerFlags
import com.android.systemui.scene.ui.view.WindowRootView
import com.android.systemui.shade.ShadeControllerImpl
import com.android.systemui.shade.ShadeLogger
@@ -47,6 +48,8 @@ import com.android.systemui.util.mockito.argumentCaptor
import com.android.systemui.util.mockito.whenever
import com.android.systemui.util.view.ViewUtil
import com.google.common.truth.Truth.assertThat
+import java.util.Optional
+import javax.inject.Provider
import org.junit.Before
import org.junit.Test
import org.mockito.ArgumentCaptor
@@ -57,40 +60,24 @@ import org.mockito.Mockito.spy
import org.mockito.Mockito.verify
import org.mockito.Mockito.`when`
import org.mockito.MockitoAnnotations
-import java.util.Optional
-import javax.inject.Provider
@SmallTest
class PhoneStatusBarViewControllerTest : SysuiTestCase() {
- @Mock
- private lateinit var shadeViewController: ShadeViewController
- @Mock
- private lateinit var featureFlags: FeatureFlags
- @Mock
- private lateinit var moveFromCenterAnimation: StatusBarMoveFromCenterAnimationController
- @Mock
- private lateinit var sysuiUnfoldComponent: SysUIUnfoldComponent
- @Mock
- private lateinit var progressProvider: ScopedUnfoldTransitionProgressProvider
- @Mock
- private lateinit var configurationController: ConfigurationController
- @Mock
- private lateinit var mStatusOverlayHoverListenerFactory: StatusOverlayHoverListenerFactory
- @Mock
- private lateinit var userChipViewModel: StatusBarUserChipViewModel
- @Mock
- private lateinit var centralSurfacesImpl: CentralSurfacesImpl
- @Mock
- private lateinit var commandQueue: CommandQueue
- @Mock
- private lateinit var shadeControllerImpl: ShadeControllerImpl
- @Mock
- private lateinit var windowRootView: Provider<WindowRootView>
- @Mock
- private lateinit var shadeLogger: ShadeLogger
- @Mock
- private lateinit var viewUtil: ViewUtil
+ @Mock private lateinit var shadeViewController: ShadeViewController
+ @Mock private lateinit var featureFlags: FeatureFlags
+ @Mock private lateinit var moveFromCenterAnimation: StatusBarMoveFromCenterAnimationController
+ @Mock private lateinit var sysuiUnfoldComponent: SysUIUnfoldComponent
+ @Mock private lateinit var progressProvider: ScopedUnfoldTransitionProgressProvider
+ @Mock private lateinit var configurationController: ConfigurationController
+ @Mock private lateinit var mStatusOverlayHoverListenerFactory: StatusOverlayHoverListenerFactory
+ @Mock private lateinit var userChipViewModel: StatusBarUserChipViewModel
+ @Mock private lateinit var centralSurfacesImpl: CentralSurfacesImpl
+ @Mock private lateinit var commandQueue: CommandQueue
+ @Mock private lateinit var shadeControllerImpl: ShadeControllerImpl
+ @Mock private lateinit var windowRootView: Provider<WindowRootView>
+ @Mock private lateinit var shadeLogger: ShadeLogger
+ @Mock private lateinit var viewUtil: ViewUtil
private lateinit var statusBarWindowStateController: StatusBarWindowStateController
private lateinit var view: PhoneStatusBarView
@@ -109,16 +96,16 @@ class PhoneStatusBarViewControllerTest : SysuiTestCase() {
// create the view and controller on main thread as it requires main looper
InstrumentationRegistry.getInstrumentation().runOnMainSync {
val parent = FrameLayout(mContext) // add parent to keep layout params
- view = LayoutInflater.from(mContext)
- .inflate(R.layout.status_bar, parent, false) as PhoneStatusBarView
+ view =
+ LayoutInflater.from(mContext).inflate(R.layout.status_bar, parent, false)
+ as PhoneStatusBarView
controller = createAndInitController(view)
}
}
@Test
fun onViewAttachedAndDrawn_moveFromCenterAnimationEnabled_moveFromCenterAnimationInitialized() {
- whenever(featureFlags.isEnabled(Flags.ENABLE_UNFOLD_STATUS_BAR_ANIMATIONS))
- .thenReturn(true)
+ whenever(featureFlags.isEnabled(Flags.ENABLE_UNFOLD_STATUS_BAR_ANIMATIONS)).thenReturn(true)
val view = createViewMock()
val argumentCaptor = ArgumentCaptor.forClass(OnPreDrawListener::class.java)
unfoldConfig.isEnabled = true
@@ -136,7 +123,7 @@ class PhoneStatusBarViewControllerTest : SysuiTestCase() {
@Test
fun onViewAttachedAndDrawn_statusBarAnimationDisabled_animationNotInitialized() {
whenever(featureFlags.isEnabled(Flags.ENABLE_UNFOLD_STATUS_BAR_ANIMATIONS))
- .thenReturn(false)
+ .thenReturn(false)
val view = createViewMock()
unfoldConfig.isEnabled = true
// create the controller on main thread as it requires main looper
@@ -150,8 +137,8 @@ class PhoneStatusBarViewControllerTest : SysuiTestCase() {
@Test
fun handleTouchEventFromStatusBar_panelsNotEnabled_returnsFalseAndNoViewEvent() {
`when`(centralSurfacesImpl.commandQueuePanelsEnabled).thenReturn(false)
- val returnVal = view.onTouchEvent(
- MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, 0f, 0))
+ val returnVal =
+ view.onTouchEvent(MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, 0f, 0))
assertThat(returnVal).isFalse()
verify(shadeViewController, never()).handleExternalTouch(any())
}
@@ -160,8 +147,8 @@ class PhoneStatusBarViewControllerTest : SysuiTestCase() {
fun handleTouchEventFromStatusBar_viewNotEnabled_returnsTrueAndNoViewEvent() {
`when`(centralSurfacesImpl.commandQueuePanelsEnabled).thenReturn(true)
`when`(shadeViewController.isViewEnabled).thenReturn(false)
- val returnVal = view.onTouchEvent(
- MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, 0f, 0))
+ val returnVal =
+ view.onTouchEvent(MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, 0f, 0))
assertThat(returnVal).isTrue()
verify(shadeViewController, never()).handleExternalTouch(any())
}
@@ -245,22 +232,23 @@ class PhoneStatusBarViewControllerTest : SysuiTestCase() {
private fun createAndInitController(view: PhoneStatusBarView): PhoneStatusBarViewController {
return PhoneStatusBarViewController.Factory(
- Optional.of(sysuiUnfoldComponent),
- Optional.of(progressProvider),
- featureFlags,
- userChipViewModel,
- centralSurfacesImpl,
- statusBarWindowStateController,
- shadeControllerImpl,
- shadeViewController,
- windowRootView,
- shadeLogger,
- viewUtil,
- configurationController,
- mStatusOverlayHoverListenerFactory
- ).create(view).also {
- it.init()
- }
+ Optional.of(sysuiUnfoldComponent),
+ Optional.of(progressProvider),
+ featureFlags,
+ FakeSceneContainerFlags(),
+ userChipViewModel,
+ centralSurfacesImpl,
+ statusBarWindowStateController,
+ shadeControllerImpl,
+ shadeViewController,
+ windowRootView,
+ shadeLogger,
+ viewUtil,
+ configurationController,
+ mStatusOverlayHoverListenerFactory
+ )
+ .create(view)
+ .also { it.init() }
}
private class UnfoldConfig : UnfoldTransitionConfig {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogImplTest.java
index 525624547528..65cac6efad1c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogImplTest.java
@@ -84,7 +84,7 @@ import java.util.function.Predicate;
@SmallTest
@RunWith(AndroidTestingRunner.class)
-@TestableLooper.RunWithLooper
+@TestableLooper.RunWithLooper(setAsMainLooper = true)
public class VolumeDialogImplTest extends SysuiTestCase {
VolumeDialogImpl mDialog;
View mActiveRinger;
@@ -141,6 +141,7 @@ public class VolumeDialogImplTest extends SysuiTestCase {
getContext().addMockSystemService(KeyguardManager.class, mKeyguard);
mTestableLooper = TestableLooper.get(this);
+ allowTestableLooperAsMainThread();
when(mPostureController.getDevicePosture())
.thenReturn(DevicePostureController.DEVICE_POSTURE_CLOSED);
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/SysuiTestCase.java b/packages/SystemUI/tests/utils/src/com/android/systemui/SysuiTestCase.java
index 28b7d4171df1..aa88a46d670c 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/SysuiTestCase.java
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/SysuiTestCase.java
@@ -166,7 +166,9 @@ public abstract class SysuiTestCase {
}
disallowTestableLooperAsMainThread();
mContext.cleanUpReceivers(this.getClass().getSimpleName());
- mFakeBroadcastDispatcher.cleanUpReceivers(this.getClass().getSimpleName());
+ if (mFakeBroadcastDispatcher != null) {
+ mFakeBroadcastDispatcher.cleanUpReceivers(this.getClass().getSimpleName());
+ }
}
@AfterClass
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorFactory.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorFactory.kt
index 11ea513c53e7..2e3bb2b545d8 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorFactory.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorFactory.kt
@@ -24,6 +24,8 @@ import com.android.systemui.flags.Flags
import com.android.systemui.keyguard.data.repository.FakeCommandQueue
import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
import com.android.systemui.scene.domain.interactor.SceneInteractor
+import com.android.systemui.scene.shared.flag.FakeSceneContainerFlags
+import com.android.systemui.scene.shared.flag.SceneContainerFlags
import com.android.systemui.shade.data.repository.FakeShadeRepository
import com.android.systemui.util.mockito.mock
@@ -37,6 +39,7 @@ object KeyguardInteractorFactory {
@JvmStatic
fun create(
featureFlags: FakeFeatureFlags = createFakeFeatureFlags(),
+ sceneContainerFlags: SceneContainerFlags = FakeSceneContainerFlags(),
repository: FakeKeyguardRepository = FakeKeyguardRepository(),
commandQueue: FakeCommandQueue = FakeCommandQueue(),
bouncerRepository: FakeKeyguardBouncerRepository = FakeKeyguardBouncerRepository(),
@@ -48,6 +51,7 @@ object KeyguardInteractorFactory {
repository = repository,
commandQueue = commandQueue,
featureFlags = featureFlags,
+ sceneContainerFlags = sceneContainerFlags,
bouncerRepository = bouncerRepository,
configurationRepository = configurationRepository,
shadeRepository = shadeRepository,
@@ -55,6 +59,7 @@ object KeyguardInteractorFactory {
repository = repository,
commandQueue = commandQueue,
featureFlags = featureFlags,
+ sceneContainerFlags = sceneContainerFlags,
bouncerRepository = bouncerRepository,
configurationRepository = configurationRepository,
shadeRepository = shadeRepository,
@@ -72,6 +77,7 @@ object KeyguardInteractorFactory {
val repository: FakeKeyguardRepository,
val commandQueue: FakeCommandQueue,
val featureFlags: FakeFeatureFlags,
+ val sceneContainerFlags: SceneContainerFlags,
val bouncerRepository: FakeKeyguardBouncerRepository,
val configurationRepository: FakeConfigurationRepository,
val shadeRepository: FakeShadeRepository,
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneTestUtils.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneTestUtils.kt
index 282d79833baa..9dea0a0c26d5 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneTestUtils.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneTestUtils.kt
@@ -31,7 +31,7 @@ import com.android.systemui.classifier.FalsingCollector
import com.android.systemui.classifier.FalsingCollectorFake
import com.android.systemui.classifier.domain.interactor.FalsingInteractor
import com.android.systemui.common.ui.data.repository.FakeConfigurationRepository
-import com.android.systemui.flags.FakeFeatureFlags
+import com.android.systemui.flags.FakeFeatureFlagsClassic
import com.android.systemui.flags.Flags
import com.android.systemui.keyguard.data.repository.FakeCommandQueue
import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
@@ -43,6 +43,7 @@ import com.android.systemui.keyguard.shared.model.WakefulnessState
import com.android.systemui.power.data.repository.FakePowerRepository
import com.android.systemui.scene.data.repository.SceneContainerRepository
import com.android.systemui.scene.domain.interactor.SceneInteractor
+import com.android.systemui.scene.shared.flag.FakeSceneContainerFlags
import com.android.systemui.scene.shared.model.SceneContainerConfig
import com.android.systemui.scene.shared.model.SceneKey
import com.android.systemui.shade.data.repository.FakeShadeRepository
@@ -67,11 +68,8 @@ class SceneTestUtils(
) {
val testDispatcher = StandardTestDispatcher()
val testScope = TestScope(testDispatcher)
- val featureFlags =
- FakeFeatureFlags().apply {
- set(Flags.SCENE_CONTAINER, true)
- set(Flags.FACE_AUTH_REFACTOR, false)
- }
+ val featureFlags = FakeFeatureFlagsClassic().apply { set(Flags.FACE_AUTH_REFACTOR, false) }
+ val sceneContainerFlags = FakeSceneContainerFlags().apply { enabled = true }
private val userRepository: UserRepository by lazy {
FakeUserRepository().apply {
val users = listOf(UserInfo(/* id= */ 0, "name", /* flags= */ 0))
@@ -164,6 +162,7 @@ class SceneTestUtils(
repository = repository,
commandQueue = FakeCommandQueue(),
featureFlags = featureFlags,
+ sceneContainerFlags = sceneContainerFlags,
bouncerRepository = FakeKeyguardBouncerRepository(),
configurationRepository = FakeConfigurationRepository(),
shadeRepository = FakeShadeRepository(),
@@ -181,7 +180,7 @@ class SceneTestUtils(
repository = BouncerRepository(),
authenticationInteractor = authenticationInteractor,
sceneInteractor = sceneInteractor,
- featureFlags = featureFlags,
+ flags = sceneContainerFlags,
falsingInteractor = falsingInteractor(),
)
}
@@ -195,7 +194,7 @@ class SceneTestUtils(
applicationScope = applicationScope(),
bouncerInteractor = bouncerInteractor,
authenticationInteractor = authenticationInteractor,
- featureFlags = featureFlags,
+ flags = sceneContainerFlags,
)
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/shared/flag/FakeSceneContainerFlags.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/shared/flag/FakeSceneContainerFlags.kt
new file mode 100644
index 000000000000..01a1ecea9997
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/shared/flag/FakeSceneContainerFlags.kt
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2023 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.systemui.scene.shared.flag
+
+class FakeSceneContainerFlags(
+ var enabled: Boolean = false,
+) : SceneContainerFlags {
+
+ override fun isEnabled(): Boolean {
+ return enabled
+ }
+
+ override fun requirementDescription(): String {
+ return ""
+ }
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/shade/data/repository/FakeShadeRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/data/repository/FakeShadeRepository.kt
index ccddca2d6611..08152a3c49cd 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/shade/data/repository/FakeShadeRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/data/repository/FakeShadeRepository.kt
@@ -33,8 +33,12 @@ class FakeShadeRepository : ShadeRepository {
private val _udfpsTransitionToFullShadeProgress = MutableStateFlow(0f)
override val udfpsTransitionToFullShadeProgress = _udfpsTransitionToFullShadeProgress
- private val _shadeExpansion = MutableStateFlow(0f)
- override val shadeExpansion = _shadeExpansion
+ private val _lockscreenShadeExpansion = MutableStateFlow(0f)
+ override val lockscreenShadeExpansion = _lockscreenShadeExpansion
+
+ private val _legacyShadeExpansion = MutableStateFlow(0f)
+ @Deprecated("Use ShadeInteractor instead")
+ override val legacyShadeExpansion = _legacyShadeExpansion
fun setShadeModel(model: ShadeModel) {
_shadeModel.value = model
@@ -48,7 +52,12 @@ class FakeShadeRepository : ShadeRepository {
_udfpsTransitionToFullShadeProgress.value = progress
}
- override fun setShadeExpansion(expansion: Float) {
- _shadeExpansion.value = expansion
+ override fun setLockscreenShadeExpansion(lockscreenShadeExpansion: Float) {
+ _lockscreenShadeExpansion.value = lockscreenShadeExpansion
+ }
+
+ @Deprecated("Should only be called by NPVC and tests")
+ override fun setLegacyShadeExpansion(expandedFraction: Float) {
+ _legacyShadeExpansion.value = expandedFraction
}
}
diff --git a/services/autofill/Android.bp b/services/autofill/Android.bp
index eb23f2f9b435..d43a219e6205 100644
--- a/services/autofill/Android.bp
+++ b/services/autofill/Android.bp
@@ -19,4 +19,19 @@ java_library_static {
defaults: ["platform_service_defaults"],
srcs: [":services.autofill-sources"],
libs: ["services.core"],
+ static_libs: ["autofill_flags_java_lib"],
+}
+
+aconfig_declarations {
+ name: "autofill_flags",
+ package: "android.service.autofill",
+ srcs: [
+ "bugfixes.aconfig",
+ "features.aconfig",
+ ],
+}
+
+java_aconfig_library {
+ name: "autofill_flags_java_lib",
+ aconfig_declarations: "autofill_flags",
}
diff --git a/services/autofill/bugfixes.aconfig b/services/autofill/bugfixes.aconfig
new file mode 100644
index 000000000000..ef237546378e
--- /dev/null
+++ b/services/autofill/bugfixes.aconfig
@@ -0,0 +1,8 @@
+package: "android.service.autofill"
+
+flag {
+ name: "test"
+ namespace: "autofill"
+ description: "Test flag "
+ bug: "297380045"
+} \ No newline at end of file
diff --git a/services/autofill/features.aconfig b/services/autofill/features.aconfig
new file mode 100644
index 000000000000..1e44de61bdd7
--- /dev/null
+++ b/services/autofill/features.aconfig
@@ -0,0 +1 @@
+package: "android.service.autofill" \ No newline at end of file
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceShellCommand.java b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceShellCommand.java
index c66fb81f51c6..39756dfee7bf 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceShellCommand.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceShellCommand.java
@@ -26,11 +26,14 @@ import android.os.RemoteCallback;
import android.os.ShellCommand;
import android.os.UserHandle;
import android.service.autofill.AutofillFieldClassificationService.Scores;
+import android.service.autofill.Flags;
import android.view.autofill.AutofillManager;
import com.android.internal.os.IResultReceiver;
import java.io.PrintWriter;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
@@ -60,6 +63,8 @@ public final class AutofillManagerServiceShellCommand extends ShellCommand {
return requestGet(pw);
case "set":
return requestSet(pw);
+ case "flags":
+ return requestFlags(pw);
default:
return handleDefaultCommands(cmd);
}
@@ -67,7 +72,7 @@ public final class AutofillManagerServiceShellCommand extends ShellCommand {
@Override
public void onHelp() {
- try (final PrintWriter pw = getOutPrintWriter();) {
+ try (final PrintWriter pw = getOutPrintWriter(); ) {
pw.println("AutoFill Service (autofill) commands:");
pw.println(" help");
pw.println(" Prints this help text.");
@@ -109,21 +114,24 @@ public final class AutofillManagerServiceShellCommand extends ShellCommand {
pw.println(" Sets whether binding to services provided by instant apps is allowed");
pw.println("");
pw.println(" set temporary-augmented-service USER_ID [COMPONENT_NAME DURATION]");
- pw.println(" Temporarily (for DURATION ms) changes the augmented autofill service "
- + "implementation.");
+ pw.println(
+ " Temporarily (for DURATION ms) changes the augmented autofill service "
+ + "implementation.");
pw.println(" To reset, call with just the USER_ID argument.");
pw.println("");
pw.println(" set default-augmented-service-enabled USER_ID [true|false]");
pw.println(" Enable / disable the default augmented autofill service for the user.");
pw.println("");
pw.println(" set temporary-detection-service USER_ID [COMPONENT_NAME DURATION]");
- pw.println(" Temporarily (for DURATION ms) changes the autofill detection service "
- + "implementation.");
+ pw.println(
+ " Temporarily (for DURATION ms) changes the autofill detection service "
+ + "implementation.");
pw.println(" To reset, call with [COMPONENT_NAME 0].");
pw.println("");
pw.println(" get default-augmented-service-enabled USER_ID");
- pw.println(" Checks whether the default augmented autofill service is enabled for "
- + "the user.");
+ pw.println(
+ " Checks whether the default augmented autofill service is enabled for "
+ + "the user.");
pw.println("");
pw.println(" list sessions [--user USER_ID]");
pw.println(" Lists all pending sessions.");
@@ -134,7 +142,34 @@ public final class AutofillManagerServiceShellCommand extends ShellCommand {
pw.println(" reset");
pw.println(" Resets all pending sessions and cached service connections.");
pw.println("");
+ pw.println(" flags");
+ pw.println(" Prints out all autofill related flags.");
+ pw.println("");
+ }
+ }
+
+ private int requestFlags(PrintWriter pw) {
+
+ if (Flags.test()) {
+ pw.println("Hello Flag World!");
+ pw.println("");
+ }
+
+ try {
+ Method[] flagMethods = Flags.class.getMethods();
+ // For some reason, unreferenced flags do not show up here
+ // Maybe compiler optomized them out of bytecode?
+ for (Method method : flagMethods) {
+ if (Modifier.isPublic(method.getModifiers())) {
+ pw.println(method.getName() + ": " + method.invoke(null));
+ }
+ }
+ } catch (Exception ex) {
+ pw.println(ex);
+ return -1;
}
+
+ return 0;
}
private int requestGet(PrintWriter pw) {
diff --git a/services/companion/java/com/android/server/companion/virtual/GenericWindowPolicyController.java b/services/companion/java/com/android/server/companion/virtual/GenericWindowPolicyController.java
index 9e7b897119a1..b07a0bb57678 100644
--- a/services/companion/java/com/android/server/companion/virtual/GenericWindowPolicyController.java
+++ b/services/companion/java/com/android/server/companion/virtual/GenericWindowPolicyController.java
@@ -27,8 +27,6 @@ import android.annotation.UserIdInt;
import android.app.WindowConfiguration;
import android.app.compat.CompatChanges;
import android.companion.virtual.VirtualDeviceManager.ActivityListener;
-import android.companion.virtual.VirtualDeviceParams;
-import android.companion.virtual.VirtualDeviceParams.ActivityPolicy;
import android.compat.annotation.ChangeId;
import android.compat.annotation.EnabledSince;
import android.content.ComponentName;
@@ -108,18 +106,14 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController
public static final long ALLOW_SECURE_ACTIVITY_DISPLAY_ON_REMOTE_DEVICE = 201712607L;
@NonNull
private final ArraySet<UserHandle> mAllowedUsers;
- @Nullable
- private final ArraySet<ComponentName> mAllowedCrossTaskNavigations;
- @Nullable
- private final ArraySet<ComponentName> mBlockedCrossTaskNavigations;
- @Nullable
- private final ArraySet<ComponentName> mAllowedActivities;
- @Nullable
- private final ArraySet<ComponentName> mBlockedActivities;
+ private final boolean mActivityLaunchAllowedByDefault;
+ @NonNull
+ private final ArraySet<ComponentName> mActivityPolicyExceptions;
+ private final boolean mCrossTaskNavigationAllowedByDefault;
+ @NonNull
+ private final ArraySet<ComponentName> mCrossTaskNavigationExceptions;
private final Object mGenericWindowPolicyControllerLock = new Object();
- @ActivityPolicy
- private final int mDefaultActivityPolicy;
- private final ActivityBlockedCallback mActivityBlockedCallback;
+ @Nullable private final ActivityBlockedCallback mActivityBlockedCallback;
private int mDisplayId = Display.INVALID_DISPLAY;
@NonNull
@@ -134,7 +128,7 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController
private final ArraySet<RunningAppsChangedListener> mRunningAppsChangedListeners =
new ArraySet<>();
@Nullable private final SecureWindowCallback mSecureWindowCallback;
- @Nullable private final Set<String> mDisplayCategories;
+ @NonNull private final Set<String> mDisplayCategories;
@GuardedBy("mGenericWindowPolicyControllerLock")
private boolean mShowTasksInHostDeviceRecents;
@@ -146,18 +140,14 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController
* @param windowFlags The window flags that this controller is interested in.
* @param systemWindowFlags The system window flags that this controller is interested in.
* @param allowedUsers The set of users that are allowed to stream in this display.
- * @param allowedCrossTaskNavigations The set of components explicitly allowed to navigate
- * across tasks on this device.
- * @param blockedCrossTaskNavigations The set of components explicitly blocked from
- * navigating across tasks on this device.
- * @param allowedActivities The set of activities explicitly allowed to stream on this device.
- * Used only if the {@code activityPolicy} is
- * {@link VirtualDeviceParams#ACTIVITY_POLICY_DEFAULT_BLOCKED}.
- * @param blockedActivities The set of activities explicitly blocked from streaming on this
- * device. Used only if the {@code activityPolicy} is
- * {@link VirtualDeviceParams#ACTIVITY_POLICY_DEFAULT_ALLOWED}
- * @param defaultActivityPolicy Whether activities are default allowed to be displayed or
- * blocked.
+ * @param activityLaunchAllowedByDefault Whether activities are default allowed to be launched
+ * or blocked.
+ * @param activityPolicyExceptions The set of activities explicitly exempt from the default
+ * activity policy.
+ * @param crossTaskNavigationAllowedByDefault Whether cross task navigations are allowed by
+ * default or not.
+ * @param crossTaskNavigationExceptions The set of components explicitly exempt from the default
+ * navigation policy.
* @param activityListener Activity listener to listen for activity changes.
* @param activityBlockedCallback Callback that is called when an activity is blocked from
* launching.
@@ -169,25 +159,23 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController
*/
public GenericWindowPolicyController(int windowFlags, int systemWindowFlags,
@NonNull ArraySet<UserHandle> allowedUsers,
- @NonNull Set<ComponentName> allowedCrossTaskNavigations,
- @NonNull Set<ComponentName> blockedCrossTaskNavigations,
- @NonNull Set<ComponentName> allowedActivities,
- @NonNull Set<ComponentName> blockedActivities,
- @ActivityPolicy int defaultActivityPolicy,
- @NonNull ActivityListener activityListener,
- @NonNull PipBlockedCallback pipBlockedCallback,
- @NonNull ActivityBlockedCallback activityBlockedCallback,
- @NonNull SecureWindowCallback secureWindowCallback,
- @NonNull IntentListenerCallback intentListenerCallback,
+ boolean activityLaunchAllowedByDefault,
+ @NonNull Set<ComponentName> activityPolicyExceptions,
+ boolean crossTaskNavigationAllowedByDefault,
+ @NonNull Set<ComponentName> crossTaskNavigationExceptions,
+ @Nullable ActivityListener activityListener,
+ @Nullable PipBlockedCallback pipBlockedCallback,
+ @Nullable ActivityBlockedCallback activityBlockedCallback,
+ @Nullable SecureWindowCallback secureWindowCallback,
+ @Nullable IntentListenerCallback intentListenerCallback,
@NonNull Set<String> displayCategories,
boolean showTasksInHostDeviceRecents) {
super();
mAllowedUsers = allowedUsers;
- mAllowedCrossTaskNavigations = new ArraySet<>(allowedCrossTaskNavigations);
- mBlockedCrossTaskNavigations = new ArraySet<>(blockedCrossTaskNavigations);
- mAllowedActivities = new ArraySet<>(allowedActivities);
- mBlockedActivities = new ArraySet<>(blockedActivities);
- mDefaultActivityPolicy = defaultActivityPolicy;
+ mActivityLaunchAllowedByDefault = activityLaunchAllowedByDefault;
+ mActivityPolicyExceptions = new ArraySet<>(activityPolicyExceptions);
+ mCrossTaskNavigationAllowedByDefault = crossTaskNavigationAllowedByDefault;
+ mCrossTaskNavigationExceptions = new ArraySet<>(crossTaskNavigationExceptions);
mActivityBlockedCallback = activityBlockedCallback;
setInterestedWindowFlags(windowFlags, systemWindowFlags);
mActivityListener = activityListener;
@@ -233,7 +221,9 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController
@Nullable Intent intent, @WindowConfiguration.WindowingMode int windowingMode,
int launchingFromDisplayId, boolean isNewTask) {
if (!canContainActivity(activityInfo, windowingMode, launchingFromDisplayId, isNewTask)) {
- mActivityBlockedCallback.onActivityBlocked(mDisplayId, activityInfo);
+ if (mActivityBlockedCallback != null) {
+ mActivityBlockedCallback.onActivityBlocked(mDisplayId, activityInfo);
+ }
return false;
}
if (mIntentListenerCallback != null && intent != null
@@ -275,22 +265,17 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController
+ mDisplayCategories);
return false;
}
- if ((mDefaultActivityPolicy == VirtualDeviceParams.ACTIVITY_POLICY_DEFAULT_ALLOWED
- && mBlockedActivities.contains(activityComponent))
- || (mDefaultActivityPolicy == VirtualDeviceParams.ACTIVITY_POLICY_DEFAULT_BLOCKED
- && !mAllowedActivities.contains(activityComponent))) {
+ if (!isAllowedByPolicy(mActivityLaunchAllowedByDefault, mActivityPolicyExceptions,
+ activityComponent)) {
Slog.d(TAG, "Virtual device launch disallowed by policy: " + activityComponent);
return false;
}
- if (isNewTask && launchingFromDisplayId != DEFAULT_DISPLAY) {
- if ((!mBlockedCrossTaskNavigations.isEmpty()
- && mBlockedCrossTaskNavigations.contains(activityComponent))
- || ((!mAllowedCrossTaskNavigations.isEmpty()
- && !mAllowedCrossTaskNavigations.contains(activityComponent)))) {
- Slog.d(TAG, "Virtual device cross task navigation disallowed by policy: "
- + activityComponent);
- return false;
- }
+ if (isNewTask && launchingFromDisplayId != DEFAULT_DISPLAY
+ && !isAllowedByPolicy(mCrossTaskNavigationAllowedByDefault,
+ mCrossTaskNavigationExceptions, activityComponent)) {
+ Slog.d(TAG, "Virtual device cross task navigation disallowed by policy: "
+ + activityComponent);
+ return false;
}
return true;
@@ -302,7 +287,7 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController
int systemWindowFlags) {
// The callback is fired only when windowFlags are changed. To let VirtualDevice owner
// aware that the virtual display has a secure window on top.
- if ((windowFlags & FLAG_SECURE) != 0) {
+ if ((windowFlags & FLAG_SECURE) != 0 && mSecureWindowCallback != null) {
// Post callback on the main thread, so it doesn't block activity launching.
mHandler.post(() -> mSecureWindowCallback.onSecureWindowShown(mDisplayId,
activityInfo.applicationInfo.uid));
@@ -314,7 +299,9 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController
// TODO(b/201712607): Add checks for the apps that use SurfaceView#setSecure.
if ((windowFlags & FLAG_SECURE) != 0
|| (systemWindowFlags & SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS) != 0) {
- mActivityBlockedCallback.onActivityBlocked(mDisplayId, activityInfo);
+ if (mActivityBlockedCallback != null) {
+ mActivityBlockedCallback.onActivityBlocked(mDisplayId, activityInfo);
+ }
return false;
}
}
@@ -367,9 +354,9 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController
if (super.isEnteringPipAllowed(uid)) {
return true;
}
- mHandler.post(() -> {
- mPipBlockedCallback.onEnteringPipBlocked(uid);
- });
+ if (mPipBlockedCallback != null) {
+ mHandler.post(() -> mPipBlockedCallback.onEnteringPipBlocked(uid));
+ }
return false;
}
@@ -389,7 +376,13 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController
}
return activityInfo.requiredDisplayCategory != null
&& mDisplayCategories.contains(activityInfo.requiredDisplayCategory);
+ }
+ private boolean isAllowedByPolicy(boolean allowedByDefault, ArraySet<ComponentName> exceptions,
+ ComponentName component) {
+ // Either allowed and the exceptions do not contain the component,
+ // or disallowed and the exceptions contain the component.
+ return allowedByDefault != exceptions.contains(component);
}
@VisibleForTesting
diff --git a/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java b/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java
index 5eefd12941ec..8f765e4b79d6 100644
--- a/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java
+++ b/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java
@@ -19,7 +19,9 @@ package com.android.server.companion.virtual;
import static android.app.admin.DevicePolicyManager.NEARBY_STREAMING_ENABLED;
import static android.app.admin.DevicePolicyManager.NEARBY_STREAMING_NOT_CONTROLLED_BY_POLICY;
import static android.app.admin.DevicePolicyManager.NEARBY_STREAMING_SAME_MANAGED_ACCOUNT_ONLY;
+import static android.companion.virtual.VirtualDeviceParams.ACTIVITY_POLICY_DEFAULT_ALLOWED;
import static android.companion.virtual.VirtualDeviceParams.DEVICE_POLICY_DEFAULT;
+import static android.companion.virtual.VirtualDeviceParams.NAVIGATION_POLICY_DEFAULT_ALLOWED;
import static android.companion.virtual.VirtualDeviceParams.POLICY_TYPE_RECENTS;
import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
@@ -840,22 +842,31 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
private GenericWindowPolicyController createWindowPolicyController(
@NonNull Set<String> displayCategories) {
- final GenericWindowPolicyController gwpc =
- new GenericWindowPolicyController(FLAG_SECURE,
- SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS,
- getAllowedUserHandles(),
- mParams.getAllowedCrossTaskNavigations(),
- mParams.getBlockedCrossTaskNavigations(),
- mParams.getAllowedActivities(),
- mParams.getBlockedActivities(),
- mParams.getDefaultActivityPolicy(),
- createListenerAdapter(),
- this::onEnteringPipBlocked,
- this::onActivityBlocked,
- this::onSecureWindowShown,
- this::shouldInterceptIntent,
- displayCategories,
- mParams.getDevicePolicy(POLICY_TYPE_RECENTS) == DEVICE_POLICY_DEFAULT);
+ final boolean activityLaunchAllowedByDefault =
+ mParams.getDefaultActivityPolicy() == ACTIVITY_POLICY_DEFAULT_ALLOWED;
+ final boolean crossTaskNavigationAllowedByDefault =
+ mParams.getDefaultNavigationPolicy() == NAVIGATION_POLICY_DEFAULT_ALLOWED;
+ final boolean showTasksInHostDeviceRecents =
+ mParams.getDevicePolicy(POLICY_TYPE_RECENTS) == DEVICE_POLICY_DEFAULT;
+
+ final GenericWindowPolicyController gwpc = new GenericWindowPolicyController(
+ FLAG_SECURE,
+ SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS,
+ getAllowedUserHandles(),
+ activityLaunchAllowedByDefault,
+ /*activityPolicyExceptions=*/activityLaunchAllowedByDefault
+ ? mParams.getBlockedActivities() : mParams.getAllowedActivities(),
+ crossTaskNavigationAllowedByDefault,
+ /*crossTaskNavigationExceptions=*/crossTaskNavigationAllowedByDefault
+ ? mParams.getBlockedCrossTaskNavigations()
+ : mParams.getAllowedCrossTaskNavigations(),
+ createListenerAdapter(),
+ this::onEnteringPipBlocked,
+ this::onActivityBlocked,
+ this::onSecureWindowShown,
+ this::shouldInterceptIntent,
+ displayCategories,
+ showTasksInHostDeviceRecents);
gwpc.registerRunningAppsChangedListener(/* listener= */ this);
return gwpc;
}
diff --git a/services/core/java/com/android/server/display/BrightnessMappingStrategy.java b/services/core/java/com/android/server/display/BrightnessMappingStrategy.java
index df2a8301f543..99a5398aa7ee 100644
--- a/services/core/java/com/android/server/display/BrightnessMappingStrategy.java
+++ b/services/core/java/com/android/server/display/BrightnessMappingStrategy.java
@@ -25,6 +25,7 @@ import android.content.res.TypedArray;
import android.hardware.display.BrightnessConfiguration;
import android.hardware.display.BrightnessCorrection;
import android.os.PowerManager;
+import android.util.LongArray;
import android.util.MathUtils;
import android.util.Pair;
import android.util.Slog;
@@ -37,7 +38,11 @@ import com.android.server.display.utils.Plog;
import com.android.server.display.whitebalance.DisplayWhiteBalanceController;
import java.io.PrintWriter;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Date;
+import java.util.List;
import java.util.Locale;
import java.util.Objects;
@@ -840,6 +845,13 @@ public abstract class BrightnessMappingStrategy {
private final boolean mIsForIdleMode;
private final DisplayWhiteBalanceController mDisplayWhiteBalanceController;
+ // Previous short-term models and the times that they were computed stored for debugging
+ // purposes
+ private List<Spline> mPreviousBrightnessSplines = new ArrayList<>();
+ private LongArray mBrightnessSplineChangeTimes = new LongArray();
+ private static final int NO_OF_PREVIOUS_CONFIGS_TO_LOG = 5;
+ private static final SimpleDateFormat FORMAT = new SimpleDateFormat("MM-dd HH:mm:ss.SSS");
+
public PhysicalMappingStrategy(BrightnessConfiguration config, float[] nits,
float[] brightness, float maxGamma, boolean isForIdleMode,
DisplayWhiteBalanceController displayWhiteBalanceController) {
@@ -982,6 +994,13 @@ public abstract class BrightnessMappingStrategy {
mUserLux = lux;
mUserBrightness = brightness;
computeSpline();
+
+ if (mPreviousBrightnessSplines.size() == NO_OF_PREVIOUS_CONFIGS_TO_LOG) {
+ mPreviousBrightnessSplines.remove(0);
+ mBrightnessSplineChangeTimes.remove(0);
+ }
+ mPreviousBrightnessSplines.add(mBrightnessSpline);
+ mBrightnessSplineChangeTimes.add(System.currentTimeMillis());
}
@Override
@@ -1042,7 +1061,16 @@ public abstract class BrightnessMappingStrategy {
pw.println(" mDefaultConfig=" + mDefaultConfig);
pw.println(" mBrightnessRangeAdjustmentApplied=" + mBrightnessRangeAdjustmentApplied);
- dumpConfigDiff(pw, hbmTransition);
+ pw.println(" Previous short-term models (oldest to newest): ");
+ for (int i = 0; i < mPreviousBrightnessSplines.size(); i++) {
+ pw.println(" Computed at "
+ + FORMAT.format(new Date(mBrightnessSplineChangeTimes.get(i))) + ": ");
+ dumpConfigDiff(pw, hbmTransition, mPreviousBrightnessSplines.get(i),
+ /* shortTermModelOnly= */ true);
+ }
+
+ pw.println(" Difference between current config and default: ");
+ dumpConfigDiff(pw, hbmTransition, mBrightnessSpline, /* shortTermModelOnly= */ false);
}
@Override
@@ -1066,9 +1094,8 @@ public abstract class BrightnessMappingStrategy {
*
* @param pw The print-writer to write to.
*/
- private void dumpConfigDiff(PrintWriter pw, float hbmTransition) {
- pw.println(" Difference between current config and default: ");
-
+ private void dumpConfigDiff(PrintWriter pw, float hbmTransition, Spline brightnessSpline,
+ boolean shortTermModelOnly) {
Pair<float[], float[]> currentCurve = mConfig.getCurve();
Spline currSpline = Spline.createSpline(currentCurve.first, currentCurve.second);
@@ -1107,7 +1134,7 @@ public abstract class BrightnessMappingStrategy {
float defaultNits = defaultSpline.interpolate(lux);
float longTermNits = currSpline.interpolate(lux);
- float shortTermNits = mBrightnessSpline.interpolate(lux);
+ float shortTermNits = brightnessSpline.interpolate(lux);
float brightness = mAdjustedNitsToBrightnessSpline.interpolate(shortTermNits);
String luxPrefix = (lux == mUserLux ? "^" : "");
@@ -1142,8 +1169,10 @@ public abstract class BrightnessMappingStrategy {
// At 80 chars, start another row
if (sbLux.length() > 80 || (i == luxes.length - 1)) {
pw.println(sbLux);
- pw.println(sbNits);
- pw.println(sbLong);
+ if (!shortTermModelOnly) {
+ pw.println(sbNits);
+ pw.println(sbLong);
+ }
pw.println(sbShort);
pw.println(sbBrightness);
pw.println(sbPercent);
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index b994105de406..90c7ce7d5bc8 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -146,6 +146,7 @@ import com.android.internal.util.ArrayUtils;
import com.android.internal.util.DumpUtils;
import com.android.internal.util.FrameworkStatsLog;
import com.android.internal.util.IndentingPrintWriter;
+import com.android.internal.util.SettingsWrapper;
import com.android.server.AnimationThread;
import com.android.server.DisplayThread;
import com.android.server.LocalServices;
@@ -159,7 +160,7 @@ import com.android.server.display.layout.Layout;
import com.android.server.display.mode.DisplayModeDirector;
import com.android.server.display.utils.SensorUtils;
import com.android.server.input.InputManagerInternal;
-import com.android.server.utils.FoldSettingWrapper;
+import com.android.server.utils.FoldSettingProvider;
import com.android.server.wm.SurfaceAnimationThread;
import com.android.server.wm.WindowManagerInternal;
@@ -472,6 +473,8 @@ public final class DisplayManagerService extends SystemService {
private SensorManager mSensorManager;
private BrightnessTracker mBrightnessTracker;
+ private SmallAreaDetectionController mSmallAreaDetectionController;
+
// Whether minimal post processing is allowed by the user.
@GuardedBy("mSyncRoot")
@@ -547,9 +550,9 @@ public final class DisplayManagerService extends SystemService {
mHandler = new DisplayManagerHandler(DisplayThread.get().getLooper());
mUiHandler = UiThread.getHandler();
mDisplayDeviceRepo = new DisplayDeviceRepository(mSyncRoot, mPersistentDataStore);
- mLogicalDisplayMapper = new LogicalDisplayMapper(mContext, mDisplayDeviceRepo,
- new LogicalDisplayListener(), mSyncRoot, mHandler,
- new FoldSettingWrapper(mContext.getContentResolver()), mFlags);
+ mLogicalDisplayMapper = new LogicalDisplayMapper(mContext,
+ new FoldSettingProvider(mContext, new SettingsWrapper()), mDisplayDeviceRepo,
+ new LogicalDisplayListener(), mSyncRoot, mHandler, mFlags);
mDisplayModeDirector = new DisplayModeDirector(context, mHandler);
mBrightnessSynchronizer = new BrightnessSynchronizer(mContext);
Resources resources = mContext.getResources();
@@ -738,6 +741,8 @@ public final class DisplayManagerService extends SystemService {
filter.addAction(Intent.ACTION_DOCK_EVENT);
mContext.registerReceiver(mIdleModeReceiver, filter);
+
+ mSmallAreaDetectionController = SmallAreaDetectionController.create(mContext);
}
@VisibleForTesting
@@ -3128,6 +3133,9 @@ public final class DisplayManagerService extends SystemService {
pw.println();
mDisplayModeDirector.dump(pw);
mBrightnessSynchronizer.dump(pw);
+ if (mSmallAreaDetectionController != null) {
+ mSmallAreaDetectionController.dump(pw);
+ }
}
private static float[] getFloatArray(TypedArray array) {
diff --git a/services/core/java/com/android/server/display/LogicalDisplayMapper.java b/services/core/java/com/android/server/display/LogicalDisplayMapper.java
index cbe0fc7e713b..b3b16ade0546 100644
--- a/services/core/java/com/android/server/display/LogicalDisplayMapper.java
+++ b/services/core/java/com/android/server/display/LogicalDisplayMapper.java
@@ -43,7 +43,7 @@ import com.android.internal.annotations.VisibleForTesting;
import com.android.server.display.feature.DisplayManagerFlags;
import com.android.server.display.layout.DisplayIdProducer;
import com.android.server.display.layout.Layout;
-import com.android.server.utils.FoldSettingWrapper;
+import com.android.server.utils.FoldSettingProvider;
import java.io.PrintWriter;
import java.util.Arrays;
@@ -149,7 +149,7 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener {
private final Listener mListener;
private final DisplayManagerService.SyncRoot mSyncRoot;
private final LogicalDisplayMapperHandler mHandler;
- private final FoldSettingWrapper mFoldSettingWrapper;
+ private final FoldSettingProvider mFoldSettingProvider;
private final PowerManager mPowerManager;
/**
@@ -196,26 +196,27 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener {
private boolean mInteractive;
private final DisplayManagerFlags mFlags;
- LogicalDisplayMapper(@NonNull Context context, @NonNull DisplayDeviceRepository repo,
+ LogicalDisplayMapper(@NonNull Context context, FoldSettingProvider foldSettingProvider,
+ @NonNull DisplayDeviceRepository repo,
@NonNull Listener listener, @NonNull DisplayManagerService.SyncRoot syncRoot,
- @NonNull Handler handler, FoldSettingWrapper foldSettingWrapper,
- DisplayManagerFlags flags) {
- this(context, repo, listener, syncRoot, handler, new DeviceStateToLayoutMap(
- (isDefault) -> isDefault ? DEFAULT_DISPLAY : sNextNonDefaultDisplayId++),
- foldSettingWrapper, flags);
+ @NonNull Handler handler, DisplayManagerFlags flags) {
+ this(context, foldSettingProvider, repo, listener, syncRoot, handler,
+ new DeviceStateToLayoutMap((isDefault) -> isDefault ? DEFAULT_DISPLAY
+ : sNextNonDefaultDisplayId++), flags);
}
- LogicalDisplayMapper(@NonNull Context context, @NonNull DisplayDeviceRepository repo,
+ LogicalDisplayMapper(@NonNull Context context, FoldSettingProvider foldSettingProvider,
+ @NonNull DisplayDeviceRepository repo,
@NonNull Listener listener, @NonNull DisplayManagerService.SyncRoot syncRoot,
@NonNull Handler handler, @NonNull DeviceStateToLayoutMap deviceStateToLayoutMap,
- FoldSettingWrapper foldSettingWrapper, DisplayManagerFlags flags) {
+ DisplayManagerFlags flags) {
mSyncRoot = syncRoot;
mPowerManager = context.getSystemService(PowerManager.class);
mInteractive = mPowerManager.isInteractive();
mHandler = new LogicalDisplayMapperHandler(handler.getLooper());
mDisplayDeviceRepo = repo;
mListener = listener;
- mFoldSettingWrapper = foldSettingWrapper;
+ mFoldSettingProvider = foldSettingProvider;
mSingleDisplayDemoMode = SystemProperties.getBoolean("persist.demo.singledisplay", false);
mSupportsConcurrentInternalDisplays = context.getResources().getBoolean(
com.android.internal.R.bool.config_supportsConcurrentInternalDisplays);
@@ -488,10 +489,13 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener {
});
} else if (sleepDevice) {
// Send the device to sleep when required.
+ int goToSleepFlag =
+ mFoldSettingProvider.shouldSleepOnFold() ? 0
+ : PowerManager.GO_TO_SLEEP_FLAG_SOFT_SLEEP;
mHandler.post(() -> {
mPowerManager.goToSleep(SystemClock.uptimeMillis(),
PowerManager.GO_TO_SLEEP_REASON_DEVICE_FOLD,
- PowerManager.GO_TO_SLEEP_FLAG_SOFT_SLEEP);
+ goToSleepFlag);
});
}
}
@@ -565,7 +569,8 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener {
&& mDeviceStatesOnWhichToSleep.get(pendingState)
&& !mDeviceStatesOnWhichToSleep.get(currentState)
&& !isOverrideActive
- && isInteractive && isBootCompleted && !mFoldSettingWrapper.shouldStayAwakeOnFold();
+ && isInteractive && isBootCompleted
+ && !mFoldSettingProvider.shouldStayAwakeOnFold();
}
private boolean areAllTransitioningDisplaysOffLocked() {
diff --git a/services/core/java/com/android/server/display/SmallAreaDetectionController.java b/services/core/java/com/android/server/display/SmallAreaDetectionController.java
new file mode 100644
index 000000000000..adaa5390cb9b
--- /dev/null
+++ b/services/core/java/com/android/server/display/SmallAreaDetectionController.java
@@ -0,0 +1,177 @@
+/*
+ * Copyright (C) 2023 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.display;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.Context;
+import android.content.pm.PackageManagerInternal;
+import android.provider.DeviceConfig;
+import android.provider.DeviceConfigInterface;
+import android.util.ArrayMap;
+import android.util.SparseArray;
+
+import com.android.internal.R;
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.os.BackgroundThread;
+import com.android.server.LocalServices;
+import com.android.server.pm.UserManagerInternal;
+
+import java.io.PrintWriter;
+import java.util.Arrays;
+import java.util.Map;
+
+final class SmallAreaDetectionController {
+ private static native void nativeUpdateSmallAreaDetection(int[] uids, float[] thresholds);
+ private static native void nativeSetSmallAreaDetectionThreshold(int uid, float threshold);
+
+ // TODO(b/281720315): Move this to DeviceConfig once server side ready.
+ private static final String KEY_SMALL_AREA_DETECTION_ALLOWLIST =
+ "small_area_detection_allowlist";
+
+ private final Object mLock = new Object();
+ private final Context mContext;
+ private final PackageManagerInternal mPackageManager;
+ private final UserManagerInternal mUserManager;
+ @GuardedBy("mLock")
+ private final Map<String, Float> mAllowPkgMap = new ArrayMap<>();
+ // TODO(b/298722189): Update allowlist when user changes
+ @GuardedBy("mLock")
+ private int[] mUserIds;
+
+ static SmallAreaDetectionController create(@NonNull Context context) {
+ final SmallAreaDetectionController controller =
+ new SmallAreaDetectionController(context, DeviceConfigInterface.REAL);
+ final String property = DeviceConfigInterface.REAL.getProperty(
+ DeviceConfig.NAMESPACE_DISPLAY_MANAGER, KEY_SMALL_AREA_DETECTION_ALLOWLIST);
+ controller.updateAllowlist(property);
+ return controller;
+ }
+
+ @VisibleForTesting
+ SmallAreaDetectionController(Context context, DeviceConfigInterface deviceConfig) {
+ mContext = context;
+ mPackageManager = LocalServices.getService(PackageManagerInternal.class);
+ mUserManager = LocalServices.getService(UserManagerInternal.class);
+ deviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_DISPLAY_MANAGER,
+ BackgroundThread.getExecutor(),
+ new SmallAreaDetectionController.OnPropertiesChangedListener());
+ mPackageManager.getPackageList(new PackageReceiver());
+ }
+
+ @VisibleForTesting
+ void updateAllowlist(@Nullable String property) {
+ synchronized (mLock) {
+ mAllowPkgMap.clear();
+ if (property != null) {
+ final String[] mapStrings = property.split(",");
+ for (String mapString : mapStrings) putToAllowlist(mapString);
+ } else {
+ final String[] defaultMapStrings = mContext.getResources()
+ .getStringArray(R.array.config_smallAreaDetectionAllowlist);
+ for (String defaultMapString : defaultMapStrings) putToAllowlist(defaultMapString);
+ }
+ updateSmallAreaDetection();
+ }
+ }
+
+ @GuardedBy("mLock")
+ private void putToAllowlist(String rowData) {
+ // Data format: package:threshold - e.g. "com.abc.music:0.05"
+ final String[] items = rowData.split(":");
+ if (items.length == 2) {
+ try {
+ final String pkg = items[0];
+ final float threshold = Float.valueOf(items[1]);
+ mAllowPkgMap.put(pkg, threshold);
+ } catch (Exception e) {
+ // Just skip if items[1] - the threshold is not parsable number
+ }
+ }
+ }
+
+ @GuardedBy("mLock")
+ private void updateUidListForAllUsers(SparseArray<Float> list, String pkg, float threshold) {
+ for (int i = 0; i < mUserIds.length; i++) {
+ final int userId = mUserIds[i];
+ final int uid = mPackageManager.getPackageUid(pkg, 0, userId);
+ if (uid > 0) list.put(uid, threshold);
+ }
+ }
+
+ @GuardedBy("mLock")
+ private void updateSmallAreaDetection() {
+ if (mAllowPkgMap.isEmpty()) return;
+
+ mUserIds = mUserManager.getUserIds();
+
+ final SparseArray<Float> uidThresholdList = new SparseArray<>();
+ for (String pkg : mAllowPkgMap.keySet()) {
+ final float threshold = mAllowPkgMap.get(pkg);
+ updateUidListForAllUsers(uidThresholdList, pkg, threshold);
+ }
+
+ final int[] uids = new int[uidThresholdList.size()];
+ final float[] thresholds = new float[uidThresholdList.size()];
+ for (int i = 0; i < uidThresholdList.size(); i++) {
+ uids[i] = uidThresholdList.keyAt(i);
+ thresholds[i] = uidThresholdList.valueAt(i);
+ }
+ updateSmallAreaDetection(uids, thresholds);
+ }
+
+ @VisibleForTesting
+ void updateSmallAreaDetection(int[] uids, float[] thresholds) {
+ nativeUpdateSmallAreaDetection(uids, thresholds);
+ }
+
+ void setSmallAreaDetectionThreshold(int uid, float threshold) {
+ nativeSetSmallAreaDetectionThreshold(uid, threshold);
+ }
+
+ void dump(PrintWriter pw) {
+ pw.println("Small area detection allowlist");
+ pw.println(" Packages:");
+ synchronized (mLock) {
+ for (String pkg : mAllowPkgMap.keySet()) {
+ pw.println(" " + pkg + " threshold = " + mAllowPkgMap.get(pkg));
+ }
+ pw.println(" mUserIds=" + Arrays.toString(mUserIds));
+ }
+ }
+
+ private class OnPropertiesChangedListener implements DeviceConfig.OnPropertiesChangedListener {
+ public void onPropertiesChanged(@NonNull DeviceConfig.Properties properties) {
+ if (properties.getKeyset().contains(KEY_SMALL_AREA_DETECTION_ALLOWLIST)) {
+ updateAllowlist(
+ properties.getString(KEY_SMALL_AREA_DETECTION_ALLOWLIST, null /*default*/));
+ }
+ }
+ }
+
+ private final class PackageReceiver implements PackageManagerInternal.PackageListObserver {
+ @Override
+ public void onPackageAdded(@NonNull String packageName, int uid) {
+ synchronized (mLock) {
+ if (mAllowPkgMap.containsKey(packageName)) {
+ setSmallAreaDetectionThreshold(uid, mAllowPkgMap.get(packageName));
+ }
+ }
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index 1ec8b10813cd..131eec36f403 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -116,6 +116,7 @@ import android.util.Slog;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
import android.util.proto.ProtoOutputStream;
+import android.view.IWindowManager;
import android.view.InputChannel;
import android.view.InputDevice;
import android.view.MotionEvent;
@@ -123,6 +124,7 @@ import android.view.WindowManager;
import android.view.WindowManager.DisplayImePolicy;
import android.view.WindowManager.LayoutParams;
import android.view.WindowManager.LayoutParams.SoftInputModeFlags;
+import android.view.WindowManagerGlobal;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.ImeTracker;
import android.view.inputmethod.InputBinding;
@@ -2988,7 +2990,8 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
"Waiting for the lazy init of mImeDrawsImeNavBarRes");
}
final boolean canImeDrawsImeNavBar =
- mImeDrawsImeNavBarRes != null && mImeDrawsImeNavBarRes.get();
+ mImeDrawsImeNavBarRes != null && mImeDrawsImeNavBarRes.get()
+ && hasNavigationBarOnCurrentDisplay();
final boolean shouldShowImeSwitcherWhenImeIsShown = shouldShowImeSwitcherLocked(
InputMethodService.IME_ACTIVE | InputMethodService.IME_VISIBLE);
return (canImeDrawsImeNavBar ? InputMethodNavButtonFlags.IME_DRAWS_IME_NAV_BAR : 0)
@@ -2996,6 +2999,21 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
? InputMethodNavButtonFlags.SHOW_IME_SWITCHER_WHEN_IME_IS_SHOWN : 0);
}
+ /**
+ * Whether the current display has a navigation bar. When this is {@code false} (e.g. emulator),
+ * the IME should <em>not</em> draw the IME navigation bar.
+ */
+ @GuardedBy("ImfLock.class")
+ private boolean hasNavigationBarOnCurrentDisplay() {
+ final IWindowManager wm = WindowManagerGlobal.getWindowManagerService();
+ try {
+ return wm.hasNavigationBar(mCurTokenDisplayId != INVALID_DISPLAY
+ ? mCurTokenDisplayId : DEFAULT_DISPLAY);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
@GuardedBy("ImfLock.class")
private boolean shouldShowImeSwitcherLocked(int visibility) {
if (!mShowOngoingImeSwitcherForPhones) return false;
diff --git a/services/core/java/com/android/server/notification/flags.aconfig b/services/core/java/com/android/server/notification/flags.aconfig
index 1908e4dff234..dcac8c98d19f 100644
--- a/services/core/java/com/android/server/notification/flags.aconfig
+++ b/services/core/java/com/android/server/notification/flags.aconfig
@@ -13,3 +13,10 @@ flag {
description: "This flag controls the polite notification feature"
bug: "270456865"
}
+
+flag {
+ name: "refactor_attention_helper"
+ namespace: "systemui"
+ description: "This flag controls the refactoring of NMS to NotificationAttentionHelper"
+ bug: "291907312"
+}
diff --git a/services/core/java/com/android/server/pm/DeletePackageHelper.java b/services/core/java/com/android/server/pm/DeletePackageHelper.java
index b8feb4d044bf..967998a790ac 100644
--- a/services/core/java/com/android/server/pm/DeletePackageHelper.java
+++ b/services/core/java/com/android/server/pm/DeletePackageHelper.java
@@ -435,6 +435,12 @@ final class DeletePackageHelper {
}
final int userId = user == null ? UserHandle.USER_ALL : user.getIdentifier();
+ if (outInfo != null) {
+ // Remember which users are affected, before the installed states are modified
+ outInfo.mRemovedUsers = (systemApp || userId == UserHandle.USER_ALL)
+ ? ps.queryInstalledUsers(allUserHandles, /* installed= */true)
+ : new int[]{userId};
+ }
if ((!systemApp || (flags & PackageManager.DELETE_SYSTEM_APP) != 0)
&& userId != UserHandle.USER_ALL) {
@@ -630,7 +636,6 @@ final class DeletePackageHelper {
// Preserve data by setting flag
flags |= PackageManager.DELETE_KEEP_DATA;
}
-
synchronized (mPm.mInstallLock) {
deleteInstalledPackageLIF(deletedPs, true, flags, allUserHandles, outInfo,
writeSettings);
diff --git a/services/core/java/com/android/server/pm/InstallPackageHelper.java b/services/core/java/com/android/server/pm/InstallPackageHelper.java
index dd043406f653..2712fa782c27 100644
--- a/services/core/java/com/android/server/pm/InstallPackageHelper.java
+++ b/services/core/java/com/android/server/pm/InstallPackageHelper.java
@@ -44,7 +44,6 @@ import static android.os.incremental.IncrementalManager.isIncrementalPath;
import static android.os.storage.StorageManager.FLAG_STORAGE_CE;
import static android.os.storage.StorageManager.FLAG_STORAGE_DE;
import static android.os.storage.StorageManager.FLAG_STORAGE_EXTERNAL;
-
import static com.android.server.pm.DexOptHelper.useArtService;
import static com.android.server.pm.InstructionSets.getAppDexInstructionSets;
import static com.android.server.pm.InstructionSets.getDexCodeInstructionSet;
@@ -1144,8 +1143,7 @@ final class InstallPackageHelper {
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "parsePackage");
final ParsedPackage parsedPackage;
try (PackageParser2 pp = mPm.mInjector.getPreparingPackageParser()) {
- if (request.getPackageLite() == null || !PackageInstallerSession.isArchivedInstallation(
- request.getInstallFlags())) {
+ if (request.getPackageLite() == null || !request.isArchived()) {
// TODO: pass packageLite from install request instead of reparsing the package
parsedPackage = pp.parsePackage(tmpPackageFile, parseFlags, false);
AndroidPackageUtils.validatePackageDexMetadata(parsedPackage);
@@ -3556,7 +3554,7 @@ final class InstallPackageHelper {
logCriticalInfo(Log.WARN, "System package " + packageName
+ " no longer exists; its data will be wiped");
mInjector.getHandler().post(
- () -> mRemovePackageHelper.removePackageData(ps, userIds, null, 0, false));
+ () -> mRemovePackageHelper.removePackageData(ps, userIds));
expectingBetter.put(ps.getPackageName(), ps.getPath());
} else {
// we still have a disabled system package, but, it still might have
@@ -3631,7 +3629,7 @@ final class InstallPackageHelper {
// partition], completely remove the package data.
final PackageSetting ps = mPm.mSettings.getPackageLPr(packageName);
if (ps != null && mPm.mPackages.get(packageName) == null) {
- mRemovePackageHelper.removePackageData(ps, userIds, null, 0, false);
+ mRemovePackageHelper.removePackageData(ps, userIds);
}
logCriticalInfo(Log.WARN, msg);
}
diff --git a/services/core/java/com/android/server/pm/InstallRequest.java b/services/core/java/com/android/server/pm/InstallRequest.java
index fe7c0864d4d0..e1cfc418bfe5 100644
--- a/services/core/java/com/android/server/pm/InstallRequest.java
+++ b/services/core/java/com/android/server/pm/InstallRequest.java
@@ -21,7 +21,6 @@ import static android.content.pm.PackageManager.INSTALL_REASON_UNKNOWN;
import static android.content.pm.PackageManager.INSTALL_SCENARIO_DEFAULT;
import static android.content.pm.PackageManager.INSTALL_SUCCEEDED;
import static android.os.Process.INVALID_UID;
-
import static com.android.server.pm.PackageManagerService.SCAN_AS_INSTANT_APP;
import static com.android.server.pm.PackageManagerService.TAG;
@@ -327,6 +326,10 @@ final class InstallRequest {
return mRemovedInfo != null && mRemovedInfo.mRemovedPackage != null;
}
+ public boolean isArchived() {
+ return PackageInstallerSession.isArchivedInstallation(getInstallFlags());
+ }
+
@Nullable
public String getRemovedPackage() {
return mRemovedInfo != null ? mRemovedInfo.mRemovedPackage : null;
diff --git a/services/core/java/com/android/server/pm/PackageArchiverService.java b/services/core/java/com/android/server/pm/PackageArchiverService.java
index 9c31dc9a1215..c7f067be8581 100644
--- a/services/core/java/com/android/server/pm/PackageArchiverService.java
+++ b/services/core/java/com/android/server/pm/PackageArchiverService.java
@@ -17,17 +17,26 @@
package com.android.server.pm;
import static android.content.pm.PackageManager.DELETE_KEEP_DATA;
+import static android.os.PowerExemptionManager.REASON_PACKAGE_UNARCHIVE;
+import static android.os.PowerExemptionManager.TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED;
+import android.Manifest;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
+import android.app.AppOpsManager;
+import android.app.BroadcastOptions;
import android.content.Context;
+import android.content.Intent;
import android.content.IntentSender;
import android.content.pm.IPackageArchiverService;
import android.content.pm.LauncherActivityInfo;
import android.content.pm.LauncherApps;
+import android.content.pm.PackageArchiver;
import android.content.pm.PackageManager;
import android.content.pm.VersionedPackage;
import android.os.Binder;
+import android.os.Bundle;
import android.os.ParcelableException;
import android.os.UserHandle;
import android.text.TextUtils;
@@ -36,6 +45,7 @@ import com.android.internal.annotations.GuardedBy;
import com.android.server.pm.pkg.ArchiveState;
import com.android.server.pm.pkg.ArchiveState.ArchiveActivityInfo;
import com.android.server.pm.pkg.PackageStateInternal;
+import com.android.server.pm.pkg.PackageUserStateInternal;
import java.nio.file.Path;
import java.util.ArrayList;
@@ -51,7 +61,12 @@ import java.util.Objects;
*/
public class PackageArchiverService extends IPackageArchiverService.Stub {
- private static final String TAG = "PackageArchiver";
+ /**
+ * The maximum time granted for an app store to start a foreground service when unarchival
+ * is requested.
+ */
+ // TODO(b/297358628) Make this configurable through a flag.
+ private static final int DEFAULT_UNARCHIVE_FOREGROUND_TIMEOUT_MS = 120 * 1000;
private final Context mContext;
private final PackageManagerService mPm;
@@ -82,17 +97,14 @@ public class PackageArchiverService extends IPackageArchiverService.Stub {
snapshot.enforceCrossUserPermission(binderUid, userId, true, true,
"archiveApp");
verifyCaller(providedUid, binderUid);
- PackageStateInternal ps = getPackageState(packageName, snapshot, binderUid, userId);
- verifyInstaller(packageName, ps);
-
- // TODO(b/291569242) Verify that this list is not empty and return failure with
- // intentsender
- List<LauncherActivityInfo> mainActivities = getLauncherApps().getActivityList(
- ps.getPackageName(),
- new UserHandle(userId));
-
- // TODO(b/282952870) Bug: should happen after the uninstall completes successfully
- storeArchiveState(ps, mainActivities, userId);
+ ArchiveState archiveState;
+ try {
+ archiveState = createArchiveState(packageName, userId);
+ // TODO(b/282952870) Should be reverted if uninstall fails/cancels
+ storeArchiveState(packageName, archiveState, userId);
+ } catch (PackageManager.NameNotFoundException e) {
+ throw new ParcelableException(e);
+ }
// TODO(b/278553670) Add special strings for the delete dialog
mPm.mInstallerService.uninstall(
@@ -100,25 +112,173 @@ public class PackageArchiverService extends IPackageArchiverService.Stub {
callerPackageName, DELETE_KEEP_DATA, intentSender, userId);
}
- private static void verifyInstaller(String packageName, PackageStateInternal ps) {
- if (ps.getInstallSource().mUpdateOwnerPackageName == null
- && ps.getInstallSource().mInstallerPackageName == null) {
+ /**
+ * Creates archived state for the package and user.
+ */
+ public ArchiveState createArchiveState(String packageName, int userId)
+ throws PackageManager.NameNotFoundException {
+ PackageStateInternal ps = getPackageState(packageName, mPm.snapshotComputer(),
+ Binder.getCallingUid(), userId);
+ String responsibleInstallerPackage = getResponsibleInstallerPackage(ps);
+ verifyInstaller(responsibleInstallerPackage);
+
+ List<LauncherActivityInfo> mainActivities = getLauncherActivityInfos(ps, userId);
+ List<ArchiveActivityInfo> archiveActivityInfos = new ArrayList<>();
+ for (int i = 0; i < mainActivities.size(); i++) {
+ // TODO(b/278553670) Extract and store launcher icons
+ ArchiveActivityInfo activityInfo = new ArchiveActivityInfo(
+ mainActivities.get(i).getLabel().toString(),
+ Path.of("/TODO"), null);
+ archiveActivityInfos.add(activityInfo);
+ }
+
+ return new ArchiveState(archiveActivityInfos, responsibleInstallerPackage);
+ }
+
+ private void verifyInstaller(String installerPackage)
+ throws PackageManager.NameNotFoundException {
+ if (TextUtils.isEmpty(installerPackage)) {
+ throw new PackageManager.NameNotFoundException("No installer found");
+ }
+ if (!verifySupportsUnarchival(installerPackage)) {
+ throw new PackageManager.NameNotFoundException("Installer does not support unarchival");
+ }
+ }
+
+ /**
+ * @return true if installerPackage support unarchival:
+ * - has an action Intent.ACTION_UNARCHIVE_PACKAGE,
+ * - has permissions to install packages.
+ */
+ public boolean verifySupportsUnarchival(String installerPackage) {
+ // TODO(b/278553670) Check if installerPackage supports unarchival.
+ return true;
+ }
+
+ @Override
+ public void requestUnarchive(
+ @NonNull String packageName,
+ @NonNull String callerPackageName,
+ @NonNull UserHandle userHandle) {
+ Objects.requireNonNull(packageName);
+ Objects.requireNonNull(callerPackageName);
+ Objects.requireNonNull(userHandle);
+
+ Computer snapshot = mPm.snapshotComputer();
+ int userId = userHandle.getIdentifier();
+ int binderUid = Binder.getCallingUid();
+ int providedUid = snapshot.getPackageUid(callerPackageName, 0, userId);
+ snapshot.enforceCrossUserPermission(binderUid, userId, true, true,
+ "unarchiveApp");
+ verifyCaller(providedUid, binderUid);
+ PackageStateInternal ps;
+ try {
+ ps = getPackageState(packageName, snapshot, binderUid, userId);
+ verifyArchived(ps, userId);
+ } catch (PackageManager.NameNotFoundException e) {
+ throw new ParcelableException(e);
+ }
+ String installerPackage = getResponsibleInstallerPackage(ps);
+ if (installerPackage == null) {
throw new ParcelableException(
new PackageManager.NameNotFoundException(
- TextUtils.formatSimple("No installer found to archive app %s.",
+ TextUtils.formatSimple("No installer found to unarchive app %s.",
packageName)));
}
+
+ mPm.mHandler.post(() -> unarchiveInternal(packageName, userHandle, installerPackage));
+ }
+
+ private void verifyArchived(PackageStateInternal ps, int userId)
+ throws PackageManager.NameNotFoundException {
+ PackageUserStateInternal userState = ps.getUserStateOrDefault(userId);
+ // TODO(b/288142708) Check for isInstalled false here too.
+ if (userState.getArchiveState() == null) {
+ throw new PackageManager.NameNotFoundException(
+ TextUtils.formatSimple("Package %s is not currently archived.",
+ ps.getPackageName()));
+ }
+ }
+
+ @RequiresPermission(
+ allOf = {
+ Manifest.permission.INTERACT_ACROSS_USERS,
+ android.Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST,
+ android.Manifest.permission.START_ACTIVITIES_FROM_BACKGROUND,
+ android.Manifest.permission.START_FOREGROUND_SERVICES_FROM_BACKGROUND},
+ conditional = true)
+ private void unarchiveInternal(String packageName, UserHandle userHandle,
+ String installerPackage) {
+ int userId = userHandle.getIdentifier();
+ Intent unarchiveIntent = new Intent(Intent.ACTION_UNARCHIVE_PACKAGE);
+ unarchiveIntent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
+ unarchiveIntent.putExtra(PackageArchiver.EXTRA_UNARCHIVE_PACKAGE_NAME, packageName);
+ unarchiveIntent.putExtra(PackageArchiver.EXTRA_UNARCHIVE_ALL_USERS,
+ userId == UserHandle.USER_ALL);
+ unarchiveIntent.setPackage(installerPackage);
+
+ // If the unarchival is requested for all users, the current user is used for unarchival.
+ UserHandle userForUnarchival = userId == UserHandle.USER_ALL
+ ? UserHandle.of(mPm.mUserManager.getCurrentUserId())
+ : userHandle;
+ mContext.sendOrderedBroadcastAsUser(
+ unarchiveIntent,
+ userForUnarchival,
+ /* receiverPermission = */ null,
+ AppOpsManager.OP_NONE,
+ createUnarchiveOptions(),
+ /* resultReceiver= */ null,
+ /* scheduler= */ null,
+ /* initialCode= */ 0,
+ /* initialData= */ null,
+ /* initialExtras= */ null);
+ }
+
+ private List<LauncherActivityInfo> getLauncherActivityInfos(PackageStateInternal ps,
+ int userId) throws PackageManager.NameNotFoundException {
+ List<LauncherActivityInfo> mainActivities =
+ Binder.withCleanCallingIdentity(() -> getLauncherApps().getActivityList(
+ ps.getPackageName(),
+ new UserHandle(userId)));
+ if (mainActivities.isEmpty()) {
+ throw new PackageManager.NameNotFoundException(
+ TextUtils.formatSimple("The app %s does not have a main activity.",
+ ps.getPackageName()));
+ }
+
+ return mainActivities;
+ }
+
+ @RequiresPermission(anyOf = {android.Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST,
+ android.Manifest.permission.START_ACTIVITIES_FROM_BACKGROUND,
+ android.Manifest.permission.START_FOREGROUND_SERVICES_FROM_BACKGROUND})
+ private Bundle createUnarchiveOptions() {
+ BroadcastOptions options = BroadcastOptions.makeBasic();
+ options.setTemporaryAppAllowlist(getUnarchiveForegroundTimeout(),
+ TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED,
+ REASON_PACKAGE_UNARCHIVE, "");
+ return options.toBundle();
+ }
+
+ private static int getUnarchiveForegroundTimeout() {
+ return DEFAULT_UNARCHIVE_FOREGROUND_TIMEOUT_MS;
+ }
+
+ private String getResponsibleInstallerPackage(PackageStateInternal ps) {
+ return TextUtils.isEmpty(ps.getInstallSource().mUpdateOwnerPackageName)
+ ? ps.getInstallSource().mInstallerPackageName
+ : ps.getInstallSource().mUpdateOwnerPackageName;
}
@NonNull
private static PackageStateInternal getPackageState(String packageName,
- Computer snapshot, int callingUid, int userId) {
+ Computer snapshot, int callingUid, int userId)
+ throws PackageManager.NameNotFoundException {
PackageStateInternal ps = snapshot.getPackageStateFiltered(packageName, callingUid,
userId);
if (ps == null) {
- throw new ParcelableException(
- new PackageManager.NameNotFoundException(
- TextUtils.formatSimple("Package %s not found.", packageName)));
+ throw new PackageManager.NameNotFoundException(
+ TextUtils.formatSimple("Package %s not found.", packageName));
}
return ps;
}
@@ -130,38 +290,25 @@ public class PackageArchiverService extends IPackageArchiverService.Stub {
return mLauncherApps;
}
- private void storeArchiveState(PackageStateInternal ps,
- List<LauncherActivityInfo> mainActivities, int userId) {
- List<ArchiveActivityInfo> activityInfos = new ArrayList<>();
- for (int i = 0; i < mainActivities.size(); i++) {
- // TODO(b/278553670) Extract and store launcher icons
- ArchiveActivityInfo activityInfo = new ArchiveActivityInfo(
- mainActivities.get(i).getLabel().toString(),
- Path.of("/TODO"), null);
- activityInfos.add(activityInfo);
- }
-
- InstallSource installSource = ps.getInstallSource();
- String installerPackageName = installSource.mUpdateOwnerPackageName != null
- ? installSource.mUpdateOwnerPackageName : installSource.mInstallerPackageName;
-
+ private void storeArchiveState(String packageName, ArchiveState archiveState, int userId)
+ throws PackageManager.NameNotFoundException {
synchronized (mPm.mLock) {
- PackageSetting packageSetting = getPackageSettingLocked(ps.getPackageName(), userId);
+ PackageSetting packageSetting = getPackageSettingLocked(packageName, userId);
packageSetting
.modifyUserState(userId)
- .setArchiveState(new ArchiveState(activityInfos, installerPackageName));
+ .setArchiveState(archiveState);
}
}
@NonNull
@GuardedBy("mPm.mLock")
- private PackageSetting getPackageSettingLocked(String packageName, int userId) {
+ private PackageSetting getPackageSettingLocked(String packageName, int userId)
+ throws PackageManager.NameNotFoundException {
PackageSetting ps = mPm.mSettings.getPackageLPr(packageName);
// Shouldn't happen, we already verify presence of the package in getPackageState()
if (ps == null || !ps.getUserStateOrDefault(userId).isInstalled()) {
- throw new ParcelableException(
- new PackageManager.NameNotFoundException(
- TextUtils.formatSimple("Package %s not found.", packageName)));
+ throw new PackageManager.NameNotFoundException(
+ TextUtils.formatSimple("Package %s not found.", packageName));
}
return ps;
}
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 1bdade2df6dc..0dd4111adbfa 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -40,7 +40,6 @@ import static android.provider.DeviceConfig.NAMESPACE_PACKAGE_MANAGER_SERVICE;
import static android.system.OsConstants.O_CREAT;
import static android.system.OsConstants.O_RDONLY;
import static android.system.OsConstants.O_WRONLY;
-
import static com.android.internal.annotations.VisibleForTesting.Visibility.PACKAGE;
import static com.android.internal.util.XmlUtils.readBitmapAttribute;
import static com.android.internal.util.XmlUtils.readByteArrayAttribute;
@@ -1166,6 +1165,11 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
throw new IllegalArgumentException(
"Archived installation can only use Streaming System DataLoader.");
}
+ if (!TextUtils.isEmpty(params.appPackageName) && !isArchivedInstallationAllowed(
+ params.appPackageName)) {
+ throw new IllegalArgumentException(
+ "Archived installation of this package is not allowed.");
+ }
}
}
@@ -2220,6 +2224,19 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
}
/**
+ * Check if this package can be installed archived.
+ */
+ private static boolean isArchivedInstallationAllowed(String packageName) {
+ final PackageManagerInternal pmi = LocalServices.getService(PackageManagerInternal.class);
+ final PackageStateInternal existingPkgSetting = pmi.getPackageStateInternal(packageName);
+ if (existingPkgSetting == null) {
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
* Checks if the package can be installed on IncFs.
*/
private static boolean isIncrementalInstallationAllowed(String packageName) {
@@ -3371,6 +3388,23 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
}
}
+ if (isArchivedInstallation()) {
+ if (!isArchivedInstallationAllowed(mPackageName)) {
+ throw new PackageManagerException(
+ PackageManager.INSTALL_FAILED_SESSION_INVALID,
+ "Archived installation of this package is not allowed.");
+ }
+
+ if (!isInstalledByAdb(getInstallSource().mInitiatingPackageName)
+ && !mPm.mArchiverService.verifySupportsUnarchival(
+ getInstallSource().mInstallerPackageName)) {
+ throw new PackageManagerException(
+ PackageManager.INSTALL_FAILED_SESSION_INVALID,
+ "Installer has to support unarchival in order to install archived "
+ + "packages.");
+ }
+ }
+
if (isIncrementalInstallation()) {
if (!isIncrementalInstallationAllowed(mPackageName)) {
throw new PackageManagerException(
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index bb4fd66e995c..0c2f1ca54f73 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -36,7 +36,6 @@ import static android.os.storage.StorageManager.FLAG_STORAGE_CE;
import static android.os.storage.StorageManager.FLAG_STORAGE_DE;
import static android.os.storage.StorageManager.FLAG_STORAGE_EXTERNAL;
import static android.provider.DeviceConfig.NAMESPACE_PACKAGE_MANAGER_SERVICE;
-
import static com.android.internal.annotations.VisibleForTesting.Visibility;
import static com.android.internal.util.FrameworkStatsLog.BOOT_TIME_EVENT_DURATION__EVENT__OTA_PACKAGE_MANAGER_INIT_TIME;
import static com.android.server.pm.DexOptHelper.useArtService;
@@ -6323,7 +6322,6 @@ public class PackageManagerService implements PackageSender, TestUtilityService
archPkg.targetSdkVersion = apk.getTargetSdkVersion();
// These get translated in flags important for user data management.
- archPkg.clearUserDataAllowed = apk.isClearUserDataAllowed();
archPkg.backupAllowed = apk.isBackupAllowed();
archPkg.defaultToDeviceProtectedStorage =
apk.isDefaultToDeviceProtectedStorage();
diff --git a/services/core/java/com/android/server/pm/PackageMetrics.java b/services/core/java/com/android/server/pm/PackageMetrics.java
index c1580c4b1cb9..7ad336c9074d 100644
--- a/services/core/java/com/android/server/pm/PackageMetrics.java
+++ b/services/core/java/com/android/server/pm/PackageMetrics.java
@@ -120,7 +120,7 @@ final class PackageMetrics {
versionCode = ps.getVersionCode();
apksSize = getApksSize(ps.getPath());
}
- } catch (IllegalStateException e) {
+ } catch (IllegalStateException | NullPointerException e) {
// no-op
}
}
diff --git a/services/core/java/com/android/server/pm/PackageRemovedInfo.java b/services/core/java/com/android/server/pm/PackageRemovedInfo.java
index c762fd3f9648..5f4452884fc9 100644
--- a/services/core/java/com/android/server/pm/PackageRemovedInfo.java
+++ b/services/core/java/com/android/server/pm/PackageRemovedInfo.java
@@ -164,8 +164,7 @@ final class PackageRemovedInfo {
}
}
- public void populateUsers(int[] userIds, PackageSetting deletedPackageSetting) {
- mRemovedUsers = userIds;
+ public void populateBroadcastUsers(PackageSetting deletedPackageSetting) {
if (mRemovedUsers == null) {
mBroadcastUsers = null;
return;
@@ -173,8 +172,8 @@ final class PackageRemovedInfo {
mBroadcastUsers = EMPTY_INT_ARRAY;
mInstantUserIds = EMPTY_INT_ARRAY;
- for (int i = userIds.length - 1; i >= 0; --i) {
- final int userId = userIds[i];
+ for (int i = mRemovedUsers.length - 1; i >= 0; --i) {
+ final int userId = mRemovedUsers[i];
if (deletedPackageSetting.getInstantApp(userId)) {
mInstantUserIds = ArrayUtils.appendInt(mInstantUserIds, userId);
} else {
diff --git a/services/core/java/com/android/server/pm/PackageSetting.java b/services/core/java/com/android/server/pm/PackageSetting.java
index 7cac3e1b9842..88184c0cb490 100644
--- a/services/core/java/com/android/server/pm/PackageSetting.java
+++ b/services/core/java/com/android/server/pm/PackageSetting.java
@@ -818,7 +818,7 @@ public class PackageSetting extends SettingBase implements PackageStateInternal
if (userState.isInstalled()) {
return true;
}
- if (userState.getCeDataInode() > 0) {
+ if (userState.dataExists()) {
return true;
}
}
diff --git a/services/core/java/com/android/server/pm/RemovePackageHelper.java b/services/core/java/com/android/server/pm/RemovePackageHelper.java
index d4f30fed6967..2aedf0d8960c 100644
--- a/services/core/java/com/android/server/pm/RemovePackageHelper.java
+++ b/services/core/java/com/android/server/pm/RemovePackageHelper.java
@@ -295,25 +295,24 @@ final class RemovePackageHelper {
outInfo.mInstallerPackageName = ps.getInstallSource().mInstallerPackageName;
outInfo.mIsStaticSharedLib = pkg != null && pkg.getStaticSharedLibraryName() != null;
outInfo.mRemovedAppId = ps.getAppId();
- outInfo.mRemovedUsers = userIds;
- outInfo.mBroadcastUsers = userIds;
+ outInfo.mBroadcastUsers = outInfo.mRemovedUsers;
outInfo.mIsExternal = ps.isExternalStorage();
outInfo.mRemovedPackageVersionCode = ps.getVersionCode();
}
}
// Called to clean up disabled system packages
- public void removePackageData(final PackageSetting deletedPs, @NonNull int[] allUserHandles,
- PackageRemovedInfo outInfo, int flags, boolean writeSettings) {
+ public void removePackageData(final PackageSetting deletedPs, @NonNull int[] allUserHandles) {
synchronized (mPm.mInstallLock) {
- removePackageDataLIF(deletedPs, allUserHandles, outInfo, flags, writeSettings);
+ removePackageDataLIF(deletedPs, allUserHandles, /* outInfo= */ null,
+ /* flags= */ 0, /* writeSettings= */ false);
}
}
/*
* This method deletes the package from internal data structures. If the DELETE_KEEP_DATA
* flag is not set, the data directory is removed as well.
- * make sure this flag is set for partially installed apps. If not its meaningless to
+ * make sure this flag is set for partially installed apps. If not it's meaningless to
* delete a partially installed application.
*/
@GuardedBy("mPm.mInstallLock")
@@ -328,8 +327,7 @@ final class RemovePackageHelper {
outInfo.mInstallerPackageName = deletedPs.getInstallSource().mInstallerPackageName;
outInfo.mIsStaticSharedLib = deletedPkg != null
&& deletedPkg.getStaticSharedLibraryName() != null;
- outInfo.populateUsers(deletedPs.queryInstalledUsers(
- mUserManagerInternal.getUserIds(), true), deletedPs);
+ outInfo.populateBroadcastUsers(deletedPs);
outInfo.mIsExternal = deletedPs.isExternalStorage();
outInfo.mRemovedPackageVersionCode = deletedPs.getVersionCode();
}
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 6eace6a920aa..1137681de5cf 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -27,7 +27,6 @@ import static android.content.pm.PackageManager.UNINSTALL_REASON_USER_TYPE;
import static android.os.Process.INVALID_UID;
import static android.os.Process.PACKAGE_INFO_GID;
import static android.os.Process.SYSTEM_UID;
-
import static com.android.server.pm.PackageManagerService.PLATFORM_PACKAGE_NAME;
import static com.android.server.pm.PackageManagerService.WRITE_USER_PACKAGE_RESTRICTIONS;
import static com.android.server.pm.SharedUidMigration.BEST_EFFORT;
@@ -4896,8 +4895,6 @@ public final class Settings implements Watchable, Snappable, ResilientAtomicFile
pw.print("]");
}
pw.println();
- File dataDir = PackageInfoUtils.getDataDir(ps, UserHandle.myUserId());
- pw.print(prefix); pw.print(" dataDir="); pw.println(dataDir.getAbsolutePath());
if (pkg != null) {
pw.print(prefix); pw.print(" versionName="); pw.println(pkg.getVersionName());
pw.print(prefix); pw.print(" usesNonSdkApi="); pw.println(pkg.isNonSdkApiRequested());
@@ -5198,6 +5195,10 @@ public final class Settings implements Watchable, Snappable, ResilientAtomicFile
pw.print(" installReason=");
pw.println(userState.getInstallReason());
+ File dataDir = PackageInfoUtils.getDataDir(ps, user.id);
+ pw.print(" dataDir=");
+ pw.println(dataDir.getAbsolutePath());
+
final PackageUserStateInternal pus = ps.readUserState(user.id);
pw.print(" firstInstallTime=");
date.setTime(pus.getFirstInstallTimeMillis());
diff --git a/services/core/java/com/android/server/pm/flags.aconfig b/services/core/java/com/android/server/pm/flags.aconfig
index 368a8432c805..7779c08e8d5a 100644
--- a/services/core/java/com/android/server/pm/flags.aconfig
+++ b/services/core/java/com/android/server/pm/flags.aconfig
@@ -6,3 +6,11 @@ flag {
description: "Feature flag for Quarantined state"
bug: "269127435"
}
+
+flag {
+ name: "new_match_uninstalled_enabled"
+ namespace: "package_manager_service"
+ description: "Feature flag for new MATCH_UNINSTALLED_PACKAGES behavior"
+ bug: "298681254"
+ is_fixed_read_only: true
+}
diff --git a/services/core/java/com/android/server/pm/pkg/PackageUserState.java b/services/core/java/com/android/server/pm/pkg/PackageUserState.java
index 7bc518c5516e..c05b3c2be622 100644
--- a/services/core/java/com/android/server/pm/pkg/PackageUserState.java
+++ b/services/core/java/com/android/server/pm/pkg/PackageUserState.java
@@ -242,4 +242,11 @@ public interface PackageUserState {
@Nullable
ArchiveState getArchiveState();
+ /**
+ * @return whether the data dir exists. True when the app is installed for the user, or when the
+ * app is uninstalled for the user with {@link PackageManager#DELETE_KEEP_DATA}.
+ *
+ * @hide
+ */
+ boolean dataExists();
}
diff --git a/services/core/java/com/android/server/pm/pkg/PackageUserStateDefault.java b/services/core/java/com/android/server/pm/pkg/PackageUserStateDefault.java
index 3534d7564c50..fc4b6863b9b8 100644
--- a/services/core/java/com/android/server/pm/pkg/PackageUserStateDefault.java
+++ b/services/core/java/com/android/server/pm/pkg/PackageUserStateDefault.java
@@ -196,4 +196,9 @@ class PackageUserStateDefault implements PackageUserStateInternal {
public ArchiveState getArchiveState() {
return null;
}
+
+ @Override
+ public boolean dataExists() {
+ return true;
+ }
}
diff --git a/services/core/java/com/android/server/pm/pkg/PackageUserStateImpl.java b/services/core/java/com/android/server/pm/pkg/PackageUserStateImpl.java
index 2349fbff11a7..0b35d8ae16ea 100644
--- a/services/core/java/com/android/server/pm/pkg/PackageUserStateImpl.java
+++ b/services/core/java/com/android/server/pm/pkg/PackageUserStateImpl.java
@@ -685,6 +685,10 @@ public class PackageUserStateImpl extends WatchableImpl implements PackageUserSt
return false;
}
+ @Override
+ public boolean dataExists() {
+ return getCeDataInode() > 0;
+ }
diff --git a/services/core/java/com/android/server/pm/pkg/PackageUserStateUtils.java b/services/core/java/com/android/server/pm/pkg/PackageUserStateUtils.java
index 54f7ebca1b66..9ab3060ce325 100644
--- a/services/core/java/com/android/server/pm/pkg/PackageUserStateUtils.java
+++ b/services/core/java/com/android/server/pm/pkg/PackageUserStateUtils.java
@@ -27,6 +27,7 @@ import android.os.Debug;
import android.util.DebugUtils;
import android.util.Slog;
+import com.android.server.pm.Flags;
import com.android.server.pm.pkg.component.ParsedMainComponent;
/** @hide */
@@ -82,15 +83,38 @@ public class PackageUserStateUtils {
return reportIfDebug(matchesUnaware || matchesAware, flags);
}
+ /**
+ * @return true if any of the following conditions is met:
+ * <p><ul>
+ * <li> If it is installed and not hidden for this user;
+ * <li> If it is installed but hidden for this user, still return true if
+ * {@link PackageManager#MATCH_UNINSTALLED_PACKAGES} or
+ * {@link PackageManager#MATCH_ARCHIVED_PACKAGES} is requested;
+ * <li> If MATCH_ANY_USER is requested, always return true, because the fact that
+ * this object exists means that the package must be installed or has data on at least one user;
+ * <li> (When feature enabled) If it is not installed but still has data (i.e., it was
+ * previously uninstalled with {@link PackageManager#DELETE_KEEP_DATA}), return true if the
+ * caller requested {@link PackageManager#MATCH_UNINSTALLED_PACKAGES} or
+ * {@link PackageManager#MATCH_ARCHIVED_PACKAGES};
+ * </ul><p>
+ */
public static boolean isAvailable(@NonNull PackageUserState state, long flags) {
- // True if it is installed for this user and it is not hidden. If it is hidden,
- // still return true if the caller requested MATCH_UNINSTALLED_PACKAGES
final boolean matchAnyUser = (flags & PackageManager.MATCH_ANY_USER) != 0;
final boolean matchUninstalled = (flags & PackageManager.MATCH_UNINSTALLED_PACKAGES) != 0;
final boolean matchArchived = (flags & PackageManager.MATCH_ARCHIVED_PACKAGES) != 0;
- return matchAnyUser
- || (state.isInstalled()
- && (!state.isHidden() || matchUninstalled || matchArchived));
+ final boolean matchDataExists = matchUninstalled || matchArchived;
+
+ if (matchAnyUser) {
+ return true;
+ }
+ if (state.isInstalled()) {
+ if (!state.isHidden()) {
+ return true;
+ } else return matchDataExists;
+ } else {
+ // not installed
+ return matchDataExists && Flags.newMatchUninstalledEnabled() && state.dataExists();
+ }
}
public static boolean reportIfDebug(boolean result, long flags) {
diff --git a/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackageUtils.java b/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackageUtils.java
index 2d55b9f8e16a..81c2f0760705 100644
--- a/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackageUtils.java
+++ b/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackageUtils.java
@@ -28,7 +28,6 @@ import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_UNEXPECTED_
import static android.os.Build.VERSION_CODES.DONUT;
import static android.os.Build.VERSION_CODES.O;
import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER;
-
import static com.android.server.pm.pkg.parsing.ParsingUtils.parseKnownActivityEmbeddingCerts;
import android.annotation.AnyRes;
@@ -514,7 +513,7 @@ public class ParsingPackageUtils {
pkg
// Default true
.setBackupAllowed(lite.isBackupAllowed())
- .setClearUserDataAllowed(lite.isClearUserDataAllowed())
+ .setClearUserDataAllowed(true)
.setClearUserDataOnFailedRestoreAllowed(
lite.isClearUserDataOnFailedRestoreAllowed())
.setAllowNativeHeapPointerTagging(true)
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index cbac39a5e0f2..9dcc2ab082c0 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -3354,6 +3354,13 @@ public class PhoneWindowManager implements WindowManagerPolicy {
return true;
}
break;
+ case KeyEvent.KEYCODE_DEL:
+ case KeyEvent.KEYCODE_GRAVE:
+ if (firstDown && event.isMetaPressed()) {
+ logKeyboardSystemsEvent(event, KeyboardLogEvent.BACK);
+ injectBackGesture(event.getDownTime());
+ return true;
+ }
case KeyEvent.KEYCODE_DPAD_UP:
if (firstDown && event.isMetaPressed() && event.isCtrlPressed()) {
StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
@@ -3365,9 +3372,14 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
break;
case KeyEvent.KEYCODE_DPAD_LEFT:
- if (firstDown && event.isMetaPressed() && event.isCtrlPressed()) {
- enterStageSplitFromRunningApp(true /* leftOrTop */);
- logKeyboardSystemsEvent(event, KeyboardLogEvent.SPLIT_SCREEN_NAVIGATION);
+ if (firstDown && event.isMetaPressed()) {
+ if (event.isCtrlPressed()) {
+ enterStageSplitFromRunningApp(true /* leftOrTop */);
+ logKeyboardSystemsEvent(event, KeyboardLogEvent.SPLIT_SCREEN_NAVIGATION);
+ } else {
+ logKeyboardSystemsEvent(event, KeyboardLogEvent.BACK);
+ injectBackGesture(event.getDownTime());
+ }
return true;
}
break;
@@ -3630,6 +3642,25 @@ public class PhoneWindowManager implements WindowManagerPolicy {
return (metaState & KeyEvent.META_META_ON) != 0;
}
+ @SuppressLint("MissingPermission")
+ private void injectBackGesture(long downtime) {
+ // Create and inject down event
+ KeyEvent downEvent = new KeyEvent(downtime, downtime, KeyEvent.ACTION_DOWN,
+ KeyEvent.KEYCODE_BACK, 0 /* repeat */, 0 /* metaState */,
+ KeyCharacterMap.VIRTUAL_KEYBOARD, 0 /* scancode */,
+ KeyEvent.FLAG_FROM_SYSTEM | KeyEvent.FLAG_VIRTUAL_HARD_KEY,
+ InputDevice.SOURCE_KEYBOARD);
+ mInputManager.injectInputEvent(downEvent, InputManager.INJECT_INPUT_EVENT_MODE_ASYNC);
+
+
+ // Create and inject up event
+ KeyEvent upEvent = KeyEvent.changeAction(downEvent, KeyEvent.ACTION_UP);
+ mInputManager.injectInputEvent(upEvent, InputManager.INJECT_INPUT_EVENT_MODE_ASYNC);
+
+ downEvent.recycle();
+ upEvent.recycle();
+ }
+
private boolean handleHomeShortcuts(int displayId, IBinder focusedToken, KeyEvent event) {
// First we always handle the home key here, so applications
// can never break it, although if keyguard is on, we do let
@@ -5302,11 +5333,6 @@ public class PhoneWindowManager implements WindowManagerPolicy {
return false;
}
- if (theaterModeEnabled) {
- Settings.Global.putInt(mContext.getContentResolver(),
- Settings.Global.THEATER_MODE_ON, 0);
- }
-
mPowerManager.wakeUp(wakeTime, reason, details);
return true;
}
diff --git a/services/core/java/com/android/server/uri/UriGrantsManagerService.java b/services/core/java/com/android/server/uri/UriGrantsManagerService.java
index 01fdc8800c0e..7862f58374a3 100644
--- a/services/core/java/com/android/server/uri/UriGrantsManagerService.java
+++ b/services/core/java/com/android/server/uri/UriGrantsManagerService.java
@@ -41,6 +41,7 @@ import static org.xmlpull.v1.XmlPullParser.START_TAG;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
import android.app.ActivityManager;
import android.app.ActivityManagerInternal;
import android.app.AppGlobals;
@@ -62,6 +63,7 @@ import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
+import android.os.Process;
import android.os.RemoteException;
import android.os.SystemClock;
import android.os.UserHandle;
@@ -1304,6 +1306,46 @@ public class UriGrantsManagerService extends IUriGrantsManager.Stub implements
return false;
}
+ /**
+ * Check if the targetPkg can be granted permission to access uri by
+ * the callingUid using the given modeFlags. See {@link #checkGrantUriPermissionUnlocked}.
+ *
+ * @param callingUid The uid of the grantor app that has permissions to the uri.
+ * @param targetPkg The package name of the granted app that needs permissions to the uri.
+ * @param uri The uri for which permissions should be granted.
+ * @param modeFlags The modes to grant. See {@link Intent#FLAG_GRANT_READ_URI_PERMISSION}, etc.
+ * @param userId The userId in which the uri is to be resolved.
+ * @return uid of the target or -1 if permission grant not required. Returns -1 if the caller
+ * does not hold INTERACT_ACROSS_USERS_FULL
+ * @throws SecurityException if the grant is not allowed.
+ */
+ @Override
+ @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)
+ public int checkGrantUriPermission_ignoreNonSystem(int callingUid, String targetPkg, Uri uri,
+ int modeFlags, int userId) {
+ if (!isCallerIsSystemOrPrivileged()) {
+ return Process.INVALID_UID;
+ }
+ final long origId = Binder.clearCallingIdentity();
+ try {
+ return checkGrantUriPermissionUnlocked(callingUid, targetPkg, uri, modeFlags,
+ userId);
+ } finally {
+ Binder.restoreCallingIdentity(origId);
+ }
+ }
+
+ private boolean isCallerIsSystemOrPrivileged() {
+ final int uid = Binder.getCallingUid();
+ if (uid == Process.SYSTEM_UID || uid == Process.ROOT_UID) {
+ return true;
+ }
+ return ActivityManager.checkComponentPermission(
+ android.Manifest.permission.INTERACT_ACROSS_USERS_FULL,
+ uid, /* owningUid = */-1, /* exported = */ true)
+ == PackageManager.PERMISSION_GRANTED;
+ }
+
@Override
public ArrayList<UriPermission> providePersistentUriGrants() {
final ArrayList<UriPermission> result = new ArrayList<>();
diff --git a/services/core/java/com/android/server/utils/FoldSettingProvider.java b/services/core/java/com/android/server/utils/FoldSettingProvider.java
new file mode 100644
index 000000000000..d62628b73019
--- /dev/null
+++ b/services/core/java/com/android/server/utils/FoldSettingProvider.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2023 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.utils;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.util.Log;
+
+import com.android.internal.R;
+import com.android.internal.util.SettingsWrapper;
+
+import java.util.Set;
+
+/**
+ * This class provides a convenient way to access the {@link Settings.System#FOLD_LOCK_BEHAVIOR}.
+ * The {@link Settings.System#FOLD_LOCK_BEHAVIOR} setting controls the behavior of the device when
+ * it is folded, and provides the user with three different options to choose from. Those are:
+ * 1. Stay awake on fold: The device will remain unlocked when it is folded.
+ * 2. Selective stay awake: The device will remain unlocked when it is folded only if there are
+ * apps with wakelocks running. This is also the set default behavior.
+ * 3. Sleep on fold: The device will lock when it is folded, regardless of which apps are running
+ * or whether any wakelocks are held.
+ *
+ * Keep the setting values in this class in sync with the values in
+ * {@link com.android.settings.display.FoldLockBehaviorSettings}
+ */
+public class FoldSettingProvider {
+
+ public static final String SETTING_VALUE_STAY_AWAKE_ON_FOLD = "stay_awake_on_fold_key";
+ public static final String SETTING_VALUE_SELECTIVE_STAY_AWAKE = "selective_stay_awake_key";
+ public static final String SETTING_VALUE_SLEEP_ON_FOLD = "sleep_on_fold_key";
+ private static final String SETTING_VALUE_DEFAULT = SETTING_VALUE_SELECTIVE_STAY_AWAKE;
+ private static final Set<String> SETTING_VALUES = Set.of(SETTING_VALUE_STAY_AWAKE_ON_FOLD,
+ SETTING_VALUE_SELECTIVE_STAY_AWAKE, SETTING_VALUE_SLEEP_ON_FOLD);
+ private static final String TAG = "FoldSettingProvider";
+
+ private final ContentResolver mContentResolver;
+ private final boolean mIsFoldLockBehaviorAvailable;
+ private final SettingsWrapper mSettingsWrapper;
+
+ public FoldSettingProvider(Context context, SettingsWrapper settingsWrapper) {
+ mContentResolver = context.getContentResolver();
+ mSettingsWrapper = settingsWrapper;
+ mIsFoldLockBehaviorAvailable = context.getResources().getBoolean(
+ R.bool.config_fold_lock_behavior);
+ }
+
+ /**
+ * Returns whether the device should remain awake after folding.
+ */
+ public boolean shouldStayAwakeOnFold() {
+ return getFoldSettingValue().equals(SETTING_VALUE_STAY_AWAKE_ON_FOLD);
+ }
+
+ /**
+ * Returns whether the device should selective remain awake after folding.
+ */
+ public boolean shouldSelectiveStayAwakeOnFold() {
+ return getFoldSettingValue().equals(SETTING_VALUE_SELECTIVE_STAY_AWAKE);
+ }
+
+ /**
+ * Returns whether the device should strictly sleep after folding.
+ */
+ public boolean shouldSleepOnFold() {
+ return getFoldSettingValue().equals(SETTING_VALUE_SLEEP_ON_FOLD);
+ }
+
+ private String getFoldSettingValue() {
+ if (!mIsFoldLockBehaviorAvailable) {
+ return SETTING_VALUE_DEFAULT;
+ }
+ String foldSettingValue = mSettingsWrapper.getStringForUser(
+ mContentResolver,
+ Settings.System.FOLD_LOCK_BEHAVIOR,
+ UserHandle.USER_CURRENT);
+ foldSettingValue = (foldSettingValue != null) ? foldSettingValue : SETTING_VALUE_DEFAULT;
+ if (!SETTING_VALUES.contains(foldSettingValue)) {
+ Log.e(TAG,
+ "getFoldSettingValue: Invalid setting value, returning default setting value");
+ foldSettingValue = SETTING_VALUE_DEFAULT;
+ }
+
+ return foldSettingValue;
+ }
+}
diff --git a/services/core/java/com/android/server/utils/FoldSettingWrapper.java b/services/core/java/com/android/server/utils/FoldSettingWrapper.java
deleted file mode 100644
index 97a1ac06e24c..000000000000
--- a/services/core/java/com/android/server/utils/FoldSettingWrapper.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (C) 2023 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.utils;
-
-import android.content.ContentResolver;
-import android.provider.Settings;
-
-/**
- * A wrapper class for the {@link Settings.System#STAY_AWAKE_ON_FOLD} setting.
- *
- * This class provides a convenient way to access the {@link Settings.System#STAY_AWAKE_ON_FOLD}
- * setting for testing.
- */
-public class FoldSettingWrapper {
- private final ContentResolver mContentResolver;
-
- public FoldSettingWrapper(ContentResolver contentResolver) {
- mContentResolver = contentResolver;
- }
-
- /**
- * Returns whether the device should remain awake after folding.
- */
- public boolean shouldStayAwakeOnFold() {
- try {
- return (Settings.System.getIntForUser(
- mContentResolver,
- Settings.System.STAY_AWAKE_ON_FOLD,
- 0) == 1);
- } catch (Settings.SettingNotFoundException e) {
- return false;
- }
- }
-}
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 53d1adfefbb9..fd42077bed7d 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -6183,6 +6183,8 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
@Override
public void onPackageReplaced(ApplicationInfo aInfo) {
synchronized (mGlobalLock) {
+ // In case if setWindowManager hasn't been called yet when booting.
+ if (mRootWindowContainer == null) return;
mRootWindowContainer.updateActivityApplicationInfo(aInfo);
}
}
diff --git a/services/core/java/com/android/server/wm/Dimmer.java b/services/core/java/com/android/server/wm/Dimmer.java
index 4f3ab8bbbe0a..ae29afa9fc49 100644
--- a/services/core/java/com/android/server/wm/Dimmer.java
+++ b/services/core/java/com/android/server/wm/Dimmer.java
@@ -22,6 +22,7 @@ import static com.android.server.wm.AlphaAnimationSpecProto.TO;
import static com.android.server.wm.AnimationSpecProto.ALPHA;
import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_DIMMER;
+import android.annotation.NonNull;
import android.graphics.Rect;
import android.util.Log;
import android.util.proto.ProtoOutputStream;
@@ -178,6 +179,7 @@ class Dimmer {
mSurfaceAnimatorStarter = surfaceAnimatorStarter;
}
+ @NonNull
WindowContainer<?> getHost() {
return mHost;
}
@@ -199,13 +201,6 @@ class Dimmer {
try {
final SurfaceControl ctl = makeDimLayer();
mDimState = new DimState(ctl);
- /**
- * See documentation on {@link #dimAbove} to understand lifecycle management of
- * Dim's via state resetting for Dim's with containers.
- */
- if (container == null) {
- mDimState.mDontReset = true;
- }
} catch (Surface.OutOfResourcesException e) {
Log.w(TAG, "OutOfResourcesException creating dim surface");
}
@@ -241,7 +236,7 @@ class Dimmer {
* @param container The container which to dim above. Should be a child of our host.
* @param alpha The alpha at which to Dim.
*/
- void dimAbove(WindowContainer container, float alpha) {
+ void dimAbove(@NonNull WindowContainer container, float alpha) {
dim(container, 1, alpha, 0);
}
@@ -253,7 +248,7 @@ class Dimmer {
* @param blurRadius The amount of blur added to the Dim.
*/
- void dimBelow(WindowContainer container, float alpha, int blurRadius) {
+ void dimBelow(@NonNull WindowContainer container, float alpha, int blurRadius) {
dim(container, -1, alpha, blurRadius);
}
@@ -316,7 +311,12 @@ class Dimmer {
if (!mDimState.isVisible) {
mDimState.isVisible = true;
t.show(mDimState.mDimLayer);
- startDimEnter(mLastRequestedDimContainer, mDimState.mSurfaceAnimator, t);
+ // Skip enter animation while starting window is on top of its activity
+ final WindowState ws = mLastRequestedDimContainer.asWindowState();
+ if (ws == null || ws.mActivityRecord == null
+ || ws.mActivityRecord.mStartingData == null) {
+ startDimEnter(mLastRequestedDimContainer, mDimState.mSurfaceAnimator, t);
+ }
}
return true;
}
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 334464c8a503..daa73db4684d 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -743,9 +743,6 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
/** Set of activities in foreground size compat mode. */
private Set<ActivityRecord> mActiveSizeCompatActivities = new ArraySet<>();
- // Used in updating the display size
- private Point mTmpDisplaySize = new Point();
-
// Used in updating override configurations
private final Configuration mTempConfig = new Configuration();
@@ -4797,25 +4794,6 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
}, false /* traverseTopToBottom */);
}
- /**
- * Starts the Keyguard exit animation on all windows that don't belong to an app token.
- */
- void startKeyguardExitOnNonAppWindows(boolean onWallpaper, boolean goingToShade,
- boolean subtle) {
- final WindowManagerPolicy policy = mWmService.mPolicy;
- forAllWindows(w -> {
- if (w.mActivityRecord == null && w.canBeHiddenByKeyguard()
- && w.wouldBeVisibleIfPolicyIgnored() && !w.isVisible()) {
- w.startAnimation(policy.createHiddenByKeyguardExit(
- onWallpaper, goingToShade, subtle));
- }
- }, true /* traverseTopToBottom */);
- for (int i = mShellRoots.size() - 1; i >= 0; --i) {
- mShellRoots.valueAt(i).startAnimation(policy.createHiddenByKeyguardExit(
- onWallpaper, goingToShade, subtle));
- }
- }
-
/** @return {@code true} if there is window to wait before enabling the screen. */
boolean shouldWaitForSystemDecorWindowsOnBoot() {
if (!isDefaultDisplay && !supportsSystemDecorations()) {
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index 1871cf6175c5..707b7799460e 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -17,6 +17,7 @@
package com.android.server.wm;
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
+import static android.inputmethodservice.InputMethodService.ENABLE_HIDE_IME_CAPTION_BAR;
import static android.view.Display.TYPE_INTERNAL;
import static android.view.InsetsFrameProvider.SOURCE_ARBITRARY_RECTANGLE;
import static android.view.InsetsFrameProvider.SOURCE_CONTAINER_BOUNDS;
@@ -1201,8 +1202,8 @@ public class DisplayPolicy {
throw new IllegalArgumentException("IME insets must be provided by a window.");
}
- if (mNavigationBar != null && navigationBarPosition(displayFrames.mRotation)
- == NAV_BAR_BOTTOM) {
+ if (!ENABLE_HIDE_IME_CAPTION_BAR && mNavigationBar != null
+ && navigationBarPosition(displayFrames.mRotation) == NAV_BAR_BOTTOM) {
// In gesture navigation, nav bar frame is larger than frame to calculate insets.
// IME should not provide frame which is smaller than the nav bar frame. Otherwise,
// nav bar might be overlapped with the content of the client when IME is shown.
diff --git a/services/core/java/com/android/server/wm/DisplayRotation.java b/services/core/java/com/android/server/wm/DisplayRotation.java
index 315c479cda30..d461d1ec02f0 100644
--- a/services/core/java/com/android/server/wm/DisplayRotation.java
+++ b/services/core/java/com/android/server/wm/DisplayRotation.java
@@ -948,7 +948,7 @@ public class DisplayRotation {
mDisplayWindowSettings.setUserRotation(mDisplayContent, userRotationMode,
userRotation);
if (changed) {
- mService.updateRotation(true /* alwaysSendConfiguration */,
+ mService.updateRotation(false /* alwaysSendConfiguration */,
false /* forceRelayout */);
}
}
@@ -2127,7 +2127,7 @@ public class DisplayRotation {
@Override
public void onChange(boolean selfChange) {
if (updateSettings()) {
- mService.updateRotation(true /* alwaysSendConfiguration */,
+ mService.updateRotation(false /* alwaysSendConfiguration */,
false /* forceRelayout */);
}
}
diff --git a/services/core/java/com/android/server/wm/LetterboxConfiguration.java b/services/core/java/com/android/server/wm/LetterboxConfiguration.java
index 97b3e3280f2b..45cf10bd3f5e 100644
--- a/services/core/java/com/android/server/wm/LetterboxConfiguration.java
+++ b/services/core/java/com/android/server/wm/LetterboxConfiguration.java
@@ -80,10 +80,10 @@ final class LetterboxConfiguration {
// Whether per-app user aspect ratio override settings is enabled
private static final String KEY_ENABLE_USER_ASPECT_RATIO_SETTINGS =
- "enable_app_compat_user_aspect_ratio_settings";
+ "enable_app_compat_aspect_ratio_user_settings";
// TODO(b/288142656): Enable user aspect ratio settings by default.
- private static final boolean DEFAULT_VALUE_ENABLE_USER_ASPECT_RATIO_SETTINGS = false;
+ private static final boolean DEFAULT_VALUE_ENABLE_USER_ASPECT_RATIO_SETTINGS = true;
// Whether per-app fullscreen user aspect ratio override option is enabled
private static final String KEY_ENABLE_USER_ASPECT_RATIO_FULLSCREEN =
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index d56acaa00f00..2fdfec04b895 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -258,10 +258,6 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
*/
final SparseArray<SleepToken> mSleepTokens = new SparseArray<>();
- // The default minimal size that will be used if the activity doesn't specify its minimal size.
- // It will be calculated when the default display gets added.
- int mDefaultMinSizeOfResizeableTaskDp = -1;
-
// Whether tasks have moved and we need to rank the tasks before next OOM scoring
private boolean mTaskLayersChanged = true;
private int mTmpTaskLayerRank;
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 21a4fe880ab6..21526e789c04 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -3543,11 +3543,6 @@ class Task extends TaskFragment {
? null : new PictureInPictureParams(top.pictureInPictureArgs);
}
- private boolean shouldDockBigOverlays() {
- final ActivityRecord topMostActivity = getTopMostActivity();
- return topMostActivity != null && topMostActivity.shouldDockBigOverlays;
- }
-
Rect getDisplayCutoutInsets() {
if (mDisplayContent == null || getDisplayInfo().displayCutout == null) return null;
final WindowState w = getTopVisibleAppMainWindow();
diff --git a/services/core/java/com/android/server/wm/Transition.java b/services/core/java/com/android/server/wm/Transition.java
index 81f91c739bc3..a6c64912edd3 100644
--- a/services/core/java/com/android/server/wm/Transition.java
+++ b/services/core/java/com/android/server/wm/Transition.java
@@ -440,10 +440,11 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener {
boolean canApplyDim(@NonNull Task task) {
if (mTransientLaunches == null) return true;
final Dimmer dimmer = task.getDimmer();
- final WindowContainer<?> dimmerHost = dimmer != null ? dimmer.getHost() : null;
- if (dimmerHost == null) return false;
- if (isInTransientHide(dimmerHost)) {
- // The layer of dimmer is inside transient-hide task, then allow to dim.
+ if (dimmer == null) {
+ return false;
+ }
+ if (dimmer.getHost().asTask() != null) {
+ // Always allow to dim if the host only affects its task.
return true;
}
// The dimmer host of a translucent task can be a display, then it is not in transient-hide.
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index dae61da26b68..4a0f44b58ecf 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -1135,13 +1135,6 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
return parent != null && parent.isAttached();
}
- void setWaitingForDrawnIfResizingChanged() {
- for (int i = mChildren.size() - 1; i >= 0; --i) {
- final WindowContainer wc = mChildren.get(i);
- wc.setWaitingForDrawnIfResizingChanged();
- }
- }
-
void onResize() {
if (mControllableInsetProvider != null) {
mControllableInsetProvider.onWindowContainerBoundsChanged();
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 9c04e0aab8f3..b12cc0b30f53 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -1717,29 +1717,6 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
}
/**
- * This is a form of rectangle "difference". It cut off each dimension of rect by the amount
- * that toRemove is "pushing into" it from the outside. Any dimension that fully contains
- * toRemove won't change.
- */
- private void cutRect(Rect rect, Rect toRemove) {
- if (toRemove.isEmpty()) return;
- if (toRemove.top < rect.bottom && toRemove.bottom > rect.top) {
- if (toRemove.right >= rect.right && toRemove.left >= rect.left) {
- rect.right = toRemove.left;
- } else if (toRemove.left <= rect.left && toRemove.right <= rect.right) {
- rect.left = toRemove.right;
- }
- }
- if (toRemove.left < rect.right && toRemove.right > rect.left) {
- if (toRemove.bottom >= rect.bottom && toRemove.top >= rect.top) {
- rect.bottom = toRemove.top;
- } else if (toRemove.top <= rect.top && toRemove.bottom <= rect.bottom) {
- rect.top = toRemove.bottom;
- }
- }
- }
-
- /**
* Retrieves the visible bounds of the window.
* @param bounds The rect which gets the bounds.
*/
@@ -3965,14 +3942,6 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
return mDragResizing != computeDragResizing();
}
- @Override
- void setWaitingForDrawnIfResizingChanged() {
- if (isDragResizeChanged()) {
- mWmService.mRoot.mWaitingForDrawn.add(this);
- }
- super.setWaitingForDrawnIfResizingChanged();
- }
-
/**
* Resets the state whether we reported a drag resize change to the app.
*/
@@ -5524,10 +5493,6 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
outRegion.translate(mWindowFrames.mFrame.left, mWindowFrames.mFrame.top);
}
- boolean hasTapExcludeRegion() {
- return !mTapExcludeRegion.isEmpty();
- }
-
boolean isImeLayeringTarget() {
return getDisplayContent().getImeTarget(IME_TARGET_LAYERING) == this;
}
diff --git a/services/core/java/com/android/server/wm/WindowToken.java b/services/core/java/com/android/server/wm/WindowToken.java
index 4d7335873074..e434f296bbb5 100644
--- a/services/core/java/com/android/server/wm/WindowToken.java
+++ b/services/core/java/com/android/server/wm/WindowToken.java
@@ -17,7 +17,6 @@
package com.android.server.wm;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
-import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ADD_REMOVE;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS;
@@ -746,17 +745,6 @@ class WindowToken extends WindowContainer<WindowState> {
return this;
}
- /**
- * Return whether windows from this token can layer above the
- * system bars, or in other words extend outside of the "Decor Frame"
- */
- boolean canLayerAboveSystemBars() {
- int layer = getWindowLayerFromType();
- int navLayer = mWmService.mPolicy.getWindowLayerFromTypeLw(TYPE_NAVIGATION_BAR,
- mOwnerCanManageAppTokens);
- return mOwnerCanManageAppTokens && (layer > navLayer);
- }
-
int getWindowLayerFromType() {
return mWmService.mPolicy.getWindowLayerFromTypeLw(windowType, mOwnerCanManageAppTokens,
mRoundedCornerOverlay);
diff --git a/services/core/jni/Android.bp b/services/core/jni/Android.bp
index 2a995b24ef4f..ec5378f01ce3 100644
--- a/services/core/jni/Android.bp
+++ b/services/core/jni/Android.bp
@@ -41,6 +41,7 @@ cc_library_static {
"com_android_server_companion_virtual_InputController.cpp",
"com_android_server_devicepolicy_CryptoTestHelper.cpp",
"com_android_server_display_DisplayControl.cpp",
+ "com_android_server_display_SmallAreaDetectionController.cpp",
"com_android_server_connectivity_Vpn.cpp",
"com_android_server_gpu_GpuService.cpp",
"com_android_server_HardwarePropertiesManagerService.cpp",
diff --git a/services/core/jni/com_android_server_display_SmallAreaDetectionController.cpp b/services/core/jni/com_android_server_display_SmallAreaDetectionController.cpp
new file mode 100644
index 000000000000..b256f168f2af
--- /dev/null
+++ b/services/core/jni/com_android_server_display_SmallAreaDetectionController.cpp
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2023 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.
+ */
+
+#define LOG_TAG "SmallAreaDetectionController"
+
+#include <gui/SurfaceComposerClient.h>
+#include <nativehelper/JNIHelp.h>
+#include <nativehelper/ScopedPrimitiveArray.h>
+
+#include "jni.h"
+#include "utils/Log.h"
+
+namespace android {
+static void nativeUpdateSmallAreaDetection(JNIEnv* env, jclass clazz, jintArray juids,
+ jfloatArray jthresholds) {
+ if (juids == nullptr || jthresholds == nullptr) return;
+
+ ScopedIntArrayRO uids(env, juids);
+ ScopedFloatArrayRO thresholds(env, jthresholds);
+
+ if (uids.size() != thresholds.size()) {
+ ALOGE("uids size exceeds thresholds size!");
+ return;
+ }
+
+ std::vector<int32_t> uidVector;
+ std::vector<float> thresholdVector;
+ size_t size = uids.size();
+ uidVector.reserve(size);
+ thresholdVector.reserve(size);
+ for (int i = 0; i < size; i++) {
+ uidVector.push_back(static_cast<int32_t>(uids[i]));
+ thresholdVector.push_back(static_cast<float>(thresholds[i]));
+ }
+ SurfaceComposerClient::updateSmallAreaDetection(uidVector, thresholdVector);
+}
+
+static void nativeSetSmallAreaDetectionThreshold(JNIEnv* env, jclass clazz, jint uid,
+ jfloat threshold) {
+ SurfaceComposerClient::setSmallAreaDetectionThreshold(uid, threshold);
+}
+
+static const JNINativeMethod gMethods[] = {
+ {"nativeUpdateSmallAreaDetection", "([I[F)V", (void*)nativeUpdateSmallAreaDetection},
+ {"nativeSetSmallAreaDetectionThreshold", "(IF)V",
+ (void*)nativeSetSmallAreaDetectionThreshold},
+};
+
+int register_android_server_display_smallAreaDetectionController(JNIEnv* env) {
+ return jniRegisterNativeMethods(env, "com/android/server/display/SmallAreaDetectionController",
+ gMethods, NELEM(gMethods));
+}
+
+}; // namespace android
diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp
index 6e0d98cab8e6..55deb2203a03 100644
--- a/services/core/jni/com_android_server_input_InputManagerService.cpp
+++ b/services/core/jni/com_android_server_input_InputManagerService.cpp
@@ -372,7 +372,7 @@ public:
virtual void onPointerDisplayIdChanged(int32_t displayId, const FloatPoint& position);
/* --- PointerControllerPolicyInterface implementation --- */
- virtual std::shared_ptr<PointerControllerInterface> createPointerController() override;
+ std::shared_ptr<PointerControllerInterface> createPointerController() override;
private:
sp<InputManagerInterface> mInputManager;
@@ -489,7 +489,7 @@ void NativeInputManager::dump(std::string& dump) {
dump += StringPrintf(INDENT "Pointer Capture: %s, seq=%" PRIu32 "\n",
mLocked.pointerCaptureRequest.enable ? "Enabled" : "Disabled",
mLocked.pointerCaptureRequest.seq);
- forEachPointerControllerLocked([&dump](PointerController& pc) { pc.dump(dump); });
+ forEachPointerControllerLocked([&dump](PointerController& pc) { dump += pc.dump(); });
} // release lock
dump += "\n";
@@ -530,9 +530,8 @@ void NativeInputManager::setDisplayViewports(JNIEnv* env, jobjectArray viewportO
{ // acquire lock
std::scoped_lock _l(mLock);
mLocked.viewports = viewports;
- forEachPointerControllerLocked([viewports = std::move(viewports)](PointerController& pc) {
- pc.onDisplayViewportsUpdated(viewports);
- });
+ forEachPointerControllerLocked(
+ [&viewports](PointerController& pc) { pc.onDisplayViewportsUpdated(viewports); });
} // release lock
mInputManager->getReader().requestRefreshConfiguration(
diff --git a/services/core/jni/onload.cpp b/services/core/jni/onload.cpp
index 97d7be6a718e..f6f673746609 100644
--- a/services/core/jni/onload.cpp
+++ b/services/core/jni/onload.cpp
@@ -67,6 +67,7 @@ int register_android_server_app_GameManagerService(JNIEnv* env);
int register_com_android_server_wm_TaskFpsCallbackController(JNIEnv* env);
int register_com_android_server_display_DisplayControl(JNIEnv* env);
int register_com_android_server_SystemClockTime(JNIEnv* env);
+int register_android_server_display_smallAreaDetectionController(JNIEnv* env);
};
using namespace android;
@@ -126,5 +127,6 @@ extern "C" jint JNI_OnLoad(JavaVM* vm, void* /* reserved */)
register_com_android_server_wm_TaskFpsCallbackController(env);
register_com_android_server_display_DisplayControl(env);
register_com_android_server_SystemClockTime(env);
+ register_android_server_display_smallAreaDetectionController(env);
return JNI_VERSION_1_4;
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/RemoteBugreportManager.java b/services/devicepolicy/java/com/android/server/devicepolicy/RemoteBugreportManager.java
index 9a8e421d5d12..8684dbe73947 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/RemoteBugreportManager.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/RemoteBugreportManager.java
@@ -111,7 +111,7 @@ public class RemoteBugreportManager {
@Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
- mInjector.getNotificationManager().cancel(LOG_TAG, NOTIFICATION_ID);
+ cancelNotification();
if (ACTION_BUGREPORT_SHARING_ACCEPTED.equals(action)) {
onBugreportSharingAccepted();
} else if (ACTION_BUGREPORT_SHARING_DECLINED.equals(action)) {
@@ -213,8 +213,7 @@ public class RemoteBugreportManager {
mRemoteBugreportServiceIsActive.set(true);
mRemoteBugreportSharingAccepted.set(false);
registerRemoteBugreportReceivers();
- mInjector.getNotificationManager().notifyAsUser(LOG_TAG, NOTIFICATION_ID,
- buildNotification(NOTIFICATION_BUGREPORT_STARTED), UserHandle.ALL);
+ notify(NOTIFICATION_BUGREPORT_STARTED);
mHandler.postDelayed(mRemoteBugreportTimeoutRunnable, REMOTE_BUGREPORT_TIMEOUT_MILLIS);
return true;
} catch (RemoteException re) {
@@ -258,13 +257,10 @@ public class RemoteBugreportManager {
final String bugreportHash = intent.getStringExtra(EXTRA_REMOTE_BUGREPORT_HASH);
if (mRemoteBugreportSharingAccepted.get()) {
shareBugreportWithDeviceOwnerIfExists(bugreportUriString, bugreportHash);
- mInjector.getNotificationManager().cancel(LOG_TAG,
- NOTIFICATION_ID);
+ cancelNotification();
} else {
mService.setDeviceOwnerRemoteBugreportUriAndHash(bugreportUriString, bugreportHash);
- mInjector.getNotificationManager().notifyAsUser(LOG_TAG, NOTIFICATION_ID,
- buildNotification(NOTIFICATION_BUGREPORT_FINISHED_NOT_ACCEPTED),
- UserHandle.ALL);
+ notify(NOTIFICATION_BUGREPORT_FINISHED_NOT_ACCEPTED);
}
mContext.unregisterReceiver(mRemoteBugreportFinishedReceiver);
}
@@ -274,7 +270,7 @@ public class RemoteBugreportManager {
mInjector.systemPropertiesSet(CTL_STOP, REMOTE_BUGREPORT_SERVICE);
mRemoteBugreportSharingAccepted.set(false);
mService.setDeviceOwnerRemoteBugreportUriAndHash(null, null);
- mInjector.getNotificationManager().cancel(LOG_TAG, NOTIFICATION_ID);
+ cancelNotification();
final Bundle extras = new Bundle();
extras.putInt(DeviceAdminReceiver.EXTRA_BUGREPORT_FAILURE_REASON,
DeviceAdminReceiver.BUGREPORT_FAILURE_FAILED_COMPLETING);
@@ -289,9 +285,7 @@ public class RemoteBugreportManager {
if (uriAndHash != null) {
shareBugreportWithDeviceOwnerIfExists(uriAndHash.first, uriAndHash.second);
} else if (mRemoteBugreportServiceIsActive.get()) {
- mInjector.getNotificationManager().notifyAsUser(LOG_TAG, NOTIFICATION_ID,
- buildNotification(NOTIFICATION_BUGREPORT_ACCEPTED_NOT_FINISHED),
- UserHandle.ALL);
+ notify(NOTIFICATION_BUGREPORT_ACCEPTED_NOT_FINISHED);
}
}
@@ -340,7 +334,16 @@ public class RemoteBugreportManager {
filterConsent.addAction(ACTION_BUGREPORT_SHARING_DECLINED);
filterConsent.addAction(ACTION_BUGREPORT_SHARING_ACCEPTED);
mContext.registerReceiver(mRemoteBugreportConsentReceiver, filterConsent);
- mInjector.getNotificationManager().notifyAsUser(LOG_TAG, NOTIFICATION_ID,
- buildNotification(NOTIFICATION_BUGREPORT_FINISHED_NOT_ACCEPTED), UserHandle.ALL);
+ notify(NOTIFICATION_BUGREPORT_FINISHED_NOT_ACCEPTED);
+ }
+
+ private void notify(@RemoteBugreportNotificationType int type) {
+ mInjector.getNotificationManager()
+ .notifyAsUser(LOG_TAG, NOTIFICATION_ID, buildNotification(type), UserHandle.ALL);
+ }
+
+ private void cancelNotification() {
+ mInjector.getNotificationManager()
+ .cancelAsUser(LOG_TAG, NOTIFICATION_ID, UserHandle.ALL);
}
}
diff --git a/services/tests/InputMethodSystemServerTests/src/com/android/inputmethodservice/InputMethodServiceTest.java b/services/tests/InputMethodSystemServerTests/src/com/android/inputmethodservice/InputMethodServiceTest.java
index e8acb067f625..6ff7b2601b79 100644
--- a/services/tests/InputMethodSystemServerTests/src/com/android/inputmethodservice/InputMethodServiceTest.java
+++ b/services/tests/InputMethodSystemServerTests/src/com/android/inputmethodservice/InputMethodServiceTest.java
@@ -16,15 +16,20 @@
package com.android.inputmethodservice;
+import static android.view.WindowInsets.Type.captionBar;
+
import static com.android.compatibility.common.util.SystemUtil.eventually;
import static com.google.common.truth.Truth.assertThat;
+import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
+import static org.junit.Assume.assumeFalse;
import android.app.Instrumentation;
import android.content.Context;
import android.content.res.Configuration;
+import android.graphics.Insets;
import android.os.RemoteException;
import android.provider.Settings;
import android.support.test.uiautomator.By;
@@ -32,6 +37,7 @@ import android.support.test.uiautomator.UiDevice;
import android.support.test.uiautomator.UiObject2;
import android.support.test.uiautomator.Until;
import android.util.Log;
+import android.view.WindowManagerGlobal;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
@@ -592,6 +598,20 @@ public class InputMethodServiceTest {
false /* orientationPortrait */);
}
+ /**
+ * This checks that when the system navigation bar is not created (e.g. emulator),
+ * then the IME caption bar is also not created.
+ */
+ @Test
+ public void testNoNavigationBar_thenImeNoCaptionBar() throws Exception {
+ boolean hasNavigationBar = WindowManagerGlobal.getWindowManagerService()
+ .hasNavigationBar(mInputMethodService.getDisplayId());
+ assumeFalse("Must not have a navigation bar", hasNavigationBar);
+
+ assertEquals(Insets.NONE, mInputMethodService.getWindow().getWindow().getDecorView()
+ .getRootWindowInsets().getInsetsIgnoringVisibility(captionBar()));
+ }
+
private void verifyInputViewStatus(
Runnable runnable, boolean expected, boolean inputViewStarted)
throws InterruptedException {
diff --git a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageManagerServiceTest.java b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageManagerServiceTest.java
index a805e5c9f87e..bea654305a9f 100644
--- a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageManagerServiceTest.java
+++ b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageManagerServiceTest.java
@@ -125,7 +125,7 @@ public class PackageManagerServiceTest {
Assert.assertNull(pri.mBroadcastUsers);
// populateUsers with nothing leaves nothing
- pri.populateUsers(null, setting);
+ pri.populateBroadcastUsers(setting);
Assert.assertNull(pri.mBroadcastUsers);
// Create a real (non-null) PackageSetting and confirm that the removed
@@ -139,9 +139,10 @@ public class PackageManagerServiceTest {
.setSecondaryCpuAbiString("secondaryCpuAbiString")
.setCpuAbiOverrideString("cpuAbiOverrideString")
.build();
- pri.populateUsers(new int[]{
+ pri.mRemovedUsers = new int[]{
1, 2, 3, 4, 5
- }, setting);
+ };
+ pri.populateBroadcastUsers(setting);
Assert.assertNotNull(pri.mBroadcastUsers);
Assert.assertEquals(5, pri.mBroadcastUsers.length);
Assert.assertNotNull(pri.mInstantUserIds);
@@ -151,9 +152,10 @@ public class PackageManagerServiceTest {
pri.mBroadcastUsers = null;
final int EXCLUDED_USER_ID = 4;
setting.setInstantApp(true, EXCLUDED_USER_ID);
- pri.populateUsers(new int[]{
+ pri.mRemovedUsers = new int[]{
1, 2, 3, EXCLUDED_USER_ID, 5
- }, setting);
+ };
+ pri.populateBroadcastUsers(setting);
Assert.assertNotNull(pri.mBroadcastUsers);
Assert.assertEquals(4, pri.mBroadcastUsers.length);
Assert.assertNotNull(pri.mInstantUserIds);
diff --git a/services/tests/displayservicetests/Android.bp b/services/tests/displayservicetests/Android.bp
index fb14419a13c0..e28028f9fc2b 100644
--- a/services/tests/displayservicetests/Android.bp
+++ b/services/tests/displayservicetests/Android.bp
@@ -35,6 +35,7 @@ android_test {
"mockingservicestests-utils-mockito",
"platform-compat-test-rules",
"platform-test-annotations",
+ "service-permission.stubs.system_server",
"services.core",
"servicestests-utils",
"testables",
diff --git a/services/tests/displayservicetests/src/com/android/server/display/AutomaticBrightnessControllerTest.java b/services/tests/displayservicetests/src/com/android/server/display/AutomaticBrightnessControllerTest.java
index d16c37a4c07a..2bdebe26e551 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/AutomaticBrightnessControllerTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/AutomaticBrightnessControllerTest.java
@@ -267,7 +267,8 @@ public class AutomaticBrightnessControllerTest {
/* shouldResetShortTermModel= */ true);
// There should be a user data point added to the mapper.
- verify(mBrightnessMappingStrategy).addUserDataPoint(1000f, 0.5f);
+ verify(mBrightnessMappingStrategy).addUserDataPoint(/* lux= */ 1000f,
+ /* brightness= */ 0.5f);
}
@Test
@@ -295,7 +296,8 @@ public class AutomaticBrightnessControllerTest {
mController.recalculateSplines(true, adjustments);
verify(mBrightnessMappingStrategy).clearUserDataPoints();
verify(mBrightnessMappingStrategy).recalculateSplines(true, adjustments);
- verify(mBrightnessMappingStrategy, times(2)).addUserDataPoint(currentLux, 0.5f);
+ verify(mBrightnessMappingStrategy, times(2)).addUserDataPoint(currentLux,
+ /* brightness= */ 0.5f);
clearInvocations(mBrightnessMappingStrategy);
@@ -342,7 +344,7 @@ public class AutomaticBrightnessControllerTest {
// Verify only happens on the first configure. (i.e. not again when switching back)
// Intentionally using any() to ensure it's not called whatsoever.
verify(mBrightnessMappingStrategy, times(1))
- .addUserDataPoint(123.0f, 0.5f);
+ .addUserDataPoint(/* lux= */ 123.0f, /* brightness= */ 0.5f);
verify(mBrightnessMappingStrategy, times(1))
.addUserDataPoint(anyFloat(), anyFloat());
}
@@ -385,7 +387,7 @@ public class AutomaticBrightnessControllerTest {
// Verify that we add the data point once when the user sets it, and again when we return
// interactive mode.
verify(mBrightnessMappingStrategy, times(2))
- .addUserDataPoint(123.0f, 0.51f);
+ .addUserDataPoint(/* lux= */ 123.0f, /* brightness= */ 0.51f);
}
@Test
@@ -428,7 +430,7 @@ public class AutomaticBrightnessControllerTest {
// Verify only happens on the first configure. (i.e. not again when switching back)
// Intentionally using any() to ensure it's not called whatsoever.
verify(mBrightnessMappingStrategy, times(1))
- .addUserDataPoint(123.0f, 0.5f);
+ .addUserDataPoint(/* lux= */ 123.0f, /* brightness= */ 0.5f);
verify(mBrightnessMappingStrategy, times(1))
.addUserDataPoint(anyFloat(), anyFloat());
}
@@ -474,7 +476,7 @@ public class AutomaticBrightnessControllerTest {
// Verify this happens on the first configure and again when switching back
// Intentionally using any() to ensure it's not called any other times whatsoever.
verify(mBrightnessMappingStrategy, times(2))
- .addUserDataPoint(123.0f, 0.5f);
+ .addUserDataPoint(/* lux= */ 123.0f, /* brightness= */ 0.5f);
verify(mBrightnessMappingStrategy, times(2))
.addUserDataPoint(anyFloat(), anyFloat());
}
@@ -533,7 +535,8 @@ public class AutomaticBrightnessControllerTest {
/* shouldResetShortTermModel= */ true);
// There should be a user data point added to the mapper.
- verify(mBrightnessMappingStrategy, times(1)).addUserDataPoint(1000f, 0.5f);
+ verify(mBrightnessMappingStrategy, times(1)).addUserDataPoint(/* lux= */ 1000f,
+ /* brightness= */ 0.5f);
verify(mBrightnessMappingStrategy, times(2)).setBrightnessConfiguration(any());
verify(mBrightnessMappingStrategy, times(3)).getBrightness(anyFloat(), any(), anyInt());
@@ -559,7 +562,8 @@ public class AutomaticBrightnessControllerTest {
/* shouldResetShortTermModel= */ true);
// Ensure we use the correct mapping strategy
- verify(mIdleBrightnessMappingStrategy, times(1)).addUserDataPoint(1000f, 0.5f);
+ verify(mIdleBrightnessMappingStrategy, times(1)).addUserDataPoint(/* lux= */ 1000f,
+ /* brightness= */ 0.5f);
}
@Test
diff --git a/services/tests/displayservicetests/src/com/android/server/display/BrightnessMappingStrategyTest.java b/services/tests/displayservicetests/src/com/android/server/display/BrightnessMappingStrategyTest.java
index ee7826f13578..97e582607133 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/BrightnessMappingStrategyTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/BrightnessMappingStrategyTest.java
@@ -445,7 +445,7 @@ public class BrightnessMappingStrategyTest {
// Add a data point in the middle of the curve where the user has set the brightness max
final int idx = LUX_LEVELS.length / 2;
- strategy.addUserDataPoint(LUX_LEVELS[idx], 1.0f);
+ strategy.addUserDataPoint(LUX_LEVELS[idx], /* brightness= */ 1.0f);
// Then make sure that all control points after the middle lux level are also set to max...
for (int i = idx; i < LUX_LEVELS.length; i++) {
@@ -662,11 +662,11 @@ public class BrightnessMappingStrategyTest {
GAMMA_CORRECTION_NITS);
BrightnessMappingStrategy strategy = BrightnessMappingStrategy.create(resources, ddc,
mMockDwbc);
- assertEquals(0.0f, strategy.getAutoBrightnessAdjustment(), 0.0001f /* tolerance */);
- strategy.addUserDataPoint(2500, 1.0f);
- assertEquals(+1.0f, strategy.getAutoBrightnessAdjustment(), 0.0001f /* tolerance */);
- strategy.addUserDataPoint(2500, 0.0f);
- assertEquals(-1.0f, strategy.getAutoBrightnessAdjustment(), 0.0001f /* tolerance */);
+ assertEquals(0.0f, strategy.getAutoBrightnessAdjustment(), /* delta= */ 0.0001f);
+ strategy.addUserDataPoint(/* lux= */ 2500, /* brightness= */ 1.0f);
+ assertEquals(+1.0f, strategy.getAutoBrightnessAdjustment(), /* delta= */ 0.0001f);
+ strategy.addUserDataPoint(/* lux= */ 2500, /* brightness= */ 0.0f);
+ assertEquals(-1.0f, strategy.getAutoBrightnessAdjustment(), /* delta= */ 0.0001f);
}
@Test
@@ -701,7 +701,7 @@ public class BrightnessMappingStrategyTest {
// Similarly, if we set a user data point at (x4, 1.0), the adjustment should be 1 - y4.
adjustment = 1.0f - y4;
gamma = (float) MathUtils.pow(MAXIMUM_GAMMA, -adjustment);
- strategy.addUserDataPoint(x4, 1.0f);
+ strategy.addUserDataPoint(x4, /* brightness= */ 1.0f);
assertEquals(MathUtils.pow(y0, gamma), strategy.getBrightness(x0), 0.0001f /* tolerance */);
assertEquals(MathUtils.pow(y2, gamma), strategy.getBrightness(x2), 0.0001f /* tolerance */);
assertEquals(1.0f, strategy.getBrightness(x4), 0.0001f /* tolerance */);
diff --git a/services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java b/services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java
index 40d7a774608b..a23539e37409 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java
@@ -64,6 +64,7 @@ import android.compat.testing.PlatformCompatChangeRule;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.pm.PackageManager;
+import android.content.pm.PackageManagerInternal;
import android.content.res.Resources;
import android.graphics.Insets;
import android.graphics.Rect;
@@ -113,6 +114,7 @@ import com.android.server.display.DisplayManagerService.SyncRoot;
import com.android.server.display.feature.DisplayManagerFlags;
import com.android.server.input.InputManagerInternal;
import com.android.server.lights.LightsManager;
+import com.android.server.pm.UserManagerInternal;
import com.android.server.sensors.SensorManagerInternal;
import com.android.server.wm.WindowManagerInternal;
@@ -291,10 +293,11 @@ public class DisplayManagerServiceTest {
@Mock LocalDisplayAdapter.SurfaceControlProxy mSurfaceControlProxy;
@Mock IBinder mMockDisplayToken;
@Mock SensorManagerInternal mMockSensorManagerInternal;
-
@Mock SensorManager mSensorManager;
-
@Mock DisplayDeviceConfig mMockDisplayDeviceConfig;
+ @Mock PackageManagerInternal mMockPackageManagerInternal;
+ @Mock UserManagerInternal mMockUserManagerInternal;
+
@Captor ArgumentCaptor<ContentRecordingSession> mContentRecordingSessionCaptor;
@Mock DisplayManagerFlags mMockFlags;
@@ -315,6 +318,10 @@ public class DisplayManagerServiceTest {
LocalServices.removeServiceForTest(VirtualDeviceManagerInternal.class);
LocalServices.addService(
VirtualDeviceManagerInternal.class, mMockVirtualDeviceManagerInternal);
+ LocalServices.removeServiceForTest(PackageManagerInternal.class);
+ LocalServices.addService(PackageManagerInternal.class, mMockPackageManagerInternal);
+ LocalServices.removeServiceForTest(UserManagerInternal.class);
+ LocalServices.addService(UserManagerInternal.class, mMockUserManagerInternal);
// TODO: b/287945043
mContext = spy(new ContextWrapper(ApplicationProvider.getApplicationContext()));
mResources = Mockito.spy(mContext.getResources());
diff --git a/services/tests/displayservicetests/src/com/android/server/display/LogicalDisplayMapperTest.java b/services/tests/displayservicetests/src/com/android/server/display/LogicalDisplayMapperTest.java
index 69544356ab5b..065dd1f1f743 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/LogicalDisplayMapperTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/LogicalDisplayMapperTest.java
@@ -44,9 +44,13 @@ import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -58,6 +62,7 @@ import android.os.IPowerManager;
import android.os.IThermalService;
import android.os.PowerManager;
import android.os.Process;
+import android.os.RemoteException;
import android.os.test.TestLooper;
import android.view.Display;
import android.view.DisplayAddress;
@@ -69,7 +74,7 @@ import androidx.test.filters.SmallTest;
import com.android.server.display.feature.DisplayManagerFlags;
import com.android.server.display.layout.DisplayIdProducer;
import com.android.server.display.layout.Layout;
-import com.android.server.utils.FoldSettingWrapper;
+import com.android.server.utils.FoldSettingProvider;
import org.junit.Before;
import org.junit.Test;
@@ -93,6 +98,7 @@ public class LogicalDisplayMapperTest {
private static int sUniqueTestDisplayId = 0;
private static final int DEVICE_STATE_CLOSED = 0;
private static final int DEVICE_STATE_OPEN = 2;
+ private static final int FLAG_GO_TO_SLEEP_ON_FOLD = 0;
private static int sNextNonDefaultDisplayId = DEFAULT_DISPLAY + 1;
private static final File NON_EXISTING_FILE = new File("/non_existing_folder/should_not_exist");
@@ -107,7 +113,7 @@ public class LogicalDisplayMapperTest {
@Mock LogicalDisplayMapper.Listener mListenerMock;
@Mock Context mContextMock;
- @Mock FoldSettingWrapper mFoldSettingWrapperMock;
+ @Mock FoldSettingProvider mFoldSettingProviderMock;
@Mock Resources mResourcesMock;
@Mock IPowerManager mIPowerManagerMock;
@Mock IThermalService mIThermalServiceMock;
@@ -120,7 +126,7 @@ public class LogicalDisplayMapperTest {
@Captor ArgumentCaptor<Integer> mDisplayEventCaptor;
@Before
- public void setUp() {
+ public void setUp() throws RemoteException {
// Share classloader to allow package private access.
System.setProperty("dexmaker.share_classloader", "true");
MockitoAnnotations.initMocks(this);
@@ -150,7 +156,9 @@ public class LogicalDisplayMapperTest {
when(mContextMock.getSystemServiceName(PowerManager.class))
.thenReturn(Context.POWER_SERVICE);
- when(mFoldSettingWrapperMock.shouldStayAwakeOnFold()).thenReturn(false);
+ when(mFoldSettingProviderMock.shouldStayAwakeOnFold()).thenReturn(false);
+ when(mFoldSettingProviderMock.shouldSleepOnFold()).thenReturn(false);
+ when(mIPowerManagerMock.isInteractive()).thenReturn(true);
when(mContextMock.getSystemService(PowerManager.class)).thenReturn(mPowerManager);
when(mContextMock.getResources()).thenReturn(mResourcesMock);
when(mResourcesMock.getBoolean(
@@ -166,9 +174,10 @@ public class LogicalDisplayMapperTest {
when(mFlagsMock.isConnectedDisplayManagementEnabled()).thenReturn(false);
mLooper = new TestLooper();
mHandler = new Handler(mLooper.getLooper());
- mLogicalDisplayMapper = new LogicalDisplayMapper(mContextMock, mDisplayDeviceRepo,
+ mLogicalDisplayMapper = new LogicalDisplayMapper(mContextMock, mFoldSettingProviderMock,
+ mDisplayDeviceRepo,
mListenerMock, new DisplayManagerService.SyncRoot(), mHandler,
- mDeviceStateToLayoutMapSpy, mFoldSettingWrapperMock, mFlagsMock);
+ mDeviceStateToLayoutMapSpy, mFlagsMock);
}
@@ -645,8 +654,8 @@ public class LogicalDisplayMapperTest {
}
@Test
- public void testDeviceShouldNotSleepWhenFoldSettingTrue() {
- when(mFoldSettingWrapperMock.shouldStayAwakeOnFold()).thenReturn(true);
+ public void testDeviceShouldNotSleepWhenStayAwakeSettingTrue() {
+ when(mFoldSettingProviderMock.shouldStayAwakeOnFold()).thenReturn(true);
assertFalse(mLogicalDisplayMapper.shouldDeviceBePutToSleep(DEVICE_STATE_CLOSED,
DEVICE_STATE_OPEN,
@@ -679,6 +688,26 @@ public class LogicalDisplayMapperTest {
}
@Test
+ public void testDeviceShouldPutToSleepWhenSleepSettingTrue() throws RemoteException {
+ when(mFoldSettingProviderMock.shouldSleepOnFold()).thenReturn(true);
+
+ finishBootAndFoldDevice();
+
+ verify(mIPowerManagerMock, atLeastOnce()).goToSleep(anyLong(), anyInt(),
+ eq(FLAG_GO_TO_SLEEP_ON_FOLD));
+ }
+
+ @Test
+ public void testDeviceShouldNotBePutToSleepWhenSleepSettingFalse() throws RemoteException {
+ when(mFoldSettingProviderMock.shouldSleepOnFold()).thenReturn(false);
+
+ finishBootAndFoldDevice();
+
+ verify(mIPowerManagerMock, never()).goToSleep(anyLong(), anyInt(),
+ eq(FLAG_GO_TO_SLEEP_ON_FOLD));
+ }
+
+ @Test
public void testDeviceStateLocked() {
DisplayDevice device1 = createDisplayDevice(TYPE_INTERNAL, 600, 800,
FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY);
@@ -930,6 +959,15 @@ public class LogicalDisplayMapperTest {
// Helper Methods
/////////////////
+ private void finishBootAndFoldDevice() {
+ mLogicalDisplayMapper.setDeviceStateLocked(DEVICE_STATE_OPEN, false);
+ advanceTime(1000);
+ mLogicalDisplayMapper.onBootCompleted();
+ advanceTime(1000);
+ mLogicalDisplayMapper.setDeviceStateLocked(DEVICE_STATE_CLOSED, false);
+ advanceTime(1000);
+ }
+
private void createDefaultDisplay(Layout layout, DisplayDevice device) {
createDefaultDisplay(layout, info(device).address);
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/display/SmallAreaDetectionControllerTest.java b/services/tests/mockingservicestests/src/com/android/server/display/SmallAreaDetectionControllerTest.java
new file mode 100644
index 000000000000..1ce79a5b596b
--- /dev/null
+++ b/services/tests/mockingservicestests/src/com/android/server/display/SmallAreaDetectionControllerTest.java
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2023 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.display;
+
+import static android.os.Process.INVALID_UID;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.ContextWrapper;
+import android.content.pm.PackageManagerInternal;
+import android.provider.DeviceConfigInterface;
+
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.server.LocalServices;
+import com.android.server.pm.UserManagerInternal;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class SmallAreaDetectionControllerTest {
+
+ @Rule
+ public MockitoRule mRule = MockitoJUnit.rule();
+
+ @Mock
+ private PackageManagerInternal mMockPackageManagerInternal;
+ @Mock
+ private UserManagerInternal mMockUserManagerInternal;
+
+ private SmallAreaDetectionController mSmallAreaDetectionController;
+
+ private static final String PKG_A = "com.a.b.c";
+ private static final String PKG_B = "com.d.e.f";
+ private static final String PKG_NOT_INSTALLED = "com.not.installed";
+ private static final float THRESHOLD_A = 0.05f;
+ private static final float THRESHOLD_B = 0.07f;
+ private static final int USER_1 = 110;
+ private static final int USER_2 = 111;
+ private static final int UID_A_1 = 11011111;
+ private static final int UID_A_2 = 11111111;
+ private static final int UID_B_1 = 11022222;
+ private static final int UID_B_2 = 11122222;
+
+ @Before
+ public void setup() {
+ LocalServices.removeServiceForTest(PackageManagerInternal.class);
+ LocalServices.addService(PackageManagerInternal.class, mMockPackageManagerInternal);
+ LocalServices.removeServiceForTest(UserManagerInternal.class);
+ LocalServices.addService(UserManagerInternal.class, mMockUserManagerInternal);
+
+ when(mMockUserManagerInternal.getUserIds()).thenReturn(new int[]{USER_1, USER_2});
+ when(mMockPackageManagerInternal.getPackageUid(PKG_A, 0, USER_1)).thenReturn(UID_A_1);
+ when(mMockPackageManagerInternal.getPackageUid(PKG_A, 0, USER_2)).thenReturn(UID_A_2);
+ when(mMockPackageManagerInternal.getPackageUid(PKG_B, 0, USER_1)).thenReturn(UID_B_1);
+ when(mMockPackageManagerInternal.getPackageUid(PKG_B, 0, USER_2)).thenReturn(UID_B_2);
+ when(mMockPackageManagerInternal.getPackageUid(PKG_NOT_INSTALLED, 0, USER_1)).thenReturn(
+ INVALID_UID);
+ when(mMockPackageManagerInternal.getPackageUid(PKG_NOT_INSTALLED, 0, USER_2)).thenReturn(
+ INVALID_UID);
+
+ mSmallAreaDetectionController = spy(new SmallAreaDetectionController(
+ new ContextWrapper(ApplicationProvider.getApplicationContext()),
+ DeviceConfigInterface.REAL));
+ doNothing().when(mSmallAreaDetectionController).updateSmallAreaDetection(any(), any());
+ }
+
+ @Test
+ public void testUpdateAllowlist_validProperty() {
+ final String property = PKG_A + ":" + THRESHOLD_A + "," + PKG_B + ":" + THRESHOLD_B;
+ mSmallAreaDetectionController.updateAllowlist(property);
+
+ final int[] resultUidArray = {UID_A_1, UID_B_1, UID_A_2, UID_B_2};
+ final float[] resultThresholdArray = {THRESHOLD_A, THRESHOLD_B, THRESHOLD_A, THRESHOLD_B};
+ verify(mSmallAreaDetectionController).updateSmallAreaDetection(eq(resultUidArray),
+ eq(resultThresholdArray));
+ }
+
+ @Test
+ public void testUpdateAllowlist_includeInvalidRow() {
+ final String property = PKG_A + "," + PKG_B + ":" + THRESHOLD_B;
+ mSmallAreaDetectionController.updateAllowlist(property);
+
+ final int[] resultUidArray = {UID_B_1, UID_B_2};
+ final float[] resultThresholdArray = {THRESHOLD_B, THRESHOLD_B};
+ verify(mSmallAreaDetectionController).updateSmallAreaDetection(eq(resultUidArray),
+ eq(resultThresholdArray));
+ }
+
+ @Test
+ public void testUpdateAllowlist_includeNotInstalledPkg() {
+ final String property =
+ PKG_A + ":" + THRESHOLD_A + "," + PKG_NOT_INSTALLED + ":" + THRESHOLD_B;
+ mSmallAreaDetectionController.updateAllowlist(property);
+
+ final int[] resultUidArray = {UID_A_1, UID_A_2};
+ final float[] resultThresholdArray = {THRESHOLD_A, THRESHOLD_A};
+ verify(mSmallAreaDetectionController).updateSmallAreaDetection(eq(resultUidArray),
+ eq(resultThresholdArray));
+ }
+
+ @Test
+ public void testUpdateAllowlist_invalidProperty() {
+ final String property = PKG_A;
+ mSmallAreaDetectionController.updateAllowlist(property);
+
+ verify(mSmallAreaDetectionController, never()).updateSmallAreaDetection(any(), any());
+ }
+}
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/PackageArchiverServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/pm/PackageArchiverServiceTest.java
index c7e1bda2e1b8..80576a688fdd 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/PackageArchiverServiceTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/PackageArchiverServiceTest.java
@@ -16,41 +16,49 @@
package com.android.server.pm;
+import static android.content.Intent.FLAG_RECEIVER_FOREGROUND;
import static android.content.pm.PackageManager.DELETE_KEEP_DATA;
-
import static com.google.common.truth.Truth.assertThat;
-
import static org.junit.Assert.assertThrows;
+import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.ArgumentMatchers.isNull;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.app.AppOpsManager;
import android.content.Context;
+import android.content.Intent;
import android.content.IntentSender;
import android.content.pm.LauncherActivityInfo;
import android.content.pm.LauncherApps;
+import android.content.pm.PackageArchiver;
import android.content.pm.PackageManager;
import android.content.pm.VersionedPackage;
import android.os.Binder;
import android.os.Build;
+import android.os.Bundle;
import android.os.ParcelableException;
import android.os.UserHandle;
import android.platform.test.annotations.Presubmit;
+import android.text.TextUtils;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
import com.android.server.pm.pkg.ArchiveState;
import com.android.server.pm.pkg.PackageStateInternal;
+import com.android.server.pm.pkg.PackageUserStateImpl;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
@@ -64,7 +72,8 @@ import java.util.List;
public class PackageArchiverServiceTest {
private static final String PACKAGE = "com.example";
- private static final String CALLER_PACKAGE = "com.vending";
+ private static final String CALLER_PACKAGE = "com.caller";
+ private static final String INSTALLER_PACKAGE = "com.installer";
@Rule
public final MockSystemRule mMockSystem = new MockSystemRule();
@@ -84,11 +93,11 @@ public class PackageArchiverServiceTest {
private final InstallSource mInstallSource =
InstallSource.create(
- CALLER_PACKAGE,
- CALLER_PACKAGE,
- CALLER_PACKAGE,
+ INSTALLER_PACKAGE,
+ INSTALLER_PACKAGE,
+ INSTALLER_PACKAGE,
Binder.getCallingUid(),
- CALLER_PACKAGE,
+ INSTALLER_PACKAGE,
/* installerAttributionTag= */ null,
/* packageSource= */ 0);
@@ -96,6 +105,8 @@ public class PackageArchiverServiceTest {
private final int mUserId = UserHandle.CURRENT.getIdentifier();
+ private PackageUserStateImpl mUserState;
+
private PackageSetting mPackageSetting;
private PackageArchiverService mArchiveService;
@@ -116,11 +127,16 @@ public class PackageArchiverServiceTest {
when(mComputer.getPackageStateFiltered(eq(PACKAGE), anyInt(), anyInt())).thenReturn(
mPackageState);
+ when(mComputer.getPackageStateFiltered(eq(INSTALLER_PACKAGE), anyInt(),
+ anyInt())).thenReturn(mock(PackageStateInternal.class));
when(mPackageState.getPackageName()).thenReturn(PACKAGE);
when(mPackageState.getInstallSource()).thenReturn(mInstallSource);
mPackageSetting = createBasicPackageSetting();
when(mMockSystem.mocks().getSettings().getPackageLPr(eq(PACKAGE))).thenReturn(
mPackageSetting);
+ mUserState = new PackageUserStateImpl().setInstalled(true);
+ mPackageSetting.setUserState(mUserId, mUserState);
+ when(mPackageState.getUserStateOrDefault(eq(mUserId))).thenReturn(mUserState);
when(mContext.getSystemService(LauncherApps.class)).thenReturn(mLauncherApps);
when(mLauncherApps.getActivityList(eq(PACKAGE), eq(UserHandle.CURRENT))).thenReturn(
mLauncherActivityInfos);
@@ -135,9 +151,7 @@ public class PackageArchiverServiceTest {
Exception e = assertThrows(
SecurityException.class,
() -> mArchiveService.requestArchive(PACKAGE, "different", mIntentSender,
- UserHandle.CURRENT
- )
- );
+ UserHandle.CURRENT));
assertThat(e).hasMessageThat().isEqualTo(
String.format(
"The UID %s of callerPackageName set by the caller doesn't match the "
@@ -154,9 +168,7 @@ public class PackageArchiverServiceTest {
Exception e = assertThrows(
ParcelableException.class,
() -> mArchiveService.requestArchive(PACKAGE, CALLER_PACKAGE, mIntentSender,
- UserHandle.CURRENT
- )
- );
+ UserHandle.CURRENT));
assertThat(e.getCause()).isInstanceOf(PackageManager.NameNotFoundException.class);
assertThat(e.getCause()).hasMessageThat().isEqualTo(
String.format("Package %s not found.", PACKAGE));
@@ -169,9 +181,7 @@ public class PackageArchiverServiceTest {
Exception e = assertThrows(
ParcelableException.class,
() -> mArchiveService.requestArchive(PACKAGE, CALLER_PACKAGE, mIntentSender,
- UserHandle.CURRENT
- )
- );
+ UserHandle.CURRENT));
assertThat(e.getCause()).isInstanceOf(PackageManager.NameNotFoundException.class);
assertThat(e.getCause()).hasMessageThat().isEqualTo(
String.format("Package %s not found.", PACKAGE));
@@ -193,25 +203,27 @@ public class PackageArchiverServiceTest {
Exception e = assertThrows(
ParcelableException.class,
() -> mArchiveService.requestArchive(PACKAGE, CALLER_PACKAGE, mIntentSender,
- UserHandle.CURRENT
- )
- );
+ UserHandle.CURRENT));
+ assertThat(e.getCause()).isInstanceOf(PackageManager.NameNotFoundException.class);
+ assertThat(e.getCause()).hasMessageThat().isEqualTo("No installer found");
+ }
+
+ @Test
+ public void archiveApp_noMainActivities() {
+ when(mLauncherApps.getActivityList(eq(PACKAGE), eq(UserHandle.CURRENT))).thenReturn(
+ List.of());
+
+ Exception e = assertThrows(
+ ParcelableException.class,
+ () -> mArchiveService.requestArchive(PACKAGE, CALLER_PACKAGE, mIntentSender,
+ UserHandle.CURRENT));
assertThat(e.getCause()).isInstanceOf(PackageManager.NameNotFoundException.class);
assertThat(e.getCause()).hasMessageThat().isEqualTo(
- String.format("No installer found to archive app %s.", PACKAGE));
+ TextUtils.formatSimple("The app %s does not have a main activity.", PACKAGE));
}
@Test
public void archiveApp_success() {
- List<ArchiveState.ArchiveActivityInfo> activityInfos = new ArrayList<>();
- for (LauncherActivityInfo mainActivity : createLauncherActivities()) {
- // TODO(b/278553670) Extract and store launcher icons
- ArchiveState.ArchiveActivityInfo activityInfo = new ArchiveState.ArchiveActivityInfo(
- mainActivity.getLabel().toString(),
- Path.of("/TODO"), null);
- activityInfos.add(activityInfo);
- }
-
mArchiveService.requestArchive(PACKAGE, CALLER_PACKAGE, mIntentSender, UserHandle.CURRENT);
verify(mInstallerService).uninstall(
@@ -220,7 +232,112 @@ public class PackageArchiverServiceTest {
eq(UserHandle.CURRENT.getIdentifier()));
assertThat(mPackageSetting.readUserState(
UserHandle.CURRENT.getIdentifier()).getArchiveState()).isEqualTo(
- new ArchiveState(activityInfos, CALLER_PACKAGE));
+ createArchiveState());
+ }
+
+ @Test
+ public void unarchiveApp_callerPackageNameIncorrect() {
+ mUserState.setArchiveState(createArchiveState()).setInstalled(false);
+
+ Exception e = assertThrows(
+ SecurityException.class,
+ () -> mArchiveService.requestUnarchive(PACKAGE, "different",
+ UserHandle.CURRENT));
+ assertThat(e).hasMessageThat().isEqualTo(
+ String.format(
+ "The UID %s of callerPackageName set by the caller doesn't match the "
+ + "caller's actual UID %s.",
+ 0,
+ Binder.getCallingUid()));
+ }
+
+ @Test
+ public void unarchiveApp_packageNotInstalled() {
+ mUserState.setArchiveState(createArchiveState()).setInstalled(false);
+ when(mComputer.getPackageStateFiltered(eq(PACKAGE), anyInt(), anyInt())).thenReturn(
+ null);
+
+ Exception e = assertThrows(
+ ParcelableException.class,
+ () -> mArchiveService.requestUnarchive(PACKAGE, CALLER_PACKAGE,
+ UserHandle.CURRENT));
+ assertThat(e.getCause()).isInstanceOf(PackageManager.NameNotFoundException.class);
+ assertThat(e.getCause()).hasMessageThat().isEqualTo(
+ String.format("Package %s not found.", PACKAGE));
+ }
+
+ @Test
+ public void unarchiveApp_notArchived() {
+ Exception e = assertThrows(
+ ParcelableException.class,
+ () -> mArchiveService.requestUnarchive(PACKAGE, CALLER_PACKAGE,
+ UserHandle.CURRENT));
+ assertThat(e.getCause()).isInstanceOf(PackageManager.NameNotFoundException.class);
+ assertThat(e.getCause()).hasMessageThat().isEqualTo(
+ String.format("Package %s is not currently archived.", PACKAGE));
+ }
+
+ @Test
+ public void unarchiveApp_noInstallerFound() {
+ mUserState.setArchiveState(createArchiveState());
+ InstallSource otherInstallSource =
+ InstallSource.create(
+ CALLER_PACKAGE,
+ CALLER_PACKAGE,
+ /* installerPackageName= */ null,
+ Binder.getCallingUid(),
+ /* updateOwnerPackageName= */ null,
+ /* installerAttributionTag= */ null,
+ /* packageSource= */ 0);
+ when(mPackageState.getInstallSource()).thenReturn(otherInstallSource);
+
+ Exception e = assertThrows(
+ ParcelableException.class,
+ () -> mArchiveService.requestUnarchive(PACKAGE, CALLER_PACKAGE,
+ UserHandle.CURRENT));
+ assertThat(e.getCause()).isInstanceOf(PackageManager.NameNotFoundException.class);
+ assertThat(e.getCause()).hasMessageThat().isEqualTo(
+ String.format("No installer found to unarchive app %s.", PACKAGE));
+ }
+
+ @Test
+ public void unarchiveApp_success() {
+ mUserState.setArchiveState(createArchiveState()).setInstalled(false);
+
+ mArchiveService.requestUnarchive(PACKAGE, CALLER_PACKAGE, UserHandle.CURRENT);
+ mMockSystem.mocks().getHandler().flush();
+
+ ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
+ verify(mContext).sendOrderedBroadcastAsUser(
+ intentCaptor.capture(),
+ eq(UserHandle.CURRENT),
+ /* receiverPermission = */ isNull(),
+ eq(AppOpsManager.OP_NONE),
+ any(Bundle.class),
+ /* resultReceiver= */ isNull(),
+ /* scheduler= */ isNull(),
+ /* initialCode= */ eq(0),
+ /* initialData= */ isNull(),
+ /* initialExtras= */ isNull());
+ Intent intent = intentCaptor.getValue();
+ assertThat(intent.getFlags() & FLAG_RECEIVER_FOREGROUND).isNotEqualTo(0);
+ assertThat(intent.getStringExtra(PackageArchiver.EXTRA_UNARCHIVE_PACKAGE_NAME)).isEqualTo(
+ PACKAGE);
+ assertThat(
+ intent.getBooleanExtra(PackageArchiver.EXTRA_UNARCHIVE_ALL_USERS, true)).isFalse();
+ assertThat(intent.getPackage()).isEqualTo(INSTALLER_PACKAGE);
+ }
+
+ private static ArchiveState createArchiveState() {
+ List<ArchiveState.ArchiveActivityInfo> activityInfos = new ArrayList<>();
+ for (LauncherActivityInfo mainActivity : createLauncherActivities()) {
+ // TODO(b/278553670) Extract and store launcher icons
+ ArchiveState.ArchiveActivityInfo activityInfo = new ArchiveState.ArchiveActivityInfo(
+ mainActivity.getLabel().toString(),
+ Path.of("/TODO"), null);
+ activityInfos.add(activityInfo);
+ }
+ return new ArchiveState(activityInfos, INSTALLER_PACKAGE);
}
private static List<LauncherActivityInfo> createLauncherActivities() {
diff --git a/services/tests/mockingservicestests/src/com/android/server/utils/FoldSettingProviderTest.java b/services/tests/mockingservicestests/src/com/android/server/utils/FoldSettingProviderTest.java
new file mode 100644
index 000000000000..3514276ccb5b
--- /dev/null
+++ b/services/tests/mockingservicestests/src/com/android/server/utils/FoldSettingProviderTest.java
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2023 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.utils;
+
+import static com.android.server.utils.FoldSettingProvider.SETTING_VALUE_SLEEP_ON_FOLD;
+import static com.android.server.utils.FoldSettingProvider.SETTING_VALUE_STAY_AWAKE_ON_FOLD;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.when;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.res.Resources;
+import android.os.UserHandle;
+import android.provider.Settings;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import com.android.internal.R;
+import com.android.internal.util.SettingsWrapper;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+public class FoldSettingProviderTest {
+
+ private static final String SETTING_VALUE_INVALID = "invalid_fold_lock_behavior";
+
+ @Mock
+ private Context mContext;
+ @Mock
+ private Resources mResources;
+ @Mock
+ private SettingsWrapper mSettingsWrapper;
+ private ContentResolver mContentResolver;
+ private FoldSettingProvider mFoldSettingProvider;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+
+ mContentResolver =
+ InstrumentationRegistry.getInstrumentation().getContext().getContentResolver();
+ when(mContext.getContentResolver()).thenReturn(mContentResolver);
+ when(mContext.getResources()).thenReturn(mResources);
+ setFoldLockBehaviorAvailability(true);
+
+ mFoldSettingProvider = new FoldSettingProvider(mContext, mSettingsWrapper);
+ }
+
+ @Test
+ public void foldSettingNotAvailable_returnDefaultSetting() {
+ setFoldLockBehaviorAvailability(false);
+ setFoldLockBehaviorSettingValue(SETTING_VALUE_STAY_AWAKE_ON_FOLD);
+ mFoldSettingProvider = new FoldSettingProvider(mContext, mSettingsWrapper);
+
+ boolean shouldSelectiveStayAwakeOnFold =
+ mFoldSettingProvider.shouldSelectiveStayAwakeOnFold();
+
+ assertThat(shouldSelectiveStayAwakeOnFold).isTrue();
+ }
+
+ @Test
+ public void foldSettingNotAvailable_notReturnStayAwakeOnFoldTrue() {
+ setFoldLockBehaviorAvailability(false);
+ setFoldLockBehaviorSettingValue(SETTING_VALUE_STAY_AWAKE_ON_FOLD);
+ mFoldSettingProvider = new FoldSettingProvider(mContext, mSettingsWrapper);
+
+ boolean shouldStayAwakeOnFold = mFoldSettingProvider.shouldStayAwakeOnFold();
+
+ assertThat(shouldStayAwakeOnFold).isFalse();
+ }
+
+ @Test
+ public void foldSettingNotAvailable_notReturnSleepOnFoldTrue() {
+ setFoldLockBehaviorAvailability(false);
+ setFoldLockBehaviorSettingValue(SETTING_VALUE_SLEEP_ON_FOLD);
+ mFoldSettingProvider = new FoldSettingProvider(mContext, mSettingsWrapper);
+
+ boolean shouldSleepOnFold = mFoldSettingProvider.shouldSleepOnFold();
+
+ assertThat(shouldSleepOnFold).isFalse();
+ }
+
+ @Test
+ public void foldSettingAvailable_returnCorrectFoldSetting() {
+ setFoldLockBehaviorSettingValue(SETTING_VALUE_STAY_AWAKE_ON_FOLD);
+
+ boolean shouldStayAwakeOnFold = mFoldSettingProvider.shouldStayAwakeOnFold();
+
+ assertThat(shouldStayAwakeOnFold).isTrue();
+ }
+
+ @Test
+ public void foldSettingInvalid_returnDefaultSetting() {
+ setFoldLockBehaviorSettingValue(SETTING_VALUE_INVALID);
+
+ boolean shouldSelectiveStayAwakeOnFold =
+ mFoldSettingProvider.shouldSelectiveStayAwakeOnFold();
+
+ assertThat(shouldSelectiveStayAwakeOnFold).isTrue();
+ }
+
+ @Test
+ public void foldSettingNotDefined_returnDefaultSetting() {
+ setFoldLockBehaviorSettingValue(null);
+
+ boolean shouldSelectiveStayAwakeOnFold =
+ mFoldSettingProvider.shouldSelectiveStayAwakeOnFold();
+
+ assertThat(shouldSelectiveStayAwakeOnFold).isTrue();
+ }
+
+ private void setFoldLockBehaviorAvailability(boolean isFoldLockBehaviorEnabled) {
+ when(mResources.getBoolean(R.bool.config_fold_lock_behavior)).thenReturn(
+ isFoldLockBehaviorEnabled);
+ }
+
+ private void setFoldLockBehaviorSettingValue(String foldLockBehaviorSettingValue) {
+ when(mSettingsWrapper.getStringForUser(any(),
+ eq(Settings.System.FOLD_LOCK_BEHAVIOR),
+ eq(UserHandle.USER_CURRENT))).thenReturn(foldLockBehaviorSettingValue);
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/companion/virtual/audio/VirtualAudioControllerTest.java b/services/tests/servicestests/src/com/android/server/companion/virtual/audio/VirtualAudioControllerTest.java
index 2bfa44ecb1d6..78655a5dd341 100644
--- a/services/tests/servicestests/src/com/android/server/companion/virtual/audio/VirtualAudioControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/companion/virtual/audio/VirtualAudioControllerTest.java
@@ -25,7 +25,6 @@ import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
-import android.companion.virtual.VirtualDeviceParams;
import android.companion.virtual.audio.IAudioConfigChangedCallback;
import android.companion.virtual.audio.IAudioRoutingCallback;
import android.content.Context;
@@ -79,11 +78,10 @@ public class VirtualAudioControllerTest {
FLAG_SECURE,
SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS,
/* allowedUsers= */ new ArraySet<>(),
- /* allowedCrossTaskNavigations= */ new ArraySet<>(),
- /* blockedCrossTaskNavigations= */ new ArraySet<>(),
- /* allowedActivities= */ new ArraySet<>(),
- /* blockedActivities= */ new ArraySet<>(),
- VirtualDeviceParams.ACTIVITY_POLICY_DEFAULT_ALLOWED,
+ /* activityLaunchAllowedByDefault= */ true,
+ /* activityPolicyExceptions= */ new ArraySet<>(),
+ /* crossTaskNavigationAllowedByDefault= */ true,
+ /* crossTaskNavigationExceptions= */ new ArraySet<>(),
/* activityListener= */ null,
/* pipBlockedCallback= */ null,
/* activityBlockedCallback= */ null,
diff --git a/services/tests/wmtests/src/com/android/server/policy/ShortcutLoggingTests.java b/services/tests/wmtests/src/com/android/server/policy/ShortcutLoggingTests.java
index 8fadecd0dc38..e13dc3eea729 100644
--- a/services/tests/wmtests/src/com/android/server/policy/ShortcutLoggingTests.java
+++ b/services/tests/wmtests/src/com/android/server/policy/ShortcutLoggingTests.java
@@ -65,6 +65,12 @@ public class ShortcutLoggingTests extends ShortcutKeyTestBase {
KeyboardLogEvent.RECENT_APPS, KeyEvent.KEYCODE_TAB, ALT_ON},
{"BACK key -> Go back", new int[]{KeyEvent.KEYCODE_BACK}, KeyboardLogEvent.BACK,
KeyEvent.KEYCODE_BACK, 0},
+ {"Meta + `(grave) -> Go back", new int[]{META_KEY, KeyEvent.KEYCODE_GRAVE},
+ KeyboardLogEvent.BACK, KeyEvent.KEYCODE_GRAVE, META_ON},
+ {"Meta + Left arrow -> Go back", new int[]{META_KEY, KeyEvent.KEYCODE_DPAD_LEFT},
+ KeyboardLogEvent.BACK, KeyEvent.KEYCODE_DPAD_LEFT, META_ON},
+ {"Meta + Del -> Go back", new int[]{META_KEY, KeyEvent.KEYCODE_DEL},
+ KeyboardLogEvent.BACK, KeyEvent.KEYCODE_DEL, META_ON},
{"APP_SWITCH key -> Open App switcher", new int[]{KeyEvent.KEYCODE_APP_SWITCH},
KeyboardLogEvent.APP_SWITCH, KeyEvent.KEYCODE_APP_SWITCH, 0},
{"ASSIST key -> Launch assistant", new int[]{KeyEvent.KEYCODE_ASSIST},
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java
index dd90e0450280..bf86563e3d86 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java
@@ -16,6 +16,7 @@
package com.android.server.wm;
+import static android.inputmethodservice.InputMethodService.ENABLE_HIDE_IME_CAPTION_BAR;
import static android.view.DisplayCutout.NO_CUTOUT;
import static android.view.InsetsSource.ID_IME;
import static android.view.RoundedCorners.NO_ROUNDED_CORNERS;
@@ -427,11 +428,11 @@ public class DisplayPolicyTests extends WindowTestsBase {
@SetupWindows(addWindows = { W_NAVIGATION_BAR, W_INPUT_METHOD })
@Test
public void testImeMinimalSourceFrame() {
+ Assume.assumeFalse("Behavior no longer needed with ENABLE_HIDE_IME_CAPTION_BAR",
+ ENABLE_HIDE_IME_CAPTION_BAR);
+
final DisplayPolicy displayPolicy = mDisplayContent.getDisplayPolicy();
- final DisplayInfo displayInfo = new DisplayInfo();
- displayInfo.logicalWidth = 1000;
- displayInfo.logicalHeight = 2000;
- displayInfo.rotation = ROTATION_0;
+ final DisplayInfo displayInfo = mDisplayContent.getDisplayInfo();
WindowManager.LayoutParams attrs = mNavBarWindow.mAttrs;
displayPolicy.addWindowLw(mNavBarWindow, attrs);
@@ -466,10 +467,6 @@ public class DisplayPolicyTests extends WindowTestsBase {
@Test
public void testImeInsetsGivenContentFrame() {
final DisplayPolicy displayPolicy = mDisplayContent.getDisplayPolicy();
- final DisplayInfo displayInfo = new DisplayInfo();
- displayInfo.logicalWidth = 1000;
- displayInfo.logicalHeight = 2000;
- displayInfo.rotation = ROTATION_0;
mDisplayContent.setInputMethodWindowLocked(mImeWindow);
mImeWindow.getControllableInsetProvider().setServerVisible(true);
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java
index 6b504925281c..915b387ddb75 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java
@@ -583,6 +583,7 @@ public class DisplayRotationTests {
enableOrientationSensor();
+ clearInvocations(sMockWm);
mOrientationSensorListener.onSensorChanged(createSensorEvent(Surface.ROTATION_90));
assertTrue(waitForUiHandler());
@@ -627,6 +628,7 @@ public class DisplayRotationTests {
when(mDisplayRotationImmersiveAppCompatPolicyMock.isRotationLockEnforced(
Surface.ROTATION_90)).thenReturn(false);
+ clearInvocations(sMockWm);
// And then ActivityRecord.setRequestedOrientation calls onSetRequestedOrientation.
mTarget.onSetRequestedOrientation();
@@ -864,6 +866,7 @@ public class DisplayRotationTests {
assertEquals(Surface.ROTATION_270, mTarget.rotationForOrientation(
SCREEN_ORIENTATION_UNSPECIFIED, Surface.ROTATION_0));
+ clearInvocations(sMockWm);
// ... until half-fold
mTarget.foldStateChanged(DeviceStateController.DeviceState.HALF_FOLDED);
assertTrue(waitForUiHandler());
@@ -899,6 +902,7 @@ public class DisplayRotationTests {
assertEquals(Surface.ROTATION_270, mTarget.rotationForOrientation(
SCREEN_ORIENTATION_UNSPECIFIED, Surface.ROTATION_0));
+ clearInvocations(sMockWm);
// ... half-fold -> still no rotation
mTarget.foldStateChanged(DeviceStateController.DeviceState.HALF_FOLDED);
assertTrue(waitForUiHandler());
diff --git a/services/tests/wmtests/src/com/android/server/wm/LetterboxConfigurationPersisterTest.java b/services/tests/wmtests/src/com/android/server/wm/LetterboxConfigurationPersisterTest.java
index 06033c7ebf75..3fcec963593c 100644
--- a/services/tests/wmtests/src/com/android/server/wm/LetterboxConfigurationPersisterTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/LetterboxConfigurationPersisterTest.java
@@ -184,7 +184,7 @@ public class LetterboxConfigurationPersisterTest {
LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_LEFT);
firstPersister.setLetterboxPositionForVerticalReachability(false,
LETTERBOX_VERTICAL_REACHABILITY_POSITION_TOP);
- waitForCompletion(mPersisterQueue);
+ waitForCompletion(firstPersisterQueue);
final int newPositionForHorizontalReachability =
firstPersister.getLetterboxPositionForHorizontalReachability(false);
final int newPositionForVerticalReachability =
diff --git a/telecomm/java/android/telecom/CallEndpoint.java b/telecomm/java/android/telecom/CallEndpoint.java
index ed4bf40061e2..a557cafd309a 100644
--- a/telecomm/java/android/telecom/CallEndpoint.java
+++ b/telecomm/java/android/telecom/CallEndpoint.java
@@ -127,7 +127,7 @@ public final class CallEndpoint implements Parcelable {
return false;
}
CallEndpoint endpoint = (CallEndpoint) obj;
- return getEndpointName().toString().contentEquals(endpoint.getEndpointName())
+ return Objects.equals(getEndpointName(), endpoint.getEndpointName())
&& getEndpointType() == endpoint.getEndpointType()
&& getIdentifier().equals(endpoint.getIdentifier());
}
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index ac8200ad420e..0c8603b339d3 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -9894,9 +9894,15 @@ public class CarrierConfigManager {
sDefaults.putBoolean(KEY_USE_ONLY_DIALED_SIM_ECC_LIST_BOOL, false);
sDefaults.putString(KEY_CARRIER_NETWORK_SERVICE_WWAN_PACKAGE_OVERRIDE_STRING, "");
sDefaults.putString(KEY_CARRIER_NETWORK_SERVICE_WLAN_PACKAGE_OVERRIDE_STRING, "");
+ sDefaults.putString(KEY_CARRIER_NETWORK_SERVICE_WLAN_CLASS_OVERRIDE_STRING, "");
+ sDefaults.putString(KEY_CARRIER_NETWORK_SERVICE_WWAN_CLASS_OVERRIDE_STRING, "");
sDefaults.putString(KEY_CARRIER_QUALIFIED_NETWORKS_SERVICE_PACKAGE_OVERRIDE_STRING, "");
+ sDefaults.putString(KEY_CARRIER_QUALIFIED_NETWORKS_SERVICE_CLASS_OVERRIDE_STRING, "");
sDefaults.putString(KEY_CARRIER_DATA_SERVICE_WWAN_PACKAGE_OVERRIDE_STRING, "");
sDefaults.putString(KEY_CARRIER_DATA_SERVICE_WLAN_PACKAGE_OVERRIDE_STRING, "");
+ sDefaults.putString(KEY_CARRIER_DATA_SERVICE_WWAN_CLASS_OVERRIDE_STRING, "");
+ sDefaults.putString(KEY_CARRIER_DATA_SERVICE_WLAN_CLASS_OVERRIDE_STRING, "");
+ sDefaults.putString(KEY_CONFIG_PLANS_PACKAGE_OVERRIDE_STRING, "");
sDefaults.putString(KEY_CARRIER_INSTANT_LETTERING_INVALID_CHARS_STRING, "");
sDefaults.putString(KEY_CARRIER_INSTANT_LETTERING_ESCAPED_CHARS_STRING, "");
sDefaults.putString(KEY_CARRIER_INSTANT_LETTERING_ENCODING_STRING, "");
diff --git a/tests/ChoreographerTests/src/main/java/android/view/choreographertests/AttachedChoreographerTest.java b/tests/ChoreographerTests/src/main/java/android/view/choreographertests/AttachedChoreographerTest.java
index bb0d30af42ee..5460e4e87e2f 100644
--- a/tests/ChoreographerTests/src/main/java/android/view/choreographertests/AttachedChoreographerTest.java
+++ b/tests/ChoreographerTests/src/main/java/android/view/choreographertests/AttachedChoreographerTest.java
@@ -421,7 +421,7 @@ public class AttachedChoreographerTest {
@Test
public void testChoreographerAttachedAfterSetFrameRate() {
- Log.i(TAG, "adyabr: starting testChoreographerAttachedAfterSetFrameRate");
+ Log.i(TAG, "starting testChoreographerAttachedAfterSetFrameRate");
class TransactionGenerator implements SurfaceControl.TransactionCommittedListener {
private SurfaceControl mSc;
diff --git a/tools/hoststubgen/.gitignore b/tools/hoststubgen/.gitignore
new file mode 100644
index 000000000000..6453bdef8cee
--- /dev/null
+++ b/tools/hoststubgen/.gitignore
@@ -0,0 +1,3 @@
+out/
+*-out/
+*.log
diff --git a/tools/hoststubgen/README.md b/tools/hoststubgen/README.md
new file mode 100644
index 000000000000..b0a126292063
--- /dev/null
+++ b/tools/hoststubgen/README.md
@@ -0,0 +1,76 @@
+# HostStubGen
+
+## Overview
+
+This directory contains tools / sample code / investigation for host side test support.
+
+
+## Directories and files
+
+- `hoststubgen/`
+ Contains source code of the "hoststubgen" tool and relevant code
+
+ - `framework-policy-override.txt`
+ This file contains "policy overrides", which allows to control what goes to stub/impl without
+ having to touch the target java files. This allows quicker iteration, because you can skip
+ having to rebuild framework.jar.
+
+ - `src/`
+
+ HostStubGen tool source code.
+
+ - `annotations-src/` See `Android.bp`.
+ - `helper-framework-buildtime-src/` See `Android.bp`.
+ - `helper-framework-runtime-src/` See `Android.bp`.
+ - `helper-runtime-src/` See `Android.bp`.
+
+ - `test-tiny-framework/` See `README.md` in it.
+
+ - `test-framework` See `README.md` in it.
+
+- `scripts`
+ - `run-host-test.sh`
+
+ Run a host side test. Use it instead of `atest` for now. (`atest` works "mostly" but it has
+ problems.)
+
+ - `dump-jar.sh`
+
+ A script to dump the content of `*.class` and `*.jar` files.
+
+ - `run-all-tests.sh`
+
+ Run all tests. Many tests may fail, but at least this should run til the end.
+ (It should print `run-all-tests.sh finished` at the end)
+
+## Build and run
+
+### Building `HostStubGen` binary
+
+```
+m hoststubgen
+```
+
+### Run the tests
+
+- Run all relevant tests and test scripts. Some of thests are still expected to fail,
+ but this should print "finished, with no unexpected failures" at the end.
+
+ However, because some of the script it executes depend on internal file paths to Soong's
+ intermediate directory, some of it might fail when something changes in the build system.
+
+ We need proper build system integration to fix them.
+```
+$ ./scripts/run-all-tests.sh
+```
+
+- See also `README.md` in `test-*` directories.
+
+## TODOs, etc
+
+ - Make sure the parent's visibility is not smaller than the member's.
+
+- @HostSideTestNativeSubstitutionClass should automatically add class-keep to the substitute class.
+ (or at least check it.)
+
+ - The `HostStubGenTest-framework-test-host-test-lib` jar somehow contain all ASM classes? Figure out where the dependency is coming from.
diff --git a/tools/hoststubgen/TEST_MAPPING b/tools/hoststubgen/TEST_MAPPING
new file mode 100644
index 000000000000..970362611f53
--- /dev/null
+++ b/tools/hoststubgen/TEST_MAPPING
@@ -0,0 +1,6 @@
+{
+ // TODO: Change to presubmit.
+ "postsubmit": [
+ { "name": "tiny-framework-dump-test" }
+ ]
+}
diff --git a/tools/hoststubgen/common.sh b/tools/hoststubgen/common.sh
new file mode 100644
index 000000000000..b49ee39a3142
--- /dev/null
+++ b/tools/hoststubgen/common.sh
@@ -0,0 +1,116 @@
+# Copyright (C) 2023 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.
+
+set -e # Exit at failure
+shopt -s globstar # Enable double-star wildcards (**)
+
+cd "${0%/*}" # Move to the script dir
+
+fail() {
+ echo "Error: $*" 1>&2
+ exit 1
+}
+
+# Print the arguments and then execute.
+run() {
+ echo "Running: $*" 1>&2
+ "$@"
+}
+
+# Concatenate the second and subsequent args with the first arg as a separator.
+# e.g. `join : a b c` -> prints `a:b:c`
+join() {
+ local IFS="$1"
+ shift
+ echo "$*"
+}
+
+abspath() {
+ for name in "${@}"; do
+ readlink -f $name
+ done
+}
+
+m() {
+ if (( $SKIP_BUILD )) ; then
+ echo "Skipping build: $*" 1>&2
+ return 0
+ fi
+ run ${ANDROID_BUILD_TOP}/build/soong/soong_ui.bash --make-mode "$@"
+}
+
+# Extract given jar files
+extract() {
+ for f in "${@}"; do
+ local out=$f.ext
+ run rm -fr $out
+ run mkdir -p $out
+
+ # It's too noisy, so only show the first few lines.
+ {
+ # Hmm unzipping kotlin jar files may produce a warning? Let's just add `|| true`...
+ run unzip $f -d $out || true
+ } |& sed -e '5,$d'
+ echo ' (omitting remaining output)'
+
+ done
+}
+
+# Find all *.java files in $1, and print them as Java class names.
+# For example, if there's a file `src/com/android/test/Test.java`, and you run
+# `list_all_classes_under_dir src`, then it'll print `com.android.test.Test`.
+list_all_classes_under_dir() {
+ local dir="$1"
+ ( # Use a subshell, so we won't change the current directory on the caller side.
+ cd "$dir"
+
+ # List the java files, but replace the slashes with dots, and remove the `.java` suffix.
+ ls **/*.java | sed -e 's!/!.!g' -e 's!.java$!!'
+ )
+}
+
+checkenv() {
+ # Make sure $ANDROID_BUILD_TOP is set.
+ : ${ANDROID_BUILD_TOP:?}
+
+ # Make sure ANDROID_BUILD_TOP doesn't contain whitespace.
+ set ${ANDROID_BUILD_TOP}
+ if [[ $# != 1 ]] ; then
+ fail "\$ANDROID_BUILD_TOP cannot contain whitespace."
+ fi
+}
+
+checkenv
+
+JAVAC=${JAVAC:-javac}
+JAVA=${JAVA:-java}
+JAR=${JAR:-jar}
+
+JAVAC_OPTS=${JAVAC_OPTS:--Xmaxerrs 99999 -Xlint:none}
+
+SOONG_INT=$ANDROID_BUILD_TOP/out/soong/.intermediates
+
+JUNIT_TEST_MAIN_CLASS=com.android.hoststubgen.hosthelper.HostTestSuite
+
+run_junit_test_jar() {
+ local jar="$1"
+ echo "Starting test: $jar ..."
+ run cd "${jar%/*}"
+
+ run $JAVA $JAVA_OPTS \
+ -cp $jar \
+ org.junit.runner.JUnitCore \
+ $main_class || return 1
+ return 0
+}
diff --git a/tools/hoststubgen/hoststubgen/.gitignore b/tools/hoststubgen/hoststubgen/.gitignore
new file mode 100644
index 000000000000..0f384074ed7f
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/.gitignore
@@ -0,0 +1 @@
+framework-all-stub-out \ No newline at end of file
diff --git a/tools/hoststubgen/hoststubgen/Android.bp b/tools/hoststubgen/hoststubgen/Android.bp
new file mode 100644
index 000000000000..a617876a6da0
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/Android.bp
@@ -0,0 +1,303 @@
+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"],
+}
+
+// This library contains the standard hoststubgen annotations.
+java_library {
+ name: "hoststubgen-annotations",
+ srcs: [
+ "annotations-src/**/*.java",
+ ],
+ host_supported: true,
+
+ // Seems like we need it to avoid circular deps.
+ // Copied it from "app-compat-annotations".
+ sdk_version: "core_current",
+ visibility: ["//visibility:public"],
+}
+
+// This library contains helper classes used in the host side test environment at runtime.
+// This library is _not_ specific to Android APIs.
+java_library_host {
+ name: "hoststubgen-helper-runtime",
+ srcs: [
+ "helper-runtime-src/**/*.java",
+ ],
+ libs: [
+ "junit",
+ "ow2-asm",
+ "ow2-asm-analysis",
+ "ow2-asm-commons",
+ "ow2-asm-tree",
+ "ow2-asm-util",
+ ],
+ static_libs: [
+ "guava",
+ ],
+ jarjar_rules: "jarjar-rules.txt",
+ visibility: ["//visibility:public"],
+}
+
+// Host-side stub generator tool.
+java_binary_host {
+ name: "hoststubgen",
+ main_class: "com.android.hoststubgen.Main",
+ srcs: ["src/**/*.kt"],
+ static_libs: [
+ "hoststubgen-helper-runtime",
+ "ow2-asm",
+ "ow2-asm-analysis",
+ "ow2-asm-commons",
+ "ow2-asm-tree",
+ "ow2-asm-util",
+ ],
+ visibility: ["//visibility:public"],
+}
+
+// File that contains the standard command line argumetns to hoststubgen.
+filegroup {
+ name: "hoststubgen-standard-options",
+ srcs: [
+ "hoststubgen-standard-options.txt",
+ ],
+ visibility: ["//visibility:public"],
+}
+
+hoststubgen_common_options = "$(location hoststubgen) " +
+ // "--in-jar $(location :framework-all) " +
+ // "--policy-override-file $(location framework-policy-override.txt) " +
+ "@$(location :hoststubgen-standard-options) " +
+
+ "--out-stub-jar $(location host_stub.jar) " +
+ "--out-impl-jar $(location host_impl.jar) " +
+
+ // "--keep-all-classes " + // Used it for an experiment. See KeepAllClassesFilter.
+ "--gen-keep-all-file $(location hoststubgen_keep_all.txt) " +
+ "--gen-input-dump-file $(location hoststubgen_dump.txt) " +
+ ""
+
+// Common defaults for stub generation.
+// This one is not specific to Android APIs.
+genrule_defaults {
+ name: "hoststubgen-command-defaults",
+ tools: ["hoststubgen"],
+ srcs: [
+ ":hoststubgen-standard-options",
+ ],
+ // Create two jar files.
+ out: [
+ "host_stub.jar",
+ "host_impl.jar",
+
+ // Following files are created just as FYI.
+ "hoststubgen_keep_all.txt",
+ "hoststubgen_dump.txt",
+ ],
+ // visibility: ["//visibility:public"],
+}
+
+// Generate the stub/impl from framework-all, with hidden APIs.
+java_genrule_host {
+ name: "framework-all-hidden-api-host",
+ defaults: ["hoststubgen-command-defaults"],
+ cmd: hoststubgen_common_options +
+ "--in-jar $(location :framework-all) " +
+ "--policy-override-file $(location framework-policy-override.txt) ",
+ srcs: [
+ ":framework-all",
+ "framework-policy-override.txt",
+ ],
+ visibility: ["//visibility:private"],
+}
+
+// Extract the stub jar from "framework-all-host" for subsequent build rules.
+java_genrule_host {
+ name: "framework-all-hidden-api-host-stub",
+ cmd: "cp $(in) $(out)",
+ srcs: [
+ ":framework-all-hidden-api-host{host_stub.jar}",
+ ],
+ out: [
+ "host_stub.jar",
+ ],
+ visibility: ["//visibility:public"],
+}
+
+// Extract the impl jar from "framework-all-host" for subsequent build rules.
+java_genrule_host {
+ name: "framework-all-hidden-api-host-impl",
+ cmd: "cp $(in) $(out)",
+ srcs: [
+ ":framework-all-hidden-api-host{host_impl.jar}",
+ ],
+ out: [
+ "host_impl.jar",
+ ],
+ visibility: ["//visibility:public"],
+}
+
+// Generate the stub/impl from framework-all, with only public/system/test APIs, without
+// hidden APIs.
+java_genrule_host {
+ name: "framework-all-test-api-host",
+ defaults: ["hoststubgen-command-defaults"],
+ cmd: hoststubgen_common_options +
+ "--intersect-stub-jar $(location :android_test_stubs_current{.jar}) " +
+ "--in-jar $(location :framework-all) " +
+ "--policy-override-file $(location framework-policy-override.txt) ",
+ srcs: [
+ ":framework-all",
+ ":android_test_stubs_current{.jar}",
+ "framework-policy-override.txt",
+ ],
+ visibility: ["//visibility:private"],
+}
+
+// Extract the stub jar from "framework-all-test-api-host" for subsequent build rules.
+java_genrule_host {
+ name: "framework-all-test-api-host-stub",
+ cmd: "cp $(in) $(out)",
+ srcs: [
+ ":framework-all-test-api-host{host_stub.jar}",
+ ],
+ out: [
+ "host_stub.jar",
+ ],
+ visibility: ["//visibility:public"],
+}
+
+// Extract the impl jar from "framework-all-test-api-host" for subsequent build rules.
+java_genrule_host {
+ name: "framework-all-test-api-host-impl",
+ cmd: "cp $(in) $(out)",
+ srcs: [
+ ":framework-all-test-api-host{host_impl.jar}",
+ ],
+ out: [
+ "host_impl.jar",
+ ],
+ visibility: ["//visibility:public"],
+}
+
+// This library contains helper classes to build hostside tests/targets.
+// This essentially contains dependencies from tests that we can't actually use the real ones.
+// For example, the actual AndroidTestCase and AndroidJUnit4 don't run on the host side (yet),
+// so we pup "fake" implementations here.
+// Ideally this library should be empty.
+java_library_host {
+ name: "hoststubgen-helper-framework-buildtime",
+ srcs: [
+ "helper-framework-buildtime-src/**/*.java",
+ ],
+ libs: [
+ // We need it to pull in some of the framework classes used in this library,
+ // such as Context.java.
+ "framework-all-hidden-api-host-impl",
+ "junit",
+ ],
+ visibility: ["//visibility:public"],
+}
+
+// This module contains "fake" libcore/dalvik classes, framework native substitution, etc,
+// that are needed at runtime.
+java_library_host {
+ name: "hoststubgen-helper-framework-runtime",
+ srcs: [
+ "helper-framework-runtime-src/**/*.java",
+ ],
+ libs: [
+ "hoststubgen-helper-runtime",
+ "framework-all-hidden-api-host-impl",
+ ],
+ visibility: ["//visibility:public"],
+}
+
+// Defaults for host side test modules.
+// We need two rules for each test.
+// 1. A "-test-lib" jar, which compiles the test against the stub jar.
+// This one is only used by the second rule, so it should be "private.
+// 2. A "-test" jar, which includes 1 + the runtime (impl) jars.
+
+// This and next ones are for tests using framework-app, with hidden APIs.
+java_defaults {
+ name: "hosttest-with-framework-all-hidden-api-test-lib-defaults",
+ installable: false,
+ libs: [
+ "framework-all-hidden-api-host-stub",
+ ],
+ static_libs: [
+ "hoststubgen-helper-framework-buildtime",
+ "framework-annotations-lib",
+ ],
+ visibility: ["//visibility:private"],
+}
+
+// Default rules to include `libandroid_runtime`. For now, it's empty, but we'll use it
+// once we start using JNI.
+java_defaults {
+ name: "hosttest-with-libandroid_runtime",
+ jni_libs: [
+ // "libandroid_runtime",
+
+ // TODO: Figure out how to build them automatically.
+ // Following ones are depended by libandroid_runtime.
+ // Without listing them here, not only we won't get them under
+ // $ANDROID_HOST_OUT/testcases/*/lib64, but also not under
+ // $ANDROID_HOST_OUT/lib64, so we'd fail to load them at runtime.
+ // ($ANDROID_HOST_OUT/lib/ gets all of them though.)
+ // "libcutils",
+ // "libharfbuzz_ng",
+ // "libminikin",
+ // "libz",
+ // "libbinder",
+ // "libhidlbase",
+ // "libvintf",
+ // "libicu",
+ // "libutils",
+ // "libtinyxml2",
+ ],
+}
+
+java_defaults {
+ name: "hosttest-with-framework-all-hidden-api-test-defaults",
+ defaults: ["hosttest-with-libandroid_runtime"],
+ installable: false,
+ test_config: "AndroidTest-host.xml",
+ static_libs: [
+ "hoststubgen-helper-runtime",
+ "hoststubgen-helper-framework-runtime",
+ "framework-all-hidden-api-host-impl",
+ ],
+}
+
+// This and next ones are for tests using framework-app, with public/system/test APIs,
+// without hidden APIs.
+java_defaults {
+ name: "hosttest-with-framework-all-test-api-test-lib-defaults",
+ installable: false,
+ libs: [
+ "framework-all-test-api-host-stub",
+ ],
+ static_libs: [
+ "hoststubgen-helper-framework-buildtime",
+ "framework-annotations-lib",
+ ],
+ visibility: ["//visibility:private"],
+}
+
+java_defaults {
+ name: "hosttest-with-framework-all-test-api-test-defaults",
+ defaults: ["hosttest-with-libandroid_runtime"],
+ installable: false,
+ test_config: "AndroidTest-host.xml",
+ static_libs: [
+ "hoststubgen-helper-runtime",
+ "hoststubgen-helper-framework-runtime",
+ "framework-all-test-api-host-impl",
+ ],
+}
diff --git a/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestClassLoadHook.java b/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestClassLoadHook.java
new file mode 100644
index 000000000000..a774336a897c
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestClassLoadHook.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2023 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 android.hosttest.annotation;
+
+import static java.lang.annotation.ElementType.TYPE;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * THIS ANNOTATION IS EXPERIMENTAL. REACH OUT TO g/ravenwood BEFORE USING IT, OR YOU HAVE ANY
+ * QUESTIONS ABOUT IT.
+ *
+ * Add this with a fully-specified method name (e.g. {@code "com.package.Class.methodName"})
+ * of a callback to get a callback at the class load time.
+ *
+ * The method must be {@code public static} with a single argument that takes
+ * {@link java.lang.Class}.
+ */
+@Target({TYPE})
+@Retention(RetentionPolicy.CLASS)
+public @interface HostSideTestClassLoadHook {
+ String value();
+}
diff --git a/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestKeep.java b/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestKeep.java
new file mode 100644
index 000000000000..06ad1c266a14
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestKeep.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2023 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 android.hosttest.annotation;
+
+import static java.lang.annotation.ElementType.CONSTRUCTOR;
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.TYPE;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * THIS ANNOTATION IS EXPERIMENTAL. REACH OUT TO g/ravenwood BEFORE USING IT, OR YOU HAVE ANY
+ * QUESTIONS ABOUT IT.
+ *
+ * Mark a class, field or a method as "Stub", meaning tests can _not_ see the APIs, but they
+ * can indirectly be used on the host side.
+ * When applied to a class, it will _not_ affect the visibility of its members. They need to be
+ * individually marked.
+ *
+ * <p>In order to expose a class and all its members, use {@link HostSideTestWholeClassStub}
+ * instead.
+ * @hide
+ */
+@Target({TYPE, FIELD, METHOD, CONSTRUCTOR})
+@Retention(RetentionPolicy.CLASS)
+public @interface HostSideTestKeep {
+}
diff --git a/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestNativeSubstitutionClass.java b/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestNativeSubstitutionClass.java
new file mode 100644
index 000000000000..9c8138351eb5
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestNativeSubstitutionClass.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2023 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 android.hosttest.annotation;
+
+import static java.lang.annotation.ElementType.TYPE;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * THIS ANNOTATION IS EXPERIMENTAL. REACH OUT TO g/ravenwood BEFORE USING IT, OR YOU HAVE ANY
+ * QUESTIONS ABOUT IT.
+ *
+ * If a class has this annotation, all its native methods will be delegated to another class.
+ * (See {@link android.os.Parcel} as an example.)
+ */
+@Target({TYPE})
+@Retention(RetentionPolicy.CLASS)
+public @interface HostSideTestNativeSubstitutionClass {
+ String value();
+}
diff --git a/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestRemove.java b/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestRemove.java
new file mode 100644
index 000000000000..46e5078fb05d
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestRemove.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2023 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 android.hosttest.annotation;
+
+import static java.lang.annotation.ElementType.CONSTRUCTOR;
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.TYPE;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * THIS ANNOTATION IS EXPERIMENTAL. REACH OUT TO g/ravenwood BEFORE USING IT, OR YOU HAVE ANY
+ * QUESTIONS ABOUT IT.
+ *
+ * Mark an item as "remove", so this cannot be used on the host side even indirectly.
+ * This is the default behavior.
+ *
+ * @hide
+ */
+@Target({TYPE, FIELD, METHOD, CONSTRUCTOR})
+@Retention(RetentionPolicy.CLASS)
+public @interface HostSideTestRemove {
+}
diff --git a/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestStub.java b/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestStub.java
new file mode 100644
index 000000000000..cabdfe0eeb77
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestStub.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2023 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 android.hosttest.annotation;
+
+import static java.lang.annotation.ElementType.CONSTRUCTOR;
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.TYPE;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * THIS ANNOTATION IS EXPERIMENTAL. REACH OUT TO g/ravenwood BEFORE USING IT, OR YOU HAVE ANY
+ * QUESTIONS ABOUT IT.
+ *
+ * Mark a class, field or a method as "Stub", meaning tests can see the APIs.
+ * When applied to a class, it will _not_ affect the visibility of its members. They need to be
+ * individually marked.
+ *
+ * <p>In order to expose a class and all its members, use {@link HostSideTestWholeClassStub}
+ * instead.
+ *
+ * @hide
+ */
+@Target({TYPE, FIELD, METHOD, CONSTRUCTOR})
+@Retention(RetentionPolicy.CLASS)
+public @interface HostSideTestStub {
+}
diff --git a/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestSubstitute.java b/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestSubstitute.java
new file mode 100644
index 000000000000..510a67e0aaed
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestSubstitute.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2023 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 android.hosttest.annotation;
+
+import static java.lang.annotation.ElementType.METHOD;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * THIS ANNOTATION IS EXPERIMENTAL. REACH OUT TO g/ravenwood BEFORE USING IT, OR YOU HAVE ANY
+ * QUESTIONS ABOUT IT.
+ *
+ * If a method has this annotation, we'll replace it with another method on the host side.
+ *
+ * See {@link android.util.LruCache#getEldest()} and its substitution.
+ *
+ * @hide
+ */
+@Target({METHOD})
+@Retention(RetentionPolicy.CLASS)
+public @interface HostSideTestSubstitute {
+ // TODO We should add "_host" as default. We're not doing it yet, because extractign the default
+ // value with ASM doesn't seem trivial. (? not sure.)
+ String suffix();
+}
diff --git a/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestThrow.java b/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestThrow.java
new file mode 100644
index 000000000000..cd1bef4be505
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestThrow.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2023 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 android.hosttest.annotation;
+
+import static java.lang.annotation.ElementType.CONSTRUCTOR;
+import static java.lang.annotation.ElementType.METHOD;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * THIS ANNOTATION IS EXPERIMENTAL. REACH OUT TO g/ravenwood BEFORE USING IT, OR YOU HAVE ANY
+ * QUESTIONS ABOUT IT.
+ *
+ * If a method has this annotation, it will throw on the host side.
+ *
+ * @hide
+ */
+@Target({METHOD, CONSTRUCTOR})
+@Retention(RetentionPolicy.CLASS)
+public @interface HostSideTestThrow {
+}
diff --git a/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestWholeClassKeep.java b/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestWholeClassKeep.java
new file mode 100644
index 000000000000..3d1ddea2cbb7
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestWholeClassKeep.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2023 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 android.hosttest.annotation;
+
+import static java.lang.annotation.ElementType.TYPE;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * THIS ANNOTATION IS EXPERIMENTAL. REACH OUT TO g/ravenwood BEFORE USING IT, OR YOU HAVE ANY
+ * QUESTIONS ABOUT IT.
+ *
+ * Same as {@link HostSideTestKeep} but it'll change the visibility of all its members too.
+ * @hide
+ */
+@Target({TYPE})
+@Retention(RetentionPolicy.CLASS)
+public @interface HostSideTestWholeClassKeep {
+}
diff --git a/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestWholeClassStub.java b/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestWholeClassStub.java
new file mode 100644
index 000000000000..1824f6f01516
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestWholeClassStub.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2023 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 android.hosttest.annotation;
+
+import static java.lang.annotation.ElementType.TYPE;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * THIS ANNOTATION IS EXPERIMENTAL. REACH OUT TO g/ravenwood BEFORE USING IT, OR YOU HAVE ANY
+ * QUESTIONS ABOUT IT.
+ *
+ * Same as {@link HostSideTestStub} but it'll change the visibility of all its members too.
+ *
+ * @hide
+ */
+@Target({TYPE})
+@Retention(RetentionPolicy.CLASS)
+public @interface HostSideTestWholeClassStub {
+}
diff --git a/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/tests/HostSideTestSuppress.java b/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/tests/HostSideTestSuppress.java
new file mode 100644
index 000000000000..b10f0ff1a4b1
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/tests/HostSideTestSuppress.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2023 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 android.hosttest.annotation.tests;
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.TYPE;
+
+import java.lang.annotation.Target;
+
+/**
+ * Use this annotation to skip certain tests for host side tests.
+ *
+ * TODO: Actually use it in the test runner.
+ */
+@Target({TYPE, FIELD, METHOD})
+public @interface HostSideTestSuppress {
+}
diff --git a/tools/hoststubgen/hoststubgen/framework-policy-override.txt b/tools/hoststubgen/hoststubgen/framework-policy-override.txt
new file mode 100644
index 000000000000..295498da02e4
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/framework-policy-override.txt
@@ -0,0 +1,98 @@
+# --------------------------------------------------------------------------------------------------
+# This file contains rules to process `framework-all.jar` to generate the host side test "stub" and
+# "impl" jars, without using Java annotations.
+#
+# Useful when:
+# - The class is auto-generated and annotations can't be added.
+# (We need to figure out what to do on auto-generated classes.)
+# - Want to quickly change filter rules without having to rebuild framework.jar.
+#
+# Using this file, one can control the visibility of APIs on a per-class, per-field and per-method
+# basis, but in most cases, per-class directives would be sufficient. That is:
+#
+# - To put the entire class, including its members and nested classes, in the "stub" jar,
+# so that the test / target code can use the API, use `stubclass`.
+#
+# class package.class stubclass
+#
+# - To put the entire class, including its members and nested classes, in the "impl" jar,
+# but not in the "stub" jar, use `keepclass`. Use this when you don't want to expose an API to
+# tests/target directly, but it's still needed at runtime, because it's used by other "stub" APIs
+# directly or indirectly.
+#
+# class package.class keepclass
+#
+# All other classes will be removed from both the stub jar and impl jar.
+#
+# --------------------------------------------------------------------------------------------------
+
+# --------------------------------------------------------------------------------------------------
+# Directions on auto-generated classes, where we can't use Java annotations (yet).
+# --------------------------------------------------------------------------------------------------
+class android.Manifest stubclass
+class android.R stubclass
+class android.os.PersistableBundleProto keepclass
+
+# This is in module-utils, where using a HostStubGen annotation would be complicated, so we
+# add a direction here rather than using a java annotation.
+# The build file says it's deprecated, anyway...? Figure out what to do with it.
+class com.android.internal.util.Preconditions keepclass
+
+# --------------------------------------------------------------------------------------------------
+# Actual framework classes
+# --------------------------------------------------------------------------------------------------
+
+# Put basic exception classes in the "impl" jar.
+# We don't put them in stub yet (until something actually needs them).
+class android.os.DeadObjectException keepclass
+class android.os.DeadSystemRuntimeException keepclass
+class android.os.NetworkOnMainThreadException keepclass
+class android.os.RemoteException keepclass
+class android.os.ServiceSpecificException keepclass
+class android.util.AndroidException keepclass
+class android.util.AndroidRuntimeException keepclass
+class android.os.DeadSystemException keepclass
+
+
+# For now, we only want to expose ArrayMap and Log, but they and their tests depend on
+# more classes.
+
+class android.util.ArrayMap stubclass
+
+# Used by ArrayMap. No need to put them in the stub, but we need them in impl.
+class android.util.MapCollections keepclass
+class android.util.ContainerHelpers keepclass
+class com.android.internal.util.XmlUtils keepclass
+class com.android.internal.util.FastMath keepclass
+class android.util.MathUtils keepclass
+
+
+class android.util.Log stubclass
+class android.util.Slog stubclass
+# We don't use Log's native code, yet. Instead, the following line enables the Java substitution.
+# Comment it out to disable Java substitution of Log's native methods.
+class android.util.Log !com.android.hoststubgen.nativesubstitution.Log_host
+
+# Used by log
+class com.android.internal.util.FastPrintWriter keepclass
+class com.android.internal.util.LineBreakBufferedWriter keepclass
+
+
+# Expose Context because it's referred to by AndroidTestCase, but don't need to expose any of
+# its members.
+class android.content.Context keep
+
+# Expose Parcel, Parcel and there relevant classes, which are used by ArrayMapTets.
+class android.os.Parcelable StubClass
+class android.os.Parcel StubClass
+class android.os.Parcel !com.android.hoststubgen.nativesubstitution.Parcel_host
+
+class android.os.IBinder stubClass
+class android.os.IInterface stubclass
+
+class android.os.BadParcelableException stubclass
+class android.os.BadTypeParcelableException stubclass
+
+class android.os.BaseBundle stubclass
+class android.os.Bundle stubclass
+class android.os.PersistableBundle stubclass
diff --git a/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/android/test/AndroidTestCase.java b/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/android/test/AndroidTestCase.java
new file mode 100644
index 000000000000..e6d38668335a
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/android/test/AndroidTestCase.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2023 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 android.test;
+
+import android.content.Context;
+
+import junit.framework.TestCase;
+
+public class AndroidTestCase extends TestCase {
+ protected Context mContext;
+ public Context getContext() {
+ throw new RuntimeException("[ravenwood] Class Context is not supported yet.");
+ }
+}
diff --git a/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/annotation/NonNull.java b/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/annotation/NonNull.java
new file mode 100644
index 000000000000..51c5d9a05e52
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/annotation/NonNull.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2013 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 androidx.annotation;
+
+// [ravenwood] TODO: Find the actual androidx jar containing it.s
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.PARAMETER;
+import static java.lang.annotation.RetentionPolicy.SOURCE;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * Denotes that a parameter, field or method return value can never be null.
+ * <p>
+ * This is a marker annotation and it has no specific attributes.
+ *
+ * @paramDoc This value cannot be {@code null}.
+ * @returnDoc This value cannot be {@code null}.
+ * @hide
+ */
+@Retention(SOURCE)
+@Target({METHOD, PARAMETER, FIELD})
+public @interface NonNull {
+}
diff --git a/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/annotation/Nullable.java b/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/annotation/Nullable.java
new file mode 100644
index 000000000000..f1f0e8b43f16
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/annotation/Nullable.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2013 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 androidx.annotation;
+
+// [ravenwood] TODO: Find the actual androidx jar containing it.s
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.PARAMETER;
+import static java.lang.annotation.RetentionPolicy.SOURCE;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * Denotes that a parameter, field or method return value can be null.
+ * <p>
+ * When decorating a method call parameter, this denotes that the parameter can
+ * legitimately be null and the method will gracefully deal with it. Typically
+ * used on optional parameters.
+ * <p>
+ * When decorating a method, this denotes the method might legitimately return
+ * null.
+ * <p>
+ * This is a marker annotation and it has no specific attributes.
+ *
+ * @paramDoc This value may be {@code null}.
+ * @returnDoc This value may be {@code null}.
+ * @hide
+ */
+@Retention(SOURCE)
+@Target({METHOD, PARAMETER, FIELD})
+public @interface Nullable {
+}
diff --git a/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/ext/junit/runners/AndroidJUnit4.java b/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/ext/junit/runners/AndroidJUnit4.java
new file mode 100644
index 000000000000..0c82e4e268d3
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/ext/junit/runners/AndroidJUnit4.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2023 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 androidx.test.ext.junit.runners;
+
+import org.junit.runners.BlockJUnit4ClassRunner;
+import org.junit.runners.model.InitializationError;
+
+// TODO: We need to simulate the androidx test runner.
+// https://source.corp.google.com/piper///depot/google3/third_party/android/androidx_test/ext/junit/java/androidx/test/ext/junit/runners/AndroidJUnit4.java
+// https://source.corp.google.com/piper///depot/google3/third_party/android/androidx_test/runner/android_junit_runner/java/androidx/test/internal/runner/junit4/AndroidJUnit4ClassRunner.java
+
+public class AndroidJUnit4 extends BlockJUnit4ClassRunner {
+ public AndroidJUnit4(Class<?> testClass) throws InitializationError {
+ super(testClass);
+ }
+}
diff --git a/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/filters/FlakyTest.java b/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/filters/FlakyTest.java
new file mode 100644
index 000000000000..2470d8390f5d
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/filters/FlakyTest.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2014 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 androidx.test.filters;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Designates a test as being flaky (non-deterministic).
+ *
+ * <p>Can then be used to filter tests on execution using -e annotation or -e notAnnotation as
+ * desired.
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.METHOD, ElementType.TYPE})
+public @interface FlakyTest {
+ /**
+ * An optional bug number associated with the test. -1 Means that no bug number is associated with
+ * the flaky annotation.
+ *
+ * @return int
+ */
+ int bugId() default -1;
+
+ /**
+ * Details, such as the reason of why the test is flaky.
+ *
+ * @return String
+ */
+ String detail() default "";
+}
diff --git a/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/filters/LargeTest.java b/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/filters/LargeTest.java
new file mode 100644
index 000000000000..578d7dc73647
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/filters/LargeTest.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2016 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 androidx.test.filters;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Annotation to assign a large test size qualifier to a test. This annotation can be used at a
+ * method or class level.
+ *
+ * <p>Test size qualifiers are a great way to structure test code and are used to assign a test to a
+ * test suite of similar run time.
+ *
+ * <p>Execution time: &gt;1000ms
+ *
+ * <p>Large tests should be focused on testing integration of all application components. These
+ * tests fully participate in the system and may make use of all resources such as databases, file
+ * systems and network. As a rule of thumb most functional UI tests are large tests.
+ *
+ * <p>Note: This class replaces the deprecated Android platform size qualifier <a
+ * href="{@docRoot}reference/android/test/suitebuilder/annotation/LargeTest.html"><code>
+ * android.test.suitebuilder.annotation.LargeTest</code></a> and is the recommended way to annotate
+ * tests written with the AndroidX Test Library.
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.METHOD, ElementType.TYPE})
+public @interface LargeTest {}
diff --git a/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/filters/MediumTest.java b/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/filters/MediumTest.java
new file mode 100644
index 000000000000..dfdaa53ee6ac
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/filters/MediumTest.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2016 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 androidx.test.filters;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Annotation to assign a medium test size qualifier to a test. This annotation can be used at a
+ * method or class level.
+ *
+ * <p>Test size qualifiers are a great way to structure test code and are used to assign a test to a
+ * test suite of similar run time.
+ *
+ * <p>Execution time: &lt;1000ms
+ *
+ * <p>Medium tests should be focused on a very limited subset of components or a single component.
+ * Resource access to the file system through well defined interfaces like databases,
+ * ContentProviders, or Context is permitted. Network access should be restricted, (long-running)
+ * blocking operations should be avoided and use mock objects instead.
+ *
+ * <p>Note: This class replaces the deprecated Android platform size qualifier <a
+ * href="{@docRoot}reference/android/test/suitebuilder/annotation/MediumTest.html"><code>
+ * android.test.suitebuilder.annotation.MediumTest</code></a> and is the recommended way to annotate
+ * tests written with the AndroidX Test Library.
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.METHOD, ElementType.TYPE})
+public @interface MediumTest {}
diff --git a/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/filters/RequiresDevice.java b/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/filters/RequiresDevice.java
new file mode 100644
index 000000000000..3d3ee3318bfa
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/filters/RequiresDevice.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2014 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 androidx.test.filters;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Indicates that a specific test should not be run on emulator.
+ *
+ * <p>It will be executed only if the test is running on the physical android device.
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.TYPE, ElementType.METHOD})
+public @interface RequiresDevice {}
diff --git a/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/filters/SdkSuppress.java b/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/filters/SdkSuppress.java
new file mode 100644
index 000000000000..dd65ddb382dc
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/filters/SdkSuppress.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2014 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 androidx.test.filters;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Indicates that a specific test or class requires a minimum or maximum API Level to execute.
+ *
+ * <p>Test(s) will be skipped when executed on android platforms less/more than specified level
+ * (inclusive).
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.TYPE, ElementType.METHOD})
+public @interface SdkSuppress {
+ /** The minimum API level to execute (inclusive) */
+ int minSdkVersion() default 1;
+ /** The maximum API level to execute (inclusive) */
+ int maxSdkVersion() default Integer.MAX_VALUE;
+ /**
+ * The {@link android.os.Build.VERSION.CODENAME} to execute on. This is intended to be used to run
+ * on a pre-release SDK, where the {@link android.os.Build.VERSION.SDK_INT} has not yet been
+ * finalized. This is treated as an OR operation with respect to the minSdkVersion and
+ * maxSdkVersion attributes.
+ *
+ * <p>For example, to filter a test so it runs on only the prerelease R SDK: <code>
+ * {@literal @}SdkSuppress(minSdkVersion = Build.VERSION_CODES.R, codeName = "R")
+ * </code>
+ */
+ String codeName() default "unset";
+}
diff --git a/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/filters/SmallTest.java b/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/filters/SmallTest.java
new file mode 100644
index 000000000000..dd32df44effe
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/filters/SmallTest.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2016 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 androidx.test.filters;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Annotation to assign a small test size qualifier to a test. This annotation can be used at a
+ * method or class level.
+ *
+ * <p>Test size qualifiers are a great way to structure test code and are used to assign a test to a
+ * test suite of similar run time.
+ *
+ * <p>Execution time: &lt;200ms
+ *
+ * <p>Small tests should be run very frequently. Focused on units of code to verify specific logical
+ * conditions. These tests should runs in an isolated environment and use mock objects for external
+ * dependencies. Resource access (such as file system, network, or databases) are not permitted.
+ * Tests that interact with hardware, make binder calls, or that facilitate android instrumentation
+ * should not use this annotation.
+ *
+ * <p>Note: This class replaces the deprecated Android platform size qualifier <a
+ * href="http://developer.android.com/reference/android/test/suitebuilder/annotation/SmallTest.html">
+ * android.test.suitebuilder.annotation.SmallTest</a> and is the recommended way to annotate tests
+ * written with the AndroidX Test Library.
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.METHOD, ElementType.TYPE})
+public @interface SmallTest {}
diff --git a/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/filters/Suppress.java b/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/filters/Suppress.java
new file mode 100644
index 000000000000..88e636c2dd77
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/filters/Suppress.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2016 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 androidx.test.filters;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Use this annotation on test classes or test methods that should not be included in a test suite.
+ * If the annotation appears on the class then no tests in that class will be included. If the
+ * annotation appears only on a test method then only that method will be excluded.
+ *
+ * <p>Note: This class replaces the deprecated Android platform annotation <a
+ * href="http://developer.android.com/reference/android/test/suitebuilder/annotation/Suppress.html">
+ * android.test.suitebuilder.annotation.Suppress</a> and is the recommended way to suppress tests
+ * written with the AndroidX Test Library.
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.METHOD, ElementType.TYPE})
+public @interface Suppress {}
diff --git a/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/runner/AndroidJUnit4.java b/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/runner/AndroidJUnit4.java
new file mode 100644
index 000000000000..e1379390f98b
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/runner/AndroidJUnit4.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2023 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 androidx.test.runner;
+
+import org.junit.runners.model.InitializationError;
+
+public class AndroidJUnit4 extends androidx.test.ext.junit.runners.AndroidJUnit4 {
+ public AndroidJUnit4(Class<?> testClass) throws InitializationError {
+ super(testClass);
+ }
+}
diff --git a/tools/hoststubgen/hoststubgen/helper-framework-runtime-src/framework/com/android/hoststubgen/nativesubstitution/Log_host.java b/tools/hoststubgen/hoststubgen/helper-framework-runtime-src/framework/com/android/hoststubgen/nativesubstitution/Log_host.java
new file mode 100644
index 000000000000..ee55c7ac6ae2
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/helper-framework-runtime-src/framework/com/android/hoststubgen/nativesubstitution/Log_host.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2023 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.hoststubgen.nativesubstitution;
+
+import android.util.Log;
+import android.util.Log.Level;
+
+import java.io.PrintStream;
+
+public class Log_host {
+
+ public static boolean isLoggable(String tag, @Level int level) {
+ return true;
+ }
+
+ public static int println_native(int bufID, int priority, String tag, String msg) {
+ final PrintStream out = System.out;
+ final String buffer;
+ switch (bufID) {
+ case Log.LOG_ID_MAIN: buffer = "main"; break;
+ case Log.LOG_ID_RADIO: buffer = "radio"; break;
+ case Log.LOG_ID_EVENTS: buffer = "event"; break;
+ case Log.LOG_ID_SYSTEM: buffer = "system"; break;
+ case Log.LOG_ID_CRASH: buffer = "crash"; break;
+ default: buffer = "buf:" + bufID; break;
+ };
+
+ final String prio;
+ switch (priority) {
+ case Log.VERBOSE: prio = "V"; break;
+ case Log.DEBUG: prio = "D"; break;
+ case Log.INFO: prio = "I"; break;
+ case Log.WARN: prio = "W"; break;
+ case Log.ERROR: prio = "E"; break;
+ case Log.ASSERT: prio = "A"; break;
+ default: prio = "prio:" + priority; break;
+ };
+
+ for (String s : msg.split("\\n")) {
+ out.println(String.format("logd: [%s] %s %s: %s", buffer, prio, tag, s));
+ }
+ return msg.length();
+ }
+
+ public static int logger_entry_max_payload_native() {
+ return 4068; // [ravenwood] This is what people use in various places.
+ }
+}
diff --git a/tools/hoststubgen/hoststubgen/helper-framework-runtime-src/framework/com/android/hoststubgen/nativesubstitution/Parcel_host.java b/tools/hoststubgen/hoststubgen/helper-framework-runtime-src/framework/com/android/hoststubgen/nativesubstitution/Parcel_host.java
new file mode 100644
index 000000000000..d749f076f3b5
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/helper-framework-runtime-src/framework/com/android/hoststubgen/nativesubstitution/Parcel_host.java
@@ -0,0 +1,404 @@
+/*
+ * Copyright (C) 2023 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.hoststubgen.nativesubstitution;
+
+import android.os.IBinder;
+
+import java.io.FileDescriptor;
+import java.nio.ByteBuffer;
+import java.nio.charset.StandardCharsets;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.atomic.AtomicLong;
+
+/**
+ * Tentative, partial implementation of the Parcel native methods, using Java's
+ * {@link ByteBuffer}. It turned out there's enough semantics differences between Parcel
+ * and {@link ByteBuffer}, so it didn't actually work.
+ * (e.g. Parcel seems to allow moving the data position to be beyond its size? Which
+ * {@link ByteBuffer} wouldn't allow...)
+ */
+public class Parcel_host {
+ private Parcel_host() {
+ }
+
+ private static final AtomicLong sNextId = new AtomicLong(0);
+
+ private static final Map<Long, Parcel_host> sInstances = new ConcurrentHashMap<>();
+
+ private boolean mDeleted = false;
+
+ private byte[] mBuffer;
+ private int mSize;
+ private int mPos;
+
+ private boolean mSensitive;
+ private boolean mAllowFds;
+
+ // TODO Use the actual value from Parcel.java.
+ private static final int OK = 0;
+
+ private void validate() {
+ if (mDeleted) {
+ // TODO: Put more info
+ throw new RuntimeException("Parcel already destroyed");
+ }
+ }
+
+ private static Parcel_host getInstance(long id) {
+ Parcel_host p = sInstances.get(id);
+ if (p == null) {
+ // TODO: Put more info
+ throw new RuntimeException("Parcel doesn't exist with id=" + id);
+ }
+ p.validate();
+ return p;
+ }
+
+ public static long nativeCreate() {
+ final long id = sNextId.getAndIncrement();
+ final Parcel_host p = new Parcel_host();
+ sInstances.put(id, p);
+ p.init();
+ return id;
+ }
+
+ private void init() {
+ mBuffer = new byte[0];
+ mSize = 0;
+ mPos = 0;
+ mSensitive = false;
+ mAllowFds = false;
+ }
+
+ private void updateSize() {
+ if (mSize < mPos) {
+ mSize = mPos;
+ }
+ }
+
+ public static void nativeDestroy(long nativePtr) {
+ getInstance(nativePtr).mDeleted = true;
+ sInstances.remove(nativePtr);
+ }
+
+ public static void nativeFreeBuffer(long nativePtr) {
+ getInstance(nativePtr).freeBuffer();
+ }
+
+ public void freeBuffer() {
+ init();
+ }
+
+ private int getCapacity() {
+ return mBuffer.length;
+ }
+
+ private void ensureMoreCapacity(int size) {
+ ensureCapacity(mPos + size);
+ }
+
+ private void ensureCapacity(int targetSize) {
+ if (targetSize <= getCapacity()) {
+ return;
+ }
+ var newSize = getCapacity() * 2;
+ if (newSize < targetSize) {
+ newSize = targetSize;
+ }
+ forceSetCapacity(newSize);
+ }
+
+ private void forceSetCapacity(int newSize) {
+ var newBuf = new byte[newSize];
+
+ // Copy
+ System.arraycopy(mBuffer, 0, newBuf, 0, Math.min(newSize, getCapacity()));
+
+ this.mBuffer = newBuf;
+ }
+
+ private void ensureDataAvailable(int requestSize) {
+ if (mSize - mPos < requestSize) {
+ throw new RuntimeException(String.format(
+ "Pacel data underflow. size=%d, pos=%d, request=%d", mSize, mPos, requestSize));
+ }
+ }
+
+ public static void nativeMarkSensitive(long nativePtr) {
+ getInstance(nativePtr).mSensitive = true;
+ }
+ public static void nativeMarkForBinder(long nativePtr, IBinder binder) {
+ throw new RuntimeException("Not implemented yet");
+ }
+ public static boolean nativeIsForRpc(long nativePtr) {
+ throw new RuntimeException("Not implemented yet");
+ }
+ public static int nativeDataSize(long nativePtr) {
+ return getInstance(nativePtr).mSize;
+ }
+ public static int nativeDataAvail(long nativePtr) {
+ var p = getInstance(nativePtr);
+ return p.mSize - p.mPos;
+ }
+ public static int nativeDataPosition(long nativePtr) {
+ return getInstance(nativePtr).mPos;
+ }
+ public static int nativeDataCapacity(long nativePtr) {
+ return getInstance(nativePtr).mBuffer.length;
+ }
+ public static void nativeSetDataSize(long nativePtr, int size) {
+ var p = getInstance(nativePtr);
+ p.ensureCapacity(size);
+ getInstance(nativePtr).mSize = size;
+ }
+ public static void nativeSetDataPosition(long nativePtr, int pos) {
+ var p = getInstance(nativePtr);
+ // TODO: Should this change the size or the capacity??
+ p.mPos = pos;
+ }
+ public static void nativeSetDataCapacity(long nativePtr, int size) {
+ var p = getInstance(nativePtr);
+ if (p.getCapacity() < size) {
+ p.forceSetCapacity(size);
+ }
+ }
+
+ public static boolean nativePushAllowFds(long nativePtr, boolean allowFds) {
+ var p = getInstance(nativePtr);
+ var prev = p.mAllowFds;
+ p.mAllowFds = allowFds;
+ return prev;
+ }
+ public static void nativeRestoreAllowFds(long nativePtr, boolean lastValue) {
+ getInstance(nativePtr).mAllowFds = lastValue;
+ }
+
+ public static void nativeWriteByteArray(long nativePtr, byte[] b, int offset, int len) {
+ nativeWriteBlob(nativePtr, b, offset, len);
+ }
+
+ public static void nativeWriteBlob(long nativePtr, byte[] b, int offset, int len) {
+ var p = getInstance(nativePtr);
+
+ if (b == null) {
+ nativeWriteInt(nativePtr, -1);
+ } else {
+ final var alignedSize = align4(b.length);
+
+ nativeWriteInt(nativePtr, b.length);
+
+ p.ensureMoreCapacity(alignedSize);
+
+ System.arraycopy(b, offset, p.mBuffer, p.mPos, len);
+ p.mPos += alignedSize;
+ p.updateSize();
+ }
+ }
+
+ public static int nativeWriteInt(long nativePtr, int value) {
+ var p = getInstance(nativePtr);
+ p.ensureMoreCapacity(Integer.BYTES);
+
+ p.mBuffer[p.mPos++] = (byte) ((value >> 24) & 0xff);
+ p.mBuffer[p.mPos++] = (byte) ((value >> 16) & 0xff);
+ p.mBuffer[p.mPos++] = (byte) ((value >> 8) & 0xff);
+ p.mBuffer[p.mPos++] = (byte) ((value >> 0) & 0xff);
+
+ p.updateSize();
+
+ return OK;
+ }
+
+ public static int nativeWriteLong(long nativePtr, long value) {
+ nativeWriteInt(nativePtr, (int) (value >>> 32));
+ nativeWriteInt(nativePtr, (int) (value));
+ return OK;
+ }
+ public static int nativeWriteFloat(long nativePtr, float val) {
+ return nativeWriteInt(nativePtr, Float.floatToIntBits(val));
+ }
+ public static int nativeWriteDouble(long nativePtr, double val) {
+ return nativeWriteLong(nativePtr, Double.doubleToLongBits(val));
+ }
+ public static void nativeSignalExceptionForError(int error) {
+ throw new RuntimeException("Not implemented yet");
+ }
+
+ private static int align4(int val) {
+ return ((val + 3) / 4) * 4;
+ }
+
+ public static void nativeWriteString8(long nativePtr, String val) {
+ if (val == null) {
+ nativeWriteBlob(nativePtr, null, 0, 0);
+ } else {
+ var bytes = val.getBytes(StandardCharsets.UTF_8);
+ nativeWriteBlob(nativePtr, bytes, 0, bytes.length);
+ }
+ }
+ public static void nativeWriteString16(long nativePtr, String val) {
+ // Just reuse String8
+ nativeWriteString8(nativePtr, val);
+ }
+ public static void nativeWriteStrongBinder(long nativePtr, IBinder val) {
+ throw new RuntimeException("Not implemented yet");
+ }
+ public static void nativeWriteFileDescriptor(long nativePtr, FileDescriptor val) {
+ throw new RuntimeException("Not implemented yet");
+ }
+
+ public static byte[] nativeCreateByteArray(long nativePtr) {
+ return nativeReadBlob(nativePtr);
+ }
+
+ public static boolean nativeReadByteArray(long nativePtr, byte[] dest, int destLen) {
+ if (dest == null) {
+ return false;
+ }
+ var data = nativeReadBlob(nativePtr);
+ if (data == null) {
+ System.err.println("Percel has NULL, which is unexpected."); // TODO: Is this correct?
+ return false;
+ }
+ // TODO: Make sure the check logic is correct.
+ if (data.length != destLen) {
+ System.err.println("Byte array size mismatch: expected="
+ + data.length + " given=" + destLen);
+ return false;
+ }
+ return true;
+ }
+
+ public static byte[] nativeReadBlob(long nativePtr) {
+ final var size = nativeReadInt(nativePtr);
+ if (size == -1) {
+ return null;
+ }
+ var p = getInstance(nativePtr);
+ p.ensureDataAvailable(size);
+
+ var bytes = new byte[size];
+ System.arraycopy(p.mBuffer, p.mPos, bytes, 0, size);
+
+ p.mPos += align4(size);
+
+ return bytes;
+ }
+ public static int nativeReadInt(long nativePtr) {
+ var p = getInstance(nativePtr);
+
+ p.ensureDataAvailable(Integer.BYTES);
+
+ var ret = (((p.mBuffer[p.mPos++] & 0xff) << 24)
+ | ((p.mBuffer[p.mPos++] & 0xff) << 16)
+ | ((p.mBuffer[p.mPos++] & 0xff) << 8)
+ | ((p.mBuffer[p.mPos++] & 0xff) << 0));
+
+ return ret;
+ }
+ public static long nativeReadLong(long nativePtr) {
+ return (((long) nativeReadInt(nativePtr)) << 32)
+ | (((long) nativeReadInt(nativePtr)) & 0xffff_ffffL);
+ }
+
+ public static float nativeReadFloat(long nativePtr) {
+ return Float.intBitsToFloat(nativeReadInt(nativePtr));
+ }
+
+ public static double nativeReadDouble(long nativePtr) {
+ return Double.longBitsToDouble(nativeReadLong(nativePtr));
+ }
+
+ public static String nativeReadString8(long nativePtr) {
+ final var bytes = nativeReadBlob(nativePtr);
+ if (bytes == null) {
+ return null;
+ }
+ return new String(bytes, StandardCharsets.UTF_8);
+ }
+ public static String nativeReadString16(long nativePtr) {
+ return nativeReadString8(nativePtr);
+ }
+ public static IBinder nativeReadStrongBinder(long nativePtr) {
+ throw new RuntimeException("Not implemented yet");
+ }
+ public static FileDescriptor nativeReadFileDescriptor(long nativePtr) {
+ throw new RuntimeException("Not implemented yet");
+ }
+
+ public static byte[] nativeMarshall(long nativePtr) {
+ throw new RuntimeException("Not implemented yet");
+ }
+ public static void nativeUnmarshall(
+ long nativePtr, byte[] data, int offset, int length) {
+ throw new RuntimeException("Not implemented yet");
+ }
+ public static int nativeCompareData(long thisNativePtr, long otherNativePtr) {
+ throw new RuntimeException("Not implemented yet");
+ }
+ public static boolean nativeCompareDataInRange(
+ long ptrA, int offsetA, long ptrB, int offsetB, int length) {
+ throw new RuntimeException("Not implemented yet");
+ }
+ public static void nativeAppendFrom(
+ long thisNativePtr, long otherNativePtr, int srcOffset, int length) {
+ var dst = getInstance(thisNativePtr);
+ var src = getInstance(otherNativePtr);
+
+ dst.ensureMoreCapacity(length);
+
+ System.arraycopy(src.mBuffer, srcOffset, dst.mBuffer, dst.mPos, length);
+ dst.mPos += length; // TODO: 4 byte align?
+ dst.updateSize();
+
+ // TODO: Update the other's position?
+ }
+
+ public static boolean nativeHasFileDescriptors(long nativePtr) {
+ // Assume false for now, because we don't support writing FDs yet.
+ return false;
+ }
+ public static boolean nativeHasFileDescriptorsInRange(
+ long nativePtr, int offset, int length) {
+ // Assume false for now, because we don't support writing FDs yet.
+ return false;
+ }
+ public static void nativeWriteInterfaceToken(long nativePtr, String interfaceName) {
+ throw new RuntimeException("Not implemented yet");
+ }
+ public static void nativeEnforceInterface(long nativePtr, String interfaceName) {
+ throw new RuntimeException("Not implemented yet");
+ }
+
+ public static boolean nativeReplaceCallingWorkSourceUid(
+ long nativePtr, int workSourceUid) {
+ throw new RuntimeException("Not implemented yet");
+ }
+ public static int nativeReadCallingWorkSourceUid(long nativePtr) {
+ throw new RuntimeException("Not implemented yet");
+ }
+
+ public static long nativeGetOpenAshmemSize(long nativePtr) {
+ throw new RuntimeException("Not implemented yet");
+ }
+ public static long getGlobalAllocSize() {
+ throw new RuntimeException("Not implemented yet");
+ }
+ public static long getGlobalAllocCount() {
+ throw new RuntimeException("Not implemented yet");
+ }
+}
diff --git a/tools/hoststubgen/hoststubgen/helper-framework-runtime-src/framework/com/android/hoststubgen/nativesubstitution/SystemProperties_host.java b/tools/hoststubgen/hoststubgen/helper-framework-runtime-src/framework/com/android/hoststubgen/nativesubstitution/SystemProperties_host.java
new file mode 100644
index 000000000000..1ec1d5f307e1
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/helper-framework-runtime-src/framework/com/android/hoststubgen/nativesubstitution/SystemProperties_host.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2023 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.hoststubgen.nativesubstitution;
+
+public class SystemProperties_host {
+ public static String native_get(String key, String def) {
+ throw new RuntimeException("Not implemented yet");
+ }
+ public static int native_get_int(String key, int def) {
+ throw new RuntimeException("Not implemented yet");
+ }
+ public static long native_get_long(String key, long def) {
+ throw new RuntimeException("Not implemented yet");
+ }
+ public static boolean native_get_boolean(String key, boolean def) {
+ throw new RuntimeException("Not implemented yet");
+ }
+
+ public static long native_find(String name) {
+ throw new RuntimeException("Not implemented yet");
+ }
+ public static String native_get(long handle) {
+ throw new RuntimeException("Not implemented yet");
+ }
+ public static int native_get_int(long handle, int def) {
+ throw new RuntimeException("Not implemented yet");
+ }
+ public static long native_get_long(long handle, long def) {
+ throw new RuntimeException("Not implemented yet");
+ }
+ public static boolean native_get_boolean(long handle, boolean def) {
+ throw new RuntimeException("Not implemented yet");
+ }
+ public static void native_set(String key, String def) {
+ throw new RuntimeException("Not implemented yet");
+ }
+ public static void native_add_change_callback() {
+ throw new RuntimeException("Not implemented yet");
+ }
+ public static void native_report_sysprop_change() {
+ throw new RuntimeException("Not implemented yet");
+ }
+}
diff --git a/tools/hoststubgen/hoststubgen/helper-framework-runtime-src/framework/com/android/hoststubgen/runtimehelper/ClassLoadHook.java b/tools/hoststubgen/hoststubgen/helper-framework-runtime-src/framework/com/android/hoststubgen/runtimehelper/ClassLoadHook.java
new file mode 100644
index 000000000000..4c2d3c404b76
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/helper-framework-runtime-src/framework/com/android/hoststubgen/runtimehelper/ClassLoadHook.java
@@ -0,0 +1,182 @@
+/*
+ * Copyright (C) 2023 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.hoststubgen.runtimehelper;
+
+import com.android.hoststubgen.hosthelper.HostTestException;
+
+import java.io.File;
+import java.io.PrintStream;
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.Arrays;
+
+/**
+ * Standard class to handle class load hook.
+ *
+ * We use this to initialize the environment necessary for some classes. (e.g. load native libs.)
+ */
+public class ClassLoadHook {
+ private static PrintStream out = System.out;
+
+ /**
+ * If true, we won't load `libandroid_runtime`
+ *
+ * <p>Looks like there's some complexity in running a host test with JNI with `atest`,
+ * so we need a way to remove the dependency.
+ */
+ private static final boolean SKIP_LOADING_LIBANDROID = "1".equals(System.getenv(
+ "HOSTTEST_SKIP_LOADING_LIBANDROID"));
+
+ public static final String CORE_NATIVE_CLASSES = "core_native_classes";
+ public static final String ICU_DATA_PATH = "icu.data.path";
+ public static final String KEYBOARD_PATHS = "keyboard_paths";
+ public static final String GRAPHICS_NATIVE_CLASSES = "graphics_native_classes";
+
+ public static final String VALUE_N_A = "**n/a**";
+ public static final String LIBANDROID_RUNTIME_NAME = "libandroid_runtime";
+
+ private static String sInitialDir = new File("").getAbsolutePath();
+
+ static {
+ log("Initialized. Current dir=" + sInitialDir);
+ }
+
+ private ClassLoadHook() {
+ }
+
+ /**
+ * Called when classes with
+ * {@code @HostSideTestClassLoadHook("com.android.hoststubgen.runtimehelper.ClassLoadHook.onClassLoaded") }
+ * are loaded.
+ */
+ public static void onClassLoaded(Class<?> clazz) {
+ System.out.println("Framework class loaded: " + clazz.getCanonicalName());
+
+ if (android.util.Log.class == clazz) {
+ loadFrameworkNativeCode();
+ }
+ }
+
+ private static void log(String message) {
+ out.println("ClassLoadHook: " + message);
+ }
+
+ private static void log(String fmt, Object... args) {
+ log(String.format(fmt, args));
+ }
+
+ private static void ensurePropertyNotSet(String key) {
+ if (System.getProperty(key) != null) {
+ throw new HostTestException("System property \"" + key + "\" is set unexpectedly");
+ }
+ }
+
+ private static void setProperty(String key, String value) {
+ System.setProperty(key, value);
+ log("Property set: %s=\"%s\"", key, value);
+ }
+
+ private static void dumpSystemProperties() {
+ for (var prop : System.getProperties().entrySet()) {
+ log(" %s=\"%s\"", prop.getKey(), prop.getValue());
+ }
+ }
+
+ private static void loadJniLibrary(String name) {
+ final String path = sInitialDir + "/lib64/" + name + ".so";
+ System.out.println("Loading " + path + " ...");
+ System.load(path);
+ System.out.println("Done loading " + path);
+ }
+
+ private static boolean sLoadFrameworkNativeCodeCalled = false;
+
+ /**
+ * Load `libandroid_runtime` if needed.
+ */
+ private static void loadFrameworkNativeCode() {
+ // This is called from class-initializers, so no synchronization is needed.
+ if (sLoadFrameworkNativeCodeCalled) {
+ // This method has already been called before.s
+ return;
+ }
+ sLoadFrameworkNativeCodeCalled = true;
+
+ // libandroid_runtime uses Java's system properties to decide what JNI methods to set up.
+ // Set up these properties for host-side tests.
+
+ if ("1".equals(System.getenv("HOSTTEST_DUMP_PROPERTIES"))) {
+ log("Java system properties:");
+ dumpSystemProperties();
+ }
+
+ if (SKIP_LOADING_LIBANDROID) {
+ log("Skip loading " + LIBANDROID_RUNTIME_NAME);
+ }
+
+ // Make sure these properties are not set.
+ ensurePropertyNotSet(CORE_NATIVE_CLASSES);
+ ensurePropertyNotSet(ICU_DATA_PATH);
+ ensurePropertyNotSet(KEYBOARD_PATHS);
+ ensurePropertyNotSet(GRAPHICS_NATIVE_CLASSES);
+
+ // Tell libandroid what JNI to use.
+ final var jniClasses = getCoreNativeClassesToUse();
+ if (jniClasses.isEmpty()) {
+ log("No classes require JNI methods, skip loading " + LIBANDROID_RUNTIME_NAME);
+ return;
+ }
+ setProperty(CORE_NATIVE_CLASSES, jniClasses);
+ setProperty(GRAPHICS_NATIVE_CLASSES, "");
+ setProperty(ICU_DATA_PATH, VALUE_N_A);
+ setProperty(KEYBOARD_PATHS, VALUE_N_A);
+
+ loadJniLibrary(LIBANDROID_RUNTIME_NAME);
+ }
+
+ /**
+ * @return if a given method is a native method or not.
+ */
+ private static boolean isNativeMethod(Class<?> clazz, String methodName, Class<?>... argTypes) {
+ try {
+ final var method = clazz.getMethod(methodName, argTypes);
+ return Modifier.isNative(method.getModifiers());
+ } catch (NoSuchMethodException e) {
+ throw new HostTestException(String.format(
+ "Class %s doesn't have method %s with args %s",
+ clazz.getCanonicalName(),
+ methodName,
+ Arrays.toString(argTypes)), e);
+ }
+ }
+
+ /**
+ * Create a list of classes as comma-separated that require JNI methods to be set up.
+ *
+ * <p>This list is used by frameworks/base/core/jni/LayoutlibLoader.cpp to decide
+ * what JNI methods to set up.
+ */
+ private static String getCoreNativeClassesToUse() {
+ final var coreNativeClassesToLoad = new ArrayList<String>();
+
+ if (isNativeMethod(android.util.Log.class, "isLoggable",
+ String.class, int.class)) {
+ coreNativeClassesToLoad.add("android.util.Log");
+ }
+
+ return String.join(",", coreNativeClassesToLoad);
+ }
+}
diff --git a/tools/hoststubgen/hoststubgen/helper-framework-runtime-src/libcore-fake/dalvik/system/VMRuntime.java b/tools/hoststubgen/hoststubgen/helper-framework-runtime-src/libcore-fake/dalvik/system/VMRuntime.java
new file mode 100644
index 000000000000..7d2b00d9420d
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/helper-framework-runtime-src/libcore-fake/dalvik/system/VMRuntime.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2023 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 dalvik.system;
+
+// [ravenwood] It's in libart, so until we get ART to work, we need to use a fake.
+// The original is here:
+// $ANDROID_BUILD_TOP/libcore/libart/src/main/java/dalvik/system/VMRuntime.java
+
+import java.lang.reflect.Array;
+
+public class VMRuntime {
+ private static final VMRuntime THE_ONE = new VMRuntime();
+
+ private VMRuntime() {
+ }
+
+ public static VMRuntime getRuntime() {
+ return THE_ONE;
+ }
+
+ public boolean is64Bit() {
+ return true;
+ }
+
+ public static boolean is64BitAbi(String abi) {
+ return true;
+ }
+
+ public Object newUnpaddedArray(Class<?> componentType, int minLength) {
+ return Array.newInstance(componentType, minLength);
+ }
+}
diff --git a/tools/hoststubgen/hoststubgen/helper-framework-runtime-src/libcore-fake/libcore/util/EmptyArray.java b/tools/hoststubgen/hoststubgen/helper-framework-runtime-src/libcore-fake/libcore/util/EmptyArray.java
new file mode 100644
index 000000000000..a1ae35a88656
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/helper-framework-runtime-src/libcore-fake/libcore/util/EmptyArray.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2023 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 libcore.util;
+
+import java.lang.annotation.Annotation;
+
+// [ravenwood] Copied from libcore. TODO: Figure out what to do with libcore.
+public class EmptyArray {
+ private EmptyArray() {}
+
+ public static final boolean[] BOOLEAN = new boolean[0];
+
+ public static final byte[] BYTE = new byte[0];
+
+ public static final char[] CHAR = new char[0];
+
+ public static final double[] DOUBLE = new double[0];
+
+ public static final float[] FLOAT = new float[0];
+
+ public static final int[] INT = new int[0];
+
+ public static final long[] LONG = new long[0];
+
+ public static final Class<?>[] CLASS = new Class[0];
+
+ public static final Object[] OBJECT = new Object[0];
+
+ public static final String[] STRING = new String[0];
+
+ public static final Throwable[] THROWABLE = new Throwable[0];
+
+ public static final StackTraceElement[] STACK_TRACE_ELEMENT = new StackTraceElement[0];
+
+ public static final java.lang.reflect.Type[] TYPE = new java.lang.reflect.Type[0];
+
+ public static final java.lang.reflect.TypeVariable[] TYPE_VARIABLE =
+ new java.lang.reflect.TypeVariable[0];
+ public static final Annotation[] ANNOTATION = new Annotation[0];
+
+}
diff --git a/tools/hoststubgen/hoststubgen/helper-framework-runtime-src/libcore-fake/libcore/util/SneakyThrow.java b/tools/hoststubgen/hoststubgen/helper-framework-runtime-src/libcore-fake/libcore/util/SneakyThrow.java
new file mode 100644
index 000000000000..e142c46bc311
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/helper-framework-runtime-src/libcore-fake/libcore/util/SneakyThrow.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2015 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 libcore.util;
+
+// [ravenwood] Copied from libcore. TODO: Figure out what to do with libcore.
+
+public class SneakyThrow {
+
+ private SneakyThrow() {
+ }
+
+ public static void sneakyThrow(Throwable t) {
+ SneakyThrow.<RuntimeException>sneakyThrow_(t);
+ }
+
+ private static <T extends Throwable> void sneakyThrow_(Throwable t) throws T {
+ throw (T) t;
+ }
+}
diff --git a/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostStubGenProcessedKeepClass.java b/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostStubGenProcessedKeepClass.java
new file mode 100644
index 000000000000..4c37579ac917
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostStubGenProcessedKeepClass.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2023 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.hoststubgen.hosthelper;
+
+import static java.lang.annotation.ElementType.TYPE;
+
+import org.objectweb.asm.Type;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Annotation added to all "stub" classes generated by HostStubGen.
+ */
+@Target({TYPE})
+@Retention(RetentionPolicy.RUNTIME)
+public @interface HostStubGenProcessedKeepClass {
+ String CLASS_INTERNAL_NAME = Type.getInternalName(HostStubGenProcessedKeepClass.class);
+ String CLASS_DESCRIPTOR = "L" + CLASS_INTERNAL_NAME + ";";
+}
diff --git a/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostStubGenProcessedStubClass.java b/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostStubGenProcessedStubClass.java
new file mode 100644
index 000000000000..34e0030f548a
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostStubGenProcessedStubClass.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2023 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.hoststubgen.hosthelper;
+
+import static java.lang.annotation.ElementType.TYPE;
+
+import org.objectweb.asm.Type;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Annotation added to all "stub" classes generated by HostStubGen.
+ */
+@Target({TYPE})
+@Retention(RetentionPolicy.RUNTIME)
+public @interface HostStubGenProcessedStubClass {
+ String CLASS_INTERNAL_NAME = Type.getInternalName(HostStubGenProcessedStubClass.class);
+ String CLASS_DESCRIPTOR = "L" + CLASS_INTERNAL_NAME + ";";
+}
diff --git a/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostTestException.java b/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostTestException.java
new file mode 100644
index 000000000000..c54c2c111229
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostTestException.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2023 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.hoststubgen.hosthelper;
+
+public class HostTestException extends RuntimeException {
+ public HostTestException(String message) {
+ super(message);
+ }
+
+ public HostTestException(String message, Throwable inner) {
+ super(message, inner);
+ }
+}
diff --git a/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostTestSuite.java b/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostTestSuite.java
new file mode 100644
index 000000000000..29f7be008eef
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostTestSuite.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2023 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.hoststubgen.hosthelper;
+
+import com.google.common.reflect.ClassPath;
+import com.google.common.reflect.ClassPath.ClassInfo;
+
+import junit.framework.JUnit4TestAdapter;
+import junit.framework.TestSuite;
+
+import java.util.regex.Pattern;
+
+/**
+ * A very simple Junit {@link TestSuite} builder that finds all classes that look like test classes.
+ *
+ * We use it to run ravenwood test jars from the command line.
+ */
+public class HostTestSuite {
+ private static final String CLASS_NAME_REGEX_ENV = "HOST_TEST_CLASS_NAME_REGEX";
+
+ /**
+ * Called by junit, and return all test-looking classes as a suite.
+ */
+ public static TestSuite suite() {
+ TestSuite suite = new TestSuite();
+
+ final Pattern classNamePattern;
+ final var filterRegex = System.getenv(CLASS_NAME_REGEX_ENV);
+ if (filterRegex == null) {
+ classNamePattern = Pattern.compile("");
+ } else {
+ classNamePattern = Pattern.compile(filterRegex);
+ }
+ try {
+ // We use guava to list all classes.
+ ClassPath cp = ClassPath.from(HostTestSuite.class.getClassLoader());
+
+ for (var classInfo : cp.getAllClasses()) {
+ Class<?> clazz = asTestClass(classInfo);
+ if (clazz != null) {
+ if (classNamePattern.matcher(clazz.getSimpleName()).find()) {
+ System.out.println("Test class found " + clazz.getName());
+ } else {
+ System.out.println("Skipping test class (for $"
+ + CLASS_NAME_REGEX_ENV + "): " + clazz.getName());
+ }
+ suite.addTest(new JUnit4TestAdapter(clazz));
+ }
+ }
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ return suite;
+ }
+
+ /**
+ * Decide whether a class looks like a test class or not, and if so, return it as a Class
+ * instance.
+ */
+ private static Class<?> asTestClass(ClassInfo classInfo) {
+ try {
+ final Class<?> clazz = classInfo.load();
+
+ // Does it extend junit.framework.TestCase?
+ if (junit.framework.TestCase.class.isAssignableFrom(clazz)) {
+ // Ignore classes in JUnit itself, or the android(x) test lib.
+ if (classInfo.getName().startsWith("junit.")
+ || classInfo.getName().startsWith("org.junit.")
+ || classInfo.getName().startsWith("android.test.")
+ || classInfo.getName().startsWith("androidx.test.")) {
+ return null; // Ignore junit classes.
+ }
+ return clazz;
+ }
+ // Does it have any "@Test" method?
+ for (var method : clazz.getMethods()) {
+ for (var an : method.getAnnotations()) {
+ if (an.annotationType() == org.junit.Test.class) {
+ return clazz;
+ }
+ }
+ }
+ return null;
+ } catch (java.lang.NoClassDefFoundError e) {
+ // Ignore unloadable classes.
+ return null;
+ }
+ }
+}
diff --git a/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostTestUtils.java b/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostTestUtils.java
new file mode 100644
index 000000000000..f7719a6e55b2
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostTestUtils.java
@@ -0,0 +1,197 @@
+/*
+ * Copyright (C) 2023 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.hoststubgen.hosthelper;
+
+import org.objectweb.asm.Type;
+
+import java.io.PrintStream;
+import java.lang.StackWalker.Option;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.HashMap;
+
+import javax.annotation.concurrent.GuardedBy;
+
+/**
+ * Utilities used in the host side test environment.
+ */
+public class HostTestUtils {
+ private HostTestUtils() {
+ }
+
+ public static final String CLASS_INTERNAL_NAME = Type.getInternalName(HostTestUtils.class);
+
+ /** If true, we won't print method call log. */
+ private static final boolean SKIP_METHOD_LOG = "1".equals(System.getenv(
+ "HOSTTEST_SKIP_METHOD_LOG"));
+
+ /** If true, we won't perform non-stub method direct call check. */
+ private static final boolean SKIP_NON_STUB_METHOD_CHECK = "1".equals(System.getenv(
+ "HOSTTEST_SKIP_NON_STUB_METHOD_CHECK"));
+
+
+ /**
+ * Method call log will be printed to it.
+ */
+ public static PrintStream logPrintStream = System.out;
+
+ /**
+ * Called from methods with FilterPolicy.Throw.
+ */
+ public static void onThrowMethodCalled() {
+ // TODO: Maybe add call tracking?
+ throw new RuntimeException("This method is not supported on the host side");
+ }
+
+ /**
+ * Called from methods with FilterPolicy.Log.
+ */
+ public static void logMethodCall(
+ String methodClass,
+ String methodName,
+ String methodDescriptor
+ ) {
+ if (SKIP_METHOD_LOG) {
+ return;
+ }
+ logPrintStream.println("# " + methodClass + "." + methodName + methodDescriptor);
+ }
+
+ private static final StackWalker sStackWalker =
+ StackWalker.getInstance(Option.RETAIN_CLASS_REFERENCE);
+
+ /**
+ * Return a {@link StackWalker} that supports {@link StackWalker#getCallerClass()}.
+ */
+ public static StackWalker getStackWalker() {
+ return sStackWalker;
+ }
+
+ /**
+ * Cache used by {@link #isClassAllowedToCallNonStubMethods}.
+ */
+ @GuardedBy("sAllowedClasses")
+ private static final HashMap<Class, Boolean> sAllowedClasses = new HashMap();
+
+ /**
+ * Return true if a given class is allowed to access non-stub methods -- that is, if the class
+ * is in the hoststubgen generated JARs. (not in the test jar.)
+ */
+ private static boolean isClassAllowedToCallNonStubMethods(Class<?> clazz) {
+ synchronized (sAllowedClasses) {
+ var cached = sAllowedClasses.get(clazz);
+ if (cached != null) {
+ return cached;
+ }
+ }
+ // All processed classes have this annotation.
+ var allowed = clazz.getAnnotation(HostStubGenProcessedKeepClass.class) != null;
+
+ // Java classes should be able to access any methods. (via callbacks, etc.)
+ if (!allowed) {
+ if (clazz.getPackageName().startsWith("java.")
+ || clazz.getPackageName().startsWith("javax.")) {
+ allowed = true;
+ }
+ }
+ synchronized (sAllowedClasses) {
+ sAllowedClasses.put(clazz, allowed);
+ }
+ return allowed;
+ }
+
+ /**
+ * Called when non-stub methods are called. We do a host-unsupported method direct call check
+ * in here.
+ */
+ public static void onNonStubMethodCalled(
+ String methodClass,
+ String methodName,
+ String methodDescriptor,
+ Class<?> callerClass) {
+ if (SKIP_NON_STUB_METHOD_CHECK) {
+ return;
+ }
+ if (isClassAllowedToCallNonStubMethods(callerClass)) {
+ return; // Generated class is allowed to call framework class.
+ }
+ logPrintStream.println("! " + methodClass + "." + methodName + methodDescriptor
+ + " called by " + callerClass.getCanonicalName());
+ }
+
+ /**
+ * Called when any top level class (not nested classes) in the impl jar is loaded.
+ *
+ * When HostStubGen inject a class-load hook, it's always a call to this method, with the
+ * actual method name as the second argument.
+ *
+ * This method discovers the hook method with reflections and call it.
+ *
+ * TODO: Add a unit test.
+ */
+ public static void onClassLoaded(Class<?> loadedClass, String callbackMethod) {
+ logPrintStream.println("! Class loaded: " + loadedClass.getCanonicalName()
+ + " calling hook " + callbackMethod);
+
+ // Forward the call to callbackMethod.
+ final int lastPeriod = callbackMethod.lastIndexOf(".");
+ final String className = callbackMethod.substring(0, lastPeriod);
+ final String methodName = callbackMethod.substring(lastPeriod + 1);
+
+ if (lastPeriod < 0 || className.isEmpty() || methodName.isEmpty()) {
+ throw new HostTestException(String.format(
+ "Unable to find class load hook: malformed method name \"%s\"",
+ callbackMethod));
+ }
+
+ Class<?> clazz = null;
+ try {
+ clazz = Class.forName(className);
+ } catch (Exception e) {
+ throw new HostTestException(String.format(
+ "Unable to find class load hook: Class %s not found", className), e);
+ }
+ if (!Modifier.isPublic(clazz.getModifiers())) {
+ throw new HostTestException(String.format(
+ "Unable to find class load hook: Class %s must be public", className));
+ }
+
+ Method method = null;
+ try {
+ method = clazz.getMethod(methodName, Class.class);
+ } catch (Exception e) {
+ throw new HostTestException(String.format(
+ "Unable to find class load hook: class %s doesn't have method %s"
+ + " (method must take exactly one parameter of type Class, and public static)",
+ className,
+ methodName), e);
+ }
+ if (!(Modifier.isPublic(method.getModifiers())
+ && Modifier.isStatic(method.getModifiers()))) {
+ throw new HostTestException(String.format(
+ "Unable to find class load hook: Method %s in class %s must be public static",
+ methodName, className));
+ }
+ try {
+ method.invoke(null, loadedClass);
+ } catch (Exception e) {
+ throw new HostTestException(String.format(
+ "Unable to invoke class load hook %s.%s",
+ className,
+ methodName), e);
+ }
+ }
+}
diff --git a/tools/hoststubgen/hoststubgen/hoststubgen-standard-options.txt b/tools/hoststubgen/hoststubgen/hoststubgen-standard-options.txt
new file mode 100644
index 000000000000..828d2a3e01c6
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/hoststubgen-standard-options.txt
@@ -0,0 +1,39 @@
+# File containing standard options to HostStubGen
+
+--debug
+
+# Uncomment below lines to enable each feature.
+--enable-non-stub-method-check
+# --no-non-stub-method-check
+
+# --enable-method-logging
+
+
+# Standard annotations.
+# Note, each line is a single argument, so we need newlines after each `--xxx-annotation`.
+--stub-annotation
+ android.hosttest.annotation.HostSideTestStub
+
+--keep-annotation
+ android.hosttest.annotation.HostSideTestKeep
+
+--stub-class-annotation
+ android.hosttest.annotation.HostSideTestWholeClassStub
+
+--keep-class-annotation
+ android.hosttest.annotation.HostSideTestWholeClassKeep
+
+--throw-annotation
+ android.hosttest.annotation.HostSideTestThrow
+
+--remove-annotation
+ android.hosttest.annotation.HostSideTestRemove
+
+--substitute-annotation
+ android.hosttest.annotation.HostSideTestSubstitute
+
+--native-substitute-annotation
+ android.hosttest.annotation.HostSideTestNativeSubstitutionClass
+
+--class-load-hook-annotation
+ android.hosttest.annotation.HostSideTestClassLoadHook
diff --git a/tools/hoststubgen/hoststubgen/jarjar-rules.txt b/tools/hoststubgen/hoststubgen/jarjar-rules.txt
new file mode 100644
index 000000000000..4e61ba6f67b3
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/jarjar-rules.txt
@@ -0,0 +1,2 @@
+# Rename guava
+rule com.google.common.** com.android.hoststubgen.x.@0 \ No newline at end of file
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/Exceptions.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/Exceptions.kt
new file mode 100644
index 000000000000..207ba52685f8
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/Exceptions.kt
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2023 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.hoststubgen
+
+/**
+ * We will not print the stack trace for exceptions implementing it.
+ */
+interface UserErrorException
+
+/**
+ * Exceptions about parsing class files.
+ */
+class ClassParseException(message: String) : Exception(message)
+
+/**
+ * Use it for internal exception that really shouldn't happen.
+ */
+class HostStubGenInternalException(message: String) : Exception(message)
+
+/**
+ * Exceptions about the content in a jar file.
+ */
+class InvalidJarFileException(message: String) : Exception(message), UserErrorException
+
+/**
+ * Exceptions missing classes, fields, methods, etc.
+ */
+class UnknownApiException(message: String) : Exception(message), UserErrorException
+
+/**
+ * Exceptions related to invalid annotations -- e.g. more than one visibility annotation
+ * on a single API.
+ */
+class InvalidAnnotationException(message: String) : Exception(message), UserErrorException
+
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGen.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGen.kt
new file mode 100644
index 000000000000..8db4b6961376
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGen.kt
@@ -0,0 +1,402 @@
+/*
+ * Copyright (C) 2023 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.hoststubgen
+
+import com.android.hoststubgen.asm.ClassNodes
+import com.android.hoststubgen.filters.AnnotationBasedFilter
+import com.android.hoststubgen.filters.ClassWidePolicyPropagatingFilter
+import com.android.hoststubgen.filters.ConstantFilter
+import com.android.hoststubgen.filters.FilterPolicy
+import com.android.hoststubgen.filters.ImplicitOutputFilter
+import com.android.hoststubgen.filters.KeepAllClassesFilter
+import com.android.hoststubgen.filters.OutputFilter
+import com.android.hoststubgen.filters.StubIntersectingFilter
+import com.android.hoststubgen.filters.createFilterFromTextPolicyFile
+import com.android.hoststubgen.filters.printAsTextPolicy
+import com.android.hoststubgen.visitors.BaseAdapter
+import org.objectweb.asm.ClassReader
+import org.objectweb.asm.ClassVisitor
+import org.objectweb.asm.ClassWriter
+import org.objectweb.asm.tree.ClassNode
+import org.objectweb.asm.util.CheckClassAdapter
+import java.io.BufferedInputStream
+import java.io.FileOutputStream
+import java.io.InputStream
+import java.io.OutputStream
+import java.io.PrintWriter
+import java.util.zip.ZipEntry
+import java.util.zip.ZipFile
+import java.util.zip.ZipOutputStream
+
+/**
+ * Actual main class.
+ */
+class HostStubGen(val options: HostStubGenOptions) {
+ fun run() {
+ val errors = HostStubGenErrors()
+
+ // Load all classes.
+ val allClasses = loadClassStructures(options.inJar)
+
+ // Dump the classes, if specified.
+ options.inputJarDumpFile?.let {
+ PrintWriter(it).use { pw -> allClasses.dump(pw) }
+ log.i("Dump file created at $it")
+ }
+
+ options.inputJarAsKeepAllFile?.let {
+ PrintWriter(it).use {
+ pw -> allClasses.forEach {
+ classNode -> printAsTextPolicy(pw, classNode)
+ }
+ }
+ log.i("Dump file created at $it")
+ }
+
+ // Build the filters.
+ val filter = buildFilter(errors, allClasses, options)
+
+ // Transform the jar.
+ convert(
+ options.inJar,
+ options.outStubJar,
+ options.outImplJar,
+ filter,
+ options.enableClassChecker,
+ allClasses,
+ errors,
+ )
+ }
+
+ /**
+ * Load all the classes, without code.
+ */
+ private fun loadClassStructures(inJar: String): ClassNodes {
+ log.i("Reading class structure from $inJar ...")
+ val start = System.currentTimeMillis()
+
+ val allClasses = ClassNodes()
+
+ log.withIndent {
+ ZipFile(inJar).use { inZip ->
+ val inEntries = inZip.entries()
+
+ while (inEntries.hasMoreElements()) {
+ val entry = inEntries.nextElement()
+
+ BufferedInputStream(inZip.getInputStream(entry)).use { bis ->
+ if (entry.name.endsWith(".class")) {
+ val cr = ClassReader(bis)
+ val cn = ClassNode()
+ cr.accept(cn, ClassReader.SKIP_CODE or ClassReader.SKIP_DEBUG
+ or ClassReader.SKIP_FRAMES)
+ if (!allClasses.addClass(cn)) {
+ log.w("Duplicate class found: ${cn.name}")
+ }
+ } else if (entry.name.endsWith(".dex")) {
+ // Seems like it's an ART jar file. We can't process it.
+ // It's a fatal error.
+ throw InvalidJarFileException(
+ "$inJar is not a desktop jar file. It contains a *.dex file.")
+ } else {
+ // Unknown file type. Skip.
+ while (bis.available() > 0) {
+ bis.skip((1024 * 1024).toLong())
+ }
+ }
+ }
+ }
+ }
+ }
+ if (allClasses.size == 0) {
+ log.w("$inJar contains no *.class files.")
+ }
+
+ val end = System.currentTimeMillis()
+ log.v("Done reading class structure in %.1f second(s).", (end - start) / 1000.0)
+ return allClasses
+ }
+
+ /**
+ * Build the filter, which decides what classes/methods/fields should be put in stub or impl
+ * jars, and "how". (e.g. with substitution?)
+ */
+ private fun buildFilter(
+ errors: HostStubGenErrors,
+ allClasses: ClassNodes,
+ options: HostStubGenOptions,
+ ): OutputFilter {
+ // We build a "chain" of multiple filters here.
+ //
+ // The filters are build in from "inside", meaning the first filter created here is
+ // the last filter used, so it has the least precedence.
+ //
+ // So, for example, the "remove" annotation, which is handled by AnnotationBasedFilter,
+ // can override a class-wide annotation, which is handled by
+ // ClassWidePolicyPropagatingFilter, and any annotations can be overridden by the
+ // text-file based filter, which is handled by parseTextFilterPolicyFile.
+
+ // The first filter is for the default policy from the command line options.
+ var filter: OutputFilter = ConstantFilter(options.defaultPolicy, "default-by-options")
+
+ // Next, we need a filter that resolves "class-wide" policies.
+ // This is used when a member (methods, fields, nested classes) don't get any polices
+ // from upper filters. e.g. when a method has no annotations, then this filter will apply
+ // the class-wide policy, if any. (if not, we'll fall back to the above filter.)
+ val classWidePropagator = ClassWidePolicyPropagatingFilter(filter)
+
+ // Next, Java annotation based filter.
+ filter = AnnotationBasedFilter(
+ errors,
+ allClasses,
+ options.stubAnnotations,
+ options.keepAnnotations,
+ options.stubClassAnnotations,
+ options.keepClassAnnotations,
+ options.throwAnnotations,
+ options.removeAnnotations,
+ options.substituteAnnotations,
+ options.nativeSubstituteAnnotations,
+ options.classLoadHookAnnotations,
+ classWidePropagator
+ )
+
+ // Next, "text based" filter, which allows to override polices without touching
+ // the target code.
+ options.policyOverrideFile?.let {
+ filter = createFilterFromTextPolicyFile(it, allClasses, filter)
+ }
+
+ // If `--intersect-stub-jar` is provided, load from these jar files too.
+ // We use this to restrict stub APIs to public/system/test APIs,
+ // by intersecting with a stub jar file created by metalava.
+ if (options.intersectStubJars.size > 0) {
+ val intersectingJars = loadIntersectingJars(options.intersectStubJars)
+
+ filter = StubIntersectingFilter(errors, intersectingJars, filter)
+ }
+
+ // Apply the implicit filter.
+ filter = ImplicitOutputFilter(errors, allClasses, filter)
+
+ // Optionally keep all classes.
+ if (options.keepAllClasses) {
+ filter = KeepAllClassesFilter(filter)
+ }
+
+ return filter
+ }
+
+ /**
+ * Load jar files specified with "--intersect-stub-jar".
+ */
+ private fun loadIntersectingJars(filenames: Set<String>): Map<String, ClassNodes> {
+ val intersectingJars = mutableMapOf<String, ClassNodes>()
+
+ filenames.forEach { filename ->
+ intersectingJars[filename] = loadClassStructures(filename)
+ }
+ return intersectingJars
+ }
+
+ /**
+ * Convert a JAR file into "stub" and "impl" JAR files.
+ */
+ private fun convert(
+ inJar: String,
+ outStubJar: String,
+ outImplJar: String,
+ filter: OutputFilter,
+ enableChecker: Boolean,
+ classes: ClassNodes,
+ errors: HostStubGenErrors,
+ ) {
+ log.i("Converting %s into [stub: %s, impl: %s] ...", inJar, outStubJar, outImplJar)
+ log.i("Checker is %s", if (enableChecker) "enabled" else "disabled")
+
+ val start = System.currentTimeMillis()
+
+ log.withIndent {
+ // Open the input jar file and process each entry.
+ ZipFile(inJar).use { inZip ->
+ ZipOutputStream(FileOutputStream(outStubJar)).use { stubOutStream ->
+ ZipOutputStream(FileOutputStream(outImplJar)).use { implOutStream ->
+ val inEntries = inZip.entries()
+ while (inEntries.hasMoreElements()) {
+ val entry = inEntries.nextElement()
+ convertSingleEntry(inZip, entry, stubOutStream, implOutStream,
+ filter, enableChecker, classes, errors)
+ }
+ log.i("Converted all entries.")
+ }
+ }
+ log.i("Created stub: $outStubJar")
+ log.i("Created impl: $outImplJar")
+ }
+ }
+ val end = System.currentTimeMillis()
+ log.v("Done transforming the jar in %.1f second(s).", (end - start) / 1000.0)
+ }
+
+ /**
+ * Convert a single ZIP entry, which may or may not be a class file.
+ */
+ private fun convertSingleEntry(
+ inZip: ZipFile,
+ entry: ZipEntry,
+ stubOutStream: ZipOutputStream,
+ implOutStream: ZipOutputStream,
+ filter: OutputFilter,
+ enableChecker: Boolean,
+ classes: ClassNodes,
+ errors: HostStubGenErrors,
+ ) {
+ log.d("Entry: %s", entry.name)
+ log.withIndent {
+ val name = entry.name
+
+ // Just ignore all the directories. (TODO: make sure it's okay)
+ if (name.endsWith("/")) {
+ return
+ }
+
+ // If it's a class, convert it.
+ if (name.endsWith(".class")) {
+ processSingleClass(inZip, entry, stubOutStream, implOutStream, filter,
+ enableChecker, classes, errors)
+ return
+ }
+
+ // Handle other file types...
+
+ // - *.uau seems to contain hidden API information.
+ // - *_compat_config.xml is also about compat-framework.
+ if (name.endsWith(".uau") ||
+ name.endsWith("_compat_config.xml")) {
+ log.d("Not needed: %s", entry.name)
+ return
+ }
+
+ // Unknown type, we just copy it to both output zip files.
+ // TODO: We probably shouldn't do it for stub jar?
+ log.v("Copying: %s", entry.name)
+ copyZipEntry(inZip, entry, stubOutStream)
+ copyZipEntry(inZip, entry, implOutStream)
+ }
+ }
+
+ /**
+ * Copy a single ZIP entry to the output.
+ */
+ private fun copyZipEntry(
+ inZip: ZipFile,
+ entry: ZipEntry,
+ out: ZipOutputStream,
+ ) {
+ BufferedInputStream(inZip.getInputStream(entry)).use { bis ->
+ // Copy unknown entries as is to the impl out. (but not to the stub out.)
+ val outEntry = ZipEntry(entry.name)
+ out.putNextEntry(outEntry)
+ while (bis.available() > 0) {
+ out.write(bis.read())
+ }
+ out.closeEntry()
+ }
+ }
+
+ /**
+ * Convert a single class to "stub" and "impl".
+ */
+ private fun processSingleClass(
+ inZip: ZipFile,
+ entry: ZipEntry,
+ stubOutStream: ZipOutputStream,
+ implOutStream: ZipOutputStream,
+ filter: OutputFilter,
+ enableChecker: Boolean,
+ classes: ClassNodes,
+ errors: HostStubGenErrors,
+ ) {
+ val className = entry.name.replaceFirst("\\.class$".toRegex(), "")
+ val classPolicy = filter.getPolicyForClass(className)
+ if (classPolicy.policy == FilterPolicy.Remove) {
+ log.d("Removing class: %s %s", className, classPolicy)
+ return
+ }
+ // Generate stub first.
+ if (classPolicy.policy.needsInStub) {
+ log.v("Creating stub class: %s Policy: %s", className, classPolicy)
+ log.withIndent {
+ BufferedInputStream(inZip.getInputStream(entry)).use { bis ->
+ val newEntry = ZipEntry(entry.name)
+ stubOutStream.putNextEntry(newEntry)
+ convertClass(/*forImpl=*/false, bis, stubOutStream, filter, enableChecker,
+ classes, errors)
+ stubOutStream.closeEntry()
+ }
+ }
+ }
+ log.v("Creating impl class: %s Policy: %s", className, classPolicy)
+ if (classPolicy.policy.needsInImpl) {
+ log.withIndent {
+ BufferedInputStream(inZip.getInputStream(entry)).use { bis ->
+ val newEntry = ZipEntry(entry.name)
+ implOutStream.putNextEntry(newEntry)
+ convertClass(/*forImpl=*/true, bis, implOutStream, filter, enableChecker,
+ classes, errors)
+ implOutStream.closeEntry()
+ }
+ }
+ }
+ }
+
+ /**
+ * Convert a single class to either "stub" or "impl".
+ */
+ private fun convertClass(
+ forImpl: Boolean,
+ input: InputStream,
+ out: OutputStream,
+ filter: OutputFilter,
+ enableChecker: Boolean,
+ classes: ClassNodes,
+ errors: HostStubGenErrors,
+ ) {
+ val cr = ClassReader(input)
+
+ // COMPUTE_FRAMES wouldn't be happy if code uses
+ val flags = ClassWriter.COMPUTE_MAXS // or ClassWriter.COMPUTE_FRAMES
+ val cw = ClassWriter(flags)
+
+ // Connect to the class writer
+ var outVisitor: ClassVisitor = cw
+ if (enableChecker) {
+ outVisitor = CheckClassAdapter(outVisitor)
+ }
+ val visitorOptions = BaseAdapter.Options(
+ enablePreTrace = options.enablePreTrace,
+ enablePostTrace = options.enablePostTrace,
+ enableMethodLogging = options.enablePreTrace,
+ enableNonStubMethodCallDetection = options.enableNonStubMethodCallDetection,
+ errors = errors,
+ )
+ outVisitor = BaseAdapter.getVisitor(classes, outVisitor, filter, forImpl, visitorOptions)
+
+ cr.accept(outVisitor, ClassReader.EXPAND_FRAMES)
+ val data = cw.toByteArray()
+ out.write(data)
+ }
+}
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenErrors.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenErrors.kt
new file mode 100644
index 000000000000..9df04892ddbd
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenErrors.kt
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2023 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.hoststubgen
+
+class HostStubGenErrors {
+ fun onErrorFound(message: String) {
+ // For now, we just throw as soon as any error is found, but eventually we should keep
+ // all errors and print them at the end.
+ throw RuntimeException(message)
+ }
+} \ No newline at end of file
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenLogger.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenLogger.kt
new file mode 100644
index 000000000000..5e71a3690700
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenLogger.kt
@@ -0,0 +1,198 @@
+/*
+ * Copyright (C) 2023 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.hoststubgen
+
+import java.io.OutputStream
+import java.io.PrintStream
+
+val log: HostStubGenLogger = HostStubGenLogger()
+
+/** Logging level */
+enum class LogLevel {
+ None,
+ Error,
+ Warn,
+ Info,
+ Verbose,
+ Debug,
+}
+
+/** Simple logging class. */
+class HostStubGenLogger(
+ private var out: PrintStream = System.out!!,
+ var level: LogLevel = LogLevel.Info,
+) {
+ companion object {
+ private val sNullPrintStream: PrintStream = PrintStream(OutputStream.nullOutputStream())
+ }
+
+ private var indentLevel: Int = 0
+ get() = field
+ set(value) {
+ field = value
+ indent = " ".repeat(value)
+ }
+ private var indent: String = ""
+
+ fun indent() {
+ indentLevel++
+ }
+
+ fun unindent() {
+ if (indentLevel <= 0) {
+ throw IllegalStateException("Unbalanced unindent() call.")
+ }
+ indentLevel--
+ }
+
+ inline fun <T> withIndent(block: () -> T): T {
+ try {
+ indent()
+ return block()
+ } finally {
+ unindent()
+ }
+ }
+
+ fun isEnabled(level: LogLevel): Boolean {
+ return level.ordinal <= this.level.ordinal
+ }
+
+ private fun println(message: String) {
+ out.print(indent)
+ out.println(message)
+ }
+
+ /** Log an error. */
+ fun e(message: String) {
+ if (level.ordinal < LogLevel.Error.ordinal) {
+ return
+ }
+ println(message)
+ }
+
+ /** Log an error. */
+ fun e(format: String, vararg args: Any?) {
+ if (level.ordinal < LogLevel.Error.ordinal) {
+ return
+ }
+ e(String.format(format, *args))
+ }
+
+ /** Log a warning. */
+ fun w(message: String) {
+ if (level.ordinal < LogLevel.Warn.ordinal) {
+ return
+ }
+ println(message)
+ }
+
+ /** Log a warning. */
+ fun w(format: String, vararg args: Any?) {
+ if (level.ordinal < LogLevel.Warn.ordinal) {
+ return
+ }
+ w(String.format(format, *args))
+ }
+
+ /** Log an info message. */
+ fun i(message: String) {
+ if (level.ordinal < LogLevel.Info.ordinal) {
+ return
+ }
+ println(message)
+ }
+
+ /** Log a debug message. */
+ fun i(format: String, vararg args: Any?) {
+ if (level.ordinal < LogLevel.Warn.ordinal) {
+ return
+ }
+ i(String.format(format, *args))
+ }
+
+ /** Log a verbose message. */
+ fun v(message: String) {
+ if (level.ordinal < LogLevel.Verbose.ordinal) {
+ return
+ }
+ println(message)
+ }
+
+ /** Log a verbose message. */
+ fun v(format: String, vararg args: Any?) {
+ if (level.ordinal < LogLevel.Verbose.ordinal) {
+ return
+ }
+ v(String.format(format, *args))
+ }
+
+ /** Log a debug message. */
+ fun d(message: String) {
+ if (level.ordinal < LogLevel.Debug.ordinal) {
+ return
+ }
+ println(message)
+ }
+
+ /** Log a debug message. */
+ fun d(format: String, vararg args: Any?) {
+ if (level.ordinal < LogLevel.Warn.ordinal) {
+ return
+ }
+ d(String.format(format, *args))
+ }
+
+ inline fun forVerbose(block: () -> Unit) {
+ if (isEnabled(LogLevel.Verbose)) {
+ block()
+ }
+ }
+
+ inline fun forDebug(block: () -> Unit) {
+ if (isEnabled(LogLevel.Debug)) {
+ block()
+ }
+ }
+
+ /** Return a stream for error. */
+ fun getErrorPrintStream(): PrintStream {
+ if (level.ordinal < LogLevel.Error.ordinal) {
+ return sNullPrintStream
+ }
+
+ // TODO Apply indent
+ return PrintStream(out)
+ }
+
+ /** Return a stream for verbose messages. */
+ fun getVerbosePrintStream(): PrintStream {
+ if (level.ordinal < LogLevel.Verbose.ordinal) {
+ return sNullPrintStream
+ }
+ // TODO Apply indent
+ return PrintStream(out)
+ }
+
+ /** Return a stream for debug messages. */
+ fun getInfoPrintStream(): PrintStream {
+ if (level.ordinal < LogLevel.Info.ordinal) {
+ return sNullPrintStream
+ }
+ // TODO Apply indent
+ return PrintStream(out)
+ }
+} \ No newline at end of file
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenOptions.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenOptions.kt
new file mode 100644
index 000000000000..9a54ecffc8c2
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenOptions.kt
@@ -0,0 +1,307 @@
+/*
+ * Copyright (C) 2023 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.hoststubgen
+
+import com.android.hoststubgen.filters.FilterPolicy
+import java.io.BufferedReader
+import java.io.File
+import java.io.FileReader
+
+/**
+ * Options that can be set from command line arguments.
+ */
+class HostStubGenOptions(
+ /** Input jar file*/
+ var inJar: String = "",
+
+ /** Output stub jar file */
+ var outStubJar: String = "",
+
+ /** Output implementation jar file */
+ var outImplJar: String = "",
+
+ var inputJarDumpFile: String? = null,
+
+ var inputJarAsKeepAllFile: String? = null,
+
+ var stubAnnotations: MutableSet<String> = mutableSetOf(),
+ var keepAnnotations: MutableSet<String> = mutableSetOf(),
+ var throwAnnotations: MutableSet<String> = mutableSetOf(),
+ var removeAnnotations: MutableSet<String> = mutableSetOf(),
+ var stubClassAnnotations: MutableSet<String> = mutableSetOf(),
+ var keepClassAnnotations: MutableSet<String> = mutableSetOf(),
+
+ var substituteAnnotations: MutableSet<String> = mutableSetOf(),
+ var nativeSubstituteAnnotations: MutableSet<String> = mutableSetOf(),
+ var classLoadHookAnnotations: MutableSet<String> = mutableSetOf(),
+
+ var intersectStubJars: MutableSet<String> = mutableSetOf(),
+
+ var policyOverrideFile: String? = null,
+
+ var defaultPolicy: FilterPolicy = FilterPolicy.Remove,
+ var keepAllClasses: Boolean = false,
+
+ var logLevel: LogLevel = LogLevel.Info,
+
+ var cleanUpOnError: Boolean = false,
+
+ var enableClassChecker: Boolean = false,
+ var enablePreTrace: Boolean = false,
+ var enablePostTrace: Boolean = false,
+
+ var enableMethodLogging: Boolean = false,
+
+ var enableNonStubMethodCallDetection: Boolean = true,
+) {
+ companion object {
+
+ private fun String.ensureFileExists(): String {
+ if (!File(this).exists()) {
+ throw InputFileNotFoundException(this)
+ }
+ return this
+ }
+
+ fun parseArgs(args: Array<String>): HostStubGenOptions {
+ val ret = HostStubGenOptions()
+
+ val ai = ArgIterator(expandAtFiles(args))
+
+ var allAnnotations = mutableSetOf<String>()
+
+ fun ensureUniqueAnnotation(name: String): String {
+ if (!allAnnotations.add(name)) {
+ throw DuplicateAnnotationException(ai.current)
+ }
+ return name
+ }
+
+ while (true) {
+ val arg = ai.nextArgOptional()
+ if (arg == null) {
+ break
+ }
+
+ when (arg) {
+ // TODO: Write help
+ "-h", "--h" -> TODO("Help is not implemented yet")
+
+ "-v", "--verbose" -> ret.logLevel = LogLevel.Verbose
+ "-d", "--debug" -> ret.logLevel = LogLevel.Debug
+ "-q", "--quiet" -> ret.logLevel = LogLevel.None
+
+ "--in-jar" -> ret.inJar = ai.nextArgRequired(arg).ensureFileExists()
+ "--out-stub-jar" -> ret.outStubJar = ai.nextArgRequired(arg)
+ "--out-impl-jar" -> ret.outImplJar = ai.nextArgRequired(arg)
+
+ "--policy-override-file" ->
+ ret.policyOverrideFile = ai.nextArgRequired(arg).ensureFileExists()
+
+ "--clean-up-on-error" -> ret.cleanUpOnError = true
+ "--no-clean-up-on-error" -> ret.cleanUpOnError = false
+
+ "--default-remove" -> ret.defaultPolicy = FilterPolicy.Remove
+ "--default-throw" -> ret.defaultPolicy = FilterPolicy.Throw
+ "--default-keep" -> ret.defaultPolicy = FilterPolicy.Keep
+ "--default-stub" -> ret.defaultPolicy = FilterPolicy.Stub
+
+ "--keep-all-classes" -> ret.keepAllClasses = true
+ "--no-keep-all-classes" -> ret.keepAllClasses = false
+
+ "--stub-annotation" ->
+ ret.stubAnnotations += ensureUniqueAnnotation(ai.nextArgRequired(arg))
+
+ "--keep-annotation" ->
+ ret.keepAnnotations += ensureUniqueAnnotation(ai.nextArgRequired(arg))
+
+ "--stub-class-annotation" ->
+ ret.stubClassAnnotations += ensureUniqueAnnotation(ai.nextArgRequired(arg))
+
+ "--keep-class-annotation" ->
+ ret.keepClassAnnotations += ensureUniqueAnnotation(ai.nextArgRequired(arg))
+
+ "--throw-annotation" ->
+ ret.throwAnnotations += ensureUniqueAnnotation(ai.nextArgRequired(arg))
+
+ "--remove-annotation" ->
+ ret.removeAnnotations += ensureUniqueAnnotation(ai.nextArgRequired(arg))
+
+ "--substitute-annotation" ->
+ ret.substituteAnnotations += ensureUniqueAnnotation(ai.nextArgRequired(arg))
+
+ "--native-substitute-annotation" ->
+ ret.nativeSubstituteAnnotations +=
+ ensureUniqueAnnotation(ai.nextArgRequired(arg))
+
+ "--class-load-hook-annotation" ->
+ ret.classLoadHookAnnotations +=
+ ensureUniqueAnnotation(ai.nextArgRequired(arg))
+
+ "--intersect-stub-jar" ->
+ ret.intersectStubJars += ai.nextArgRequired(arg).ensureFileExists()
+
+ "--gen-keep-all-file" ->
+ ret.inputJarAsKeepAllFile = ai.nextArgRequired(arg)
+
+ // Following options are for debugging.
+ "--enable-class-checker" -> ret.enableClassChecker = true
+ "--no-class-checker" -> ret.enableClassChecker = false
+
+ "--enable-pre-trace" -> ret.enablePreTrace = true
+ "--no-pre-trace" -> ret.enablePreTrace = false
+
+ "--enable-post-trace" -> ret.enablePostTrace = true
+ "--no-post-trace" -> ret.enablePostTrace = false
+
+ "--enable-method-logging" -> ret.enableMethodLogging = true
+ "--no-method-logging" -> ret.enableMethodLogging = false
+
+ "--enable-non-stub-method-check" -> ret.enableNonStubMethodCallDetection = true
+ "--no-non-stub-method-check" -> ret.enableNonStubMethodCallDetection = false
+
+ "--gen-input-dump-file" -> ret.inputJarDumpFile = ai.nextArgRequired(arg)
+
+ else -> throw ArgumentsException("Unknown option: $arg")
+ }
+ }
+ if (ret.inJar.isEmpty()) {
+ throw ArgumentsException("Required option missing: --in-jar")
+ }
+ if (ret.outStubJar.isEmpty()) {
+ throw ArgumentsException("Required option missing: --out-stub-jar")
+ }
+ if (ret.outImplJar.isEmpty()) {
+ throw ArgumentsException("Required option missing: --out-impl-jar")
+ }
+
+ return ret
+ }
+
+ /**
+ * Scan the arguments, and if any of them starts with an `@`, then load from the file
+ * and use its content as arguments.
+ *
+ * In this file, each line is treated as a single argument.
+ *
+ * The file can contain '#' as comments.
+ */
+ private fun expandAtFiles(args: Array<String>): List<String> {
+ val ret = mutableListOf<String>()
+
+ args.forEach { arg ->
+ if (!arg.startsWith('@')) {
+ ret += arg
+ return@forEach
+ }
+ // Read from the file, and add each line to the result.
+ val filename = arg.substring(1).ensureFileExists()
+
+ log.v("Expanding options file $filename")
+
+ BufferedReader(FileReader(filename)).use { reader ->
+ while (true) {
+ var line = reader.readLine()
+ if (line == null) {
+ break // EOF
+ }
+
+ line = normalizeTextLine(line)
+ if (line.isNotEmpty()) {
+ ret += line
+ }
+ }
+ }
+ }
+ return ret
+ }
+ }
+
+ open class ArgumentsException(message: String?) : Exception(message), UserErrorException
+
+ /** Thrown when the same annotation is used with different annotation arguments. */
+ class DuplicateAnnotationException(annotationName: String?) :
+ ArgumentsException("Duplicate annotation specified: '$annotationName'")
+
+ /** Thrown when an input file does not exist. */
+ class InputFileNotFoundException(filename: String) :
+ ArgumentsException("File '$filename' not found")
+
+ private class ArgIterator(
+ private val args: List<String>,
+ private var currentIndex: Int = -1
+ ) {
+ val current: String
+ get() = args.get(currentIndex)
+
+ /**
+ * Get the next argument, or [null] if there's no more arguments.
+ */
+ fun nextArgOptional(): String? {
+ if ((currentIndex + 1) >= args.size) {
+ return null
+ }
+ return args.get(++currentIndex)
+ }
+
+ /**
+ * Get the next argument, or throw if
+ */
+ fun nextArgRequired(argName: String): String {
+ nextArgOptional().let {
+ if (it == null) {
+ throw ArgumentsException("Missing parameter for option $argName")
+ }
+ if (it.isEmpty()) {
+ throw ArgumentsException("Parameter can't be empty for option $argName")
+ }
+ return it
+ }
+ }
+ }
+
+ override fun toString(): String {
+ return """
+ HostStubGenOptions{
+ inJar='$inJar',
+ outStubJar='$outStubJar',
+ outImplJar='$outImplJar',
+ inputJarDumpFile=$inputJarDumpFile,
+ inputJarAsKeepAllFile=$inputJarAsKeepAllFile,
+ stubAnnotations=$stubAnnotations,
+ keepAnnotations=$keepAnnotations,
+ throwAnnotations=$throwAnnotations,
+ removeAnnotations=$removeAnnotations,
+ stubClassAnnotations=$stubClassAnnotations,
+ keepClassAnnotations=$keepClassAnnotations,
+ substituteAnnotations=$substituteAnnotations,
+ nativeSubstituteAnnotations=$nativeSubstituteAnnotations,
+ classLoadHookAnnotations=$classLoadHookAnnotations,
+ intersectStubJars=$intersectStubJars,
+ policyOverrideFile=$policyOverrideFile,
+ defaultPolicy=$defaultPolicy,
+ keepAllClasses=$keepAllClasses,
+ logLevel=$logLevel,
+ cleanUpOnError=$cleanUpOnError,
+ enableClassChecker=$enableClassChecker,
+ enablePreTrace=$enablePreTrace,
+ enablePostTrace=$enablePostTrace,
+ enableMethodLogging=$enableMethodLogging,
+ enableNonStubMethodCallDetection=$enableNonStubMethodCallDetection,
+ }
+ """.trimIndent()
+ }
+}
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/Main.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/Main.kt
new file mode 100644
index 000000000000..0321d9db03ed
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/Main.kt
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2023 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("Main")
+
+package com.android.hoststubgen
+
+const val COMMAND_NAME = "HostStubGen"
+
+/**
+ * Entry point.
+ */
+fun main(args: Array<String>) {
+ var success = false
+ var clanupOnError = false
+ try {
+ // Parse the command line arguments.
+ val options = HostStubGenOptions.parseArgs(args)
+ clanupOnError = options.cleanUpOnError
+
+ log.level = options.logLevel
+
+ log.v("HostStubGen started")
+ log.v("Options: $options")
+
+ // Run.
+ HostStubGen(options).run()
+
+ success = true
+ } catch (e: Exception) {
+ log.e("$COMMAND_NAME: Error: ${e.message}")
+ if (e !is UserErrorException) {
+ e.printStackTrace(log.getErrorPrintStream())
+ }
+ if (clanupOnError) {
+ TODO("clanupOnError is not implemented yet")
+ }
+ }
+
+ log.v("HostStubGen finished")
+
+ System.exit(if (success) 0 else 1 )
+}
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/Utils.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/Utils.kt
new file mode 100644
index 000000000000..9fbd6d09bfb0
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/Utils.kt
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2023 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.hoststubgen
+
+/**
+ * A regex that maches whitespate.
+ */
+val whitespaceRegex = """\s+""".toRegex()
+
+/**
+ * Remove the comment ('#' and following) and surrounding whitespace from a line.
+ */
+fun normalizeTextLine(s: String): String {
+ // Remove # and after. (comment)
+ val pos = s.indexOf('#')
+ val uncommented = if (pos < 0) s else s.substring(0, pos)
+
+ // Remove surrounding whitespace.
+ return uncommented.trim()
+}
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/asm/AsmUtils.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/asm/AsmUtils.kt
new file mode 100644
index 000000000000..a51bdcf0c793
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/asm/AsmUtils.kt
@@ -0,0 +1,177 @@
+/*
+ * Copyright (C) 2023 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.hoststubgen.asm
+
+import com.android.hoststubgen.ClassParseException
+import com.android.hoststubgen.HostStubGenInternalException
+import org.objectweb.asm.MethodVisitor
+import org.objectweb.asm.Opcodes
+import org.objectweb.asm.Type
+import org.objectweb.asm.tree.AnnotationNode
+import org.objectweb.asm.tree.ClassNode
+
+
+/** Name of the class initializer method. */
+val CLASS_INITIALIZER_NAME = "<clinit>"
+
+/** Descriptor of the class initializer method. */
+val CLASS_INITIALIZER_DESC = "()V"
+
+/**
+ * Find any of [anyAnnotations] from the list of visible / invisible annotations.
+ */
+fun findAnyAnnotation(
+ anyAnnotations: Set<String>,
+ visibleAnnotations: List<AnnotationNode>?,
+ invisibleAnnotations: List<AnnotationNode>?,
+ ): AnnotationNode? {
+ for (an in visibleAnnotations ?: emptyList()) {
+ if (anyAnnotations.contains(an.desc)) {
+ return an
+ }
+ }
+ for (an in invisibleAnnotations ?: emptyList()) {
+ if (anyAnnotations.contains(an.desc)) {
+ return an
+ }
+ }
+ return null
+}
+
+fun findAnnotationValueAsString(an: AnnotationNode, propertyName: String): String? {
+ for (i in 0..(an.values?.size ?: 0) - 2 step 2) {
+ val name = an.values[i]
+
+ if (name != propertyName) {
+ continue
+ }
+ val value = an.values[i + 1]
+ if (value is String) {
+ return value
+ }
+ throw ClassParseException(
+ "The type of '$name' in annotation \"${an.desc}\" must be String" +
+ ", but is ${value?.javaClass?.canonicalName}")
+ }
+ return null
+}
+
+private val removeLastElement = """[./][^./]*$""".toRegex()
+
+fun getPackageNameFromClassName(className: String): String {
+ return className.replace(removeLastElement, "")
+}
+
+fun resolveClassName(className: String, packageName: String): String {
+ if (className.contains('.') || className.contains('/')) {
+ return className
+ }
+ return "$packageName.$className"
+}
+
+fun String.toJvmClassName(): String {
+ return this.replace('.', '/')
+}
+
+fun String.toHumanReadableClassName(): String {
+ return this.replace('/', '.')
+}
+
+fun String.toHumanReadableMethodName(): String {
+ return this.replace('/', '.')
+}
+
+private val numericalInnerClassName = """.*\$\d+$""".toRegex()
+
+fun isAnonymousInnerClass(cn: ClassNode): Boolean {
+ // TODO: Is there a better way?
+ return cn.name.matches(numericalInnerClassName)
+}
+
+/**
+ * Take a class name. If it's a nested class, then return the name of its direct outer class name.
+ * Otherwise, return null.
+ */
+fun getDirectOuterClassName(className: String): String? {
+ val pos = className.indexOf('$')
+ if (pos < 0) {
+ return null
+ }
+ return className.substring(0, pos)
+}
+
+/**
+ * Write bytecode to push all the method arguments to the stack.
+ * The number of arguments and their type are taken from [methodDescriptor].
+ */
+fun writeByteCodeToPushArguments(methodDescriptor: String, writer: MethodVisitor) {
+ var i = -1
+ Type.getArgumentTypes(methodDescriptor).forEach { type ->
+ i++
+
+ // See https://en.wikipedia.org/wiki/List_of_Java_bytecode_instructions
+
+ // Note, long and double will consume two local variable spaces, so the extra `i++`.
+ when (type) {
+ Type.VOID_TYPE -> throw HostStubGenInternalException("VOID_TYPE not expected")
+ Type.BOOLEAN_TYPE, Type.INT_TYPE, Type.SHORT_TYPE, Type.CHAR_TYPE
+ -> writer.visitVarInsn(Opcodes.ILOAD, i)
+ Type.LONG_TYPE -> writer.visitVarInsn(Opcodes.LLOAD, i++)
+ Type.FLOAT_TYPE -> writer.visitVarInsn(Opcodes.FLOAD, i)
+ Type.DOUBLE_TYPE -> writer.visitVarInsn(Opcodes.DLOAD, i++)
+ else -> writer.visitVarInsn(Opcodes.ALOAD, i)
+ }
+ }
+}
+
+/**
+ * Write bytecode to "RETURN" that matches the method's return type, according to
+ * [methodDescriptor].
+ */
+fun writeByteCodeToReturn(methodDescriptor: String, writer: MethodVisitor) {
+ Type.getReturnType(methodDescriptor).let { type ->
+ // See https://en.wikipedia.org/wiki/List_of_Java_bytecode_instructions
+ when (type) {
+ Type.VOID_TYPE -> writer.visitInsn(Opcodes.RETURN)
+ Type.BOOLEAN_TYPE, Type.INT_TYPE, Type.SHORT_TYPE, Type.CHAR_TYPE
+ -> writer.visitInsn(Opcodes.IRETURN)
+ Type.LONG_TYPE -> writer.visitInsn(Opcodes.LRETURN)
+ Type.FLOAT_TYPE -> writer.visitInsn(Opcodes.FRETURN)
+ Type.DOUBLE_TYPE -> writer.visitInsn(Opcodes.DRETURN)
+ else -> writer.visitInsn(Opcodes.ARETURN)
+ }
+ }
+}
+
+/**
+ * Return the "visibility" modifier from an `access` integer.
+ *
+ * (see https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.1-200-E.1)
+ */
+fun getVisibilityModifier(access: Int): Int {
+ return access and (Opcodes.ACC_PUBLIC or Opcodes.ACC_PRIVATE or Opcodes.ACC_PROTECTED)
+}
+
+/**
+ * Return true if an `access` integer is "private" or "package private".
+ */
+fun isVisibilityPrivateOrPackagePrivate(access: Int): Boolean {
+ return when (getVisibilityModifier(access)) {
+ 0 -> true // Package private.
+ Opcodes.ACC_PRIVATE -> true
+ else -> false
+ }
+}
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/asm/ClassNodes.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/asm/ClassNodes.kt
new file mode 100644
index 000000000000..4df0bfc4a8d1
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/asm/ClassNodes.kt
@@ -0,0 +1,149 @@
+package com.android.hoststubgen.asm
+
+import com.android.hoststubgen.ClassParseException
+import org.objectweb.asm.tree.AnnotationNode
+import org.objectweb.asm.tree.ClassNode
+import org.objectweb.asm.tree.FieldNode
+import org.objectweb.asm.tree.MethodNode
+import org.objectweb.asm.tree.TypeAnnotationNode
+import java.io.PrintWriter
+import java.util.Arrays
+
+/**
+ * Stores all classes loaded from a jar file, in a form of [ClassNode]
+ */
+class ClassNodes {
+ val mAllClasses: MutableMap<String, ClassNode> = HashMap()
+
+ /**
+ * Total number of classes registered.
+ */
+ val size: Int
+ get() = mAllClasses.size
+
+ /** Add a [ClassNode] */
+ fun addClass(cn: ClassNode): Boolean {
+ if (mAllClasses.containsKey(cn.name)) {
+ return false
+ }
+ mAllClasses[cn.name.toJvmClassName()] = cn
+ return true
+ }
+
+ /** Get a class's [ClassNodes] (which may not exist) */
+ fun findClass(name: String): ClassNode? {
+ return mAllClasses[name.toJvmClassName()]
+ }
+
+ /** Get a class's [ClassNodes] (which must exists) */
+ fun getClass(name: String): ClassNode {
+ return findClass(name) ?: throw ClassParseException("Class $name not found")
+ }
+
+ /** Find a field, which may not exist. */
+ fun findField(
+ className: String,
+ fieldName: String,
+ ): FieldNode? {
+ return findClass(className)?.fields?.firstOrNull { it.name == fieldName }?.let { fn ->
+ return fn
+ }
+ }
+
+ /** Find a method, which may not exist. */
+ fun findMethod(
+ className: String,
+ methodName: String,
+ descriptor: String,
+ ): MethodNode? {
+ return findClass(className)?.methods
+ ?.firstOrNull { it.name == methodName && it.desc == descriptor }?.let { mn ->
+ return mn
+ }
+ }
+
+ /** @return true if a class has a class initializer. */
+ fun hasClassInitializer(className: String): Boolean {
+ return findMethod(className, CLASS_INITIALIZER_NAME, CLASS_INITIALIZER_DESC) != null
+ }
+
+ /** Run the lambda on each class in alphabetical order. */
+ fun forEach(consumer: (classNode: ClassNode) -> Unit) {
+ val keys = mAllClasses.keys.toTypedArray()
+ Arrays.sort(keys)
+
+ for (name in keys) {
+ consumer(mAllClasses[name]!!)
+ }
+ }
+
+ /**
+ * Dump all classes.
+ */
+ fun dump(pw: PrintWriter) {
+ forEach { classNode -> dumpClass(pw, classNode) }
+ }
+
+ private fun dumpClass(pw: PrintWriter, cn: ClassNode) {
+ pw.printf("Class: %s [access: %x]\n", cn.name, cn.access)
+ dumpAnnotations(pw, " ",
+ cn.visibleTypeAnnotations, cn.invisibleTypeAnnotations,
+ cn.visibleAnnotations, cn.invisibleAnnotations,
+ )
+
+ for (f in cn.fields ?: emptyList()) {
+ pw.printf(" Field: %s [sig: %s] [desc: %s] [access: %x]\n",
+ f.name, f.signature, f.desc, f.access)
+ dumpAnnotations(pw, " ",
+ f.visibleTypeAnnotations, f.invisibleTypeAnnotations,
+ f.visibleAnnotations, f.invisibleAnnotations,
+ )
+ }
+ for (m in cn.methods ?: emptyList()) {
+ pw.printf(" Method: %s [sig: %s] [desc: %s] [access: %x]\n",
+ m.name, m.signature, m.desc, m.access)
+ dumpAnnotations(pw, " ",
+ m.visibleTypeAnnotations, m.invisibleTypeAnnotations,
+ m.visibleAnnotations, m.invisibleAnnotations,
+ )
+ }
+ }
+
+ private fun dumpAnnotations(
+ pw: PrintWriter,
+ prefix: String,
+ visibleTypeAnnotations: List<TypeAnnotationNode>?,
+ invisibleTypeAnnotations: List<TypeAnnotationNode>?,
+ visibleAnnotations: List<AnnotationNode>?,
+ invisibleAnnotations: List<AnnotationNode>?,
+ ) {
+ for (an in visibleTypeAnnotations ?: emptyList()) {
+ pw.printf("%sTypeAnnotation(vis): %s\n", prefix, an.desc)
+ }
+ for (an in invisibleTypeAnnotations ?: emptyList()) {
+ pw.printf("%sTypeAnnotation(inv): %s\n", prefix, an.desc)
+ }
+ for (an in visibleAnnotations ?: emptyList()) {
+ pw.printf("%sAnnotation(vis): %s\n", prefix, an.desc)
+ if (an.values == null) {
+ continue
+ }
+ var i = 0
+ while (i < an.values.size - 1) {
+ pw.printf("%s - %s -> %s \n", prefix, an.values[i], an.values[i + 1])
+ i += 2
+ }
+ }
+ for (an in invisibleAnnotations ?: emptyList()) {
+ pw.printf("%sAnnotation(inv): %s\n", prefix, an.desc)
+ if (an.values == null) {
+ continue
+ }
+ var i = 0
+ while (i < an.values.size - 1) {
+ pw.printf("%s - %s -> %s \n", prefix, an.values[i], an.values[i + 1])
+ i += 2
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/AnnotationBasedFilter.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/AnnotationBasedFilter.kt
new file mode 100644
index 000000000000..454569d2f1c5
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/AnnotationBasedFilter.kt
@@ -0,0 +1,401 @@
+/*
+ * Copyright (C) 2023 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.hoststubgen.filters
+
+import com.android.hoststubgen.ClassParseException
+import com.android.hoststubgen.HostStubGenErrors
+import com.android.hoststubgen.HostStubGenInternalException
+import com.android.hoststubgen.InvalidAnnotationException
+import com.android.hoststubgen.asm.ClassNodes
+import com.android.hoststubgen.asm.findAnnotationValueAsString
+import com.android.hoststubgen.asm.findAnyAnnotation
+import com.android.hoststubgen.asm.toHumanReadableMethodName
+import com.android.hoststubgen.asm.toJvmClassName
+import com.android.hoststubgen.log
+import org.objectweb.asm.tree.AnnotationNode
+import org.objectweb.asm.tree.ClassNode
+
+// TODO: Detect invalid cases, such as...
+// - Class's visibility is lower than the members'.
+// - HostSideTestSubstituteWith is set, but it doesn't have @Stub or @Keep
+
+/**
+ * [OutputFilter] using Java annotations.
+ */
+class AnnotationBasedFilter(
+ private val errors: HostStubGenErrors,
+ private val classes: ClassNodes,
+ stubAnnotations_: Set<String>,
+ keepAnnotations_: Set<String>,
+ stubClassAnnotations_: Set<String>,
+ keepClassAnnotations_: Set<String>,
+ throwAnnotations_: Set<String>,
+ removeAnnotations_: Set<String>,
+ substituteAnnotations_: Set<String>,
+ nativeSubstituteAnnotations_: Set<String>,
+ classLoadHookAnnotations_: Set<String>,
+ fallback: OutputFilter,
+) : DelegatingFilter(fallback) {
+ private var stubAnnotations = convertToInternalNames(stubAnnotations_)
+ private var keepAnnotations = convertToInternalNames(keepAnnotations_)
+ private var stubClassAnnotations = convertToInternalNames(stubClassAnnotations_)
+ private var keepClassAnnotations = convertToInternalNames(keepClassAnnotations_)
+ private var throwAnnotations = convertToInternalNames(throwAnnotations_)
+ private var removeAnnotations = convertToInternalNames(removeAnnotations_)
+ private var substituteAnnotations = convertToInternalNames(substituteAnnotations_)
+ private var nativeSubstituteAnnotations = convertToInternalNames(nativeSubstituteAnnotations_)
+ private var classLoadHookAnnotations = convertToInternalNames(classLoadHookAnnotations_)
+
+ /** Annotations that control API visibility. */
+ private var visibilityAnnotations: Set<String> = convertToInternalNames(
+ stubAnnotations_ +
+ keepAnnotations_ +
+ stubClassAnnotations_ +
+ keepClassAnnotations_ +
+ throwAnnotations_ +
+ removeAnnotations_)
+
+ /**
+ * All the annotations we use. Note, this one is in a [convertToJvmNames] format unlike
+ * other ones, because of how it's used.
+ */
+ private var allAnnotations: Set<String> = convertToJvmNames(
+ stubAnnotations_ +
+ keepAnnotations_ +
+ stubClassAnnotations_ +
+ keepClassAnnotations_ +
+ throwAnnotations_ +
+ removeAnnotations_ +
+ substituteAnnotations_ +
+ nativeSubstituteAnnotations_ +
+ classLoadHookAnnotations_)
+
+ private val substitutionHelper = SubstitutionHelper()
+
+ private val reasonAnnotation = "annotation"
+ private val reasonClassAnnotation = "class-annotation"
+
+ /**
+ * Throw if an item has more than one visibility annotations.
+ *
+ * name1 - 4 are only used in exception messages. We take them as separate strings
+ * to avoid unnecessary string concatenations.
+ */
+ private fun detectInvalidAnnotations(
+ visibles: List<AnnotationNode>?,
+ invisibles: List<AnnotationNode>?,
+ type: String,
+ name1: String,
+ name2: String,
+ name3: String,
+ ) {
+ var count = 0
+ for (an in visibles ?: emptyList()) {
+ if (visibilityAnnotations.contains(an.desc)) {
+ count++
+ }
+ }
+ for (an in invisibles ?: emptyList()) {
+ if (visibilityAnnotations.contains(an.desc)) {
+ count++
+ }
+ }
+ if (count > 1) {
+ val description = if (name2 == "" && name3 == "") {
+ "$type $name1"
+ } else {
+ "$type $name1.$name2$name3"
+ }
+ throw InvalidAnnotationException(
+ "Found more than one visibility annotations on $description")
+ }
+ }
+
+ /**
+ * Find a visibility annotation.
+ *
+ * name1 - 4 are only used in exception messages.
+ */
+ private fun findAnnotation(
+ visibles: List<AnnotationNode>?,
+ invisibles: List<AnnotationNode>?,
+ type: String,
+ name1: String,
+ name2: String = "",
+ name3: String = "",
+ ): FilterPolicyWithReason? {
+ detectInvalidAnnotations(visibles, invisibles, type, name1, name2, name3)
+
+ findAnyAnnotation(stubAnnotations, visibles, invisibles)?.let {
+ return FilterPolicy.Stub.withReason(reasonAnnotation)
+ }
+ findAnyAnnotation(stubClassAnnotations, visibles, invisibles)?.let {
+ return FilterPolicy.StubClass.withReason(reasonClassAnnotation)
+ }
+ findAnyAnnotation(keepAnnotations, visibles, invisibles)?.let {
+ return FilterPolicy.Keep.withReason(reasonAnnotation)
+ }
+ findAnyAnnotation(keepClassAnnotations, visibles, invisibles)?.let {
+ return FilterPolicy.KeepClass.withReason(reasonClassAnnotation)
+ }
+ findAnyAnnotation(throwAnnotations, visibles, invisibles)?.let {
+ return FilterPolicy.Throw.withReason(reasonAnnotation)
+ }
+ findAnyAnnotation(removeAnnotations, visibles, invisibles)?.let {
+ return FilterPolicy.Remove.withReason(reasonAnnotation)
+ }
+ return null
+ }
+
+ override fun getPolicyForClass(className: String): FilterPolicyWithReason {
+ val cn = classes.getClass(className)
+
+ findAnnotation(
+ cn.visibleAnnotations,
+ cn.invisibleAnnotations,
+ "class",
+ className)?.let {
+ return it
+ }
+
+ // If it's any of the annotations, then always keep it.
+ if (allAnnotations.contains(className)) {
+ return FilterPolicy.KeepClass.withReason("HostStubGen Annotation")
+ }
+
+ return super.getPolicyForClass(className)
+ }
+
+ override fun getPolicyForField(
+ className: String,
+ fieldName: String
+ ): FilterPolicyWithReason {
+ val cn = classes.getClass(className)
+
+ cn.fields?.firstOrNull { it.name == fieldName }?.let {fn ->
+ findAnnotation(
+ fn.visibleAnnotations,
+ fn.invisibleAnnotations,
+ "field",
+ className,
+ fieldName
+ )?.let { policy ->
+ // If the item has an annotation, then use it.
+ return policy
+ }
+ }
+ return super.getPolicyForField(className, fieldName)
+ }
+
+ override fun getPolicyForMethod(
+ className: String,
+ methodName: String,
+ descriptor: String
+ ): FilterPolicyWithReason {
+ val cn = classes.getClass(className)
+
+ cn.methods?.firstOrNull { it.name == methodName && it.desc == descriptor }?.let { mn ->
+ // @SubstituteWith is going to complicate the policy here, so we ask helper
+ // what to do.
+ substitutionHelper.getPolicyFromSubstitution(cn, mn.name, mn.desc)?.let {
+ return it
+ }
+
+ // If there's no substitution, then we check the annotation.
+ findAnnotation(
+ mn.visibleAnnotations,
+ mn.invisibleAnnotations,
+ "method",
+ className,
+ methodName,
+ descriptor
+ )?.let { policy ->
+ return policy
+ }
+ }
+ return super.getPolicyForMethod(className, methodName, descriptor)
+ }
+
+ override fun getRenameTo(
+ className: String,
+ methodName: String,
+ descriptor: String
+ ): String? {
+ val cn = classes.getClass(className)
+
+ // If the method has a "substitute with" annotation, then return its "value" parameter.
+ cn.methods?.firstOrNull { it.name == methodName && it.desc == descriptor }?.let { mn ->
+ return substitutionHelper.getRenameTo(cn, mn.name, mn.desc)
+ }
+ return null
+ }
+
+ override fun getNativeSubstitutionClass(className: String): String? {
+ classes.getClass(className).let { cn ->
+ findAnyAnnotation(nativeSubstituteAnnotations,
+ cn.visibleAnnotations, cn.invisibleAnnotations)?.let { an ->
+ return getAnnotationField(an, "value")?.toJvmClassName()
+ }
+ }
+ return null
+ }
+
+ override fun getClassLoadHook(className: String): String? {
+ classes.getClass(className).let { cn ->
+ findAnyAnnotation(classLoadHookAnnotations,
+ cn.visibleAnnotations, cn.invisibleAnnotations)?.let { an ->
+ return getAnnotationField(an, "value")?.toHumanReadableMethodName()
+ }
+ }
+ return null
+ }
+
+ private data class MethodKey(val name: String, val desc: String)
+
+ /**
+ * In order to handle substitution, we need to build a reverse mapping of substitution
+ * methods.
+ *
+ * This class automatically builds such a map internally that the above methods can
+ * take advantage of.
+ */
+ private inner class SubstitutionHelper {
+ private var currentClass: ClassNode? = null
+
+ private var policiesFromSubstitution = mutableMapOf<MethodKey, FilterPolicyWithReason>()
+ private var substituteToMethods = mutableMapOf<MethodKey, String>()
+
+ fun getPolicyFromSubstitution(cn: ClassNode, methodName: String, descriptor: String):
+ FilterPolicyWithReason? {
+ setClass(cn)
+ return policiesFromSubstitution[MethodKey(methodName, descriptor)]
+ }
+
+ fun getRenameTo(cn: ClassNode, methodName: String, descriptor: String): String? {
+ setClass(cn)
+ return substituteToMethods[MethodKey(methodName, descriptor)]
+ }
+
+ /**
+ * Every time we see a different class, we scan all its methods for substitution attributes,
+ * and compute (implicit) policies caused by them.
+ *
+ * For example, for the following methods:
+ *
+ * @Stub
+ * @Substitute(suffix = "_host")
+ * private void foo() {
+ * // This isn't supported on the host side.
+ * }
+ * private void foo_host() {
+ * // Host side implementation
+ * }
+ *
+ * We internally handle them as:
+ *
+ * foo() -> Remove
+ * foo_host() -> Stub, and then rename it to foo().
+ */
+ private fun setClass(cn: ClassNode) {
+ if (currentClass == cn) {
+ return
+ }
+ // If the class is changing, we'll rebuild the internal structure.
+ currentClass = cn
+
+ policiesFromSubstitution.clear()
+ substituteToMethods.clear()
+
+ for (mn in cn.methods ?: emptyList()) {
+ findAnyAnnotation(substituteAnnotations,
+ mn.visibleAnnotations,
+ mn.invisibleAnnotations)?.let { an ->
+
+ // Find the policy for this method.
+ val policy = outermostFilter.getPolicyForMethod(cn.name, mn.name, mn.desc)
+ .policy.resolveClassWidePolicy()
+ // Make sure it's either Stub or Keep.
+ if (!(policy.needsInStub || policy.needsInImpl)) {
+ // TODO: Use the real annotation names in the message
+ errors.onErrorFound("@SubstituteWith must have either @Stub or @Keep")
+ return@let
+ }
+ if (!policy.isUsableWithMethods) {
+ throw HostStubGenInternalException("Policy $policy shouldn't show up here")
+ }
+
+ val suffix = getAnnotationField(an, "suffix") ?: return@let
+ val renameFrom = mn.name + suffix
+ val renameTo = mn.name
+
+ if (renameFrom == renameTo) {
+ errors.onErrorFound("@SubstituteWith have a different name")
+ return@let
+ }
+
+ // This mn has "SubstituteWith". This means,
+ // 1. Re move the "rename-to" method, so add it to substitutedMethods.
+ policiesFromSubstitution[MethodKey(renameTo, mn.desc)] =
+ FilterPolicy.Remove.withReason("substitute-to")
+
+ // 2. We also keep the from-to in the map.
+ policiesFromSubstitution[MethodKey(renameFrom, mn.desc)] =
+ policy.withReason("substitute-from")
+ substituteToMethods[MethodKey(renameFrom, mn.desc)] = renameTo
+
+ log.v("Substitution found: %s%s -> %s", renameFrom, mn.desc, renameTo)
+ }
+ }
+ }
+ }
+
+ /**
+ * Return the (String) value of 'value' parameter from an annotation.
+ */
+ private fun getAnnotationField(an: AnnotationNode, name: String): String? {
+ try {
+ val suffix = findAnnotationValueAsString(an, name)
+ if (suffix == null) {
+ errors.onErrorFound("Annotation \"${an.desc}\" must have field $name")
+ }
+ return suffix
+ } catch (e: ClassParseException) {
+ errors.onErrorFound(e.message!!)
+ return null
+ }
+ }
+
+ companion object {
+ /**
+ * Convert from human-readable type names (e.g. "com.android.TypeName") to the internal type
+ * names (e.g. "Lcom/android/TypeName).
+ */
+ private fun convertToInternalNames(input: Set<String>): Set<String> {
+ val ret = mutableSetOf<String>()
+ input.forEach { ret.add("L" + it.toJvmClassName() + ";") }
+ return ret
+ }
+
+ /**
+ * Convert from human-readable type names to JVM type names.
+ */
+ private fun convertToJvmNames(input: Set<String>): Set<String> {
+ val ret = mutableSetOf<String>()
+ input.forEach { ret.add(it.toJvmClassName()) }
+ return ret
+ }
+ }
+} \ No newline at end of file
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/ClassWidePolicyPropagatingFilter.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/ClassWidePolicyPropagatingFilter.kt
new file mode 100644
index 000000000000..6aac3d88b8b1
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/ClassWidePolicyPropagatingFilter.kt
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2023 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.hoststubgen.filters
+
+import com.android.hoststubgen.asm.getDirectOuterClassName
+
+/**
+ * This is used as the second last fallback filter. This filter propagates the class-wide policy
+ * (obtained from [outermostFilter]) to the fields and methods.
+ */
+class ClassWidePolicyPropagatingFilter(
+ fallback: OutputFilter,
+ ) : DelegatingFilter(fallback) {
+
+ private fun getClassWidePolicy(className: String, resolve: Boolean): FilterPolicyWithReason? {
+ var currentClass = className
+
+ while (true) {
+ outermostFilter.getPolicyForClass(className).let { policy ->
+ if (policy.policy.isClassWidePolicy) {
+ val p = if (resolve) policy.policy.resolveClassWidePolicy() else policy.policy
+
+ return p.withReason(policy.reason).wrapReason("class-wide in $currentClass")
+ }
+ // If the class's policy is remove, then remove it.
+ if (policy.policy == FilterPolicy.Remove) {
+ return FilterPolicy.Remove.withReason("class-wide in $currentClass")
+ }
+ }
+
+ // Next, look at the outer class...
+ val outer = getDirectOuterClassName(currentClass)
+ if (outer == null) {
+ return null
+ }
+ currentClass = outer
+ }
+ }
+
+ override fun getPolicyForClass(className: String): FilterPolicyWithReason {
+ // If it's a nested class, use the outer class's policy.
+ getDirectOuterClassName(className)?.let { outerName ->
+ getClassWidePolicy(outerName, resolve = false)?.let { policy ->
+ return policy
+ }
+ }
+
+ return super.getPolicyForClass(className)
+ }
+
+ override fun getPolicyForField(
+ className: String,
+ fieldName: String
+ ): FilterPolicyWithReason {
+ return getClassWidePolicy(className, resolve = true)
+ ?: super.getPolicyForField(className, fieldName)
+ }
+
+ override fun getPolicyForMethod(
+ className: String,
+ methodName: String,
+ descriptor: String
+ ): FilterPolicyWithReason {
+ return getClassWidePolicy(className, resolve = true)
+ ?: super.getPolicyForMethod(className, methodName, descriptor)
+ }
+} \ No newline at end of file
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/ConstantFilter.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/ConstantFilter.kt
new file mode 100644
index 000000000000..33010baaf894
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/ConstantFilter.kt
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2023 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.hoststubgen.filters
+
+import com.android.hoststubgen.HostStubGenInternalException
+
+
+/**
+ * [OutputFilter] with a given policy. Used to represent the default policy.
+ *
+ * This is used as the last fallback filter.
+ *
+ * @param policy the policy. Cannot be a "substitute" policy.
+ */
+class ConstantFilter(
+ policy: FilterPolicy,
+ val reason: String
+) : OutputFilter() {
+ val classPolicy: FilterPolicy
+ val fieldPolicy: FilterPolicy
+ val methodPolicy: FilterPolicy
+
+ init {
+ if (policy.isSubstitute) {
+ throw HostStubGenInternalException(
+ "ConstantFilter doesn't allow substitution policies.")
+ }
+ if (policy.isClassWidePolicy) {
+ // We prevent it, because there's no point in using class-wide policies because
+ // all members get othe same policy too anyway.
+ throw HostStubGenInternalException(
+ "ConstantFilter doesn't allow class-wide policies.")
+ }
+ methodPolicy = policy
+
+ // TODO: Need to think about the realistic default behavior.
+ classPolicy = if (policy != FilterPolicy.Throw) policy else FilterPolicy.Remove
+ fieldPolicy = classPolicy
+ }
+
+ override fun getPolicyForClass(className: String): FilterPolicyWithReason {
+ return classPolicy.withReason(reason)
+ }
+
+ override fun getPolicyForField(className: String, fieldName: String): FilterPolicyWithReason {
+ return fieldPolicy.withReason(reason)
+ }
+
+ override fun getPolicyForMethod(
+ className: String,
+ methodName: String,
+ descriptor: String,
+ ): FilterPolicyWithReason {
+ return methodPolicy.withReason(reason)
+ }
+}
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/DelegatingFilter.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/DelegatingFilter.kt
new file mode 100644
index 000000000000..f0763c4ba097
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/DelegatingFilter.kt
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2023 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.hoststubgen.filters
+
+/**
+ * Base class for an [OutputFilter] that uses another filter as a fallback.
+ */
+abstract class DelegatingFilter(
+ // fallback shouldn't be used by subclasses, so make it private.
+ // They should instead be calling into `super` or `outermostFilter`.
+ private val fallback: OutputFilter
+) : OutputFilter() {
+ init {
+ fallback.outermostFilter = this
+ }
+
+ override var outermostFilter: OutputFilter = this
+ get() = field
+ set(value) {
+ field = value
+ // Propagate the inner filters.
+ fallback.outermostFilter = value
+ }
+
+ override fun getPolicyForClass(className: String): FilterPolicyWithReason {
+ return fallback.getPolicyForClass(className)
+ }
+
+ override fun getPolicyForField(
+ className: String,
+ fieldName: String
+ ): FilterPolicyWithReason {
+ return fallback.getPolicyForField(className, fieldName)
+ }
+
+ override fun getPolicyForMethod(
+ className: String,
+ methodName: String,
+ descriptor: String
+ ): FilterPolicyWithReason {
+ return fallback.getPolicyForMethod(className, methodName, descriptor)
+ }
+
+ override fun getRenameTo(
+ className: String,
+ methodName: String,
+ descriptor: String
+ ): String? {
+ return fallback.getRenameTo(className, methodName, descriptor)
+ }
+
+ override fun getNativeSubstitutionClass(className: String): String? {
+ return fallback.getNativeSubstitutionClass(className)
+ }
+
+ override fun getClassLoadHook(className: String): String? {
+ return fallback.getClassLoadHook(className)
+ }
+}
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/FilterPolicy.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/FilterPolicy.kt
new file mode 100644
index 000000000000..f11ac2f7325d
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/FilterPolicy.kt
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2023 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.hoststubgen.filters
+
+enum class FilterPolicy {
+ /**
+ * Keep the item in the stub jar file, so tests can use it.
+ */
+ Stub,
+
+ /**
+ * Keep the item in the impl jar file, but not in the stub file. Tests cannot use it directly,
+ * but indirectly.
+ */
+ Keep,
+
+ /**
+ * Only used for types. Keep the class in the stub, and also all its members.
+ * But each member can have another annotations to override it.
+ */
+ StubClass,
+
+ /**
+ * Only used for types. Keep the class in the impl, not in the stub, and also all its members.
+ * But each member can have another annotations to override it.
+ */
+ KeepClass,
+
+ /**
+ * Same as [Stub], but replace it with a "substitution" method. Only usable with methods.
+ */
+ SubstituteAndStub,
+
+ /**
+ * Same as [Keep], but replace it with a "substitution" method. Only usable with methods.
+ */
+ SubstituteAndKeep,
+
+ /**
+ * Only usable with methods. The item will be kept in the impl jar file, but when called,
+ * it'll throw.
+ */
+ Throw,
+
+ /**
+ * Remove the item completely.
+ */
+ Remove;
+
+ val isSubstitute: Boolean
+ get() = this == SubstituteAndStub || this == SubstituteAndKeep
+
+ val needsInStub: Boolean
+ get() = this == Stub || this == StubClass || this == SubstituteAndStub
+
+ val needsInImpl: Boolean
+ get() = this != Remove
+
+ /** Returns whether a policy can be used with classes */
+ val isUsableWithClasses: Boolean
+ get() {
+ return when (this) {
+ Stub, StubClass, Keep, KeepClass, Remove -> true
+ else -> false
+ }
+ }
+
+ /** Returns whether a policy can be used with fields. */
+ val isUsableWithFields: Boolean
+ get() {
+ return when (this) {
+ Stub, Keep, Remove -> true
+ else -> false
+ }
+ }
+
+ /** Returns whether a policy can be used with methods */
+ val isUsableWithMethods: Boolean
+ get() {
+ return when (this) {
+ StubClass, KeepClass -> false
+ else -> true
+ }
+ }
+
+ /** Returns whether a policy is a class-wide one. */
+ val isClassWidePolicy: Boolean
+ get() {
+ return when (this) {
+ StubClass, KeepClass -> true
+ else -> false
+ }
+ }
+
+ fun getSubstitutionBasePolicy(): FilterPolicy {
+ return when (this) {
+ SubstituteAndKeep -> Keep
+ SubstituteAndStub -> Stub
+ else -> this
+ }
+ }
+
+ /**
+ * Convert {Stub,Keep}Class to the corresponding Stub or Keep.
+ */
+ fun resolveClassWidePolicy(): FilterPolicy {
+ return when (this) {
+ StubClass -> Stub
+ KeepClass -> Keep
+ else -> this
+ }
+ }
+
+ /**
+ * Create a [FilterPolicyWithReason] with a given reason.
+ */
+ fun withReason(reason: String): FilterPolicyWithReason {
+ return FilterPolicyWithReason(this, reason)
+ }
+} \ No newline at end of file
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/FilterPolicyWithReason.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/FilterPolicyWithReason.kt
new file mode 100644
index 000000000000..b64a2f5fd8a5
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/FilterPolicyWithReason.kt
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2023 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.hoststubgen.filters
+
+/**
+ * Captures a [FilterPolicy] with a human-readable reason.
+ */
+data class FilterPolicyWithReason (
+ val policy: FilterPolicy,
+ val reason: String = "",
+) {
+ /**
+ * Return a new [FilterPolicy] with an updated reason, while keeping the original reason
+ * as an "inner-reason".
+ */
+ fun wrapReason(reason: String): FilterPolicyWithReason {
+ return FilterPolicyWithReason(policy, "$reason [inner-reason: ${this.reason}]")
+ }
+
+ /**
+ * If the visibility is lower than "Keep" (meaning if it's "remove"),
+ * then return a new [FilterPolicy] with "Keep".
+ * Otherwise, return itself
+ */
+ fun promoteToKeep(promotionReason: String): FilterPolicyWithReason {
+ if (policy.needsInImpl) {
+ return this
+ }
+ val newPolicy = if (policy.isClassWidePolicy) FilterPolicy.KeepClass else FilterPolicy.Keep
+
+ return FilterPolicyWithReason(newPolicy,
+ "$promotionReason [original remove reason: ${this.reason}]")
+ }
+
+ /**
+ * If the visibility is above "Keep" (meaning if it's "stub"),
+ * then return a new [FilterPolicy] with "Keep".
+ * Otherwise, return itself
+ */
+ fun demoteToKeep(promotionReason: String): FilterPolicyWithReason {
+ if (!policy.needsInStub) {
+ return this
+ }
+ val newPolicy = if (policy.isClassWidePolicy) FilterPolicy.KeepClass else FilterPolicy.Keep
+
+ return FilterPolicyWithReason(newPolicy,
+ "$promotionReason [original stub reason: ${this.reason}]")
+ }
+
+ override fun toString(): String {
+ return "[$policy - reason: $reason]"
+ }
+} \ No newline at end of file
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/ImplicitOutputFilter.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/ImplicitOutputFilter.kt
new file mode 100644
index 000000000000..9c372ff68e37
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/ImplicitOutputFilter.kt
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2023 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.hoststubgen.filters
+
+import com.android.hoststubgen.HostStubGenErrors
+import com.android.hoststubgen.HostStubGenInternalException
+import com.android.hoststubgen.asm.isAnonymousInnerClass
+import com.android.hoststubgen.log
+import com.android.hoststubgen.asm.ClassNodes
+import com.android.hoststubgen.asm.isVisibilityPrivateOrPackagePrivate
+
+/**
+ * Filter implementing "implicit" rules, such as:
+ * - "keep all anonymous inner classes if the outer class is keep".
+ * (But anonymous inner classes should never be in "stub")
+ * - For classes in stub, make sure private parameterless constructors are also in stub, if any.
+ */
+class ImplicitOutputFilter(
+ private val errors: HostStubGenErrors,
+ private val classes: ClassNodes,
+ fallback: OutputFilter
+) : DelegatingFilter(fallback) {
+ private fun getClassImplicitPolicy(className: String): FilterPolicyWithReason? {
+ // TODO: This check should be cached.
+ val cn = classes.getClass(className)
+
+ if (isAnonymousInnerClass(cn)) {
+ log.forDebug {
+// log.d(" anon-inner class: ${className} outer: ${cn.outerClass} ")
+ }
+ if (cn.outerClass == null) {
+ throw HostStubGenInternalException(
+ "outerClass is null for anonymous inner class")
+ }
+ // If the outer class needs to be in impl, it should be in impl too.
+ val outerPolicy = outermostFilter.getPolicyForClass(cn.outerClass)
+ if (outerPolicy.policy.needsInImpl) {
+ return FilterPolicy.KeepClass.withReason("anonymous-inner-class")
+ }
+ }
+ return null
+ }
+
+ override fun getPolicyForClass(className: String): FilterPolicyWithReason {
+ // Use the implicit policy, if any.
+ getClassImplicitPolicy(className)?.let { return it }
+
+ return super.getPolicyForClass(className)
+ }
+
+ override fun getPolicyForMethod(
+ className: String,
+ methodName: String,
+ descriptor: String
+ ): FilterPolicyWithReason {
+ val fallback = super.getPolicyForMethod(className, methodName, descriptor)
+
+ // If the class is in the stub, then we need to put the private constructor in the stub too,
+ // to prevent the class from getting instantiated.
+ if (outermostFilter.getPolicyForClass(className).policy.needsInStub &&
+ !fallback.policy.needsInStub &&
+ (methodName == "<init>") && // Constructor?
+ (descriptor == "()V")) { // Has zero parameters?
+ classes.findMethod(className, methodName, descriptor)?.let { mn ->
+ if (isVisibilityPrivateOrPackagePrivate(mn.access)) {
+ return FilterPolicy.Stub.withReason("private constructor in stub class")
+ }
+ }
+ }
+
+ return fallback
+ }
+} \ No newline at end of file
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/InMemoryOutputFilter.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/InMemoryOutputFilter.kt
new file mode 100644
index 000000000000..f3551d49bd36
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/InMemoryOutputFilter.kt
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2023 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.hoststubgen.filters
+
+import com.android.hoststubgen.UnknownApiException
+import com.android.hoststubgen.asm.ClassNodes
+import com.android.hoststubgen.asm.toHumanReadableClassName
+import com.android.hoststubgen.asm.toHumanReadableMethodName
+
+// TODO: Validate all input names.
+
+class InMemoryOutputFilter(
+ private val classes: ClassNodes,
+ fallback: OutputFilter,
+) : DelegatingFilter(fallback) {
+ private val mPolicies: MutableMap<String, FilterPolicyWithReason> = mutableMapOf()
+ private val mRenames: MutableMap<String, String> = mutableMapOf()
+ private val mNativeSubstitutionClasses: MutableMap<String, String> = mutableMapOf()
+ private val mClassLoadHooks: MutableMap<String, String> = mutableMapOf()
+
+ private fun getClassKey(className: String): String {
+ return className.toHumanReadableClassName()
+ }
+
+ private fun getFieldKey(className: String, fieldName: String): String {
+ return getClassKey(className) + "." + fieldName
+ }
+
+ private fun getMethodKey(className: String, methodName: String, signature: String): String {
+ return getClassKey(className) + "." + methodName + ";" + signature
+ }
+
+ override fun getPolicyForClass(className: String): FilterPolicyWithReason {
+ return mPolicies[getClassKey(className)] ?: super.getPolicyForClass(className)
+ }
+
+ private fun ensureClassExists(className: String) {
+ if (classes.findClass(className) == null) {
+ throw UnknownApiException("Unknown class $className")
+ }
+ }
+
+ private fun ensureFieldExists(className: String, fieldName: String) {
+ if (classes.findField(className, fieldName) == null) {
+ throw UnknownApiException("Unknown field $className.$fieldName")
+ }
+ }
+
+ private fun ensureMethodExists(
+ className: String,
+ methodName: String,
+ descriptor: String
+ ) {
+ if (classes.findMethod(className, methodName, descriptor) == null) {
+ throw UnknownApiException("Unknown method $className.$methodName$descriptor")
+ }
+ }
+
+ fun setPolicyForClass(className: String, policy: FilterPolicyWithReason) {
+ ensureClassExists(className)
+ mPolicies[getClassKey(className)] = policy
+ }
+
+ override fun getPolicyForField(className: String, fieldName: String): FilterPolicyWithReason {
+ return mPolicies[getFieldKey(className, fieldName)]
+ ?: super.getPolicyForField(className, fieldName)
+ }
+
+ fun setPolicyForField(className: String, fieldName: String, policy: FilterPolicyWithReason) {
+ ensureFieldExists(className, fieldName)
+ mPolicies[getFieldKey(className, fieldName)] = policy
+ }
+
+ override fun getPolicyForMethod(
+ className: String,
+ methodName: String,
+ descriptor: String,
+ ): FilterPolicyWithReason {
+ return mPolicies[getMethodKey(className, methodName, descriptor)]
+ ?: super.getPolicyForMethod(className, methodName, descriptor)
+ }
+
+ fun setPolicyForMethod(
+ className: String,
+ methodName: String,
+ descriptor: String,
+ policy: FilterPolicyWithReason,
+ ) {
+ ensureMethodExists(className, methodName, descriptor)
+ mPolicies[getMethodKey(className, methodName, descriptor)] = policy
+ }
+
+ override fun getRenameTo(className: String, methodName: String, descriptor: String): String? {
+ return mRenames[getMethodKey(className, methodName, descriptor)]
+ ?: super.getRenameTo(className, methodName, descriptor)
+ }
+
+ fun setRenameTo(className: String, methodName: String, descriptor: String, toName: String) {
+ ensureMethodExists(className, methodName, descriptor)
+ ensureMethodExists(className, toName, descriptor)
+ mRenames[getMethodKey(className, methodName, descriptor)] = toName
+ }
+
+ override fun getNativeSubstitutionClass(className: String): String? {
+ return mNativeSubstitutionClasses[getClassKey(className)]
+ ?: super.getNativeSubstitutionClass(className)
+ }
+
+ fun setNativeSubstitutionClass(from: String, to: String) {
+ ensureClassExists(from)
+
+ // Native substitute classes may be provided from other jars, so we can't do this check.
+ // ensureClassExists(to)
+ mNativeSubstitutionClasses[getClassKey(from)] = to.toHumanReadableClassName()
+ }
+
+ override fun getClassLoadHook(className: String): String? {
+ return mClassLoadHooks[getClassKey(className)]
+ ?: super.getClassLoadHook(className)
+ }
+
+ fun setClassLoadHook(className: String, methodName: String) {
+ mClassLoadHooks[getClassKey(className)] = methodName.toHumanReadableMethodName()
+ }
+} \ No newline at end of file
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/KeepAllClassesFilter.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/KeepAllClassesFilter.kt
new file mode 100644
index 000000000000..45dd38d10ef5
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/KeepAllClassesFilter.kt
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2023 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.hoststubgen.filters
+
+/**
+ * An [OutputFilter] that keeps all classes by default. (but none of its members)
+ *
+ * We're not currently using it, but using it *might* make certain things easier. For example, with
+ * this, all classes would at least be loadable.
+ */
+class KeepAllClassesFilter(fallback: OutputFilter) : DelegatingFilter(fallback) {
+ override fun getPolicyForClass(className: String): FilterPolicyWithReason {
+ // If the default visibility wouldn't keep it, change it to "keep".
+ val f = super.getPolicyForClass(className)
+ return f.promoteToKeep("keep-all-classes")
+ }
+} \ No newline at end of file
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/OutputFilter.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/OutputFilter.kt
new file mode 100644
index 000000000000..392ee4b81613
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/OutputFilter.kt
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2023 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.hoststubgen.filters
+
+/**
+ * Base class for "filters", which decides what APIs should go to the stub / impl jars.
+ */
+abstract class OutputFilter {
+ /**
+ * Filters are stacked over one another. This fields contains the "outermost" filter in a
+ * filter stack chain.
+ *
+ * Subclasses must use this filter to get a policy, when they need to infer a policy
+ * from the policy of another API.
+ *
+ * For example, [ClassWidePolicyPropagatingFilter] needs to check the policy of the enclosing
+ * class to propagate "class-wide" policies, but when it does so, it can't just use
+ * `this.getPolicyForClass()` because that wouldn't return policies decided by "outer"
+ * filters. Instead, it uses [outermostFilter.getPolicyForClass()].
+ *
+ * Note, [outermostFilter] can be itself, so make sure not to cause infinity recursions when
+ * using it.
+ */
+ open var outermostFilter: OutputFilter = this
+ get() = field
+ set(value) {
+ field = value
+ }
+
+ abstract fun getPolicyForClass(className: String): FilterPolicyWithReason
+
+ abstract fun getPolicyForField(className: String, fieldName: String): FilterPolicyWithReason
+
+ abstract fun getPolicyForMethod(
+ className: String,
+ methodName: String,
+ descriptor: String,
+ ): FilterPolicyWithReason
+
+ /**
+ * If a given method is a substitute-from method, return the substitute-to method name.
+ *
+ * The substitute-to and from methods must have the same signature, in the same class.
+ */
+ open fun getRenameTo(className: String, methodName: String, descriptor: String): String? {
+ return null
+ }
+
+ /**
+ * Return a "native substitution class" name for a given class.
+ *
+ * The result will be in a "human readable" form. (e.g. uses '.'s instead of '/'s)
+ *
+ * (which corresponds to @HostSideTestNativeSubstitutionClass of the standard annotations.)
+ */
+ open fun getNativeSubstitutionClass(className: String): String? {
+ return null
+ }
+
+ /**
+ * Return a "class load hook" method name for a given class.
+ *
+ * (which corresponds to @HostSideTestClassLoadHook of the standard annotations.)
+ */
+ open fun getClassLoadHook(className: String): String? {
+ return null
+ }
+} \ No newline at end of file
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/StubIntersectingFilter.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/StubIntersectingFilter.kt
new file mode 100644
index 000000000000..f92a0271d7c7
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/StubIntersectingFilter.kt
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2023 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.hoststubgen.filters
+
+import com.android.hoststubgen.HostStubGenErrors
+import com.android.hoststubgen.asm.ClassNodes
+
+private const val REASON = "demoted, not in intersect jars"
+
+/**
+ * An [OutputFilter] that will restrict what to put in stub to only what shows up in "intersecting
+ * jar" files.
+ *
+ * For example, if the Android public API stub jar is provided, then the HostStubGen's output
+ * stub will be restricted to public APIs.
+ */
+class StubIntersectingFilter(
+ private val errors: HostStubGenErrors,
+ /**
+ * If a class / field / method is not in any of these jars, then we will not put it in
+ * stub.
+ */
+ private val intersectingJars: Map<String, ClassNodes>,
+ fallback: OutputFilter,
+) : DelegatingFilter(fallback) {
+ private inline fun exists(predicate: (ClassNodes) -> Boolean): Boolean {
+ intersectingJars.forEach { entry ->
+ if (predicate(entry.value)) {
+ return true
+ }
+ }
+ return false
+ }
+
+ /**
+ * If [origPolicy] is less than "Stub", then return it as-is.
+ *
+ * Otherwise, call [inStubChecker] to see if the API is in any of [intersectingJars].
+ * If yes, then return [origPolicy] as-is. Otherwise, demote to "Keep".
+ */
+ private fun intersectWithStub(
+ origPolicy: FilterPolicyWithReason,
+ inStubChecker: () -> Boolean,
+ ): FilterPolicyWithReason {
+ if (origPolicy.policy.needsInStub) {
+ // Only check the stub jars, when the class is supposed to be in stub otherwise.
+ if (!inStubChecker()) {
+ return origPolicy.demoteToKeep(REASON)
+ }
+ }
+ return origPolicy
+ }
+
+ override fun getPolicyForClass(className: String): FilterPolicyWithReason {
+ return intersectWithStub(super.getPolicyForClass(className)) {
+ exists { classes -> classes.findClass(className) != null }
+ }
+ }
+
+ override fun getPolicyForField(
+ className: String,
+ fieldName: String
+ ): FilterPolicyWithReason {
+ return intersectWithStub(super.getPolicyForField(className, fieldName)) {
+ exists { classes -> classes.findField(className, fieldName) != null }
+ }
+ }
+
+ override fun getPolicyForMethod(
+ className: String,
+ methodName: String,
+ descriptor: String
+ ): FilterPolicyWithReason {
+ return intersectWithStub(super.getPolicyForMethod(className, methodName, descriptor)) {
+ exists { classes -> classes.findMethod(className, methodName, descriptor) != null }
+ }
+ }
+} \ No newline at end of file
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/TextFileFilterPolicyParser.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/TextFileFilterPolicyParser.kt
new file mode 100644
index 000000000000..46546e8b9491
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/TextFileFilterPolicyParser.kt
@@ -0,0 +1,213 @@
+/*
+ * Copyright (C) 2023 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.hoststubgen.filters
+
+import com.android.hoststubgen.UserErrorException
+import com.android.hoststubgen.asm.ClassNodes
+import com.android.hoststubgen.log
+import com.android.hoststubgen.normalizeTextLine
+import com.android.hoststubgen.whitespaceRegex
+import org.objectweb.asm.Opcodes
+import org.objectweb.asm.tree.ClassNode
+import java.io.BufferedReader
+import java.io.FileReader
+import java.io.PrintWriter
+import java.util.Objects
+
+/**
+ * Print a class node as a "keep" policy.
+ */
+fun printAsTextPolicy(pw: PrintWriter, cn: ClassNode) {
+ pw.printf("class %s\t%s\n", cn.name, "keep")
+
+ for (f in cn.fields ?: emptyList()) {
+ pw.printf(" field %s\t%s\n", f.name, "keep")
+ }
+ for (m in cn.methods ?: emptyList()) {
+ pw.printf(" method %s\t%s\t%s\n", m.name, m.desc, "keep")
+ }
+}
+
+/** Return true if [access] is either public or protected. */
+private fun isVisible(access: Int): Boolean {
+ return (access and (Opcodes.ACC_PUBLIC or Opcodes.ACC_PROTECTED)) != 0
+}
+
+/**
+ * Exception for a parse error.
+ */
+private class ParseException : Exception, UserErrorException {
+ val hasSourceInfo: Boolean
+
+ constructor(message: String) : super(message) {
+ hasSourceInfo = false
+ }
+
+ constructor(message: String, file: String, line: Int) :
+ super("$message in file $file line $line") {
+ hasSourceInfo = true
+ }
+
+ fun withSourceInfo(filename: String, lineNo: Int): ParseException {
+ if (hasSourceInfo) {
+ return this // Already has source information.
+ } else {
+ return ParseException(this.message ?: "", filename, lineNo)
+ }
+ }
+}
+
+private const val FILTER_REASON = "file-override"
+
+/**
+ * Read a given "policy" file and return as an [OutputFilter]
+ */
+fun createFilterFromTextPolicyFile(
+ filename: String,
+ classes: ClassNodes,
+ fallback: OutputFilter,
+ ): OutputFilter {
+ log.i("Loading offloaded annotations from $filename ...")
+ log.withIndent {
+ val ret = InMemoryOutputFilter(classes, fallback)
+
+ var lineNo = 0
+
+ try {
+ BufferedReader(FileReader(filename)).use { reader ->
+ var className = ""
+
+ while (true) {
+ var line = reader.readLine()
+ if (line == null) {
+ break
+ }
+ lineNo++
+
+ line = normalizeTextLine(line)
+
+ if (line.isEmpty()) {
+ continue // skip empty lines.
+ }
+
+ val fields = line.split(whitespaceRegex).toTypedArray()
+ when (fields[0].lowercase()) {
+ "c", "class" -> {
+ if (fields.size < 3) {
+ throw ParseException("Class ('c') expects 2 fields.")
+ }
+ className = fields[1]
+ if (fields[2].startsWith("!")) {
+ // It's a native-substitution.
+ val toClass = fields[2].substring(1)
+ ret.setNativeSubstitutionClass(className, toClass)
+ } else if (fields[2].startsWith("~")) {
+ // It's a class-load hook
+ val callback = fields[2].substring(1)
+ ret.setClassLoadHook(className, callback)
+ } else {
+ val policy = parsePolicy(fields[2])
+ if (!policy.isUsableWithClasses) {
+ throw ParseException("Class can't have policy '$policy'")
+ }
+ Objects.requireNonNull(className)
+
+ // TODO: Duplicate check, etc
+ ret.setPolicyForClass(className, policy.withReason(FILTER_REASON))
+ }
+ }
+
+ "f", "field" -> {
+ if (fields.size < 3) {
+ throw ParseException("Field ('f') expects 2 fields.")
+ }
+ val name = fields[1]
+ val policy = parsePolicy(fields[2])
+ if (!policy.isUsableWithFields) {
+ throw ParseException("Field can't have policy '$policy'")
+ }
+ Objects.requireNonNull(className)
+
+ // TODO: Duplicate check, etc
+ ret.setPolicyForField(className, name, policy.withReason(FILTER_REASON))
+ }
+
+ "m", "method" -> {
+ if (fields.size < 4) {
+ throw ParseException("Method ('m') expects 3 fields.")
+ }
+ val name = fields[1]
+ val signature = fields[2]
+ val policy = parsePolicy(fields[3])
+
+ if (!policy.isUsableWithMethods) {
+ throw ParseException("Method can't have policy '$policy'")
+ }
+
+ Objects.requireNonNull(className)
+
+ ret.setPolicyForMethod(className, name, signature,
+ policy.withReason(FILTER_REASON))
+ if (policy.isSubstitute) {
+ val fromName = fields[3].substring(1)
+
+ if (fromName == name) {
+ throw ParseException(
+ "Substitution must have a different name")
+ }
+
+ // Set the policy for the "from" method.
+ ret.setPolicyForMethod(className, fromName, signature,
+ policy.getSubstitutionBasePolicy()
+ .withReason(FILTER_REASON))
+
+ // Keep "from" -> "to" mapping.
+ ret.setRenameTo(className, fromName, signature, name)
+ }
+ }
+
+ else -> {
+ throw ParseException("Unknown directive \"${fields[0]}\"")
+ }
+ }
+ }
+ }
+ } catch (e: ParseException) {
+ throw e.withSourceInfo(filename, lineNo)
+ }
+ return ret
+ }
+}
+
+private fun parsePolicy(s: String): FilterPolicy {
+ return when (s.lowercase()) {
+ "s", "stub" -> FilterPolicy.Stub
+ "k", "keep" -> FilterPolicy.Keep
+ "t", "throw" -> FilterPolicy.Throw
+ "r", "remove" -> FilterPolicy.Remove
+ "sc", "stubclass" -> FilterPolicy.StubClass
+ "kc", "keepclass" -> FilterPolicy.KeepClass
+ else -> {
+ if (s.startsWith("@")) {
+ FilterPolicy.SubstituteAndStub
+ } else if (s.startsWith("%")) {
+ FilterPolicy.SubstituteAndKeep
+ } else {
+ throw ParseException("Invalid policy \"$s\"")
+ }
+ }
+ }
+}
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/BaseAdapter.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/BaseAdapter.kt
new file mode 100644
index 000000000000..3cf9a1d7fb82
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/BaseAdapter.kt
@@ -0,0 +1,252 @@
+/*
+ * Copyright (C) 2023 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.hoststubgen.visitors
+
+import com.android.hoststubgen.HostStubGenErrors
+import com.android.hoststubgen.asm.ClassNodes
+import com.android.hoststubgen.asm.getPackageNameFromClassName
+import com.android.hoststubgen.asm.resolveClassName
+import com.android.hoststubgen.asm.toJvmClassName
+import com.android.hoststubgen.filters.FilterPolicy
+import com.android.hoststubgen.filters.FilterPolicyWithReason
+import com.android.hoststubgen.filters.OutputFilter
+import com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+import com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+import com.android.hoststubgen.log
+import org.objectweb.asm.ClassVisitor
+import org.objectweb.asm.FieldVisitor
+import org.objectweb.asm.MethodVisitor
+import org.objectweb.asm.Opcodes
+import org.objectweb.asm.util.TraceClassVisitor
+import java.io.PrintWriter
+
+val OPCODE_VERSION = Opcodes.ASM9
+
+abstract class BaseAdapter (
+ protected val classes: ClassNodes,
+ nextVisitor: ClassVisitor,
+ protected val filter: OutputFilter,
+ protected val options: Options,
+) : ClassVisitor(OPCODE_VERSION, nextVisitor) {
+
+ /**
+ * Options to control the behavior.
+ */
+ data class Options (
+ val errors: HostStubGenErrors,
+ val enablePreTrace: Boolean,
+ val enablePostTrace: Boolean,
+ val enableMethodLogging: Boolean,
+ val enableNonStubMethodCallDetection: Boolean,
+ )
+
+ protected lateinit var currentPackageName: String
+ protected lateinit var currentClassName: String
+ protected var nativeSubstitutionClass: String? = null
+ protected lateinit var classPolicy: FilterPolicyWithReason
+
+ /**
+ * Return whether an item with a given policy should be included in the output.
+ */
+ protected abstract fun shouldEmit(policy: FilterPolicy): Boolean
+
+ override fun visit(
+ version: Int,
+ access: Int,
+ name: String,
+ signature: String?,
+ superName: String?,
+ interfaces: Array<String>,
+ ) {
+ super.visit(version, access, name, signature, superName, interfaces)
+ currentClassName = name
+ currentPackageName = getPackageNameFromClassName(name)
+ classPolicy = filter.getPolicyForClass(currentClassName)
+
+ log.d("[%s] visit: %s (package: %s)", this.javaClass.simpleName, name, currentPackageName)
+ log.indent()
+ log.v("Emitting class: %s", name)
+ log.indent()
+
+ filter.getNativeSubstitutionClass(currentClassName)?.let { className ->
+ val fullClassName = resolveClassName(className, currentPackageName).toJvmClassName()
+ log.d(" NativeSubstitutionClass: $fullClassName")
+ if (classes.findClass(fullClassName) == null) {
+ log.w("Native substitution class $fullClassName not found. Class must be " +
+ "available at runtime.")
+ } else {
+ // If the class exists, it must have a KeepClass policy.
+ if (filter.getPolicyForClass(fullClassName).policy != FilterPolicy.KeepClass) {
+ // TODO: Use real annotation name.
+ options.errors.onErrorFound(
+ "Native substitution class $fullClassName should have @Keep.")
+ }
+ }
+
+ nativeSubstitutionClass = fullClassName
+ }
+ // Inject annotations to generated classes.
+ if (classPolicy.policy.needsInStub) {
+ visitAnnotation(HostStubGenProcessedStubClass.CLASS_DESCRIPTOR, true)
+ }
+ if (classPolicy.policy.needsInImpl) {
+ visitAnnotation(HostStubGenProcessedKeepClass.CLASS_DESCRIPTOR, true)
+ }
+ }
+
+ override fun visitEnd() {
+ log.unindent()
+ log.unindent()
+ super.visitEnd()
+ }
+
+ var skipMemberModificationNestCount = 0
+
+ /**
+ * This method allows writing class members without any modifications.
+ */
+ protected inline fun writeRawMembers(callback: () -> Unit) {
+ skipMemberModificationNestCount++
+ try {
+ callback()
+ } finally {
+ skipMemberModificationNestCount--
+ }
+ }
+
+ override fun visitField(
+ access: Int,
+ name: String,
+ descriptor: String,
+ signature: String?,
+ value: Any?,
+ ): FieldVisitor? {
+ if (skipMemberModificationNestCount > 0) {
+ return super.visitField(access, name, descriptor, signature, value)
+ }
+ val policy = filter.getPolicyForField(currentClassName, name)
+ log.d("visitField: %s %s [%x] Policy: %s", name, descriptor, access, policy)
+
+ log.withIndent {
+ if (!shouldEmit(policy.policy)) {
+ log.d("Removing %s %s", name, policy)
+ return null
+ }
+
+ log.v("Emitting field: %s %s %s", name, descriptor, policy)
+ return super.visitField(access, name, descriptor, signature, value)
+ }
+ }
+
+ override fun visitMethod(
+ access: Int,
+ name: String,
+ descriptor: String,
+ signature: String?,
+ exceptions: Array<String>?,
+ ): MethodVisitor? {
+ if (skipMemberModificationNestCount > 0) {
+ return super.visitMethod(access, name, descriptor, signature, exceptions)
+ }
+ val p = filter.getPolicyForMethod(currentClassName, name, descriptor)
+ log.d("visitMethod: %s%s [%x] [%s] Policy: %s", name, descriptor, access, signature, p)
+
+ log.withIndent {
+ // If it's a substitute-to method, then skip.
+ val policy = filter.getPolicyForMethod(currentClassName, name, descriptor)
+ if (policy.policy.isSubstitute) {
+ log.d("Skipping %s%s %s", name, descriptor, policy)
+ return null
+ }
+ if (!shouldEmit(p.policy)) {
+ log.d("Removing %s%s %s", name, descriptor, policy)
+ return null
+ }
+
+ // Maybe rename the method.
+ val newName: String
+ val substituteTo = filter.getRenameTo(currentClassName, name, descriptor)
+ if (substituteTo != null) {
+ newName = substituteTo
+ log.v("Emitting %s.%s%s as %s %s", currentClassName, name, descriptor,
+ newName, policy)
+ } else {
+ log.v("Emitting method: %s%s %s", name, descriptor, policy)
+ newName = name
+ }
+
+ // Let subclass update the flag.
+ // But note, we only use it when calling the super's method,
+ // but not for visitMethodInner(), beucase when subclass wants to change access,
+ // it can do so inside visitMethodInner().
+ val newAccess = updateAccessFlags(access, name, descriptor)
+
+ return visitMethodInner(access, newName, descriptor, signature, exceptions, policy,
+ super.visitMethod(newAccess, newName, descriptor, signature, exceptions))
+ }
+ }
+
+ open fun updateAccessFlags(
+ access: Int,
+ name: String,
+ descriptor: String,
+ ): Int {
+ return access
+ }
+
+ abstract fun visitMethodInner(
+ access: Int,
+ name: String,
+ descriptor: String,
+ signature: String?,
+ exceptions: Array<String>?,
+ policy: FilterPolicyWithReason,
+ superVisitor: MethodVisitor?,
+ ): MethodVisitor?
+
+ companion object {
+ fun getVisitor(
+ classes: ClassNodes,
+ nextVisitor: ClassVisitor,
+ filter: OutputFilter,
+ forImpl: Boolean,
+ options: Options,
+ ): ClassVisitor {
+ var next = nextVisitor
+
+ val verbosePrinter = PrintWriter(log.getVerbosePrintStream())
+
+ // TODO: This doesn't work yet.
+
+ // Inject TraceClassVisitor for debugging.
+ if (options.enablePostTrace) {
+ next = TraceClassVisitor(next, verbosePrinter)
+ }
+ var ret: ClassVisitor
+ if (forImpl) {
+ ret = ImplGeneratingAdapter(classes, next, filter, options)
+ } else {
+ ret = StubGeneratingAdapter(classes, next, filter, options)
+ }
+
+ // Inject TraceClassVisitor for debugging.
+ if (options.enablePreTrace) {
+ ret = TraceClassVisitor(ret, verbosePrinter)
+ }
+ return ret
+ }
+ }
+} \ No newline at end of file
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/BodyReplacingMethodVisitor.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/BodyReplacingMethodVisitor.kt
new file mode 100644
index 000000000000..8250412b3717
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/BodyReplacingMethodVisitor.kt
@@ -0,0 +1,354 @@
+/*
+ * Copyright (C) 2023 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.hoststubgen.visitors
+
+import org.objectweb.asm.AnnotationVisitor
+import org.objectweb.asm.Attribute
+import org.objectweb.asm.Handle
+import org.objectweb.asm.Label
+import org.objectweb.asm.MethodVisitor
+import org.objectweb.asm.Opcodes
+import org.objectweb.asm.TypePath
+
+/**
+ * A method visitor that removes everything from method body.
+ *
+ * To inject a method body, override [visitCode] and create the opcodes there.
+ */
+abstract class BodyReplacingMethodVisitor(
+ access: Int,
+ name: String,
+ descriptor: String,
+ signature: String?,
+ exceptions: Array<String>?,
+ next: MethodVisitor?,
+) : MethodVisitor(OPCODE_VERSION, next) {
+ val isVoid: Boolean
+ val isStatic: Boolean
+
+ init {
+ isVoid = descriptor.endsWith(")V")
+ isStatic = access and Opcodes.ACC_STATIC != 0
+ }
+
+ // Following methods are for things that we need to keep.
+ // Since they're all calling the super method, we can just remove them, but we keep them
+ // just to clarify what we're keeping.
+
+ final override fun visitParameter(
+ name: String?,
+ access: Int
+ ) {
+ super.visitParameter(name, access)
+ }
+
+ final override fun visitAnnotationDefault(): AnnotationVisitor? {
+ return super.visitAnnotationDefault()
+ }
+
+ final override fun visitAnnotation(
+ descriptor: String?,
+ visible: Boolean
+ ): AnnotationVisitor? {
+ return super.visitAnnotation(descriptor, visible)
+ }
+
+ final override fun visitTypeAnnotation(
+ typeRef: Int,
+ typePath: TypePath?,
+ descriptor: String?,
+ visible: Boolean
+ ): AnnotationVisitor? {
+ return super.visitTypeAnnotation(typeRef, typePath, descriptor, visible)
+ }
+
+ final override fun visitAnnotableParameterCount(
+ parameterCount: Int,
+ visible: Boolean
+ ) {
+ super.visitAnnotableParameterCount(parameterCount, visible)
+ }
+
+ final override fun visitParameterAnnotation(
+ parameter: Int,
+ descriptor: String?,
+ visible: Boolean
+ ): AnnotationVisitor? {
+ return super.visitParameterAnnotation(parameter, descriptor, visible)
+ }
+
+ final override fun visitAttribute(attribute: Attribute?) {
+ super.visitAttribute(attribute)
+ }
+
+ override fun visitEnd() {
+ super.visitEnd()
+ }
+
+ /**
+ * Control when to emit the code. We use this to ignore all visitXxx method calls caused by
+ * the original method, so we'll remove all the original code.
+ *
+ * Only when visitXxx methods are called from [emitNewCode], we pass-through to the base class,
+ * so the body will be generated.
+ *
+ * (See also https://asm.ow2.io/asm4-guide.pdf section 3.2.1 about the MethovVisitor
+ * call order.)
+ */
+ var emitCode = false
+
+ final override fun visitCode() {
+ super.visitCode()
+
+ try {
+ emitCode = true
+
+ emitNewCode()
+ } finally {
+ emitCode = false
+ }
+ }
+
+ /**
+ * Subclass must implement it and emit code, and call [visitMaxs] at the end.
+ */
+ abstract fun emitNewCode()
+
+ final override fun visitMaxs(
+ maxStack: Int,
+ maxLocals: Int
+ ) {
+ if (emitCode) {
+ super.visitMaxs(maxStack, maxLocals)
+ }
+ }
+
+ // Following methods are called inside a method body, and we don't want to
+ // emit any of them, so they are all no-op.
+
+ final override fun visitFrame(
+ type: Int,
+ numLocal: Int,
+ local: Array<out Any>?,
+ numStack: Int,
+ stack: Array<out Any>?
+ ) {
+ if (emitCode) {
+ super.visitFrame(type, numLocal, local, numStack, stack)
+ }
+ }
+
+ final override fun visitInsn(opcode: Int) {
+ if (emitCode) {
+ super.visitInsn(opcode)
+ }
+ }
+
+ final override fun visitIntInsn(
+ opcode: Int,
+ operand: Int
+ ) {
+ if (emitCode) {
+ super.visitIntInsn(opcode, operand)
+ }
+ }
+
+ final override fun visitVarInsn(
+ opcode: Int,
+ varIndex: Int
+ ) {
+ if (emitCode) {
+ super.visitVarInsn(opcode, varIndex)
+ }
+ }
+
+ final override fun visitTypeInsn(
+ opcode: Int,
+ type: String?
+ ) {
+ if (emitCode) {
+ super.visitTypeInsn(opcode, type)
+ }
+ }
+
+ final override fun visitFieldInsn(
+ opcode: Int,
+ owner: String?,
+ name: String?,
+ descriptor: String?
+ ) {
+ if (emitCode) {
+ super.visitFieldInsn(opcode, owner, name, descriptor)
+ }
+ }
+
+ final override fun visitMethodInsn(
+ opcode: Int,
+ owner: String?,
+ name: String?,
+ descriptor: String?,
+ isInterface: Boolean
+ ) {
+ if (emitCode) {
+ super.visitMethodInsn(opcode, owner, name, descriptor, isInterface)
+ }
+ }
+
+ final override fun visitInvokeDynamicInsn(
+ name: String?,
+ descriptor: String?,
+ bootstrapMethodHandle: Handle?,
+ vararg bootstrapMethodArguments: Any?
+ ) {
+ if (emitCode) {
+ super.visitInvokeDynamicInsn(name, descriptor, bootstrapMethodHandle,
+ *bootstrapMethodArguments)
+ }
+ }
+
+ final override fun visitJumpInsn(
+ opcode: Int,
+ label: Label?
+ ) {
+ if (emitCode) {
+ super.visitJumpInsn(opcode, label)
+ }
+ }
+
+ final override fun visitLabel(label: Label?) {
+ if (emitCode) {
+ super.visitLabel(label)
+ }
+ }
+
+ final override fun visitLdcInsn(value: Any?) {
+ if (emitCode) {
+ super.visitLdcInsn(value)
+ }
+ }
+
+ final override fun visitIincInsn(
+ varIndex: Int,
+ increment: Int
+ ) {
+ if (emitCode) {
+ super.visitIincInsn(varIndex, increment)
+ }
+ }
+
+ final override fun visitTableSwitchInsn(
+ min: Int,
+ max: Int,
+ dflt: Label?,
+ vararg labels: Label?
+ ) {
+ if (emitCode) {
+ super.visitTableSwitchInsn(min, max, dflt, *labels)
+ }
+ }
+
+ final override fun visitLookupSwitchInsn(
+ dflt: Label?,
+ keys: IntArray?,
+ labels: Array<out Label>?
+ ) {
+ if (emitCode) {
+ super.visitLookupSwitchInsn(dflt, keys, labels)
+ }
+ }
+
+ final override fun visitMultiANewArrayInsn(
+ descriptor: String?,
+ numDimensions: Int
+ ) {
+ if (emitCode) {
+ super.visitMultiANewArrayInsn(descriptor, numDimensions)
+ }
+ }
+
+ final override fun visitInsnAnnotation(
+ typeRef: Int,
+ typePath: TypePath?,
+ descriptor: String?,
+ visible: Boolean
+ ): AnnotationVisitor? {
+ if (emitCode) {
+ return super.visitInsnAnnotation(typeRef, typePath, descriptor, visible)
+ }
+ return null
+ }
+
+ final override fun visitTryCatchBlock(
+ start: Label?,
+ end: Label?,
+ handler: Label?,
+ type: String?
+ ) {
+ if (emitCode) {
+ super.visitTryCatchBlock(start, end, handler, type)
+ }
+ }
+
+ final override fun visitTryCatchAnnotation(
+ typeRef: Int,
+ typePath: TypePath?,
+ descriptor: String?,
+ visible: Boolean
+ ): AnnotationVisitor? {
+ if (emitCode) {
+ return super.visitTryCatchAnnotation(typeRef, typePath, descriptor, visible)
+ }
+ return null
+ }
+
+ final override fun visitLocalVariable(
+ name: String?,
+ descriptor: String?,
+ signature: String?,
+ start: Label?,
+ end: Label?,
+ index: Int
+ ) {
+ if (emitCode) {
+ super.visitLocalVariable(name, descriptor, signature, start, end, index)
+ }
+ }
+
+ final override fun visitLocalVariableAnnotation(
+ typeRef: Int,
+ typePath: TypePath?,
+ start: Array<out Label>?,
+ end: Array<out Label>?,
+ index: IntArray?,
+ descriptor: String?,
+ visible: Boolean
+ ): AnnotationVisitor? {
+ if (emitCode) {
+ return super.visitLocalVariableAnnotation(
+ typeRef, typePath, start, end, index, descriptor, visible)
+ }
+ return null
+ }
+
+ final override fun visitLineNumber(
+ line: Int,
+ start: Label?
+ ) {
+ if (emitCode) {
+ super.visitLineNumber(line, start)
+ }
+ }
+}
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/ImplGeneratingAdapter.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/ImplGeneratingAdapter.kt
new file mode 100644
index 000000000000..ac068861ec8d
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/ImplGeneratingAdapter.kt
@@ -0,0 +1,370 @@
+/*
+ * Copyright (C) 2023 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.hoststubgen.visitors
+
+import com.android.hoststubgen.asm.CLASS_INITIALIZER_DESC
+import com.android.hoststubgen.asm.CLASS_INITIALIZER_NAME
+import com.android.hoststubgen.asm.ClassNodes
+import com.android.hoststubgen.asm.isVisibilityPrivateOrPackagePrivate
+import com.android.hoststubgen.asm.writeByteCodeToPushArguments
+import com.android.hoststubgen.asm.writeByteCodeToReturn
+import com.android.hoststubgen.filters.FilterPolicy
+import com.android.hoststubgen.filters.FilterPolicyWithReason
+import com.android.hoststubgen.filters.OutputFilter
+import com.android.hoststubgen.hosthelper.HostTestUtils
+import com.android.hoststubgen.log
+import org.objectweb.asm.ClassVisitor
+import org.objectweb.asm.MethodVisitor
+import org.objectweb.asm.Opcodes
+import org.objectweb.asm.Type
+
+/**
+ * An adapter that generates the "impl" class file from an input class file.
+ */
+class ImplGeneratingAdapter(
+ classes: ClassNodes,
+ nextVisitor: ClassVisitor,
+ filter: OutputFilter,
+ options: Options,
+) : BaseAdapter(classes, nextVisitor, filter, options) {
+
+ override fun shouldEmit(policy: FilterPolicy): Boolean {
+ return policy.needsInImpl
+ }
+
+ private var classLoadHookMethod: String? = null
+
+ override fun visit(
+ version: Int,
+ access: Int,
+ name: String,
+ signature: String?,
+ superName: String?,
+ interfaces: Array<String>
+ ) {
+ super.visit(version, access, name, signature, superName, interfaces)
+
+ classLoadHookMethod = filter.getClassLoadHook(currentClassName)
+
+ // classLoadHookMethod is non-null, then we need to inject code to call it
+ // in the class initializer.
+ // If the target class already has a class initializer, then we need to inject code to it.
+ // Otherwise, we need to create one.
+
+ classLoadHookMethod?.let { callback ->
+ log.d(" ClassLoadHook: $callback")
+ if (!classes.hasClassInitializer(currentClassName)) {
+ injectClassLoadHook(callback)
+ }
+ }
+ }
+
+ private fun injectClassLoadHook(callback: String) {
+ writeRawMembers {
+ // Create a class initializer to call onClassLoaded().
+ // Each class can only have at most one class initializer, but the base class
+ // StaticInitMerger will merge it with the existing one, if any.
+ visitMethod(
+ Opcodes.ACC_PRIVATE or Opcodes.ACC_STATIC,
+ "<clinit>",
+ "()V",
+ null,
+ null
+ )!!.let { mv ->
+ // Method prologue
+ mv.visitCode()
+
+ writeClassLoadHookCall(mv)
+ mv.visitInsn(Opcodes.RETURN)
+
+ // Method epilogue
+ mv.visitMaxs(0, 0)
+ mv.visitEnd()
+ }
+ }
+ }
+
+ private fun writeClassLoadHookCall(mv: MethodVisitor) {
+ // First argument: the class type.
+ mv.visitLdcInsn(Type.getType("L" + currentClassName + ";"))
+
+ // Second argument: method name
+ mv.visitLdcInsn(classLoadHookMethod)
+
+ // Call HostTestUtils.onClassLoaded().
+ mv.visitMethodInsn(
+ Opcodes.INVOKESTATIC,
+ HostTestUtils.CLASS_INTERNAL_NAME,
+ "onClassLoaded",
+ "(Ljava/lang/Class;Ljava/lang/String;)V",
+ false
+ )
+ }
+
+ override fun updateAccessFlags(
+ access: Int,
+ name: String,
+ descriptor: String,
+ ): Int {
+ if ((access and Opcodes.ACC_NATIVE) != 0 && nativeSubstitutionClass != null) {
+ return access and Opcodes.ACC_NATIVE.inv()
+ }
+ return access
+ }
+
+ override fun visitMethodInner(
+ access: Int,
+ name: String,
+ descriptor: String,
+ signature: String?,
+ exceptions: Array<String>?,
+ policy: FilterPolicyWithReason,
+ superVisitor: MethodVisitor?,
+ ): MethodVisitor? {
+ // Inject method log, if needed.
+ var innerVisitor = superVisitor
+
+ // If method logging is enabled, inject call to the logging method.
+ if (options.enableMethodLogging) {
+ innerVisitor = LogInjectingMethodAdapter(
+ access,
+ name,
+ descriptor,
+ signature,
+ exceptions,
+ innerVisitor,
+ )
+ }
+
+ // If this class already has a class initializer and a class load hook is needed, then
+ // we inject code.
+ if (classLoadHookMethod != null &&
+ name == CLASS_INITIALIZER_NAME &&
+ descriptor == CLASS_INITIALIZER_DESC) {
+ innerVisitor = ClassLoadHookInjectingMethodAdapter(
+ access,
+ name,
+ descriptor,
+ signature,
+ exceptions,
+ innerVisitor,
+ )
+ }
+
+ // If non-stub method call detection is enabled, then inject a call to the checker.
+ if (options.enableNonStubMethodCallDetection && doesMethodNeedNonStubCallCheck(
+ access, name, descriptor, policy) ) {
+ innerVisitor = NonStubMethodCallDetectingAdapter(
+ access,
+ name,
+ descriptor,
+ signature,
+ exceptions,
+ innerVisitor,
+ )
+ }
+
+ log.withIndent {
+ if ((access and Opcodes.ACC_NATIVE) != 0 && nativeSubstitutionClass != null) {
+ log.v("Rewriting native method...")
+ return NativeSubstitutingMethodAdapter(
+ access, name, descriptor, signature, exceptions, innerVisitor)
+ }
+ if (policy.policy == FilterPolicy.Throw) {
+ log.v("Making method throw...")
+ return ThrowingMethodAdapter(
+ access, name, descriptor, signature, exceptions, innerVisitor)
+ }
+ }
+
+ return innerVisitor
+ }
+
+ fun doesMethodNeedNonStubCallCheck(
+ access: Int,
+ name: String,
+ descriptor: String,
+ policy: FilterPolicyWithReason,
+ ): Boolean {
+ // If a method is in the stub, then no need to check.
+ if (policy.policy.needsInStub) {
+ return false
+ }
+ // If a method is private or package-private, no need to check.
+ // Technically test code can use framework package name, so it's a bit too lenient.
+ if (isVisibilityPrivateOrPackagePrivate(access)) {
+ return false
+ }
+ // TODO: If the method overrides a method that's accessible by tests, then we shouldn't
+ // do the check. (e.g. overrides a stub method or java standard method.)
+
+ return true
+ }
+
+ /**
+ * A method adapter that replaces the method body with a HostTestUtils.onThrowMethodCalled()
+ * call.
+ */
+ private inner class ThrowingMethodAdapter(
+ access: Int,
+ val name: String,
+ descriptor: String,
+ signature: String?,
+ exceptions: Array<String>?,
+ next: MethodVisitor?
+ ) : BodyReplacingMethodVisitor(access, name, descriptor, signature, exceptions, next) {
+ override fun emitNewCode() {
+ visitMethodInsn(Opcodes.INVOKESTATIC,
+ HostTestUtils.CLASS_INTERNAL_NAME,
+ "onThrowMethodCalled",
+ "()V",
+ false)
+
+ // We still need a RETURN opcode for the return type.
+ // For now, let's just inject a `throw`.
+ visitTypeInsn(Opcodes.NEW, "java/lang/RuntimeException")
+ visitInsn(Opcodes.DUP)
+ visitLdcInsn("Unreachable")
+ visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/RuntimeException",
+ "<init>", "(Ljava/lang/String;)V", false)
+ visitInsn(Opcodes.ATHROW)
+
+ // visitMaxs(3, if (isStatic) 0 else 1)
+ visitMaxs(0, 0) // We let ASM figure them out.
+ }
+ }
+
+ /**
+ * A method adapter that replaces a native method call with a call to the "native substitution"
+ * class.
+ */
+ private inner class NativeSubstitutingMethodAdapter(
+ access: Int,
+ private val name: String,
+ private val descriptor: String,
+ signature: String?,
+ exceptions: Array<String>?,
+ next: MethodVisitor?
+ ) : MethodVisitor(OPCODE_VERSION, next) {
+ override fun visitCode() {
+ super.visitCode()
+
+ throw RuntimeException("NativeSubstitutingMethodVisitor should be called on " +
+ " native method, where visitCode() shouldn't be called.")
+ }
+
+ override fun visitEnd() {
+ writeByteCodeToPushArguments(descriptor, this)
+
+ visitMethodInsn(Opcodes.INVOKESTATIC,
+ nativeSubstitutionClass,
+ name,
+ descriptor,
+ false)
+
+ writeByteCodeToReturn(descriptor, this)
+
+ visitMaxs(99, 0) // We let ASM figure them out.
+ super.visitEnd()
+ }
+ }
+
+ /**
+ * A method adapter that injects a call to HostTestUtils.logMethodCall() to every method.
+ *
+ * Note, when the target method is a constructor, it may contain calls to `super(...)` or
+ * `this(...)`. The logging code will be injected *before* such calls.
+ */
+ private inner class LogInjectingMethodAdapter(
+ access: Int,
+ val name: String,
+ val descriptor: String,
+ signature: String?,
+ exceptions: Array<String>?,
+ next: MethodVisitor?
+ ) : MethodVisitor(OPCODE_VERSION, next) {
+ override fun visitCode() {
+ super.visitCode()
+ visitLdcInsn(currentClassName)
+ visitLdcInsn(name)
+ visitLdcInsn(descriptor)
+ visitMethodInsn(Opcodes.INVOKESTATIC,
+ HostTestUtils.CLASS_INTERNAL_NAME,
+ "logMethodCall",
+ "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V",
+ false)
+ }
+ }
+
+ /**
+ * Inject a class load hook call.
+ */
+ private inner class ClassLoadHookInjectingMethodAdapter(
+ access: Int,
+ val name: String,
+ val descriptor: String,
+ signature: String?,
+ exceptions: Array<String>?,
+ next: MethodVisitor?
+ ) : MethodVisitor(OPCODE_VERSION, next) {
+ override fun visitCode() {
+ super.visitCode()
+
+ writeClassLoadHookCall(this)
+ }
+ }
+
+ /**
+ * A method adapter that detects calls to non-stub methods.
+ */
+ private inner class NonStubMethodCallDetectingAdapter(
+ access: Int,
+ val name: String,
+ val descriptor: String,
+ signature: String?,
+ exceptions: Array<String>?,
+ next: MethodVisitor?
+ ) : MethodVisitor(OPCODE_VERSION, next) {
+ override fun visitCode() {
+ super.visitCode()
+
+ // First three arguments to HostTestUtils.onNonStubMethodCalled().
+ visitLdcInsn(currentClassName)
+ visitLdcInsn(name)
+ visitLdcInsn(descriptor)
+
+ // Call: HostTestUtils.getStackWalker().getCallerClass().
+ // This push the caller Class in the stack.
+ visitMethodInsn(Opcodes.INVOKESTATIC,
+ HostTestUtils.CLASS_INTERNAL_NAME,
+ "getStackWalker",
+ "()Ljava/lang/StackWalker;",
+ false)
+ visitMethodInsn(Opcodes.INVOKEVIRTUAL,
+ "java/lang/StackWalker",
+ "getCallerClass",
+ "()Ljava/lang/Class;",
+ false)
+
+ // Then call onNonStubMethodCalled().
+ visitMethodInsn(Opcodes.INVOKESTATIC,
+ HostTestUtils.CLASS_INTERNAL_NAME,
+ "onNonStubMethodCalled",
+ "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V",
+ false)
+ }
+ }
+} \ No newline at end of file
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/StubGeneratingAdapter.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/StubGeneratingAdapter.kt
new file mode 100644
index 000000000000..37e2a888969d
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/StubGeneratingAdapter.kt
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2023 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.hoststubgen.visitors
+
+import com.android.hoststubgen.asm.ClassNodes
+import com.android.hoststubgen.filters.FilterPolicy
+import com.android.hoststubgen.filters.FilterPolicyWithReason
+import com.android.hoststubgen.filters.OutputFilter
+import com.android.hoststubgen.log
+import org.objectweb.asm.ClassVisitor
+import org.objectweb.asm.MethodVisitor
+import org.objectweb.asm.Opcodes
+
+/**
+ * An adapter that generates the "impl" class file from an input class file.
+ */
+class StubGeneratingAdapter(
+ classes: ClassNodes,
+ nextVisitor: ClassVisitor,
+ filter: OutputFilter,
+ options: Options,
+) : BaseAdapter(classes, nextVisitor, filter, options) {
+
+ override fun shouldEmit(policy: FilterPolicy): Boolean {
+ return policy.needsInStub
+ }
+
+ override fun visitMethodInner(
+ access: Int,
+ name: String,
+ descriptor: String,
+ signature: String?,
+ exceptions: Array<String>?,
+ policy: FilterPolicyWithReason,
+ superVisitor: MethodVisitor?,
+ ): MethodVisitor? {
+ return StubMethodVisitor(access, name, descriptor, signature, exceptions, superVisitor)
+ }
+
+ private inner class StubMethodVisitor(
+ access: Int,
+ val name: String,
+ descriptor: String,
+ signature: String?,
+ exceptions: Array<String>?,
+ next: MethodVisitor?
+ ) : BodyReplacingMethodVisitor(access, name, descriptor, signature, exceptions, next) {
+ override fun emitNewCode() {
+ log.d(" Generating stub method for $currentClassName.$name")
+
+ // Inject the following code:
+ // throw new RuntimeException("Stub!");
+
+ /*
+ NEW java/lang/RuntimeException
+ DUP
+ LDC "not supported on host side"
+ INVOKESPECIAL java/lang/RuntimeException.<init> (Ljava/lang/String;)V
+ ATHROW
+ MAXSTACK = 3
+ MAXLOCALS = 2 <- 1 for this, 1 for return value.
+ */
+ visitTypeInsn(Opcodes.NEW, "java/lang/RuntimeException")
+ visitInsn(Opcodes.DUP)
+ visitLdcInsn("Stub!")
+ visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/RuntimeException",
+ "<init>", "(Ljava/lang/String;)V", false)
+ visitInsn(Opcodes.ATHROW)
+ visitMaxs(0, 0) // We let ASM figure them out.
+ }
+ }
+}
diff --git a/tools/hoststubgen/hoststubgen/test-framework/Android.bp b/tools/hoststubgen/hoststubgen/test-framework/Android.bp
new file mode 100644
index 000000000000..2b91cc161b7f
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/test-framework/Android.bp
@@ -0,0 +1,19 @@
+// Copyright (C) 2023 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+build = ["AndroidHostTest.bp"]
diff --git a/tools/hoststubgen/hoststubgen/test-framework/AndroidHostTest.bp b/tools/hoststubgen/hoststubgen/test-framework/AndroidHostTest.bp
new file mode 100644
index 000000000000..e7fb2debfc4e
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/test-framework/AndroidHostTest.bp
@@ -0,0 +1,44 @@
+// Copyright (C) 2023 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.
+
+// Add `build = ["AndroidHostTest.bp"]` to Android.bp to include this file.
+
+// Compile the test jar, using 2 rules.
+// 1. Build the test against the stub.
+java_library_host {
+ name: "HostStubGenTest-framework-test-host-test-lib",
+ defaults: ["hosttest-with-framework-all-hidden-api-test-lib-defaults"],
+ srcs: [
+ "src/**/*.java",
+ ],
+ static_libs: [
+ "junit",
+ "truth-prebuilt",
+ "mockito",
+
+ // http://cs/h/googleplex-android/platform/superproject/main/+/main:platform_testing/libraries/annotations/src/android/platform/test/annotations/
+ "platform-test-annotations",
+ "hoststubgen-annotations",
+ ],
+}
+
+// 2. Link the above module with necessary runtime dependencies, so it can be executed stand-alone.
+java_test_host {
+ name: "HostStubGenTest-framework-all-test-host-test",
+ defaults: ["hosttest-with-framework-all-hidden-api-test-defaults"],
+ static_libs: [
+ "HostStubGenTest-framework-test-host-test-lib",
+ ],
+ test_suites: ["general-tests"],
+}
diff --git a/tools/hoststubgen/hoststubgen/test-framework/AndroidTest-host.xml b/tools/hoststubgen/hoststubgen/test-framework/AndroidTest-host.xml
new file mode 100644
index 000000000000..f35dcf69ecc9
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/test-framework/AndroidTest-host.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2023 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.
+-->
+
+<!-- [Ravenwood] Copied from $ANDROID_BUILD_TOP/cts/hostsidetests/devicepolicy/AndroidTest.xml -->
+<configuration description="CtsContentTestCases host-side test">
+ <option name="test-suite-tag" value="ravenwood" />
+ <option name="config-descriptor:metadata" key="component" value="framework" />
+ <option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
+ <option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
+ <option name="config-descriptor:metadata" key="parameter" value="not_secondary_user" />
+ <option name="config-descriptor:metadata" key="parameter" value="no_foldable_states" />
+
+ <test class="com.android.tradefed.testtype.IsolatedHostTest" >
+ <option name="jar" value="HostStubGenTest-framework-all-test-host-test.jar" />
+ </test>
+</configuration>
diff --git a/tools/hoststubgen/hoststubgen/test-framework/README.md b/tools/hoststubgen/hoststubgen/test-framework/README.md
new file mode 100644
index 000000000000..20e2f873b152
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/test-framework/README.md
@@ -0,0 +1,27 @@
+# HostStubGen: real framework test
+
+This directory contains tests against the actual framework.jar code. The tests were
+copied from somewhere else in the android tree. We use this directory to quickly run existing
+tests.
+
+## How to run
+
+- With `atest`. This is the proper way to run it, but it may fail due to atest's known problems.
+
+ See the top level README.md on why `--no-bazel-mode` is needed (for now).
+
+```
+$ atest --no-bazel-mode HostStubGenTest-framework-test-host-test
+```
+
+- With `run-ravenwood-test`
+
+```
+$ run-ravenwood-test HostStubGenTest-framework-test-host-test
+```
+
+- Advanced option: `run-test-without-atest.sh` runs the test without using `atest` or `run-ravenwood-test`
+
+```
+$ ./run-test-without-atest.sh
+``` \ No newline at end of file
diff --git a/tools/hoststubgen/hoststubgen/test-framework/run-test-without-atest.sh b/tools/hoststubgen/hoststubgen/test-framework/run-test-without-atest.sh
new file mode 100755
index 000000000000..cfc06a12e881
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/test-framework/run-test-without-atest.sh
@@ -0,0 +1,85 @@
+#!/bin/bash
+# Copyright (C) 2023 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.
+
+# Run HostStubGenTest-framework-test-host-test directly with JUnit.
+# (without using atest.)
+
+source "${0%/*}"/../../common.sh
+
+
+# Options:
+# -v enable verbose log
+# -d enable debugger
+
+verbose=0
+debug=0
+while getopts "vd" opt; do
+ case "$opt" in
+ v) verbose=1 ;;
+ d) debug=1 ;;
+ esac
+done
+shift $(($OPTIND - 1))
+
+
+if (( $verbose )) ; then
+ JAVA_OPTS="$JAVA_OPTS -verbose:class"
+fi
+
+if (( $debug )) ; then
+ JAVA_OPTS="$JAVA_OPTS -agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=8700"
+fi
+
+#=======================================
+module=HostStubGenTest-framework-all-test-host-test
+module_jar=$ANDROID_BUILD_TOP/out/host/linux-x86/testcases/$module/$module.jar
+run m $module
+
+out=out
+
+rm -fr $out
+mkdir -p $out
+
+
+# Copy and extract the relevant jar files so we can look into them.
+run cp \
+ $module_jar \
+ $SOONG_INT/frameworks/base/tools/hoststubgen/hoststubgen/framework-all-hidden-api-host/linux_glibc_common/gen/*.jar \
+ $out
+
+run extract $out/*.jar
+
+# Result is the number of failed tests.
+result=0
+
+
+# This suite runs all tests in the JAR.
+tests=(com.android.hoststubgen.hosthelper.HostTestSuite)
+
+# Uncomment this to run a specific test.
+# tests=(com.android.hoststubgen.frameworktest.LogTest)
+
+
+for class in ${tests[@]} ; do
+ echo "Running $class ..."
+
+ run cd "${module_jar%/*}"
+ run $JAVA $JAVA_OPTS \
+ -cp $module_jar \
+ org.junit.runner.JUnitCore \
+ $class || result=$(( $result + 1 ))
+done
+
+exit $result
diff --git a/tools/hoststubgen/hoststubgen/test-framework/src/com/android/hoststubgen/frameworktest/ArrayMapTest.java b/tools/hoststubgen/hoststubgen/test-framework/src/com/android/hoststubgen/frameworktest/ArrayMapTest.java
new file mode 100644
index 000000000000..62bbf48955da
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/test-framework/src/com/android/hoststubgen/frameworktest/ArrayMapTest.java
@@ -0,0 +1,737 @@
+/*
+ * Copyright (C) 2023 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.hoststubgen.frameworktest;
+
+// [ravewnwood] Copied from cts/, and commented out unsupported stuff.
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.ArrayMap;
+import android.util.Log;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.AbstractMap;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.NoSuchElementException;
+import java.util.Set;
+import java.util.function.BiFunction;
+
+/**
+ * Some basic tests for {@link android.util.ArrayMap}.
+ */
+@RunWith(AndroidJUnit4.class)
+public class ArrayMapTest {
+ static final boolean DEBUG = false;
+
+ static final int OP_ADD = 1;
+ static final int OP_REM = 2;
+
+ static int[] OPS = new int[]{
+ OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD,
+ OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD,
+ OP_REM, OP_REM, OP_REM, OP_REM, OP_REM, OP_REM, OP_REM, OP_REM, OP_REM,
+ OP_REM, OP_REM, OP_REM, OP_REM, OP_REM, OP_REM, OP_REM, OP_REM, OP_REM,
+
+ OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD,
+ OP_REM, OP_REM, OP_REM, OP_REM, OP_REM, OP_REM, OP_REM, OP_REM, OP_REM,
+
+ OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD,
+ OP_REM, OP_REM, OP_REM, OP_REM, OP_REM, OP_REM, OP_REM, OP_REM, OP_REM,
+
+ OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD,
+ OP_REM, OP_REM, OP_REM, OP_REM, OP_REM, OP_REM, OP_REM, OP_REM, OP_REM,
+
+ OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD,
+ OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD,
+ OP_ADD, OP_ADD, OP_ADD,
+ OP_REM, OP_REM, OP_REM, OP_REM, OP_REM, OP_REM, OP_REM, OP_REM, OP_REM,
+ OP_REM, OP_REM, OP_REM,
+ OP_REM, OP_REM, OP_REM, OP_REM, OP_REM, OP_REM, OP_REM, OP_REM, OP_REM,
+ };
+
+ static int[] KEYS = new int[]{
+ // General adding and removing.
+ -1, 1900, 600, 200, 1200, 1500, 1800, 100, 1900,
+ 2100, 300, 800, 600, 1100, 1300, 2000, 1000, 1400,
+ 600, -1, 1900, 600, 300, 2100, 200, 800, 800,
+ 1800, 1500, 1300, 1100, 2000, 1400, 1000, 1200, 1900,
+
+ // Shrink when removing item from end.
+ 100, 200, 300, 400, 500, 600, 700, 800, 900,
+ 900, 800, 700, 600, 500, 400, 300, 200, 100,
+
+ // Shrink when removing item from middle.
+ 100, 200, 300, 400, 500, 600, 700, 800, 900,
+ 900, 800, 700, 600, 500, 400, 200, 300, 100,
+
+ // Shrink when removing item from front.
+ 100, 200, 300, 400, 500, 600, 700, 800, 900,
+ 900, 800, 700, 600, 500, 400, 100, 200, 300,
+
+ // Test hash collisions.
+ 105, 106, 108, 104, 102, 102, 107, 5, 205,
+ 4, 202, 203, 3, 5, 101, 109, 200, 201,
+ 0, -1, 100,
+ 106, 108, 104, 102, 103, 105, 107, 101, 109,
+ -1, 100, 0,
+ 4, 5, 3, 5, 200, 203, 202, 201, 205,
+ };
+
+ public static class ControlledHash implements Parcelable {
+ final int mValue;
+
+ ControlledHash(int value) {
+ mValue = value;
+ }
+
+ @Override
+ public final boolean equals(Object o) {
+ if (o == null) {
+ return false;
+ }
+ return mValue == ((ControlledHash)o).mValue;
+ }
+
+ @Override
+ public final int hashCode() {
+ return mValue/100;
+ }
+
+ @Override
+ public final String toString() {
+ return Integer.toString(mValue);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeInt(mValue);
+ }
+
+ public static final Parcelable.Creator<ControlledHash> CREATOR
+ = new Parcelable.Creator<ControlledHash>() {
+ public ControlledHash createFromParcel(Parcel in) {
+ return new ControlledHash(in.readInt());
+ }
+
+ public ControlledHash[] newArray(int size) {
+ return new ControlledHash[size];
+ }
+ };
+ }
+
+ private static boolean compare(Object v1, Object v2) {
+ if (v1 == null) {
+ return v2 == null;
+ }
+ if (v2 == null) {
+ return false;
+ }
+ return v1.equals(v2);
+ }
+
+ private static void compareMaps(HashMap map, ArrayMap array) {
+ if (map.size() != array.size()) {
+ fail("Bad size: expected " + map.size() + ", got " + array.size());
+ }
+
+ Set<Entry> mapSet = map.entrySet();
+ for (Map.Entry entry : mapSet) {
+ Object expValue = entry.getValue();
+ Object gotValue = array.get(entry.getKey());
+ if (!compare(expValue, gotValue)) {
+ fail("Bad value: expected " + expValue + ", got " + gotValue
+ + " at key " + entry.getKey());
+ }
+ }
+
+ for (int i = 0; i < array.size(); i++) {
+ Object gotValue = array.valueAt(i);
+ Object key = array.keyAt(i);
+ Object expValue = map.get(key);
+ if (!compare(expValue, gotValue)) {
+ fail("Bad value: expected " + expValue + ", got " + gotValue
+ + " at key " + key);
+ }
+ }
+
+ if (map.entrySet().hashCode() != array.entrySet().hashCode()) {
+ fail("Entry set hash codes differ: map=0x"
+ + Integer.toHexString(map.entrySet().hashCode()) + " array=0x"
+ + Integer.toHexString(array.entrySet().hashCode()));
+ }
+
+ if (!map.entrySet().equals(array.entrySet())) {
+ fail("Failed calling equals on map entry set against array set");
+ }
+
+ if (!array.entrySet().equals(map.entrySet())) {
+ fail("Failed calling equals on array entry set against map set");
+ }
+
+ if (map.keySet().hashCode() != array.keySet().hashCode()) {
+ fail("Key set hash codes differ: map=0x"
+ + Integer.toHexString(map.keySet().hashCode()) + " array=0x"
+ + Integer.toHexString(array.keySet().hashCode()));
+ }
+
+ if (!map.keySet().equals(array.keySet())) {
+ fail("Failed calling equals on map key set against array set");
+ }
+
+ if (!array.keySet().equals(map.keySet())) {
+ fail("Failed calling equals on array key set against map set");
+ }
+
+ if (!map.keySet().containsAll(array.keySet())) {
+ fail("Failed map key set contains all of array key set");
+ }
+
+ if (!array.keySet().containsAll(map.keySet())) {
+ fail("Failed array key set contains all of map key set");
+ }
+
+ if (!array.containsAll(map.keySet())) {
+ fail("Failed array contains all of map key set");
+ }
+
+ if (!map.entrySet().containsAll(array.entrySet())) {
+ fail("Failed map entry set contains all of array entry set");
+ }
+
+ if (!array.entrySet().containsAll(map.entrySet())) {
+ fail("Failed array entry set contains all of map entry set");
+ }
+ }
+
+ private static void validateArrayMap(ArrayMap array) {
+ Set<Map.Entry> entrySet = array.entrySet();
+ int index = 0;
+ Iterator<Entry> entryIt = entrySet.iterator();
+ while (entryIt.hasNext()) {
+ Map.Entry entry = entryIt.next();
+ Object value = entry.getKey();
+ Object realValue = array.keyAt(index);
+ if (!compare(realValue, value)) {
+ fail("Bad array map entry set: expected key " + realValue
+ + ", got " + value + " at index " + index);
+ }
+ value = entry.getValue();
+ realValue = array.valueAt(index);
+ if (!compare(realValue, value)) {
+ fail("Bad array map entry set: expected value " + realValue
+ + ", got " + value + " at index " + index);
+ }
+ index++;
+ }
+
+ index = 0;
+ Set keySet = array.keySet();
+ Iterator keyIt = keySet.iterator();
+ while (keyIt.hasNext()) {
+ Object value = keyIt.next();
+ Object realValue = array.keyAt(index);
+ if (!compare(realValue, value)) {
+ fail("Bad array map key set: expected key " + realValue
+ + ", got " + value + " at index " + index);
+ }
+ index++;
+ }
+
+ index = 0;
+ Collection valueCol = array.values();
+ Iterator valueIt = valueCol.iterator();
+ while (valueIt.hasNext()) {
+ Object value = valueIt.next();
+ Object realValue = array.valueAt(index);
+ if (!compare(realValue, value)) {
+ fail("Bad array map value col: expected value " + realValue
+ + ", got " + value + " at index " + index);
+ }
+ index++;
+ }
+ }
+
+ private static void compareBundles(Bundle bundle1, Bundle bundle2) {
+ Set<String> keySet1 = bundle1.keySet();
+ Iterator<String> iterator1 = keySet1.iterator();
+ while (iterator1.hasNext()) {
+ String key = iterator1.next();
+ int value1 = bundle1.getInt(key);
+ if (bundle2.get(key) == null) {
+ fail("Bad Bundle: bundle2 didn't have expected key " + key);
+ }
+ int value2 = bundle2.getInt(key);
+ if (value1 != value2) {
+ fail("Bad Bundle: at key key " + key + " expected " + value1 + ", got " + value2);
+ }
+ }
+ Set<String> keySet2 = bundle2.keySet();
+ Iterator<String> iterator2 = keySet2.iterator();
+ while (iterator2.hasNext()) {
+ String key = iterator2.next();
+ if (bundle1.get(key) == null) {
+ fail("Bad Bundle: bundle1 didn't have expected key " + key);
+ }
+ int value1 = bundle1.getInt(key);
+ int value2 = bundle2.getInt(key);
+ if (value1 != value2) {
+ fail("Bad Bundle: at key key " + key + " expected " + value1 + ", got " + value2);
+ }
+ }
+ }
+
+ private static void dump(Map map, ArrayMap array) {
+ Log.e("test", "HashMap of " + map.size() + " entries:");
+ Set<Map.Entry> mapSet = map.entrySet();
+ for (Map.Entry entry : mapSet) {
+ Log.e("test", " " + entry.getKey() + " -> " + entry.getValue());
+ }
+ Log.e("test", "ArrayMap of " + array.size() + " entries:");
+ for (int i = 0; i < array.size(); i++) {
+ Log.e("test", " " + array.keyAt(i) + " -> " + array.valueAt(i));
+ }
+ }
+
+ private static void dump(ArrayMap map1, ArrayMap map2) {
+ Log.e("test", "ArrayMap of " + map1.size() + " entries:");
+ for (int i = 0; i < map1.size(); i++) {
+ Log.e("test", " " + map1.keyAt(i) + " -> " + map1.valueAt(i));
+ }
+ Log.e("test", "ArrayMap of " + map2.size() + " entries:");
+ for (int i = 0; i < map2.size(); i++) {
+ Log.e("test", " " + map2.keyAt(i) + " -> " + map2.valueAt(i));
+ }
+ }
+
+ private static void dump(Bundle bundle1, Bundle bundle2) {
+ Log.e("test", "First Bundle of " + bundle1.size() + " entries:");
+ Set<String> keys1 = bundle1.keySet();
+ for (String key : keys1) {
+ Log.e("test", " " + key + " -> " + bundle1.get(key));
+ }
+ Log.e("test", "Second Bundle of " + bundle2.size() + " entries:");
+ Set<String> keys2 = bundle2.keySet();
+ for (String key : keys2) {
+ Log.e("test", " " + key + " -> " + bundle2.get(key));
+ }
+ }
+
+ @Test
+ public void testBasicArrayMap() {
+ HashMap<ControlledHash, Integer> hashMap = new HashMap<>();
+ ArrayMap<ControlledHash, Integer> arrayMap = new ArrayMap<>();
+ Bundle bundle = new Bundle();
+
+ for (int i = 0; i < OPS.length; i++) {
+ Integer oldHash;
+ Integer oldArray;
+ ControlledHash key = KEYS[i] < 0 ? null : new ControlledHash(KEYS[i]);
+ String strKey = KEYS[i] < 0 ? null : Integer.toString(KEYS[i]);
+ switch (OPS[i]) {
+ case OP_ADD:
+ if (DEBUG) Log.i("test", "Adding key: " + key);
+ oldHash = hashMap.put(key, i);
+ oldArray = arrayMap.put(key, i);
+ bundle.putInt(strKey, i);
+ break;
+ case OP_REM:
+ if (DEBUG) Log.i("test", "Removing key: " + key);
+ oldHash = hashMap.remove(key);
+ oldArray = arrayMap.remove(key);
+ bundle.remove(strKey);
+ break;
+ default:
+ fail("Bad operation " + OPS[i] + " @ " + i);
+ return;
+ }
+ if (!compare(oldHash, oldArray)) {
+ String msg = "Bad result: expected " + oldHash + ", got " + oldArray;
+ Log.e("test", msg);
+ dump(hashMap, arrayMap);
+ fail(msg);
+ }
+ try {
+ validateArrayMap(arrayMap);
+ } catch (Throwable e) {
+ Log.e("test", e.getMessage());
+ dump(hashMap, arrayMap);
+ throw e;
+ }
+ try {
+ compareMaps(hashMap, arrayMap);
+ } catch (Throwable e) {
+ Log.e("test", e.getMessage());
+ dump(hashMap, arrayMap);
+ throw e;
+ }
+ Parcel parcel = Parcel.obtain();
+ bundle.writeToParcel(parcel, 0);
+ parcel.setDataPosition(0);
+ Bundle bundle2 = parcel.readBundle();
+ try {
+ compareBundles(bundle, bundle2);
+ } catch (Throwable e) {
+ Log.e("test", e.getMessage());
+ dump(bundle, bundle2);
+ throw e;
+ }
+ }
+
+ arrayMap.put(new ControlledHash(50000), 100);
+ ControlledHash lookup = new ControlledHash(50000);
+ Iterator<ControlledHash> it = arrayMap.keySet().iterator();
+ while (it.hasNext()) {
+ if (it.next().equals(lookup)) {
+ it.remove();
+ }
+ }
+ if (arrayMap.containsKey(lookup)) {
+ String msg = "Bad map iterator: didn't remove test key";
+ Log.e("test", msg);
+ dump(hashMap, arrayMap);
+ fail(msg);
+ }
+ }
+
+ @Test
+ public void testCopyArrayMap() {
+ // map copy constructor test
+ ArrayMap newMap = new ArrayMap<Integer, String>();
+ for (int i = 0; i < 10; ++i) {
+ newMap.put(i, String.valueOf(i));
+ }
+ ArrayMap mapCopy = new ArrayMap(newMap);
+ if (!compare(mapCopy, newMap)) {
+ String msg = "ArrayMap copy constructor failure: expected " +
+ newMap + ", got " + mapCopy;
+ Log.e("test", msg);
+ dump(newMap, mapCopy);
+ fail(msg);
+ return;
+ }
+ }
+
+ @Test
+ public void testEqualsArrayMap() {
+ ArrayMap<Integer, String> map1 = new ArrayMap<>();
+ ArrayMap<Integer, String> map2 = new ArrayMap<>();
+ HashMap<Integer, String> map3 = new HashMap<>();
+ if (!compare(map1, map2) || !compare(map1, map3) || !compare(map3, map2)) {
+ fail("ArrayMap equals failure for empty maps " + map1 + ", " +
+ map2 + ", " + map3);
+ }
+
+ for (int i = 0; i < 10; ++i) {
+ String value = String.valueOf(i);
+ map1.put(i, value);
+ map2.put(i, value);
+ map3.put(i, value);
+ }
+ if (!compare(map1, map2) || !compare(map1, map3) || !compare(map3, map2)) {
+ fail("ArrayMap equals failure for populated maps " + map1 + ", " +
+ map2 + ", " + map3);
+ }
+
+ map1.remove(0);
+ if (compare(map1, map2) || compare(map1, map3) || compare(map3, map1)) {
+ fail("ArrayMap equals failure for map size " + map1 + ", " +
+ map2 + ", " + map3);
+ }
+
+ map1.put(0, "-1");
+ if (compare(map1, map2) || compare(map1, map3) || compare(map3, map1)) {
+ fail("ArrayMap equals failure for map contents " + map1 + ", " +
+ map2 + ", " + map3);
+ }
+ }
+
+// /**
+// * Test creating a malformed array map with duplicated keys and that we will catch this when
+// * unparcelling.
+// */
+// @Test
+// public void testDuplicateKeys() throws NoSuchMethodException,
+// InvocationTargetException, IllegalAccessException, NoSuchFieldException {
+// ArrayMap<String, Object> map1 = new ArrayMap(2);
+//
+// Method appendMethod = ArrayMap.class.getMethod("append", Object.class, Object.class);
+// appendMethod.invoke(map1, Integer.toString(100000), "foo");
+// appendMethod.invoke(map1, Integer.toString(100000), "bar");
+//
+// // Now parcel/unparcel, and verify we get the expected error.
+// Parcel parcel = Parcel.obtain();
+// Method writeArrayMapMethod = Parcel.class.getMethod("writeArrayMap", ArrayMap.class);
+// writeArrayMapMethod.invoke(parcel, map1);
+// parcel.setDataPosition(0);
+// ArrayMap<String, Object> map2 = new ArrayMap(2);
+//
+// try {
+// Parcel.class.getMethod("readArrayMap", ArrayMap.class, ClassLoader.class).invoke(
+// parcel, map2, null);
+// } catch (InvocationTargetException e) {
+// Throwable cause = e.getCause();
+// if (cause instanceof IllegalArgumentException) {
+// // Good!
+// return;
+// }
+// throw e;
+// }
+//
+// String msg = "Didn't throw expected IllegalArgumentException";
+// Log.e("test", msg);
+// dump(map1, map2);
+// fail(msg);
+// }
+
+ private static void checkEntrySetToArray(ArrayMap<?, ?> testMap) {
+ try {
+ testMap.entrySet().toArray();
+ fail();
+ } catch (UnsupportedOperationException expected) {
+ }
+
+ try {
+ Map.Entry<?, ?>[] entries = new Map.Entry[20];
+ testMap.entrySet().toArray(entries);
+ fail();
+ } catch (UnsupportedOperationException expected) {
+ }
+ }
+
+ // http://b/32294038, Test ArrayMap.entrySet().toArray()
+ @Test
+ public void testEntrySetArray() {
+ // Create
+ ArrayMap<Integer, String> testMap = new ArrayMap<>();
+
+ // Test empty
+ checkEntrySetToArray(testMap);
+
+ // Test non-empty
+ for (int i = 0; i < 10; ++i) {
+ testMap.put(i, String.valueOf(i));
+ }
+ checkEntrySetToArray(testMap);
+ }
+
+ @Test
+ public void testCanNotIteratePastEnd_entrySetIterator() {
+ Map<String, String> map = new ArrayMap<>();
+ map.put("key 1", "value 1");
+ map.put("key 2", "value 2");
+ Set<Map.Entry<String, String>> expectedEntriesToIterate = new HashSet<>(Arrays.asList(
+ entryOf("key 1", "value 1"),
+ entryOf("key 2", "value 2")
+ ));
+ Iterator<Map.Entry<String, String>> iterator = map.entrySet().iterator();
+
+ // Assert iteration over the expected two entries in any order
+ assertTrue(iterator.hasNext());
+ Map.Entry<String, String> firstEntry = copyOf(iterator.next());
+ assertTrue(expectedEntriesToIterate.remove(firstEntry));
+
+ assertTrue(iterator.hasNext());
+ Map.Entry<String, String> secondEntry = copyOf(iterator.next());
+ assertTrue(expectedEntriesToIterate.remove(secondEntry));
+
+ assertFalse(iterator.hasNext());
+
+ try {
+ iterator.next();
+ fail();
+ } catch (NoSuchElementException expected) {
+ }
+ }
+
+ private static <K, V> Map.Entry<K, V> entryOf(K key, V value) {
+ return new AbstractMap.SimpleEntry<>(key, value);
+ }
+
+ private static <K, V> Map.Entry<K, V> copyOf(Map.Entry<K, V> entry) {
+ return entryOf(entry.getKey(), entry.getValue());
+ }
+
+ @Test
+ public void testCanNotIteratePastEnd_keySetIterator() {
+ Map<String, String> map = new ArrayMap<>();
+ map.put("key 1", "value 1");
+ map.put("key 2", "value 2");
+ Set<String> expectedKeysToIterate = new HashSet<>(Arrays.asList("key 1", "key 2"));
+ Iterator<String> iterator = map.keySet().iterator();
+
+ // Assert iteration over the expected two keys in any order
+ assertTrue(iterator.hasNext());
+ String firstKey = iterator.next();
+ assertTrue(expectedKeysToIterate.remove(firstKey));
+
+ assertTrue(iterator.hasNext());
+ String secondKey = iterator.next();
+ assertTrue(expectedKeysToIterate.remove(secondKey));
+
+ assertFalse(iterator.hasNext());
+
+ try {
+ iterator.next();
+ fail();
+ } catch (NoSuchElementException expected) {
+ }
+ }
+
+ @Test
+ public void testCanNotIteratePastEnd_valuesIterator() {
+ Map<String, String> map = new ArrayMap<>();
+ map.put("key 1", "value 1");
+ map.put("key 2", "value 2");
+ Set<String> expectedValuesToIterate = new HashSet<>(Arrays.asList("value 1", "value 2"));
+ Iterator<String> iterator = map.values().iterator();
+
+ // Assert iteration over the expected two values in any order
+ assertTrue(iterator.hasNext());
+ String firstValue = iterator.next();
+ assertTrue(expectedValuesToIterate.remove(firstValue));
+
+ assertTrue(iterator.hasNext());
+ String secondValue = iterator.next();
+ assertTrue(expectedValuesToIterate.remove(secondValue));
+
+ assertFalse(iterator.hasNext());
+
+ try {
+ iterator.next();
+ fail();
+ } catch (NoSuchElementException expected) {
+ }
+ }
+
+ @Test
+ public void testForEach() {
+ ArrayMap<String, Integer> map = new ArrayMap<>();
+
+ for (int i = 0; i < 50; ++i) {
+ map.put(Integer.toString(i), i * 10);
+ }
+
+ // Make sure forEach goes through all of the elements.
+ HashMap<String, Integer> seen = new HashMap<>();
+ map.forEach(seen::put);
+ compareMaps(seen, map);
+ }
+
+ /**
+ * The entrySet Iterator returns itself from each call to {@code next()}. This is unusual
+ * behavior for {@link Iterator#next()}; this test ensures that any future change to this
+ * behavior is deliberate.
+ */
+ @Test
+ public void testUnusualBehavior_eachEntryIsSameAsIterator_entrySetIterator() {
+ Map<String, String> map = new ArrayMap<>();
+ map.put("key 1", "value 1");
+ map.put("key 2", "value 2");
+ Iterator<Map.Entry<String, String>> iterator = map.entrySet().iterator();
+
+ assertSame(iterator, iterator.next());
+ assertSame(iterator, iterator.next());
+ }
+
+ @SuppressWarnings("SelfEquals")
+ @Test
+ public void testUnusualBehavior_equalsThrowsAfterRemove_entrySetIterator() {
+ Map<String, String> map = new ArrayMap<>();
+ map.put("key 1", "value 1");
+ map.put("key 2", "value 2");
+ Iterator<Map.Entry<String, String>> iterator = map.entrySet().iterator();
+ iterator.next();
+ iterator.remove();
+ try {
+ iterator.equals(iterator);
+ fail();
+ } catch (IllegalStateException expected) {
+ }
+ }
+
+ private static <T> void assertEqualsBothWays(T a, T b) {
+ assertEquals(a, b);
+ assertEquals(b, a);
+ assertEquals(a.hashCode(), b.hashCode());
+ }
+
+ @Test
+ public void testRemoveAll() {
+ final ArrayMap<Integer, String> map = new ArrayMap<>();
+ for (Integer i : Arrays.asList(0, 1, 2, 3, 4, 5)) {
+ map.put(i, i.toString());
+ }
+
+ final ArrayMap<Integer, String> expectedMap = new ArrayMap<>();
+ for (Integer i : Arrays.asList(2, 4)) {
+ expectedMap.put(i, String.valueOf(i));
+ }
+ map.removeAll(Arrays.asList(0, 1, 3, 5, 6));
+ if (!compare(map, expectedMap)) {
+ fail("ArrayMap removeAll failure, expect " + expectedMap + ", but " + map);
+ }
+
+ map.removeAll(Collections.emptyList());
+ if (!compare(map, expectedMap)) {
+ fail("ArrayMap removeAll failure for empty maps, expect " + expectedMap + ", but " +
+ map);
+ }
+
+ map.removeAll(Arrays.asList(2, 4));
+ if (!map.isEmpty()) {
+ fail("ArrayMap removeAll failure, expect empty, but " + map);
+ }
+ }
+
+ @Test
+ public void testReplaceAll() {
+ final ArrayMap<Integer, Integer> map = new ArrayMap<>();
+ final ArrayMap<Integer, Integer> expectedMap = new ArrayMap<>();
+ final BiFunction<Integer, Integer, Integer> function = (k, v) -> 2 * v;
+ for (Integer i : Arrays.asList(0, 1, 2, 3, 4, 5)) {
+ map.put(i, i);
+ expectedMap.put(i, 2 * i);
+ }
+
+ map.replaceAll(function);
+ if (!compare(map, expectedMap)) {
+ fail("ArrayMap replaceAll failure, expect " + expectedMap + ", but " + map);
+ }
+ }
+} \ No newline at end of file
diff --git a/tools/hoststubgen/hoststubgen/test-framework/src/com/android/hoststubgen/frameworktest/LogTest.java b/tools/hoststubgen/hoststubgen/test-framework/src/com/android/hoststubgen/frameworktest/LogTest.java
new file mode 100644
index 000000000000..56544b4d5151
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/test-framework/src/com/android/hoststubgen/frameworktest/LogTest.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2023 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.hoststubgen.frameworktest;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.util.Log;
+import android.util.Slog;
+
+import org.junit.Test;
+
+/**
+ * Some basic tests for {@link android.util.Log}.
+ */
+public class LogTest {
+ @Test
+ public void testBasicLogging() {
+ Log.v("TAG", "Test v log");
+ Log.d("TAG", "Test d log");
+ Log.i("TAG", "Test i log");
+ Log.w("TAG", "Test w log");
+ Log.e("TAG", "Test e log");
+
+ Slog.v("TAG", "Test v slog");
+ Slog.d("TAG", "Test d slog");
+ Slog.i("TAG", "Test i slog");
+ Slog.w("TAG", "Test w slog");
+ Slog.e("TAG", "Test e slog");
+ }
+
+ @Test
+ public void testNativeMethods() {
+ assertThat(Log.isLoggable("mytag", Log.INFO)).isTrue();
+ }
+}
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/Android.bp b/tools/hoststubgen/hoststubgen/test-tiny-framework/Android.bp
new file mode 100644
index 000000000000..8c76a612020f
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/Android.bp
@@ -0,0 +1,141 @@
+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"],
+}
+
+// A library that simulates framework-all.jar
+java_library {
+ name: "hoststubgen-test-tiny-framework",
+ installable: true,
+ host_supported: true,
+ srcs: ["tiny-framework/src/**/*.java"],
+ static_libs: [
+ "hoststubgen-annotations",
+ ],
+}
+
+// Create stub/impl jars from "hoststubgen-test-tiny-framework", using the following 3 rules.
+java_genrule_host {
+ name: "hoststubgen-test-tiny-framework-host",
+ defaults: ["hoststubgen-command-defaults"],
+ cmd: hoststubgen_common_options +
+ "--in-jar $(location :hoststubgen-test-tiny-framework) " +
+ "--policy-override-file $(location policy-override-tiny-framework.txt) ",
+ srcs: [
+ ":hoststubgen-test-tiny-framework",
+ "policy-override-tiny-framework.txt",
+ ],
+}
+
+java_genrule_host {
+ name: "hoststubgen-test-tiny-framework-host-stub",
+ cmd: "cp $(in) $(out)",
+ srcs: [
+ ":hoststubgen-test-tiny-framework-host{host_stub.jar}",
+ ],
+ out: [
+ "host_stub.jar",
+ ],
+}
+
+java_genrule_host {
+ name: "hoststubgen-test-tiny-framework-host-impl",
+ cmd: "cp $(in) $(out)",
+ srcs: [
+ ":hoststubgen-test-tiny-framework-host{host_impl.jar}",
+ ],
+ out: [
+ "host_impl.jar",
+ ],
+}
+
+// Compile the test jar, using 2 rules.
+// 1. Build the test against the stub.
+java_library_host {
+ name: "hoststubgen-test-tiny-test-lib",
+ srcs: ["tiny-test/src/**/*.java"],
+
+ libs: [
+ "hoststubgen-test-tiny-framework-host-stub",
+ ],
+ static_libs: [
+ "junit",
+ "truth-prebuilt",
+
+ // http://cs/h/googleplex-android/platform/superproject/main/+/main:platform_testing/libraries/annotations/src/android/platform/test/annotations/
+ "platform-test-annotations",
+ ],
+ visibility: ["//visibility:private"],
+}
+
+// 2. Link "hoststubgen-test-tiny-test-lib" with necessary runtime dependencies, so it can be
+// executed stand-alone.
+java_test_host {
+ name: "hoststubgen-test-tiny-test",
+ test_config: "AndroidTest-host.xml",
+ static_libs: [
+ "hoststubgen-test-tiny-test-lib",
+ "hoststubgen-helper-runtime",
+ "hoststubgen-test-tiny-framework-host-impl",
+ ],
+ test_suites: ["general-tests"],
+}
+
+// Dump the original, stub and impl jars as text files.
+// We use them in test-and-update-golden.sh.
+java_genrule_host {
+ name: "hoststubgen-test-tiny-framework-orig-dump",
+ defaults: ["hoststubgen-jar-dump-defaults"],
+ srcs: [
+ ":hoststubgen-test-tiny-framework",
+ ],
+ out: [
+ "01-hoststubgen-test-tiny-framework-orig-dump.txt",
+ ],
+ visibility: ["//visibility:private"],
+}
+
+java_genrule_host {
+ name: "hoststubgen-test-tiny-framework-host-stub-dump",
+ defaults: ["hoststubgen-jar-dump-defaults"],
+ srcs: [
+ ":hoststubgen-test-tiny-framework-host-stub",
+ ],
+ out: [
+ "02-hoststubgen-test-tiny-framework-host-stub-dump.txt",
+ ],
+ visibility: ["//visibility:private"],
+}
+
+java_genrule_host {
+ name: "hoststubgen-test-tiny-framework-host-impl-dump",
+ defaults: ["hoststubgen-jar-dump-defaults"],
+ srcs: [
+ ":hoststubgen-test-tiny-framework-host-impl",
+ ],
+ out: [
+ "03-hoststubgen-test-tiny-framework-host-impl-dump.txt",
+ ],
+ visibility: ["//visibility:private"],
+}
+
+// Run it with `atest`. Compare the dump of the jar files to the golden output.
+python_test_host {
+ name: "tiny-framework-dump-test",
+ srcs: [
+ "tiny-framework-dump-test.py",
+ ],
+ data: [
+ "golden-output/*.txt",
+ ],
+ java_data: [
+ "hoststubgen-test-tiny-framework-host-stub-dump",
+ "hoststubgen-test-tiny-framework-host-impl-dump",
+ "hoststubgen-test-tiny-framework-orig-dump",
+ ],
+ test_suites: ["general-tests"],
+}
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/AndroidTest-host.xml b/tools/hoststubgen/hoststubgen/test-tiny-framework/AndroidTest-host.xml
new file mode 100644
index 000000000000..84aad69c33bc
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/AndroidTest-host.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2023 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.
+-->
+
+<!-- [Ravenwood] Copied from $ANDROID_BUILD_TOP/cts/hostsidetests/devicepolicy/AndroidTest.xml -->
+<configuration description="HostStubGen sample test">
+ <option name="test-suite-tag" value="ravenwood" />
+ <option name="config-descriptor:metadata" key="component" value="framework" />
+ <option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
+ <option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
+ <option name="config-descriptor:metadata" key="parameter" value="not_secondary_user" />
+ <option name="config-descriptor:metadata" key="parameter" value="no_foldable_states" />
+
+ <test class="com.android.tradefed.testtype.IsolatedHostTest" >
+ <option name="jar" value="hoststubgen-test-tiny-test.jar" />
+ </test>
+</configuration>
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/README.md b/tools/hoststubgen/hoststubgen/test-tiny-framework/README.md
new file mode 100644
index 000000000000..f3c0450d42a3
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/README.md
@@ -0,0 +1,27 @@
+# HostStubGen: tiny-framework test
+
+This directory contains a small classes that "simulates" framework.jar, and tests against it.
+
+This test doesn't use the actual android framework code.
+
+## How to run
+
+- With `atest`. This is the proper way to run it, but `atest` has known problems that may
+ affect the result. If you see weird problems, try the next `run-ravenwood-test` command.
+
+```
+$ atest hoststubgen-test-tiny-test
+```
+
+- With `run-ravenwood-test` should work too. This is the proper way to run it.
+
+```
+$ run-ravenwood-test hoststubgen-test-tiny-test
+```
+
+- `run-test-manually.sh` also run the test, but it builds the stub/impl jars and the test without
+ using the build system. This is useful for debugging the tool.
+
+```
+$ ./run-test-manually.sh
+``` \ No newline at end of file
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/diff-and-update-golden.sh b/tools/hoststubgen/hoststubgen/test-tiny-framework/diff-and-update-golden.sh
new file mode 100755
index 000000000000..4d588694b8da
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/diff-and-update-golden.sh
@@ -0,0 +1,134 @@
+#!/bin/bash
+# Copyright (C) 2023 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.
+
+help() {
+ cat <<'EOF'
+
+ diff-and-update-golden.sh [OPTIONS]
+
+ Compare the generated jar files from tiny-framework to the "golden" files.
+
+ OPTIONS:
+ -u: Update the golden files.
+
+ -3: Run `meld` to compare original, stub and impl jar files in 3-way diff.
+ This is useful to visualize the exact differences between 3 jar files.
+
+ -2: Run `meld` to compare original <-> impl, and impl <-> stub as two different diffs.
+EOF
+}
+
+source "${0%/*}"/../../common.sh
+
+SCRIPT_NAME="${0##*/}"
+
+GOLDEN_DIR=golden-output
+mkdir -p $GOLDEN_DIR
+
+DIFF_CMD=${DIFF:-diff -u --ignore-blank-lines --ignore-space-change}
+
+update=0
+three_way=0
+two_way=0
+while getopts "u32" opt; do
+case "$opt" in
+ u)
+ update=1
+ ;;
+ 3)
+ three_way=1
+ ;;
+ 2)
+ two_way=1
+ ;;
+ '?')
+ help
+ exit 1
+ ;;
+esac
+done
+shift $(($OPTIND - 1))
+
+
+# Build the dump files, which are the input of this test.
+run m tiny-framework-dump-test
+
+
+# Get the path to the generate text files. (not the golden files.)
+# We get them from $OUT/module-info.json
+
+files=(
+$(python3 -c '
+import sys
+import os
+import json
+
+with open(sys.argv[1], "r") as f:
+ data = json.load(f)
+
+ # Equivalent to: jq -r '.["tiny-framework-dump-test"]["installed"][]'
+ for path in data["tiny-framework-dump-test"]["installed"]:
+
+ if "golden-output" in path:
+ continue
+ if path.endswith(".txt"):
+ print(os.getenv("ANDROID_BUILD_TOP") + "/" + path)
+' $OUT/module-info.json)
+)
+
+# Next, compare each file and update them in $GOLDEN_DIR
+
+any_file_changed=0
+
+for file in ${files[*]} ; do
+ name=$(basename $file)
+ echo "# Checking $name ..."
+
+ file_changed=0
+ if run $DIFF_CMD $GOLDEN_DIR/$name $file; then
+ : # No diff
+ else
+ file_changed=1
+ any_file_changed=1
+ fi
+
+ if (( $update && $file_changed )) ; then
+ echo "# Updating $name ..."
+ run cp $file $GOLDEN_DIR/$name
+ fi
+done
+
+if (( $three_way )) ; then
+ echo "# Running 3-way diff with meld..."
+ run meld ${files[*]} &
+fi
+
+if (( $two_way )) ; then
+ echo "# Running meld..."
+ run meld --diff ${files[0]} ${files[1]} --diff ${files[1]} ${files[2]}
+fi
+
+if (( $any_file_changed == 0 )) ; then
+ echo "$SCRIPT_NAME: Success: no changes detected."
+ exit 0
+else
+ if (( $update )) ; then
+ echo "$SCRIPT_NAME: Warning: golden files have been updated."
+ exit 2
+ else
+ echo "$SCRIPT_NAME: Failure: changes detected. See above diff for the details."
+ exit 3
+ fi
+fi
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/01-hoststubgen-test-tiny-framework-orig-dump.txt b/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/01-hoststubgen-test-tiny-framework-orig-dump.txt
new file mode 100644
index 000000000000..1aa485963f97
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/01-hoststubgen-test-tiny-framework-orig-dump.txt
@@ -0,0 +1,1671 @@
+## Class: android/hosttest/annotation/HostSideTestClassLoadHook.class
+ Compiled from "HostSideTestClassLoadHook.java"
+public interface android.hosttest.annotation.HostSideTestClassLoadHook extends java.lang.annotation.Annotation
+ minor version: 0
+ major version: 61
+ flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION
+ this_class: #x // android/hosttest/annotation/HostSideTestClassLoadHook
+ super_class: #x // java/lang/Object
+ interfaces: 1, fields: 0, methods: 1, attributes: 2
+ public abstract java.lang.String value();
+ descriptor: ()Ljava/lang/String;
+ flags: (0x0401) ACC_PUBLIC, ACC_ABSTRACT
+}
+SourceFile: "HostSideTestClassLoadHook.java"
+RuntimeVisibleAnnotations:
+ 0: #x(#x=[e#x.#x])
+ java.lang.annotation.Target(
+ value=[Ljava/lang/annotation/ElementType;.TYPE]
+ )
+ 1: #x(#x=e#x.#x)
+ java.lang.annotation.Retention(
+ value=Ljava/lang/annotation/RetentionPolicy;.CLASS
+ )
+## Class: android/hosttest/annotation/HostSideTestKeep.class
+ Compiled from "HostSideTestKeep.java"
+public interface android.hosttest.annotation.HostSideTestKeep extends java.lang.annotation.Annotation
+ minor version: 0
+ major version: 61
+ flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION
+ this_class: #x // android/hosttest/annotation/HostSideTestKeep
+ super_class: #x // java/lang/Object
+ interfaces: 1, fields: 0, methods: 0, attributes: 2
+}
+SourceFile: "HostSideTestKeep.java"
+RuntimeVisibleAnnotations:
+ 0: #x(#x=[e#x.#x,e#x.#x,e#x.#x,e#x.#x])
+ java.lang.annotation.Target(
+ value=[Ljava/lang/annotation/ElementType;.TYPE,Ljava/lang/annotation/ElementType;.FIELD,Ljava/lang/annotation/ElementType;.METHOD,Ljava/lang/annotation/ElementType;.CONSTRUCTOR]
+ )
+ 1: #x(#x=e#x.#x)
+ java.lang.annotation.Retention(
+ value=Ljava/lang/annotation/RetentionPolicy;.CLASS
+ )
+## Class: android/hosttest/annotation/HostSideTestNativeSubstitutionClass.class
+ Compiled from "HostSideTestNativeSubstitutionClass.java"
+public interface android.hosttest.annotation.HostSideTestNativeSubstitutionClass extends java.lang.annotation.Annotation
+ minor version: 0
+ major version: 61
+ flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION
+ this_class: #x // android/hosttest/annotation/HostSideTestNativeSubstitutionClass
+ super_class: #x // java/lang/Object
+ interfaces: 1, fields: 0, methods: 1, attributes: 2
+ public abstract java.lang.String value();
+ descriptor: ()Ljava/lang/String;
+ flags: (0x0401) ACC_PUBLIC, ACC_ABSTRACT
+}
+SourceFile: "HostSideTestNativeSubstitutionClass.java"
+RuntimeVisibleAnnotations:
+ 0: #x(#x=[e#x.#x])
+ java.lang.annotation.Target(
+ value=[Ljava/lang/annotation/ElementType;.TYPE]
+ )
+ 1: #x(#x=e#x.#x)
+ java.lang.annotation.Retention(
+ value=Ljava/lang/annotation/RetentionPolicy;.CLASS
+ )
+## Class: android/hosttest/annotation/HostSideTestRemove.class
+ Compiled from "HostSideTestRemove.java"
+public interface android.hosttest.annotation.HostSideTestRemove extends java.lang.annotation.Annotation
+ minor version: 0
+ major version: 61
+ flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION
+ this_class: #x // android/hosttest/annotation/HostSideTestRemove
+ super_class: #x // java/lang/Object
+ interfaces: 1, fields: 0, methods: 0, attributes: 2
+}
+SourceFile: "HostSideTestRemove.java"
+RuntimeVisibleAnnotations:
+ 0: #x(#x=[e#x.#x,e#x.#x,e#x.#x,e#x.#x])
+ java.lang.annotation.Target(
+ value=[Ljava/lang/annotation/ElementType;.TYPE,Ljava/lang/annotation/ElementType;.FIELD,Ljava/lang/annotation/ElementType;.METHOD,Ljava/lang/annotation/ElementType;.CONSTRUCTOR]
+ )
+ 1: #x(#x=e#x.#x)
+ java.lang.annotation.Retention(
+ value=Ljava/lang/annotation/RetentionPolicy;.CLASS
+ )
+## Class: android/hosttest/annotation/HostSideTestStub.class
+ Compiled from "HostSideTestStub.java"
+public interface android.hosttest.annotation.HostSideTestStub extends java.lang.annotation.Annotation
+ minor version: 0
+ major version: 61
+ flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION
+ this_class: #x // android/hosttest/annotation/HostSideTestStub
+ super_class: #x // java/lang/Object
+ interfaces: 1, fields: 0, methods: 0, attributes: 2
+}
+SourceFile: "HostSideTestStub.java"
+RuntimeVisibleAnnotations:
+ 0: #x(#x=[e#x.#x,e#x.#x,e#x.#x,e#x.#x])
+ java.lang.annotation.Target(
+ value=[Ljava/lang/annotation/ElementType;.TYPE,Ljava/lang/annotation/ElementType;.FIELD,Ljava/lang/annotation/ElementType;.METHOD,Ljava/lang/annotation/ElementType;.CONSTRUCTOR]
+ )
+ 1: #x(#x=e#x.#x)
+ java.lang.annotation.Retention(
+ value=Ljava/lang/annotation/RetentionPolicy;.CLASS
+ )
+## Class: android/hosttest/annotation/HostSideTestSubstitute.class
+ Compiled from "HostSideTestSubstitute.java"
+public interface android.hosttest.annotation.HostSideTestSubstitute extends java.lang.annotation.Annotation
+ minor version: 0
+ major version: 61
+ flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION
+ this_class: #x // android/hosttest/annotation/HostSideTestSubstitute
+ super_class: #x // java/lang/Object
+ interfaces: 1, fields: 0, methods: 1, attributes: 2
+ public abstract java.lang.String suffix();
+ descriptor: ()Ljava/lang/String;
+ flags: (0x0401) ACC_PUBLIC, ACC_ABSTRACT
+}
+SourceFile: "HostSideTestSubstitute.java"
+RuntimeVisibleAnnotations:
+ 0: #x(#x=[e#x.#x])
+ java.lang.annotation.Target(
+ value=[Ljava/lang/annotation/ElementType;.METHOD]
+ )
+ 1: #x(#x=e#x.#x)
+ java.lang.annotation.Retention(
+ value=Ljava/lang/annotation/RetentionPolicy;.CLASS
+ )
+## Class: android/hosttest/annotation/HostSideTestThrow.class
+ Compiled from "HostSideTestThrow.java"
+public interface android.hosttest.annotation.HostSideTestThrow extends java.lang.annotation.Annotation
+ minor version: 0
+ major version: 61
+ flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION
+ this_class: #x // android/hosttest/annotation/HostSideTestThrow
+ super_class: #x // java/lang/Object
+ interfaces: 1, fields: 0, methods: 0, attributes: 2
+}
+SourceFile: "HostSideTestThrow.java"
+RuntimeVisibleAnnotations:
+ 0: #x(#x=[e#x.#x,e#x.#x])
+ java.lang.annotation.Target(
+ value=[Ljava/lang/annotation/ElementType;.METHOD,Ljava/lang/annotation/ElementType;.CONSTRUCTOR]
+ )
+ 1: #x(#x=e#x.#x)
+ java.lang.annotation.Retention(
+ value=Ljava/lang/annotation/RetentionPolicy;.CLASS
+ )
+## Class: android/hosttest/annotation/HostSideTestWholeClassKeep.class
+ Compiled from "HostSideTestWholeClassKeep.java"
+public interface android.hosttest.annotation.HostSideTestWholeClassKeep extends java.lang.annotation.Annotation
+ minor version: 0
+ major version: 61
+ flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION
+ this_class: #x // android/hosttest/annotation/HostSideTestWholeClassKeep
+ super_class: #x // java/lang/Object
+ interfaces: 1, fields: 0, methods: 0, attributes: 2
+}
+SourceFile: "HostSideTestWholeClassKeep.java"
+RuntimeVisibleAnnotations:
+ 0: #x(#x=[e#x.#x])
+ java.lang.annotation.Target(
+ value=[Ljava/lang/annotation/ElementType;.TYPE]
+ )
+ 1: #x(#x=e#x.#x)
+ java.lang.annotation.Retention(
+ value=Ljava/lang/annotation/RetentionPolicy;.CLASS
+ )
+## Class: android/hosttest/annotation/HostSideTestWholeClassStub.class
+ Compiled from "HostSideTestWholeClassStub.java"
+public interface android.hosttest.annotation.HostSideTestWholeClassStub extends java.lang.annotation.Annotation
+ minor version: 0
+ major version: 61
+ flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION
+ this_class: #x // android/hosttest/annotation/HostSideTestWholeClassStub
+ super_class: #x // java/lang/Object
+ interfaces: 1, fields: 0, methods: 0, attributes: 2
+}
+SourceFile: "HostSideTestWholeClassStub.java"
+RuntimeVisibleAnnotations:
+ 0: #x(#x=[e#x.#x])
+ java.lang.annotation.Target(
+ value=[Ljava/lang/annotation/ElementType;.TYPE]
+ )
+ 1: #x(#x=e#x.#x)
+ java.lang.annotation.Retention(
+ value=Ljava/lang/annotation/RetentionPolicy;.CLASS
+ )
+## Class: android/hosttest/annotation/tests/HostSideTestSuppress.class
+ Compiled from "HostSideTestSuppress.java"
+public interface android.hosttest.annotation.tests.HostSideTestSuppress extends java.lang.annotation.Annotation
+ minor version: 0
+ major version: 61
+ flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION
+ this_class: #x // android/hosttest/annotation/tests/HostSideTestSuppress
+ super_class: #x // java/lang/Object
+ interfaces: 1, fields: 0, methods: 0, attributes: 2
+}
+SourceFile: "HostSideTestSuppress.java"
+RuntimeVisibleAnnotations:
+ 0: #x(#x=[e#x.#x,e#x.#x,e#x.#x])
+ java.lang.annotation.Target(
+ value=[Ljava/lang/annotation/ElementType;.TYPE,Ljava/lang/annotation/ElementType;.FIELD,Ljava/lang/annotation/ElementType;.METHOD]
+ )
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl.class
+ Compiled from "TinyFrameworkCallerCheck.java"
+class com.android.hoststubgen.test.tinyframework.TinyFrameworkCallerCheck$Impl
+ minor version: 0
+ major version: 61
+ flags: (0x0020) ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 0, methods: 3, attributes: 3
+ private com.android.hoststubgen.test.tinyframework.TinyFrameworkCallerCheck$Impl();
+ descriptor: ()V
+ flags: (0x0002) ACC_PRIVATE
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: aload_0
+ 1: invokespecial #x // Method java/lang/Object."<init>":()V
+ 4: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl;
+
+ public static int getOneKeep();
+ descriptor: ()I
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=1, locals=0, args_size=0
+ 0: iconst_1
+ 1: ireturn
+ LineNumberTable:
+ RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestKeep
+
+ public static int getOneStub();
+ descriptor: ()I
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=1, locals=0, args_size=0
+ 0: iconst_1
+ 1: ireturn
+ LineNumberTable:
+ RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestStub
+}
+SourceFile: "TinyFrameworkCallerCheck.java"
+NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck
+InnerClasses:
+ private static #x= #x of #x; // Impl=class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl of class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck.class
+ Compiled from "TinyFrameworkCallerCheck.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkCallerCheck
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 0, methods: 3, attributes: 4
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkCallerCheck();
+ descriptor: ()V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: aload_0
+ 1: invokespecial #x // Method java/lang/Object."<init>":()V
+ 4: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck;
+
+ public static int getOne_withCheck();
+ descriptor: ()I
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=1, locals=0, args_size=0
+ 0: invokestatic #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl.getOneKeep:()I
+ 3: ireturn
+ LineNumberTable:
+
+ public static int getOne_noCheck();
+ descriptor: ()I
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=1, locals=0, args_size=0
+ 0: invokestatic #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl.getOneStub:()I
+ 3: ireturn
+ LineNumberTable:
+}
+SourceFile: "TinyFrameworkCallerCheck.java"
+RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestWholeClassStub
+NestMembers:
+ com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl
+InnerClasses:
+ private static #x= #x of #x; // Impl=class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl of class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations.class
+ Compiled from "TinyFrameworkClassAnnotations.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassAnnotations
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 3, methods: 10, attributes: 2
+ public int stub;
+ descriptor: I
+ flags: (0x0001) ACC_PUBLIC
+ RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestStub
+
+ public int keep;
+ descriptor: I
+ flags: (0x0001) ACC_PUBLIC
+ RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestKeep
+
+ public int remove;
+ descriptor: I
+ flags: (0x0001) ACC_PUBLIC
+
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkClassAnnotations();
+ descriptor: ()V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=2, locals=1, args_size=1
+ 0: aload_0
+ 1: invokespecial #x // Method java/lang/Object."<init>":()V
+ 4: aload_0
+ 5: iconst_1
+ 6: putfield #x // Field stub:I
+ 9: aload_0
+ 10: iconst_2
+ 11: putfield #x // Field keep:I
+ 14: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 15 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations;
+ RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestStub
+
+ public int addOne(int);
+ descriptor: (I)I
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=2, locals=2, args_size=2
+ 0: aload_0
+ 1: iload_1
+ 2: invokevirtual #x // Method addOneInner:(I)I
+ 5: ireturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 6 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations;
+ 0 6 1 value I
+ RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestStub
+
+ public int addOneInner(int);
+ descriptor: (I)I
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=2, locals=2, args_size=2
+ 0: iload_1
+ 1: iconst_1
+ 2: iadd
+ 3: ireturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 4 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations;
+ 0 4 1 value I
+ RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestKeep
+
+ public void toBeRemoved(java.lang.String);
+ descriptor: (Ljava/lang/String;)V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=2, locals=2, args_size=2
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: invokespecial #x // Method java/lang/RuntimeException."<init>":()V
+ 7: athrow
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 8 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations;
+ 0 8 1 foo Ljava/lang/String;
+ RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestRemove
+
+ public int addTwo(int);
+ descriptor: (I)I
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=3, locals=2, args_size=2
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String not supported on host side
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 10 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations;
+ 0 10 1 value I
+ RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestStub
+ 1: #x(#x=s#x)
+ android.hosttest.annotation.HostSideTestSubstitute(
+ suffix="_host"
+ )
+
+ public int addTwo_host(int);
+ descriptor: (I)I
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=2, locals=2, args_size=2
+ 0: iload_1
+ 1: iconst_2
+ 2: iadd
+ 3: ireturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 4 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations;
+ 0 4 1 value I
+
+ public static native int nativeAddThree(int);
+ descriptor: (I)I
+ flags: (0x0109) ACC_PUBLIC, ACC_STATIC, ACC_NATIVE
+ RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestStub
+ 1: #x(#x=s#x)
+ android.hosttest.annotation.HostSideTestSubstitute(
+ suffix="_host"
+ )
+
+ public static int nativeAddThree_host(int);
+ descriptor: (I)I
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=2, locals=1, args_size=1
+ 0: iload_0
+ 1: iconst_3
+ 2: iadd
+ 3: ireturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 4 0 value I
+
+ public java.lang.String unsupportedMethod();
+ descriptor: ()Ljava/lang/String;
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: ldc #x // String This value shouldn\'t be seen on the host side.
+ 2: areturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 3 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations;
+ RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestThrow
+
+ public java.lang.String visibleButUsesUnsupportedMethod();
+ descriptor: ()Ljava/lang/String;
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: aload_0
+ 1: invokevirtual #x // Method unsupportedMethod:()Ljava/lang/String;
+ 4: areturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations;
+ RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestStub
+}
+SourceFile: "TinyFrameworkClassAnnotations.java"
+RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestStub
+ 1: #x(#x=s#x)
+ android.hosttest.annotation.HostSideTestClassLoadHook(
+ value="com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook.onClassLoaded"
+ )
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations.class
+ Compiled from "TinyFrameworkClassClassWideAnnotations.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassClassWideAnnotations
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 3, methods: 10, attributes: 2
+ public int stub;
+ descriptor: I
+ flags: (0x0001) ACC_PUBLIC
+
+ public int keep;
+ descriptor: I
+ flags: (0x0001) ACC_PUBLIC
+
+ public int remove;
+ descriptor: I
+ flags: (0x0001) ACC_PUBLIC
+
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkClassClassWideAnnotations();
+ descriptor: ()V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=2, locals=1, args_size=1
+ 0: aload_0
+ 1: invokespecial #x // Method java/lang/Object."<init>":()V
+ 4: aload_0
+ 5: iconst_1
+ 6: putfield #x // Field stub:I
+ 9: aload_0
+ 10: iconst_2
+ 11: putfield #x // Field keep:I
+ 14: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 15 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations;
+
+ public int addOne(int);
+ descriptor: (I)I
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=2, locals=2, args_size=2
+ 0: aload_0
+ 1: iload_1
+ 2: invokevirtual #x // Method addOneInner:(I)I
+ 5: ireturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 6 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations;
+ 0 6 1 value I
+
+ public int addOneInner(int);
+ descriptor: (I)I
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=2, locals=2, args_size=2
+ 0: iload_1
+ 1: iconst_1
+ 2: iadd
+ 3: ireturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 4 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations;
+ 0 4 1 value I
+
+ public void toBeRemoved(java.lang.String);
+ descriptor: (Ljava/lang/String;)V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=2, locals=2, args_size=2
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: invokespecial #x // Method java/lang/RuntimeException."<init>":()V
+ 7: athrow
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 8 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations;
+ 0 8 1 foo Ljava/lang/String;
+
+ public int addTwo(int);
+ descriptor: (I)I
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=3, locals=2, args_size=2
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String not supported on host side
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 10 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations;
+ 0 10 1 value I
+ RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestStub
+ 1: #x(#x=s#x)
+ android.hosttest.annotation.HostSideTestSubstitute(
+ suffix="_host"
+ )
+
+ public int addTwo_host(int);
+ descriptor: (I)I
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=2, locals=2, args_size=2
+ 0: iload_1
+ 1: iconst_2
+ 2: iadd
+ 3: ireturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 4 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations;
+ 0 4 1 value I
+
+ public static native int nativeAddThree(int);
+ descriptor: (I)I
+ flags: (0x0109) ACC_PUBLIC, ACC_STATIC, ACC_NATIVE
+ RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestStub
+ 1: #x(#x=s#x)
+ android.hosttest.annotation.HostSideTestSubstitute(
+ suffix="_host"
+ )
+
+ public static int nativeAddThree_host(int);
+ descriptor: (I)I
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=2, locals=1, args_size=1
+ 0: iload_0
+ 1: iconst_3
+ 2: iadd
+ 3: ireturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 4 0 value I
+
+ public java.lang.String unsupportedMethod();
+ descriptor: ()Ljava/lang/String;
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: ldc #x // String This value shouldn\'t be seen on the host side.
+ 2: areturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 3 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations;
+
+ public java.lang.String visibleButUsesUnsupportedMethod();
+ descriptor: ()Ljava/lang/String;
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: aload_0
+ 1: invokevirtual #x // Method unsupportedMethod:()Ljava/lang/String;
+ 4: areturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations;
+}
+SourceFile: "TinyFrameworkClassClassWideAnnotations.java"
+RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestWholeClassStub
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkClassLoadHook.class
+ Compiled from "TinyFrameworkClassLoadHook.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkClassLoadHook
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 1, methods: 3, attributes: 2
+ public static final java.util.Set<java.lang.Class<?>> sLoadedClasses;
+ descriptor: Ljava/util/Set;
+ flags: (0x0019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL
+ Signature: #x // Ljava/util/Set<Ljava/lang/Class<*>;>;
+
+ private com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook();
+ descriptor: ()V
+ flags: (0x0002) ACC_PRIVATE
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: aload_0
+ 1: invokespecial #x // Method java/lang/Object."<init>":()V
+ 4: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassLoadHook;
+
+ public static void onClassLoaded(java.lang.Class<?>);
+ descriptor: (Ljava/lang/Class;)V
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=2, locals=1, args_size=1
+ 0: getstatic #x // Field sLoadedClasses:Ljava/util/Set;
+ 3: aload_0
+ 4: invokeinterface #x, 2 // InterfaceMethod java/util/Set.add:(Ljava/lang/Object;)Z
+ 9: pop
+ 10: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 11 0 clazz Ljava/lang/Class;
+ LocalVariableTypeTable:
+ Start Length Slot Name Signature
+ 0 11 0 clazz Ljava/lang/Class<*>;
+ Signature: #x // (Ljava/lang/Class<*>;)V
+
+ static {};
+ descriptor: ()V
+ flags: (0x0008) ACC_STATIC
+ Code:
+ stack=2, locals=0, args_size=0
+ 0: new #x // class java/util/HashSet
+ 3: dup
+ 4: invokespecial #x // Method java/util/HashSet."<init>":()V
+ 7: putstatic #x // Field sLoadedClasses:Ljava/util/Set;
+ 10: return
+ LineNumberTable:
+}
+SourceFile: "TinyFrameworkClassLoadHook.java"
+RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestWholeClassStub
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializer.class
+ Compiled from "TinyFrameworkClassWithInitializer.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassWithInitializer
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializer
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 1, methods: 2, attributes: 2
+ public static boolean sInitialized;
+ descriptor: Z
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkClassWithInitializer();
+ descriptor: ()V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: aload_0
+ 1: invokespecial #x // Method java/lang/Object."<init>":()V
+ 4: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializer;
+
+ static {};
+ descriptor: ()V
+ flags: (0x0008) ACC_STATIC
+ Code:
+ stack=1, locals=0, args_size=0
+ 0: iconst_1
+ 1: putstatic #x // Field sInitialized:Z
+ 4: return
+ LineNumberTable:
+}
+SourceFile: "TinyFrameworkClassWithInitializer.java"
+RuntimeInvisibleAnnotations:
+ 0: #x(#x=s#x)
+ android.hosttest.annotation.HostSideTestClassLoadHook(
+ value="com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook.onClassLoaded"
+ )
+ 1: #x()
+ android.hosttest.annotation.HostSideTestWholeClassStub
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkExceptionTester.class
+ Compiled from "TinyFrameworkExceptionTester.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkExceptionTester
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkExceptionTester
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 0, methods: 2, attributes: 2
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkExceptionTester();
+ descriptor: ()V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: aload_0
+ 1: invokespecial #x // Method java/lang/Object."<init>":()V
+ 4: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkExceptionTester;
+
+ public static int testException();
+ descriptor: ()I
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=4, locals=1, args_size=0
+ 0: new #x // class java/lang/IllegalStateException
+ 3: dup
+ 4: ldc #x // String Inner exception
+ 6: invokespecial #x // Method java/lang/IllegalStateException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+ 10: astore_0
+ 11: new #x // class java/lang/RuntimeException
+ 14: dup
+ 15: ldc #x // String Outer exception
+ 17: aload_0
+ 18: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;Ljava/lang/Throwable;)V
+ 21: athrow
+ Exception table:
+ from to target type
+ 0 10 10 Class java/lang/Exception
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 11 11 0 e Ljava/lang/Exception;
+ StackMapTable: number_of_entries = 1
+ frame_type = 74 /* same_locals_1_stack_item */
+ stack = [ class java/lang/Exception ]
+}
+SourceFile: "TinyFrameworkExceptionTester.java"
+RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestWholeClassStub
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy.class
+ Compiled from "TinyFrameworkForTextPolicy.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkForTextPolicy
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 3, methods: 10, attributes: 1
+ public int stub;
+ descriptor: I
+ flags: (0x0001) ACC_PUBLIC
+
+ public int keep;
+ descriptor: I
+ flags: (0x0001) ACC_PUBLIC
+
+ public int remove;
+ descriptor: I
+ flags: (0x0001) ACC_PUBLIC
+
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkForTextPolicy();
+ descriptor: ()V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=2, locals=1, args_size=1
+ 0: aload_0
+ 1: invokespecial #x // Method java/lang/Object."<init>":()V
+ 4: aload_0
+ 5: iconst_1
+ 6: putfield #x // Field stub:I
+ 9: aload_0
+ 10: iconst_2
+ 11: putfield #x // Field keep:I
+ 14: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 15 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy;
+
+ public int addOne(int);
+ descriptor: (I)I
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=2, locals=2, args_size=2
+ 0: aload_0
+ 1: iload_1
+ 2: invokevirtual #x // Method addOneInner:(I)I
+ 5: ireturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 6 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy;
+ 0 6 1 value I
+
+ public int addOneInner(int);
+ descriptor: (I)I
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=2, locals=2, args_size=2
+ 0: iload_1
+ 1: iconst_1
+ 2: iadd
+ 3: ireturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 4 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy;
+ 0 4 1 value I
+
+ public void toBeRemoved(java.lang.String);
+ descriptor: (Ljava/lang/String;)V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=2, locals=2, args_size=2
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: invokespecial #x // Method java/lang/RuntimeException."<init>":()V
+ 7: athrow
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 8 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy;
+ 0 8 1 foo Ljava/lang/String;
+
+ public int addTwo(int);
+ descriptor: (I)I
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=3, locals=2, args_size=2
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String not supported on host side
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 10 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy;
+ 0 10 1 value I
+
+ public int addTwo_host(int);
+ descriptor: (I)I
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=2, locals=2, args_size=2
+ 0: iload_1
+ 1: iconst_2
+ 2: iadd
+ 3: ireturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 4 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy;
+ 0 4 1 value I
+
+ public static native int nativeAddThree(int);
+ descriptor: (I)I
+ flags: (0x0109) ACC_PUBLIC, ACC_STATIC, ACC_NATIVE
+
+ public static int addThree_host(int);
+ descriptor: (I)I
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=2, locals=1, args_size=1
+ 0: iload_0
+ 1: iconst_3
+ 2: iadd
+ 3: ireturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 4 0 value I
+
+ public java.lang.String unsupportedMethod();
+ descriptor: ()Ljava/lang/String;
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: ldc #x // String This value shouldn\'t be seen on the host side.
+ 2: areturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 3 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy;
+
+ public java.lang.String visibleButUsesUnsupportedMethod();
+ descriptor: ()Ljava/lang/String;
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: aload_0
+ 1: invokevirtual #x // Method unsupportedMethod:()Ljava/lang/String;
+ 4: areturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy;
+}
+SourceFile: "TinyFrameworkForTextPolicy.java"
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNative.class
+ Compiled from "TinyFrameworkNative.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNative
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNative
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 0, methods: 5, attributes: 2
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkNative();
+ descriptor: ()V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: aload_0
+ 1: invokespecial #x // Method java/lang/Object."<init>":()V
+ 4: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative;
+
+ public static native int nativeAddTwo(int);
+ descriptor: (I)I
+ flags: (0x0109) ACC_PUBLIC, ACC_STATIC, ACC_NATIVE
+
+ public static int nativeAddTwo_should_be_like_this(int);
+ descriptor: (I)I
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: iload_0
+ 1: invokestatic #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.nativeAddTwo:(I)I
+ 4: ireturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 arg I
+
+ public static native long nativeLongPlus(long, long);
+ descriptor: (JJ)J
+ flags: (0x0109) ACC_PUBLIC, ACC_STATIC, ACC_NATIVE
+
+ public static long nativeLongPlus_should_be_like_this(long, long);
+ descriptor: (JJ)J
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=4, locals=4, args_size=2
+ 0: lload_0
+ 1: lload_2
+ 2: invokestatic #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.nativeLongPlus:(JJ)J
+ 5: lreturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 6 0 arg1 J
+ 0 6 2 arg2 J
+}
+SourceFile: "TinyFrameworkNative.java"
+RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestWholeClassStub
+ 1: #x(#x=s#x)
+ android.hosttest.annotation.HostSideTestNativeSubstitutionClass(
+ value="TinyFrameworkNative_host"
+ )
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.class
+ Compiled from "TinyFrameworkNative_host.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNative_host
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 0, methods: 3, attributes: 2
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkNative_host();
+ descriptor: ()V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: aload_0
+ 1: invokespecial #x // Method java/lang/Object."<init>":()V
+ 4: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host;
+
+ public static int nativeAddTwo(int);
+ descriptor: (I)I
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=2, locals=1, args_size=1
+ 0: iload_0
+ 1: iconst_2
+ 2: iadd
+ 3: ireturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 4 0 arg I
+
+ public static long nativeLongPlus(long, long);
+ descriptor: (JJ)J
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=4, locals=4, args_size=2
+ 0: lload_0
+ 1: lload_2
+ 2: ladd
+ 3: lreturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 4 0 arg1 J
+ 0 4 2 arg2 J
+}
+SourceFile: "TinyFrameworkNative_host.java"
+RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestWholeClassKeep
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1.class
+ Compiled from "TinyFrameworkNestedClasses.java"
+class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$1 extends java.lang.Object implements java.util.function.Supplier<java.lang.Integer>
+ minor version: 0
+ major version: 61
+ flags: (0x0020) ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1
+ super_class: #x // java/lang/Object
+ interfaces: 1, fields: 1, methods: 3, attributes: 5
+ final com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses this$0;
+ descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;
+ flags: (0x1010) ACC_FINAL, ACC_SYNTHETIC
+
+ com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$1(com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses);
+ descriptor: (Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;)V
+ flags: (0x0000)
+ Code:
+ stack=2, locals=2, args_size=2
+ 0: aload_0
+ 1: aload_1
+ 2: putfield #x // Field this$0:Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;
+ 5: aload_0
+ 6: invokespecial #x // Method java/lang/Object."<init>":()V
+ 9: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 10 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1;
+ 0 10 1 this$0 Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;
+
+ public java.lang.Integer get();
+ descriptor: ()Ljava/lang/Integer;
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: iconst_1
+ 1: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
+ 4: areturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1;
+
+ public java.lang.Object get();
+ descriptor: ()Ljava/lang/Object;
+ flags: (0x1041) ACC_PUBLIC, ACC_BRIDGE, ACC_SYNTHETIC
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: aload_0
+ 1: invokevirtual #x // Method get:()Ljava/lang/Integer;
+ 4: areturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1;
+}
+Signature: #x // Ljava/lang/Object;Ljava/util/function/Supplier<Ljava/lang/Integer;>;
+SourceFile: "TinyFrameworkNestedClasses.java"
+EnclosingMethod: #x.#x // com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses
+NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+InnerClasses:
+ #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2.class
+ Compiled from "TinyFrameworkNestedClasses.java"
+class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$2 extends java.lang.Object implements java.util.function.Supplier<java.lang.Integer>
+ minor version: 0
+ major version: 61
+ flags: (0x0020) ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2
+ super_class: #x // java/lang/Object
+ interfaces: 1, fields: 0, methods: 3, attributes: 5
+ com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$2();
+ descriptor: ()V
+ flags: (0x0000)
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: aload_0
+ 1: invokespecial #x // Method java/lang/Object."<init>":()V
+ 4: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2;
+
+ public java.lang.Integer get();
+ descriptor: ()Ljava/lang/Integer;
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: iconst_2
+ 1: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
+ 4: areturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2;
+
+ public java.lang.Object get();
+ descriptor: ()Ljava/lang/Object;
+ flags: (0x1041) ACC_PUBLIC, ACC_BRIDGE, ACC_SYNTHETIC
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: aload_0
+ 1: invokevirtual #x // Method get:()Ljava/lang/Integer;
+ 4: areturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2;
+}
+Signature: #x // Ljava/lang/Object;Ljava/util/function/Supplier<Ljava/lang/Integer;>;
+SourceFile: "TinyFrameworkNestedClasses.java"
+EnclosingMethod: #x.#x // com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses
+NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+InnerClasses:
+ #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3.class
+ Compiled from "TinyFrameworkNestedClasses.java"
+class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$3 extends java.lang.Object implements java.util.function.Supplier<java.lang.Integer>
+ minor version: 0
+ major version: 61
+ flags: (0x0020) ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3
+ super_class: #x // java/lang/Object
+ interfaces: 1, fields: 1, methods: 3, attributes: 5
+ final com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses this$0;
+ descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;
+ flags: (0x1010) ACC_FINAL, ACC_SYNTHETIC
+
+ com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$3(com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses);
+ descriptor: (Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;)V
+ flags: (0x0000)
+ Code:
+ stack=2, locals=2, args_size=2
+ 0: aload_0
+ 1: aload_1
+ 2: putfield #x // Field this$0:Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;
+ 5: aload_0
+ 6: invokespecial #x // Method java/lang/Object."<init>":()V
+ 9: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 10 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3;
+ 0 10 1 this$0 Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;
+
+ public java.lang.Integer get();
+ descriptor: ()Ljava/lang/Integer;
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: iconst_3
+ 1: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
+ 4: areturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3;
+
+ public java.lang.Object get();
+ descriptor: ()Ljava/lang/Object;
+ flags: (0x1041) ACC_PUBLIC, ACC_BRIDGE, ACC_SYNTHETIC
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: aload_0
+ 1: invokevirtual #x // Method get:()Ljava/lang/Integer;
+ 4: areturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3;
+}
+Signature: #x // Ljava/lang/Object;Ljava/util/function/Supplier<Ljava/lang/Integer;>;
+SourceFile: "TinyFrameworkNestedClasses.java"
+EnclosingMethod: #x.#x // com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses.getSupplier
+NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+InnerClasses:
+ #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4.class
+ Compiled from "TinyFrameworkNestedClasses.java"
+class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$4 extends java.lang.Object implements java.util.function.Supplier<java.lang.Integer>
+ minor version: 0
+ major version: 61
+ flags: (0x0020) ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4
+ super_class: #x // java/lang/Object
+ interfaces: 1, fields: 0, methods: 3, attributes: 5
+ com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$4();
+ descriptor: ()V
+ flags: (0x0000)
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: aload_0
+ 1: invokespecial #x // Method java/lang/Object."<init>":()V
+ 4: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4;
+
+ public java.lang.Integer get();
+ descriptor: ()Ljava/lang/Integer;
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: iconst_4
+ 1: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
+ 4: areturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4;
+
+ public java.lang.Object get();
+ descriptor: ()Ljava/lang/Object;
+ flags: (0x1041) ACC_PUBLIC, ACC_BRIDGE, ACC_SYNTHETIC
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: aload_0
+ 1: invokevirtual #x // Method get:()Ljava/lang/Integer;
+ 4: areturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4;
+}
+Signature: #x // Ljava/lang/Object;Ljava/util/function/Supplier<Ljava/lang/Integer;>;
+SourceFile: "TinyFrameworkNestedClasses.java"
+EnclosingMethod: #x.#x // com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses.getSupplier_static
+NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+InnerClasses:
+ #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass.class
+ Compiled from "TinyFrameworkNestedClasses.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$BaseClass
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 1, methods: 1, attributes: 3
+ public int value;
+ descriptor: I
+ flags: (0x0001) ACC_PUBLIC
+
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$BaseClass(int);
+ descriptor: (I)V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=2, locals=2, args_size=2
+ 0: aload_0
+ 1: invokespecial #x // Method java/lang/Object."<init>":()V
+ 4: aload_0
+ 5: iload_1
+ 6: putfield #x // Field value:I
+ 9: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 10 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass;
+ 0 10 1 x I
+}
+SourceFile: "TinyFrameworkNestedClasses.java"
+NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+InnerClasses:
+ public static #x= #x of #x; // BaseClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass.class
+ Compiled from "TinyFrameworkNestedClasses.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$InnerClass
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 2, methods: 1, attributes: 4
+ public int value;
+ descriptor: I
+ flags: (0x0001) ACC_PUBLIC
+
+ final com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses this$0;
+ descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;
+ flags: (0x1010) ACC_FINAL, ACC_SYNTHETIC
+
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$InnerClass(com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses);
+ descriptor: (Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;)V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=2, locals=2, args_size=2
+ 0: aload_0
+ 1: aload_1
+ 2: putfield #x // Field this$0:Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;
+ 5: aload_0
+ 6: invokespecial #x // Method java/lang/Object."<init>":()V
+ 9: aload_0
+ 10: iconst_5
+ 11: putfield #x // Field value:I
+ 14: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 15 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass;
+ 0 15 1 this$0 Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;
+}
+SourceFile: "TinyFrameworkNestedClasses.java"
+RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestWholeClassStub
+NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+InnerClasses:
+ public #x= #x of #x; // InnerClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1.class
+ Compiled from "TinyFrameworkNestedClasses.java"
+class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$StaticNestedClass$1 extends java.lang.Object implements java.util.function.Supplier<java.lang.Integer>
+ minor version: 0
+ major version: 61
+ flags: (0x0020) ACC_SUPER
+ 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
+ com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$StaticNestedClass$1();
+ descriptor: ()V
+ flags: (0x0000)
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: aload_0
+ 1: invokespecial #x // Method java/lang/Object."<init>":()V
+ 4: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1;
+
+ public java.lang.Integer get();
+ descriptor: ()Ljava/lang/Integer;
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: bipush 7
+ 2: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
+ 5: areturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 6 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1;
+
+ public java.lang.Object get();
+ descriptor: ()Ljava/lang/Object;
+ flags: (0x1041) ACC_PUBLIC, ACC_BRIDGE, ACC_SYNTHETIC
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: aload_0
+ 1: invokevirtual #x // Method get:()Ljava/lang/Integer;
+ 4: areturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1;
+}
+Signature: #x // Ljava/lang/Object;Ljava/util/function/Supplier<Ljava/lang/Integer;>;
+SourceFile: "TinyFrameworkNestedClasses.java"
+EnclosingMethod: #x.#x // com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$StaticNestedClass.getSupplier_static
+NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+InnerClasses:
+ public static #x= #x of #x; // StaticNestedClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+ #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass.class
+ Compiled from "TinyFrameworkNestedClasses.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$StaticNestedClass
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 1, methods: 2, attributes: 4
+ public int value;
+ descriptor: I
+ flags: (0x0001) ACC_PUBLIC
+
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$StaticNestedClass();
+ descriptor: ()V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=2, locals=1, args_size=1
+ 0: aload_0
+ 1: invokespecial #x // Method java/lang/Object."<init>":()V
+ 4: aload_0
+ 5: bipush 6
+ 7: putfield #x // Field value:I
+ 10: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 11 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass;
+
+ public static java.util.function.Supplier<java.lang.Integer> getSupplier_static();
+ descriptor: ()Ljava/util/function/Supplier;
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=2, locals=0, args_size=0
+ 0: new #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1
+ 3: dup
+ 4: invokespecial #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1."<init>":()V
+ 7: areturn
+ LineNumberTable:
+ Signature: #x // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>;
+}
+SourceFile: "TinyFrameworkNestedClasses.java"
+RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestWholeClassStub
+NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+InnerClasses:
+ public static #x= #x of #x; // StaticNestedClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+ #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass.class
+ Compiled from "TinyFrameworkNestedClasses.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$SubClass extends com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$BaseClass
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ 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
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$SubClass(int);
+ descriptor: (I)V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=2, locals=2, args_size=2
+ 0: aload_0
+ 1: iload_1
+ 2: invokespecial #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass."<init>":(I)V
+ 5: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 6 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass;
+ 0 6 1 x I
+}
+SourceFile: "TinyFrameworkNestedClasses.java"
+NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+InnerClasses:
+ public static #x= #x of #x; // BaseClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+ public static #x= #x of #x; // SubClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses.class
+ Compiled from "TinyFrameworkNestedClasses.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 2, methods: 4, attributes: 4
+ public final java.util.function.Supplier<java.lang.Integer> mSupplier;
+ descriptor: Ljava/util/function/Supplier;
+ flags: (0x0011) ACC_PUBLIC, ACC_FINAL
+ Signature: #x // Ljava/util/function/Supplier<Ljava/lang/Integer;>;
+
+ public static final java.util.function.Supplier<java.lang.Integer> sSupplier;
+ descriptor: Ljava/util/function/Supplier;
+ flags: (0x0019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL
+ Signature: #x // Ljava/util/function/Supplier<Ljava/lang/Integer;>;
+
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses();
+ descriptor: ()V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=4, locals=1, args_size=1
+ 0: aload_0
+ 1: invokespecial #x // Method java/lang/Object."<init>":()V
+ 4: aload_0
+ 5: new #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1
+ 8: dup
+ 9: aload_0
+ 10: invokespecial #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1."<init>":(Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;)V
+ 13: putfield #x // Field mSupplier:Ljava/util/function/Supplier;
+ 16: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 17 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;
+
+ public java.util.function.Supplier<java.lang.Integer> getSupplier();
+ descriptor: ()Ljava/util/function/Supplier;
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=3, locals=1, args_size=1
+ 0: new #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3
+ 3: dup
+ 4: aload_0
+ 5: invokespecial #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3."<init>":(Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;)V
+ 8: areturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 9 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;
+ Signature: #x // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>;
+
+ public static java.util.function.Supplier<java.lang.Integer> getSupplier_static();
+ descriptor: ()Ljava/util/function/Supplier;
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=2, locals=0, args_size=0
+ 0: new #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4
+ 3: dup
+ 4: invokespecial #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4."<init>":()V
+ 7: areturn
+ LineNumberTable:
+ Signature: #x // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>;
+
+ static {};
+ descriptor: ()V
+ flags: (0x0008) ACC_STATIC
+ Code:
+ stack=2, locals=0, args_size=0
+ 0: new #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2
+ 3: dup
+ 4: invokespecial #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2."<init>":()V
+ 7: putstatic #x // Field sSupplier:Ljava/util/function/Supplier;
+ 10: return
+ LineNumberTable:
+}
+SourceFile: "TinyFrameworkNestedClasses.java"
+RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestWholeClassStub
+NestMembers:
+ com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass
+ com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass
+ com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass
+ com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1
+ com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass
+ com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4
+ com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3
+ com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2
+ com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1
+InnerClasses:
+ #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1
+ #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3
+ #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4
+ #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2
+ public static #x= #x of #x; // SubClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+ public static #x= #x of #x; // BaseClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+ public static #x= #x of #x; // StaticNestedClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+ public #x= #x of #x; // InnerClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+ #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/02-hoststubgen-test-tiny-framework-host-stub-dump.txt b/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/02-hoststubgen-test-tiny-framework-host-stub-dump.txt
new file mode 100644
index 000000000000..6e1528aedc1e
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/02-hoststubgen-test-tiny-framework-host-stub-dump.txt
@@ -0,0 +1,837 @@
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl.class
+ Compiled from "TinyFrameworkCallerCheck.java"
+class com.android.hoststubgen.test.tinyframework.TinyFrameworkCallerCheck$Impl
+ minor version: 0
+ major version: 61
+ flags: (0x0020) ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 0, methods: 2, attributes: 4
+ private com.android.hoststubgen.test.tinyframework.TinyFrameworkCallerCheck$Impl();
+ descriptor: ()V
+ flags: (0x0002) ACC_PRIVATE
+ Code:
+ stack=3, locals=1, args_size=1
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+
+ public static int getOneStub();
+ descriptor: ()I
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=3, locals=0, args_size=0
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+ RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestStub
+}
+InnerClasses:
+ private static #x= #x of #x; // Impl=class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl of class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck
+SourceFile: "TinyFrameworkCallerCheck.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ 1: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck.class
+ Compiled from "TinyFrameworkCallerCheck.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkCallerCheck
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 0, methods: 3, attributes: 5
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkCallerCheck();
+ descriptor: ()V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=3, locals=1, args_size=1
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+
+ public static int getOne_withCheck();
+ descriptor: ()I
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=3, locals=0, args_size=0
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+
+ public static int getOne_noCheck();
+ descriptor: ()I
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=3, locals=0, args_size=0
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+}
+InnerClasses:
+ private static #x= #x of #x; // Impl=class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl of class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck
+SourceFile: "TinyFrameworkCallerCheck.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ 1: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestWholeClassStub
+NestMembers:
+ com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations.class
+ Compiled from "TinyFrameworkClassAnnotations.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassAnnotations
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 1, methods: 5, attributes: 3
+ public int stub;
+ descriptor: I
+ flags: (0x0001) ACC_PUBLIC
+ RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestStub
+
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkClassAnnotations();
+ descriptor: ()V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=3, locals=1, args_size=1
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+ RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestStub
+
+ public int addOne(int);
+ descriptor: (I)I
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=3, locals=2, args_size=2
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+ RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestStub
+
+ public int addTwo(int);
+ descriptor: (I)I
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=3, locals=2, args_size=2
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+
+ public static int nativeAddThree(int);
+ descriptor: (I)I
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=3, locals=1, args_size=1
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+
+ public java.lang.String visibleButUsesUnsupportedMethod();
+ descriptor: ()Ljava/lang/String;
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=3, locals=1, args_size=1
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+ RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestStub
+}
+SourceFile: "TinyFrameworkClassAnnotations.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ 1: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestStub
+ 1: #x(#x=s#x)
+ android.hosttest.annotation.HostSideTestClassLoadHook(
+ value="com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook.onClassLoaded"
+ )
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations.class
+ Compiled from "TinyFrameworkClassClassWideAnnotations.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassClassWideAnnotations
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 3, methods: 8, attributes: 3
+ public int stub;
+ descriptor: I
+ flags: (0x0001) ACC_PUBLIC
+
+ public int keep;
+ descriptor: I
+ flags: (0x0001) ACC_PUBLIC
+
+ public int remove;
+ descriptor: I
+ flags: (0x0001) ACC_PUBLIC
+
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkClassClassWideAnnotations();
+ descriptor: ()V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=3, locals=1, args_size=1
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+
+ public int addOne(int);
+ descriptor: (I)I
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=3, locals=2, args_size=2
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+
+ public int addOneInner(int);
+ descriptor: (I)I
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=3, locals=2, args_size=2
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+
+ public void toBeRemoved(java.lang.String);
+ descriptor: (Ljava/lang/String;)V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=3, locals=2, args_size=2
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+
+ public int addTwo(int);
+ descriptor: (I)I
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=3, locals=2, args_size=2
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+
+ public static int nativeAddThree(int);
+ descriptor: (I)I
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=3, locals=1, args_size=1
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+
+ public java.lang.String unsupportedMethod();
+ descriptor: ()Ljava/lang/String;
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=3, locals=1, args_size=1
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+
+ public java.lang.String visibleButUsesUnsupportedMethod();
+ descriptor: ()Ljava/lang/String;
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=3, locals=1, args_size=1
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+}
+SourceFile: "TinyFrameworkClassClassWideAnnotations.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ 1: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestWholeClassStub
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkClassLoadHook.class
+ Compiled from "TinyFrameworkClassLoadHook.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkClassLoadHook
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 1, methods: 3, attributes: 3
+ public static final java.util.Set<java.lang.Class<?>> sLoadedClasses;
+ descriptor: Ljava/util/Set;
+ flags: (0x0019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL
+ Signature: #x // Ljava/util/Set<Ljava/lang/Class<*>;>;
+
+ private com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook();
+ descriptor: ()V
+ flags: (0x0002) ACC_PRIVATE
+ Code:
+ stack=3, locals=1, args_size=1
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+
+ public static void onClassLoaded(java.lang.Class<?>);
+ descriptor: (Ljava/lang/Class;)V
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=3, locals=1, args_size=1
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+ Signature: #x // (Ljava/lang/Class<*>;)V
+
+ static {};
+ descriptor: ()V
+ flags: (0x0008) ACC_STATIC
+ Code:
+ stack=3, locals=0, args_size=0
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+}
+SourceFile: "TinyFrameworkClassLoadHook.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ 1: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestWholeClassStub
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializer.class
+ Compiled from "TinyFrameworkClassWithInitializer.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassWithInitializer
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializer
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 1, methods: 2, attributes: 3
+ public static boolean sInitialized;
+ descriptor: Z
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkClassWithInitializer();
+ descriptor: ()V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=3, locals=1, args_size=1
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+
+ static {};
+ descriptor: ()V
+ flags: (0x0008) ACC_STATIC
+ Code:
+ stack=3, locals=0, args_size=0
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+}
+SourceFile: "TinyFrameworkClassWithInitializer.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ 1: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+RuntimeInvisibleAnnotations:
+ 0: #x(#x=s#x)
+ android.hosttest.annotation.HostSideTestClassLoadHook(
+ value="com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook.onClassLoaded"
+ )
+ 1: #x()
+ android.hosttest.annotation.HostSideTestWholeClassStub
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkExceptionTester.class
+ Compiled from "TinyFrameworkExceptionTester.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkExceptionTester
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkExceptionTester
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 0, methods: 2, attributes: 3
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkExceptionTester();
+ descriptor: ()V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=3, locals=1, args_size=1
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+
+ public static int testException();
+ descriptor: ()I
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=3, locals=0, args_size=0
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+}
+SourceFile: "TinyFrameworkExceptionTester.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ 1: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestWholeClassStub
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy.class
+ Compiled from "TinyFrameworkForTextPolicy.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkForTextPolicy
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 1, methods: 5, attributes: 2
+ public int stub;
+ descriptor: I
+ flags: (0x0001) ACC_PUBLIC
+
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkForTextPolicy();
+ descriptor: ()V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=3, locals=1, args_size=1
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+
+ public int addOne(int);
+ descriptor: (I)I
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=3, locals=2, args_size=2
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+
+ public int addTwo(int);
+ descriptor: (I)I
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=3, locals=2, args_size=2
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+
+ public static int nativeAddThree(int);
+ descriptor: (I)I
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=3, locals=1, args_size=1
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+
+ public java.lang.String visibleButUsesUnsupportedMethod();
+ descriptor: ()Ljava/lang/String;
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=3, locals=1, args_size=1
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+}
+SourceFile: "TinyFrameworkForTextPolicy.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ 1: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNative.class
+ Compiled from "TinyFrameworkNative.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNative
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNative
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 0, methods: 5, attributes: 3
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkNative();
+ descriptor: ()V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=3, locals=1, args_size=1
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+
+ public static native int nativeAddTwo(int);
+ descriptor: (I)I
+ flags: (0x0109) ACC_PUBLIC, ACC_STATIC, ACC_NATIVE
+
+ public static int nativeAddTwo_should_be_like_this(int);
+ descriptor: (I)I
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=3, locals=1, args_size=1
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+
+ public static native long nativeLongPlus(long, long);
+ descriptor: (JJ)J
+ flags: (0x0109) ACC_PUBLIC, ACC_STATIC, ACC_NATIVE
+
+ public static long nativeLongPlus_should_be_like_this(long, long);
+ descriptor: (JJ)J
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=3, locals=4, args_size=2
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+}
+SourceFile: "TinyFrameworkNative.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ 1: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestWholeClassStub
+ 1: #x(#x=s#x)
+ android.hosttest.annotation.HostSideTestNativeSubstitutionClass(
+ value="TinyFrameworkNative_host"
+ )
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass.class
+ Compiled from "TinyFrameworkNestedClasses.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$BaseClass
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 1, methods: 1, attributes: 4
+ public int value;
+ descriptor: I
+ flags: (0x0001) ACC_PUBLIC
+
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$BaseClass(int);
+ descriptor: (I)V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=3, locals=2, args_size=2
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+}
+InnerClasses:
+ public static #x= #x of #x; // BaseClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+SourceFile: "TinyFrameworkNestedClasses.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ 1: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass.class
+ Compiled from "TinyFrameworkNestedClasses.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$InnerClass
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 2, methods: 1, attributes: 5
+ public int value;
+ descriptor: I
+ flags: (0x0001) ACC_PUBLIC
+
+ final com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses this$0;
+ descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;
+ flags: (0x1010) ACC_FINAL, ACC_SYNTHETIC
+
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$InnerClass(com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses);
+ descriptor: (Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;)V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=3, locals=2, args_size=2
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+}
+InnerClasses:
+ public #x= #x of #x; // InnerClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+SourceFile: "TinyFrameworkNestedClasses.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ 1: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestWholeClassStub
+NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass.class
+ Compiled from "TinyFrameworkNestedClasses.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$StaticNestedClass
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 1, methods: 2, attributes: 5
+ public int value;
+ descriptor: I
+ flags: (0x0001) ACC_PUBLIC
+
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$StaticNestedClass();
+ descriptor: ()V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=3, locals=1, args_size=1
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+
+ public static java.util.function.Supplier<java.lang.Integer> getSupplier_static();
+ descriptor: ()Ljava/util/function/Supplier;
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=3, locals=0, args_size=0
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+ Signature: #x // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>;
+}
+InnerClasses:
+ public static #x= #x of #x; // StaticNestedClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+ #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1
+SourceFile: "TinyFrameworkNestedClasses.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ 1: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestWholeClassStub
+NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass.class
+ Compiled from "TinyFrameworkNestedClasses.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$SubClass extends com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$BaseClass
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ 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: 4
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$SubClass(int);
+ descriptor: (I)V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=3, locals=2, args_size=2
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+}
+InnerClasses:
+ public static #x= #x of #x; // BaseClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+ public static #x= #x of #x; // SubClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+SourceFile: "TinyFrameworkNestedClasses.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ 1: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses.class
+ Compiled from "TinyFrameworkNestedClasses.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 2, methods: 4, attributes: 5
+ public final java.util.function.Supplier<java.lang.Integer> mSupplier;
+ descriptor: Ljava/util/function/Supplier;
+ flags: (0x0011) ACC_PUBLIC, ACC_FINAL
+ Signature: #x // Ljava/util/function/Supplier<Ljava/lang/Integer;>;
+
+ public static final java.util.function.Supplier<java.lang.Integer> sSupplier;
+ descriptor: Ljava/util/function/Supplier;
+ flags: (0x0019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL
+ Signature: #x // Ljava/util/function/Supplier<Ljava/lang/Integer;>;
+
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses();
+ descriptor: ()V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=3, locals=1, args_size=1
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+
+ public java.util.function.Supplier<java.lang.Integer> getSupplier();
+ descriptor: ()Ljava/util/function/Supplier;
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=3, locals=1, args_size=1
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+ Signature: #x // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>;
+
+ public static java.util.function.Supplier<java.lang.Integer> getSupplier_static();
+ descriptor: ()Ljava/util/function/Supplier;
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=3, locals=0, args_size=0
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+ Signature: #x // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>;
+
+ static {};
+ descriptor: ()V
+ flags: (0x0008) ACC_STATIC
+ Code:
+ stack=3, locals=0, args_size=0
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+}
+InnerClasses:
+ #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1
+ #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3
+ #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4
+ #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2
+ public static #x= #x of #x; // SubClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+ public static #x= #x of #x; // BaseClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+ public static #x= #x of #x; // StaticNestedClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+ public #x= #x of #x; // InnerClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+ #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1
+SourceFile: "TinyFrameworkNestedClasses.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ 1: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestWholeClassStub
+NestMembers:
+ com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass
+ com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass
+ com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass
+ com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1
+ com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass
+ com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4
+ com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3
+ com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2
+ com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/03-hoststubgen-test-tiny-framework-host-impl-dump.txt b/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/03-hoststubgen-test-tiny-framework-host-impl-dump.txt
new file mode 100644
index 000000000000..5672e9c36706
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/03-hoststubgen-test-tiny-framework-host-impl-dump.txt
@@ -0,0 +1,1774 @@
+## Class: android/hosttest/annotation/HostSideTestClassLoadHook.class
+ Compiled from "HostSideTestClassLoadHook.java"
+public interface android.hosttest.annotation.HostSideTestClassLoadHook extends java.lang.annotation.Annotation
+ minor version: 0
+ major version: 61
+ flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION
+ this_class: #x // android/hosttest/annotation/HostSideTestClassLoadHook
+ super_class: #x // java/lang/Object
+ interfaces: 1, fields: 0, methods: 1, attributes: 2
+ public abstract java.lang.String value();
+ descriptor: ()Ljava/lang/String;
+ flags: (0x0401) ACC_PUBLIC, ACC_ABSTRACT
+}
+SourceFile: "HostSideTestClassLoadHook.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ 1: #x(#x=[e#x.#x])
+ java.lang.annotation.Target(
+ value=[Ljava/lang/annotation/ElementType;.TYPE]
+ )
+ 2: #x(#x=e#x.#x)
+ java.lang.annotation.Retention(
+ value=Ljava/lang/annotation/RetentionPolicy;.CLASS
+ )
+## Class: android/hosttest/annotation/HostSideTestKeep.class
+ Compiled from "HostSideTestKeep.java"
+public interface android.hosttest.annotation.HostSideTestKeep extends java.lang.annotation.Annotation
+ minor version: 0
+ major version: 61
+ flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION
+ this_class: #x // android/hosttest/annotation/HostSideTestKeep
+ super_class: #x // java/lang/Object
+ interfaces: 1, fields: 0, methods: 0, attributes: 2
+}
+SourceFile: "HostSideTestKeep.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ 1: #x(#x=[e#x.#x,e#x.#x,e#x.#x,e#x.#x])
+ java.lang.annotation.Target(
+ value=[Ljava/lang/annotation/ElementType;.TYPE,Ljava/lang/annotation/ElementType;.FIELD,Ljava/lang/annotation/ElementType;.METHOD,Ljava/lang/annotation/ElementType;.CONSTRUCTOR]
+ )
+ 2: #x(#x=e#x.#x)
+ java.lang.annotation.Retention(
+ value=Ljava/lang/annotation/RetentionPolicy;.CLASS
+ )
+## Class: android/hosttest/annotation/HostSideTestNativeSubstitutionClass.class
+ Compiled from "HostSideTestNativeSubstitutionClass.java"
+public interface android.hosttest.annotation.HostSideTestNativeSubstitutionClass extends java.lang.annotation.Annotation
+ minor version: 0
+ major version: 61
+ flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION
+ this_class: #x // android/hosttest/annotation/HostSideTestNativeSubstitutionClass
+ super_class: #x // java/lang/Object
+ interfaces: 1, fields: 0, methods: 1, attributes: 2
+ public abstract java.lang.String value();
+ descriptor: ()Ljava/lang/String;
+ flags: (0x0401) ACC_PUBLIC, ACC_ABSTRACT
+}
+SourceFile: "HostSideTestNativeSubstitutionClass.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ 1: #x(#x=[e#x.#x])
+ java.lang.annotation.Target(
+ value=[Ljava/lang/annotation/ElementType;.TYPE]
+ )
+ 2: #x(#x=e#x.#x)
+ java.lang.annotation.Retention(
+ value=Ljava/lang/annotation/RetentionPolicy;.CLASS
+ )
+## Class: android/hosttest/annotation/HostSideTestRemove.class
+ Compiled from "HostSideTestRemove.java"
+public interface android.hosttest.annotation.HostSideTestRemove extends java.lang.annotation.Annotation
+ minor version: 0
+ major version: 61
+ flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION
+ this_class: #x // android/hosttest/annotation/HostSideTestRemove
+ super_class: #x // java/lang/Object
+ interfaces: 1, fields: 0, methods: 0, attributes: 2
+}
+SourceFile: "HostSideTestRemove.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ 1: #x(#x=[e#x.#x,e#x.#x,e#x.#x,e#x.#x])
+ java.lang.annotation.Target(
+ value=[Ljava/lang/annotation/ElementType;.TYPE,Ljava/lang/annotation/ElementType;.FIELD,Ljava/lang/annotation/ElementType;.METHOD,Ljava/lang/annotation/ElementType;.CONSTRUCTOR]
+ )
+ 2: #x(#x=e#x.#x)
+ java.lang.annotation.Retention(
+ value=Ljava/lang/annotation/RetentionPolicy;.CLASS
+ )
+## Class: android/hosttest/annotation/HostSideTestStub.class
+ Compiled from "HostSideTestStub.java"
+public interface android.hosttest.annotation.HostSideTestStub extends java.lang.annotation.Annotation
+ minor version: 0
+ major version: 61
+ flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION
+ this_class: #x // android/hosttest/annotation/HostSideTestStub
+ super_class: #x // java/lang/Object
+ interfaces: 1, fields: 0, methods: 0, attributes: 2
+}
+SourceFile: "HostSideTestStub.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ 1: #x(#x=[e#x.#x,e#x.#x,e#x.#x,e#x.#x])
+ java.lang.annotation.Target(
+ value=[Ljava/lang/annotation/ElementType;.TYPE,Ljava/lang/annotation/ElementType;.FIELD,Ljava/lang/annotation/ElementType;.METHOD,Ljava/lang/annotation/ElementType;.CONSTRUCTOR]
+ )
+ 2: #x(#x=e#x.#x)
+ java.lang.annotation.Retention(
+ value=Ljava/lang/annotation/RetentionPolicy;.CLASS
+ )
+## Class: android/hosttest/annotation/HostSideTestSubstitute.class
+ Compiled from "HostSideTestSubstitute.java"
+public interface android.hosttest.annotation.HostSideTestSubstitute extends java.lang.annotation.Annotation
+ minor version: 0
+ major version: 61
+ flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION
+ this_class: #x // android/hosttest/annotation/HostSideTestSubstitute
+ super_class: #x // java/lang/Object
+ interfaces: 1, fields: 0, methods: 1, attributes: 2
+ public abstract java.lang.String suffix();
+ descriptor: ()Ljava/lang/String;
+ flags: (0x0401) ACC_PUBLIC, ACC_ABSTRACT
+}
+SourceFile: "HostSideTestSubstitute.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ 1: #x(#x=[e#x.#x])
+ java.lang.annotation.Target(
+ value=[Ljava/lang/annotation/ElementType;.METHOD]
+ )
+ 2: #x(#x=e#x.#x)
+ java.lang.annotation.Retention(
+ value=Ljava/lang/annotation/RetentionPolicy;.CLASS
+ )
+## Class: android/hosttest/annotation/HostSideTestThrow.class
+ Compiled from "HostSideTestThrow.java"
+public interface android.hosttest.annotation.HostSideTestThrow extends java.lang.annotation.Annotation
+ minor version: 0
+ major version: 61
+ flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION
+ this_class: #x // android/hosttest/annotation/HostSideTestThrow
+ super_class: #x // java/lang/Object
+ interfaces: 1, fields: 0, methods: 0, attributes: 2
+}
+SourceFile: "HostSideTestThrow.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ 1: #x(#x=[e#x.#x,e#x.#x])
+ java.lang.annotation.Target(
+ value=[Ljava/lang/annotation/ElementType;.METHOD,Ljava/lang/annotation/ElementType;.CONSTRUCTOR]
+ )
+ 2: #x(#x=e#x.#x)
+ java.lang.annotation.Retention(
+ value=Ljava/lang/annotation/RetentionPolicy;.CLASS
+ )
+## Class: android/hosttest/annotation/HostSideTestWholeClassKeep.class
+ Compiled from "HostSideTestWholeClassKeep.java"
+public interface android.hosttest.annotation.HostSideTestWholeClassKeep extends java.lang.annotation.Annotation
+ minor version: 0
+ major version: 61
+ flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION
+ this_class: #x // android/hosttest/annotation/HostSideTestWholeClassKeep
+ super_class: #x // java/lang/Object
+ interfaces: 1, fields: 0, methods: 0, attributes: 2
+}
+SourceFile: "HostSideTestWholeClassKeep.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ 1: #x(#x=[e#x.#x])
+ java.lang.annotation.Target(
+ value=[Ljava/lang/annotation/ElementType;.TYPE]
+ )
+ 2: #x(#x=e#x.#x)
+ java.lang.annotation.Retention(
+ value=Ljava/lang/annotation/RetentionPolicy;.CLASS
+ )
+## Class: android/hosttest/annotation/HostSideTestWholeClassStub.class
+ Compiled from "HostSideTestWholeClassStub.java"
+public interface android.hosttest.annotation.HostSideTestWholeClassStub extends java.lang.annotation.Annotation
+ minor version: 0
+ major version: 61
+ flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION
+ this_class: #x // android/hosttest/annotation/HostSideTestWholeClassStub
+ super_class: #x // java/lang/Object
+ interfaces: 1, fields: 0, methods: 0, attributes: 2
+}
+SourceFile: "HostSideTestWholeClassStub.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ 1: #x(#x=[e#x.#x])
+ java.lang.annotation.Target(
+ value=[Ljava/lang/annotation/ElementType;.TYPE]
+ )
+ 2: #x(#x=e#x.#x)
+ java.lang.annotation.Retention(
+ value=Ljava/lang/annotation/RetentionPolicy;.CLASS
+ )
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl.class
+ Compiled from "TinyFrameworkCallerCheck.java"
+class com.android.hoststubgen.test.tinyframework.TinyFrameworkCallerCheck$Impl
+ minor version: 0
+ major version: 61
+ flags: (0x0020) ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 0, methods: 3, attributes: 4
+ private com.android.hoststubgen.test.tinyframework.TinyFrameworkCallerCheck$Impl();
+ descriptor: ()V
+ flags: (0x0002) ACC_PRIVATE
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: aload_0
+ 1: invokespecial #x // Method java/lang/Object."<init>":()V
+ 4: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl;
+
+ public static int getOneKeep();
+ descriptor: ()I
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=4, locals=0, args_size=0
+ 0: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl
+ 2: ldc #x // String getOneKeep
+ 4: ldc #x // String ()I
+ 6: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
+ 9: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
+ 12: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
+ 15: iconst_1
+ 16: ireturn
+ LineNumberTable:
+ RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestKeep
+
+ public static int getOneStub();
+ descriptor: ()I
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=1, locals=0, args_size=0
+ 0: iconst_1
+ 1: ireturn
+ LineNumberTable:
+ RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestStub
+}
+InnerClasses:
+ private static #x= #x of #x; // Impl=class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl of class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck
+SourceFile: "TinyFrameworkCallerCheck.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ 1: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck.class
+ Compiled from "TinyFrameworkCallerCheck.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkCallerCheck
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 0, methods: 3, attributes: 5
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkCallerCheck();
+ descriptor: ()V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: aload_0
+ 1: invokespecial #x // Method java/lang/Object."<init>":()V
+ 4: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck;
+
+ public static int getOne_withCheck();
+ descriptor: ()I
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=1, locals=0, args_size=0
+ 0: invokestatic #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl.getOneKeep:()I
+ 3: ireturn
+ LineNumberTable:
+
+ public static int getOne_noCheck();
+ descriptor: ()I
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=1, locals=0, args_size=0
+ 0: invokestatic #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl.getOneStub:()I
+ 3: ireturn
+ LineNumberTable:
+}
+InnerClasses:
+ private static #x= #x of #x; // Impl=class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl of class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck
+SourceFile: "TinyFrameworkCallerCheck.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ 1: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestWholeClassStub
+NestMembers:
+ com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations.class
+ Compiled from "TinyFrameworkClassAnnotations.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassAnnotations
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 2, methods: 8, attributes: 3
+ public int stub;
+ descriptor: I
+ flags: (0x0001) ACC_PUBLIC
+ RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestStub
+
+ public int keep;
+ descriptor: I
+ flags: (0x0001) ACC_PUBLIC
+ RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestKeep
+
+ private static {};
+ descriptor: ()V
+ flags: (0x000a) ACC_PRIVATE, ACC_STATIC
+ Code:
+ stack=2, locals=0, args_size=0
+ 0: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations
+ 2: ldc #x // String com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook.onClassLoaded
+ 4: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V
+ 7: return
+
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkClassAnnotations();
+ descriptor: ()V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=2, locals=1, args_size=1
+ 0: aload_0
+ 1: invokespecial #x // Method java/lang/Object."<init>":()V
+ 4: aload_0
+ 5: iconst_1
+ 6: putfield #x // Field stub:I
+ 9: aload_0
+ 10: iconst_2
+ 11: putfield #x // Field keep:I
+ 14: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 15 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations;
+ RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestStub
+
+ public int addOne(int);
+ descriptor: (I)I
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=2, locals=2, args_size=2
+ 0: aload_0
+ 1: iload_1
+ 2: invokevirtual #x // Method addOneInner:(I)I
+ 5: ireturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 6 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations;
+ 0 6 1 value I
+ RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestStub
+
+ public int addOneInner(int);
+ descriptor: (I)I
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=4, locals=2, args_size=2
+ 0: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations
+ 2: ldc #x // String addOneInner
+ 4: ldc #x // String (I)I
+ 6: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
+ 9: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
+ 12: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
+ 15: iload_1
+ 16: iconst_1
+ 17: iadd
+ 18: ireturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 15 4 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations;
+ 15 4 1 value I
+ RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestKeep
+
+ public int addTwo(int);
+ descriptor: (I)I
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=2, locals=2, args_size=2
+ 0: iload_1
+ 1: iconst_2
+ 2: iadd
+ 3: ireturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 4 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations;
+ 0 4 1 value I
+
+ public static int nativeAddThree(int);
+ descriptor: (I)I
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=2, locals=1, args_size=1
+ 0: iload_0
+ 1: iconst_3
+ 2: iadd
+ 3: ireturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 4 0 value I
+
+ public java.lang.String unsupportedMethod();
+ descriptor: ()Ljava/lang/String;
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=4, locals=1, args_size=1
+ 0: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations
+ 2: ldc #x // String unsupportedMethod
+ 4: ldc #x // String ()Ljava/lang/String;
+ 6: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
+ 9: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
+ 12: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
+ 15: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onThrowMethodCalled:()V
+ 18: new #x // class java/lang/RuntimeException
+ 21: dup
+ 22: ldc #x // String Unreachable
+ 24: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 27: athrow
+ RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestThrow
+
+ public java.lang.String visibleButUsesUnsupportedMethod();
+ descriptor: ()Ljava/lang/String;
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: aload_0
+ 1: invokevirtual #x // Method unsupportedMethod:()Ljava/lang/String;
+ 4: areturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations;
+ RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestStub
+}
+SourceFile: "TinyFrameworkClassAnnotations.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ 1: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestStub
+ 1: #x(#x=s#x)
+ android.hosttest.annotation.HostSideTestClassLoadHook(
+ value="com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook.onClassLoaded"
+ )
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations.class
+ Compiled from "TinyFrameworkClassClassWideAnnotations.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassClassWideAnnotations
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 3, methods: 8, attributes: 3
+ public int stub;
+ descriptor: I
+ flags: (0x0001) ACC_PUBLIC
+
+ public int keep;
+ descriptor: I
+ flags: (0x0001) ACC_PUBLIC
+
+ public int remove;
+ descriptor: I
+ flags: (0x0001) ACC_PUBLIC
+
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkClassClassWideAnnotations();
+ descriptor: ()V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=2, locals=1, args_size=1
+ 0: aload_0
+ 1: invokespecial #x // Method java/lang/Object."<init>":()V
+ 4: aload_0
+ 5: iconst_1
+ 6: putfield #x // Field stub:I
+ 9: aload_0
+ 10: iconst_2
+ 11: putfield #x // Field keep:I
+ 14: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 15 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations;
+
+ public int addOne(int);
+ descriptor: (I)I
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=2, locals=2, args_size=2
+ 0: aload_0
+ 1: iload_1
+ 2: invokevirtual #x // Method addOneInner:(I)I
+ 5: ireturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 6 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations;
+ 0 6 1 value I
+
+ public int addOneInner(int);
+ descriptor: (I)I
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=2, locals=2, args_size=2
+ 0: iload_1
+ 1: iconst_1
+ 2: iadd
+ 3: ireturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 4 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations;
+ 0 4 1 value I
+
+ public void toBeRemoved(java.lang.String);
+ descriptor: (Ljava/lang/String;)V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=2, locals=2, args_size=2
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: invokespecial #x // Method java/lang/RuntimeException."<init>":()V
+ 7: athrow
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 8 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations;
+ 0 8 1 foo Ljava/lang/String;
+
+ public int addTwo(int);
+ descriptor: (I)I
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=2, locals=2, args_size=2
+ 0: iload_1
+ 1: iconst_2
+ 2: iadd
+ 3: ireturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 4 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations;
+ 0 4 1 value I
+
+ public static int nativeAddThree(int);
+ descriptor: (I)I
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=2, locals=1, args_size=1
+ 0: iload_0
+ 1: iconst_3
+ 2: iadd
+ 3: ireturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 4 0 value I
+
+ public java.lang.String unsupportedMethod();
+ descriptor: ()Ljava/lang/String;
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: ldc #x // String This value shouldn\'t be seen on the host side.
+ 2: areturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 3 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations;
+
+ public java.lang.String visibleButUsesUnsupportedMethod();
+ descriptor: ()Ljava/lang/String;
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: aload_0
+ 1: invokevirtual #x // Method unsupportedMethod:()Ljava/lang/String;
+ 4: areturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations;
+}
+SourceFile: "TinyFrameworkClassClassWideAnnotations.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ 1: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestWholeClassStub
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkClassLoadHook.class
+ Compiled from "TinyFrameworkClassLoadHook.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkClassLoadHook
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 1, methods: 3, attributes: 3
+ public static final java.util.Set<java.lang.Class<?>> sLoadedClasses;
+ descriptor: Ljava/util/Set;
+ flags: (0x0019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL
+ Signature: #x // Ljava/util/Set<Ljava/lang/Class<*>;>;
+
+ private com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook();
+ descriptor: ()V
+ flags: (0x0002) ACC_PRIVATE
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: aload_0
+ 1: invokespecial #x // Method java/lang/Object."<init>":()V
+ 4: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassLoadHook;
+
+ public static void onClassLoaded(java.lang.Class<?>);
+ descriptor: (Ljava/lang/Class;)V
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=2, locals=1, args_size=1
+ 0: getstatic #x // Field sLoadedClasses:Ljava/util/Set;
+ 3: aload_0
+ 4: invokeinterface #x, 2 // InterfaceMethod java/util/Set.add:(Ljava/lang/Object;)Z
+ 9: pop
+ 10: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 11 0 clazz Ljava/lang/Class;
+ LocalVariableTypeTable:
+ Start Length Slot Name Signature
+ 0 11 0 clazz Ljava/lang/Class<*>;
+ Signature: #x // (Ljava/lang/Class<*>;)V
+
+ static {};
+ descriptor: ()V
+ flags: (0x0008) ACC_STATIC
+ Code:
+ stack=2, locals=0, args_size=0
+ 0: new #x // class java/util/HashSet
+ 3: dup
+ 4: invokespecial #x // Method java/util/HashSet."<init>":()V
+ 7: putstatic #x // Field sLoadedClasses:Ljava/util/Set;
+ 10: return
+ LineNumberTable:
+}
+SourceFile: "TinyFrameworkClassLoadHook.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ 1: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestWholeClassStub
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializer.class
+ Compiled from "TinyFrameworkClassWithInitializer.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassWithInitializer
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializer
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 1, methods: 2, attributes: 3
+ public static boolean sInitialized;
+ descriptor: Z
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkClassWithInitializer();
+ descriptor: ()V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: aload_0
+ 1: invokespecial #x // Method java/lang/Object."<init>":()V
+ 4: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializer;
+
+ static {};
+ descriptor: ()V
+ flags: (0x0008) ACC_STATIC
+ Code:
+ stack=2, locals=0, args_size=0
+ 0: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializer
+ 2: ldc #x // String com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook.onClassLoaded
+ 4: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V
+ 7: iconst_1
+ 8: putstatic #x // Field sInitialized:Z
+ 11: return
+ LineNumberTable:
+}
+SourceFile: "TinyFrameworkClassWithInitializer.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ 1: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+RuntimeInvisibleAnnotations:
+ 0: #x(#x=s#x)
+ android.hosttest.annotation.HostSideTestClassLoadHook(
+ value="com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook.onClassLoaded"
+ )
+ 1: #x()
+ android.hosttest.annotation.HostSideTestWholeClassStub
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkExceptionTester.class
+ Compiled from "TinyFrameworkExceptionTester.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkExceptionTester
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkExceptionTester
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 0, methods: 2, attributes: 3
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkExceptionTester();
+ descriptor: ()V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: aload_0
+ 1: invokespecial #x // Method java/lang/Object."<init>":()V
+ 4: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkExceptionTester;
+
+ public static int testException();
+ descriptor: ()I
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=4, locals=1, args_size=0
+ 0: new #x // class java/lang/IllegalStateException
+ 3: dup
+ 4: ldc #x // String Inner exception
+ 6: invokespecial #x // Method java/lang/IllegalStateException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+ 10: astore_0
+ 11: new #x // class java/lang/RuntimeException
+ 14: dup
+ 15: ldc #x // String Outer exception
+ 17: aload_0
+ 18: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;Ljava/lang/Throwable;)V
+ 21: athrow
+ Exception table:
+ from to target type
+ 0 10 10 Class java/lang/Exception
+ StackMapTable: number_of_entries = 1
+ frame_type = 74 /* same_locals_1_stack_item */
+ stack = [ class java/lang/Exception ]
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 11 11 0 e Ljava/lang/Exception;
+}
+SourceFile: "TinyFrameworkExceptionTester.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ 1: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestWholeClassStub
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy.class
+ Compiled from "TinyFrameworkForTextPolicy.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkForTextPolicy
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 2, methods: 8, attributes: 2
+ public int stub;
+ descriptor: I
+ flags: (0x0001) ACC_PUBLIC
+
+ public int keep;
+ descriptor: I
+ flags: (0x0001) ACC_PUBLIC
+
+ private static {};
+ descriptor: ()V
+ flags: (0x000a) ACC_PRIVATE, ACC_STATIC
+ Code:
+ stack=2, locals=0, args_size=0
+ 0: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy
+ 2: ldc #x // String com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook.onClassLoaded
+ 4: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V
+ 7: return
+
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkForTextPolicy();
+ descriptor: ()V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=2, locals=1, args_size=1
+ 0: aload_0
+ 1: invokespecial #x // Method java/lang/Object."<init>":()V
+ 4: aload_0
+ 5: iconst_1
+ 6: putfield #x // Field stub:I
+ 9: aload_0
+ 10: iconst_2
+ 11: putfield #x // Field keep:I
+ 14: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 15 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy;
+
+ public int addOne(int);
+ descriptor: (I)I
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=2, locals=2, args_size=2
+ 0: aload_0
+ 1: iload_1
+ 2: invokevirtual #x // Method addOneInner:(I)I
+ 5: ireturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 6 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy;
+ 0 6 1 value I
+
+ public int addOneInner(int);
+ descriptor: (I)I
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=4, locals=2, args_size=2
+ 0: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy
+ 2: ldc #x // String addOneInner
+ 4: ldc #x // String (I)I
+ 6: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
+ 9: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
+ 12: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
+ 15: iload_1
+ 16: iconst_1
+ 17: iadd
+ 18: ireturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 15 4 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy;
+ 15 4 1 value I
+
+ public int addTwo(int);
+ descriptor: (I)I
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=2, locals=2, args_size=2
+ 0: iload_1
+ 1: iconst_2
+ 2: iadd
+ 3: ireturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 4 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy;
+ 0 4 1 value I
+
+ public static int nativeAddThree(int);
+ descriptor: (I)I
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=2, locals=1, args_size=1
+ 0: iload_0
+ 1: iconst_3
+ 2: iadd
+ 3: ireturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 4 0 value I
+
+ public java.lang.String unsupportedMethod();
+ descriptor: ()Ljava/lang/String;
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=4, locals=1, args_size=1
+ 0: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy
+ 2: ldc #x // String unsupportedMethod
+ 4: ldc #x // String ()Ljava/lang/String;
+ 6: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
+ 9: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
+ 12: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
+ 15: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onThrowMethodCalled:()V
+ 18: new #x // class java/lang/RuntimeException
+ 21: dup
+ 22: ldc #x // String Unreachable
+ 24: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 27: athrow
+
+ public java.lang.String visibleButUsesUnsupportedMethod();
+ descriptor: ()Ljava/lang/String;
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: aload_0
+ 1: invokevirtual #x // Method unsupportedMethod:()Ljava/lang/String;
+ 4: areturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy;
+}
+SourceFile: "TinyFrameworkForTextPolicy.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ 1: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNative.class
+ Compiled from "TinyFrameworkNative.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNative
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNative
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 0, methods: 5, attributes: 3
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkNative();
+ descriptor: ()V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: aload_0
+ 1: invokespecial #x // Method java/lang/Object."<init>":()V
+ 4: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative;
+
+ public static int nativeAddTwo(int);
+ descriptor: (I)I
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: iload_0
+ 1: invokestatic #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.nativeAddTwo:(I)I
+ 4: ireturn
+
+ public static int nativeAddTwo_should_be_like_this(int);
+ descriptor: (I)I
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: iload_0
+ 1: invokestatic #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.nativeAddTwo:(I)I
+ 4: ireturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 arg I
+
+ public static long nativeLongPlus(long, long);
+ descriptor: (JJ)J
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=4, locals=4, args_size=2
+ 0: lload_0
+ 1: lload_2
+ 2: invokestatic #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.nativeLongPlus:(JJ)J
+ 5: lreturn
+
+ public static long nativeLongPlus_should_be_like_this(long, long);
+ descriptor: (JJ)J
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=4, locals=4, args_size=2
+ 0: lload_0
+ 1: lload_2
+ 2: invokestatic #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.nativeLongPlus:(JJ)J
+ 5: lreturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 6 0 arg1 J
+ 0 6 2 arg2 J
+}
+SourceFile: "TinyFrameworkNative.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ 1: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestWholeClassStub
+ 1: #x(#x=s#x)
+ android.hosttest.annotation.HostSideTestNativeSubstitutionClass(
+ value="TinyFrameworkNative_host"
+ )
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.class
+ Compiled from "TinyFrameworkNative_host.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNative_host
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 0, methods: 3, attributes: 3
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkNative_host();
+ descriptor: ()V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=4, locals=1, args_size=1
+ 0: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host
+ 2: ldc #x // String <init>
+ 4: ldc #x // String ()V
+ 6: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
+ 9: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
+ 12: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
+ 15: aload_0
+ 16: invokespecial #x // Method java/lang/Object."<init>":()V
+ 19: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 15 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host;
+
+ public static int nativeAddTwo(int);
+ descriptor: (I)I
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=4, locals=1, args_size=1
+ 0: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host
+ 2: ldc #x // String nativeAddTwo
+ 4: ldc #x // String (I)I
+ 6: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
+ 9: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
+ 12: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
+ 15: iload_0
+ 16: iconst_2
+ 17: iadd
+ 18: ireturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 15 4 0 arg I
+
+ public static long nativeLongPlus(long, long);
+ descriptor: (JJ)J
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=4, locals=4, args_size=2
+ 0: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host
+ 2: ldc #x // String nativeLongPlus
+ 4: ldc #x // String (JJ)J
+ 6: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
+ 9: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
+ 12: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
+ 15: lload_0
+ 16: lload_2
+ 17: ladd
+ 18: lreturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 15 4 0 arg1 J
+ 15 4 2 arg2 J
+}
+SourceFile: "TinyFrameworkNative_host.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestWholeClassKeep
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1.class
+ Compiled from "TinyFrameworkNestedClasses.java"
+class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$1 extends java.lang.Object implements java.util.function.Supplier<java.lang.Integer>
+ minor version: 0
+ major version: 61
+ flags: (0x0020) ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1
+ super_class: #x // java/lang/Object
+ interfaces: 1, fields: 1, methods: 3, attributes: 6
+ final com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses this$0;
+ descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;
+ flags: (0x1010) ACC_FINAL, ACC_SYNTHETIC
+
+ com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$1(com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses);
+ descriptor: (Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;)V
+ flags: (0x0000)
+ Code:
+ stack=2, locals=2, args_size=2
+ 0: aload_0
+ 1: aload_1
+ 2: putfield #x // Field this$0:Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;
+ 5: aload_0
+ 6: invokespecial #x // Method java/lang/Object."<init>":()V
+ 9: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 10 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1;
+ 0 10 1 this$0 Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;
+
+ public java.lang.Integer get();
+ descriptor: ()Ljava/lang/Integer;
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=4, locals=1, args_size=1
+ 0: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1
+ 2: ldc #x // String get
+ 4: ldc #x // String ()Ljava/lang/Integer;
+ 6: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
+ 9: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
+ 12: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
+ 15: iconst_1
+ 16: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
+ 19: areturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 15 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1;
+
+ public java.lang.Object get();
+ descriptor: ()Ljava/lang/Object;
+ flags: (0x1041) ACC_PUBLIC, ACC_BRIDGE, ACC_SYNTHETIC
+ Code:
+ stack=4, locals=1, args_size=1
+ 0: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1
+ 2: ldc #x // String get
+ 4: ldc #x // String ()Ljava/lang/Object;
+ 6: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
+ 9: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
+ 12: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
+ 15: aload_0
+ 16: invokevirtual #x // Method get:()Ljava/lang/Integer;
+ 19: areturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 15 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1;
+}
+InnerClasses:
+ #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1
+EnclosingMethod: #x.#x // com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses
+Signature: #x // Ljava/lang/Object;Ljava/util/function/Supplier<Ljava/lang/Integer;>;
+SourceFile: "TinyFrameworkNestedClasses.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2.class
+ Compiled from "TinyFrameworkNestedClasses.java"
+class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$2 extends java.lang.Object implements java.util.function.Supplier<java.lang.Integer>
+ minor version: 0
+ major version: 61
+ flags: (0x0020) ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2
+ super_class: #x // java/lang/Object
+ interfaces: 1, fields: 0, methods: 3, attributes: 6
+ com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$2();
+ descriptor: ()V
+ flags: (0x0000)
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: aload_0
+ 1: invokespecial #x // Method java/lang/Object."<init>":()V
+ 4: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2;
+
+ public java.lang.Integer get();
+ descriptor: ()Ljava/lang/Integer;
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=4, locals=1, args_size=1
+ 0: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2
+ 2: ldc #x // String get
+ 4: ldc #x // String ()Ljava/lang/Integer;
+ 6: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
+ 9: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
+ 12: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
+ 15: iconst_2
+ 16: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
+ 19: areturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 15 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2;
+
+ public java.lang.Object get();
+ descriptor: ()Ljava/lang/Object;
+ flags: (0x1041) ACC_PUBLIC, ACC_BRIDGE, ACC_SYNTHETIC
+ Code:
+ stack=4, locals=1, args_size=1
+ 0: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2
+ 2: ldc #x // String get
+ 4: ldc #x // String ()Ljava/lang/Object;
+ 6: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
+ 9: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
+ 12: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
+ 15: aload_0
+ 16: invokevirtual #x // Method get:()Ljava/lang/Integer;
+ 19: areturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 15 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2;
+}
+InnerClasses:
+ #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2
+EnclosingMethod: #x.#x // com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses
+Signature: #x // Ljava/lang/Object;Ljava/util/function/Supplier<Ljava/lang/Integer;>;
+SourceFile: "TinyFrameworkNestedClasses.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3.class
+ Compiled from "TinyFrameworkNestedClasses.java"
+class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$3 extends java.lang.Object implements java.util.function.Supplier<java.lang.Integer>
+ minor version: 0
+ major version: 61
+ flags: (0x0020) ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3
+ super_class: #x // java/lang/Object
+ interfaces: 1, fields: 1, methods: 3, attributes: 6
+ final com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses this$0;
+ descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;
+ flags: (0x1010) ACC_FINAL, ACC_SYNTHETIC
+
+ com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$3(com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses);
+ descriptor: (Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;)V
+ flags: (0x0000)
+ Code:
+ stack=2, locals=2, args_size=2
+ 0: aload_0
+ 1: aload_1
+ 2: putfield #x // Field this$0:Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;
+ 5: aload_0
+ 6: invokespecial #x // Method java/lang/Object."<init>":()V
+ 9: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 10 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3;
+ 0 10 1 this$0 Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;
+
+ public java.lang.Integer get();
+ descriptor: ()Ljava/lang/Integer;
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=4, locals=1, args_size=1
+ 0: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3
+ 2: ldc #x // String get
+ 4: ldc #x // String ()Ljava/lang/Integer;
+ 6: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
+ 9: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
+ 12: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
+ 15: iconst_3
+ 16: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
+ 19: areturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 15 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3;
+
+ public java.lang.Object get();
+ descriptor: ()Ljava/lang/Object;
+ flags: (0x1041) ACC_PUBLIC, ACC_BRIDGE, ACC_SYNTHETIC
+ Code:
+ stack=4, locals=1, args_size=1
+ 0: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3
+ 2: ldc #x // String get
+ 4: ldc #x // String ()Ljava/lang/Object;
+ 6: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
+ 9: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
+ 12: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
+ 15: aload_0
+ 16: invokevirtual #x // Method get:()Ljava/lang/Integer;
+ 19: areturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 15 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3;
+}
+InnerClasses:
+ #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3
+EnclosingMethod: #x.#x // com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses.getSupplier
+Signature: #x // Ljava/lang/Object;Ljava/util/function/Supplier<Ljava/lang/Integer;>;
+SourceFile: "TinyFrameworkNestedClasses.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4.class
+ Compiled from "TinyFrameworkNestedClasses.java"
+class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$4 extends java.lang.Object implements java.util.function.Supplier<java.lang.Integer>
+ minor version: 0
+ major version: 61
+ flags: (0x0020) ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4
+ super_class: #x // java/lang/Object
+ interfaces: 1, fields: 0, methods: 3, attributes: 6
+ com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$4();
+ descriptor: ()V
+ flags: (0x0000)
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: aload_0
+ 1: invokespecial #x // Method java/lang/Object."<init>":()V
+ 4: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4;
+
+ public java.lang.Integer get();
+ descriptor: ()Ljava/lang/Integer;
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=4, locals=1, args_size=1
+ 0: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4
+ 2: ldc #x // String get
+ 4: ldc #x // String ()Ljava/lang/Integer;
+ 6: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
+ 9: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
+ 12: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
+ 15: iconst_4
+ 16: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
+ 19: areturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 15 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4;
+
+ public java.lang.Object get();
+ descriptor: ()Ljava/lang/Object;
+ flags: (0x1041) ACC_PUBLIC, ACC_BRIDGE, ACC_SYNTHETIC
+ Code:
+ stack=4, locals=1, args_size=1
+ 0: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4
+ 2: ldc #x // String get
+ 4: ldc #x // String ()Ljava/lang/Object;
+ 6: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
+ 9: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
+ 12: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
+ 15: aload_0
+ 16: invokevirtual #x // Method get:()Ljava/lang/Integer;
+ 19: areturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 15 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4;
+}
+InnerClasses:
+ #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4
+EnclosingMethod: #x.#x // com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses.getSupplier_static
+Signature: #x // Ljava/lang/Object;Ljava/util/function/Supplier<Ljava/lang/Integer;>;
+SourceFile: "TinyFrameworkNestedClasses.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass.class
+ Compiled from "TinyFrameworkNestedClasses.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$BaseClass
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 1, methods: 1, attributes: 4
+ public int value;
+ descriptor: I
+ flags: (0x0001) ACC_PUBLIC
+
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$BaseClass(int);
+ descriptor: (I)V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=2, locals=2, args_size=2
+ 0: aload_0
+ 1: invokespecial #x // Method java/lang/Object."<init>":()V
+ 4: aload_0
+ 5: iload_1
+ 6: putfield #x // Field value:I
+ 9: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 10 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass;
+ 0 10 1 x I
+}
+InnerClasses:
+ public static #x= #x of #x; // BaseClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+SourceFile: "TinyFrameworkNestedClasses.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ 1: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass.class
+ Compiled from "TinyFrameworkNestedClasses.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$InnerClass
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 2, methods: 1, attributes: 5
+ public int value;
+ descriptor: I
+ flags: (0x0001) ACC_PUBLIC
+
+ final com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses this$0;
+ descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;
+ flags: (0x1010) ACC_FINAL, ACC_SYNTHETIC
+
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$InnerClass(com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses);
+ descriptor: (Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;)V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=2, locals=2, args_size=2
+ 0: aload_0
+ 1: aload_1
+ 2: putfield #x // Field this$0:Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;
+ 5: aload_0
+ 6: invokespecial #x // Method java/lang/Object."<init>":()V
+ 9: aload_0
+ 10: iconst_5
+ 11: putfield #x // Field value:I
+ 14: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 15 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass;
+ 0 15 1 this$0 Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;
+}
+InnerClasses:
+ public #x= #x of #x; // InnerClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+SourceFile: "TinyFrameworkNestedClasses.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ 1: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestWholeClassStub
+NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1.class
+ Compiled from "TinyFrameworkNestedClasses.java"
+class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$StaticNestedClass$1 extends java.lang.Object implements java.util.function.Supplier<java.lang.Integer>
+ minor version: 0
+ major version: 61
+ flags: (0x0020) ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1
+ super_class: #x // java/lang/Object
+ interfaces: 1, fields: 0, methods: 3, attributes: 6
+ com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$StaticNestedClass$1();
+ descriptor: ()V
+ flags: (0x0000)
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: aload_0
+ 1: invokespecial #x // Method java/lang/Object."<init>":()V
+ 4: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1;
+
+ public java.lang.Integer get();
+ descriptor: ()Ljava/lang/Integer;
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=4, locals=1, args_size=1
+ 0: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1
+ 2: ldc #x // String get
+ 4: ldc #x // String ()Ljava/lang/Integer;
+ 6: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
+ 9: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
+ 12: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
+ 15: bipush 7
+ 17: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
+ 20: areturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 15 6 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1;
+
+ public java.lang.Object get();
+ descriptor: ()Ljava/lang/Object;
+ flags: (0x1041) ACC_PUBLIC, ACC_BRIDGE, ACC_SYNTHETIC
+ Code:
+ stack=4, locals=1, args_size=1
+ 0: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1
+ 2: ldc #x // String get
+ 4: ldc #x // String ()Ljava/lang/Object;
+ 6: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
+ 9: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
+ 12: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
+ 15: aload_0
+ 16: invokevirtual #x // Method get:()Ljava/lang/Integer;
+ 19: areturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 15 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1;
+}
+InnerClasses:
+ public static #x= #x of #x; // StaticNestedClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+ #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1
+EnclosingMethod: #x.#x // com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$StaticNestedClass.getSupplier_static
+Signature: #x // Ljava/lang/Object;Ljava/util/function/Supplier<Ljava/lang/Integer;>;
+SourceFile: "TinyFrameworkNestedClasses.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass.class
+ Compiled from "TinyFrameworkNestedClasses.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$StaticNestedClass
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 1, methods: 2, attributes: 5
+ public int value;
+ descriptor: I
+ flags: (0x0001) ACC_PUBLIC
+
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$StaticNestedClass();
+ descriptor: ()V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=2, locals=1, args_size=1
+ 0: aload_0
+ 1: invokespecial #x // Method java/lang/Object."<init>":()V
+ 4: aload_0
+ 5: bipush 6
+ 7: putfield #x // Field value:I
+ 10: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 11 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass;
+
+ public static java.util.function.Supplier<java.lang.Integer> getSupplier_static();
+ descriptor: ()Ljava/util/function/Supplier;
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=2, locals=0, args_size=0
+ 0: new #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1
+ 3: dup
+ 4: invokespecial #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1."<init>":()V
+ 7: areturn
+ LineNumberTable:
+ Signature: #x // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>;
+}
+InnerClasses:
+ public static #x= #x of #x; // StaticNestedClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+ #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1
+SourceFile: "TinyFrameworkNestedClasses.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ 1: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestWholeClassStub
+NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass.class
+ Compiled from "TinyFrameworkNestedClasses.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$SubClass extends com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$BaseClass
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ 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: 4
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$SubClass(int);
+ descriptor: (I)V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=2, locals=2, args_size=2
+ 0: aload_0
+ 1: iload_1
+ 2: invokespecial #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass."<init>":(I)V
+ 5: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 6 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass;
+ 0 6 1 x I
+}
+InnerClasses:
+ public static #x= #x of #x; // BaseClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+ public static #x= #x of #x; // SubClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+SourceFile: "TinyFrameworkNestedClasses.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ 1: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses.class
+ Compiled from "TinyFrameworkNestedClasses.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 2, methods: 4, attributes: 5
+ public final java.util.function.Supplier<java.lang.Integer> mSupplier;
+ descriptor: Ljava/util/function/Supplier;
+ flags: (0x0011) ACC_PUBLIC, ACC_FINAL
+ Signature: #x // Ljava/util/function/Supplier<Ljava/lang/Integer;>;
+
+ public static final java.util.function.Supplier<java.lang.Integer> sSupplier;
+ descriptor: Ljava/util/function/Supplier;
+ flags: (0x0019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL
+ Signature: #x // Ljava/util/function/Supplier<Ljava/lang/Integer;>;
+
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses();
+ descriptor: ()V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=4, locals=1, args_size=1
+ 0: aload_0
+ 1: invokespecial #x // Method java/lang/Object."<init>":()V
+ 4: aload_0
+ 5: new #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1
+ 8: dup
+ 9: aload_0
+ 10: invokespecial #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1."<init>":(Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;)V
+ 13: putfield #x // Field mSupplier:Ljava/util/function/Supplier;
+ 16: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 17 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;
+
+ public java.util.function.Supplier<java.lang.Integer> getSupplier();
+ descriptor: ()Ljava/util/function/Supplier;
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=3, locals=1, args_size=1
+ 0: new #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3
+ 3: dup
+ 4: aload_0
+ 5: invokespecial #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3."<init>":(Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;)V
+ 8: areturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 9 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;
+ Signature: #x // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>;
+
+ public static java.util.function.Supplier<java.lang.Integer> getSupplier_static();
+ descriptor: ()Ljava/util/function/Supplier;
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=2, locals=0, args_size=0
+ 0: new #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4
+ 3: dup
+ 4: invokespecial #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4."<init>":()V
+ 7: areturn
+ LineNumberTable:
+ Signature: #x // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>;
+
+ static {};
+ descriptor: ()V
+ flags: (0x0008) ACC_STATIC
+ Code:
+ stack=2, locals=0, args_size=0
+ 0: new #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2
+ 3: dup
+ 4: invokespecial #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2."<init>":()V
+ 7: putstatic #x // Field sSupplier:Ljava/util/function/Supplier;
+ 10: return
+ LineNumberTable:
+}
+InnerClasses:
+ #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1
+ #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3
+ #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4
+ #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2
+ public static #x= #x of #x; // SubClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+ public static #x= #x of #x; // BaseClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+ public static #x= #x of #x; // StaticNestedClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+ public #x= #x of #x; // InnerClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+ #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1
+SourceFile: "TinyFrameworkNestedClasses.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ 1: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestWholeClassStub
+NestMembers:
+ com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass
+ com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass
+ com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass
+ com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1
+ com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass
+ com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4
+ com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3
+ com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2
+ com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/policy-override-tiny-framework.txt b/tools/hoststubgen/hoststubgen/test-tiny-framework/policy-override-tiny-framework.txt
new file mode 100644
index 000000000000..079d2a84e498
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/policy-override-tiny-framework.txt
@@ -0,0 +1,17 @@
+class com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy stub
+ field stub stub
+ field keep keep
+ # field remove remove # Implicitly remove
+ method <init> ()V stub
+ method addOne (I)I stub
+ method addOneInner (I)I keep
+ method toBeRemoved (Ljava/lang/String;)V remove
+ method addTwo (I)I @addTwo_host
+ # method addTwo_host (I)I # used as a substitute
+ method nativeAddThree (I)I @addThree_host
+ # method addThree_host (I)I # used as a substitute
+ method unsupportedMethod ()Ljava/lang/String; throw
+ method visibleButUsesUnsupportedMethod ()Ljava/lang/String; stub
+
+# Class load hook
+class com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy ~com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook.onClassLoaded
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/run-test-manually.sh b/tools/hoststubgen/hoststubgen/test-tiny-framework/run-test-manually.sh
new file mode 100755
index 000000000000..fd486468a1a7
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/run-test-manually.sh
@@ -0,0 +1,132 @@
+#!/bin/bash
+# Copyright (C) 2023 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.
+
+
+source "${0%/*}"/../../common.sh
+
+# This scripts run the "tiny-framework" test, but does most stuff from the command line, using
+# the native java and javac commands.
+# This is useful to
+
+
+debug=0
+while getopts "d" opt; do
+case "$opt" in
+ d) debug=1 ;;
+esac
+done
+shift $(($OPTIND - 1))
+
+
+out=out
+
+rm -fr $out
+mkdir -p $out
+
+HOSTSTUBGEN=hoststubgen
+
+# Rebuild the tool and the dependencies. These are the only things we build with the build system.
+run m $HOSTSTUBGEN hoststubgen-annotations hoststubgen-helper-runtime truth-prebuilt junit
+
+
+# Build tiny-framework
+
+tiny_framework_classes=$out/tiny-framework/classes/
+tiny_framework_jar=$out/tiny-framework.jar
+tiny_framework_host_stub_jar=$out/tiny-framework_host_stub.jar
+tiny_framework_host_impl_jar=$out/tiny-framework_host_impl.jar
+
+tiny_test_classes=$out/tiny-test/classes/
+tiny_test_jar=$out/tiny-test.jar
+
+framework_compile_classpaths=(
+ $SOONG_INT/frameworks/base/tools/hoststubgen/hoststubgen/hoststubgen-annotations/android_common/javac/hoststubgen-annotations.jar
+)
+
+test_compile_classpaths=(
+ $SOONG_INT/external/junit/junit/android_common/combined/junit.jar
+ $SOONG_INT/prebuilts/tools/common/m2/truth-prebuilt/android_common/combined/truth-prebuilt.jar
+)
+
+test_runtime_classpaths=(
+ $SOONG_INT/frameworks/base/tools/hoststubgen/hoststubgen/hoststubgen-helper-runtime/linux_glibc_common/javac/hoststubgen-helper-runtime.jar
+)
+
+# This suite runs all tests in the JAR.
+test_classes=(com.android.hoststubgen.hosthelper.HostTestSuite)
+
+# Uncomment this to run a specific test.
+# tests=(com.android.hoststubgen.test.tinyframework.TinyFrameworkBenchmark)
+
+
+# Build tiny-framework.jar
+echo "# Building tiny-framework..."
+run $JAVAC \
+ -cp $( \
+ join : \
+ ${framework_compile_classpaths[@]} \
+ ) \
+ -d $tiny_framework_classes \
+ tiny-framework/src/**/*.java
+
+run $JAR cvf $tiny_framework_jar \
+ -C $tiny_framework_classes .
+
+# Build stub/impl jars
+echo "# Generating the stub and impl jars..."
+run $HOSTSTUBGEN \
+ @../hoststubgen-standard-options.txt \
+ --in-jar $tiny_framework_jar \
+ --out-stub-jar $tiny_framework_host_stub_jar \
+ --out-impl-jar $tiny_framework_host_impl_jar \
+ --policy-override-file policy-override-tiny-framework.txt \
+ --gen-keep-all-file out/tiny-framework_keep_all.txt \
+ --gen-input-dump-file out/tiny-framework_dump.txt \
+ $HOSTSTUBGEN_OPTS
+
+# Extract the jar files, so we can look into them.
+extract $tiny_framework_host_stub_jar $tiny_framework_host_impl_jar
+
+# Build the test
+echo "# Building tiny-test..."
+run $JAVAC \
+ -cp $( \
+ join : \
+ $tiny_framework_host_stub_jar \
+ "${test_compile_classpaths[@]}" \
+ ) \
+ -d $tiny_test_classes \
+ tiny-test/src/**/*.java
+
+run $JAR cvf $tiny_test_jar \
+ -C $tiny_test_classes .
+
+if (( $debug )) ; then
+ JAVA_OPTS="$JAVA_OPTS -agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=8700"
+fi
+
+# Run the test
+echo "# Running tiny-test..."
+run $JAVA \
+ $JAVA_OPTS \
+ -cp $( \
+ join : \
+ $tiny_test_jar \
+ $tiny_framework_host_impl_jar \
+ "${test_compile_classpaths[@]}" \
+ "${test_runtime_classpaths[@]}" \
+ ) \
+ org.junit.runner.JUnitCore \
+ ${test_classes[@]}
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework-dump-test.py b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework-dump-test.py
new file mode 100755
index 000000000000..cee29dcd1d59
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework-dump-test.py
@@ -0,0 +1,64 @@
+#!/usr/bin/python3
+# Copyright (C) 2023 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.
+
+# Compare the tiny-framework JAR dumps to the golden files.
+
+import sys
+import os
+import unittest
+import subprocess
+
+GOLDEN_DIR = 'golden-output'
+
+# Run diff.
+def run_diff(file1, file2):
+ command = ['diff', '-u', '--ignore-blank-lines', '--ignore-space-change', file1, file2]
+ print(' '.join(command))
+ result = subprocess.run(command, stderr = sys.stdout)
+
+ success = result.returncode == 0
+
+ if success:
+ print(f'No diff found.')
+ else:
+ print(f'Fail: {file1} and {file2} are different.')
+
+ return success
+
+
+# Check one golden file.
+def check_one_file(filename):
+ print(f'= Checking file: {filename}')
+ return run_diff(os.path.join(GOLDEN_DIR, filename), filename)
+
+class TestWithGoldenOutput(unittest.TestCase):
+
+ # Test to check the generated jar files to the golden output.
+ def test_compare_to_golden(self):
+ files = os.listdir(GOLDEN_DIR)
+ files.sort()
+
+ print(f"Golden files: {files}")
+ success = True
+
+ for file in files:
+ if not check_one_file(file):
+ success = False
+
+ if not success:
+ self.fail('Some files are different. See stdout log for more details.')
+
+if __name__ == "__main__":
+ unittest.main(verbosity=2)
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck.java b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck.java
new file mode 100644
index 000000000000..f53020771cc3
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2023 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.hoststubgen.test.tinyframework;
+
+import android.hosttest.annotation.HostSideTestKeep;
+import android.hosttest.annotation.HostSideTestStub;
+import android.hosttest.annotation.HostSideTestWholeClassStub;
+
+/**
+ * Used by the benchmark.
+ */
+@HostSideTestWholeClassStub
+public class TinyFrameworkCallerCheck {
+
+ /**
+ * This method uses an inner method (which has the caller check).
+ *
+ * Benchmark result: 768ns
+ */
+ public static int getOne_withCheck() {
+ return Impl.getOneKeep();
+ }
+
+ /**
+ * This method doesn't have any caller check.
+ *
+ * Benchmark result: 2ns
+ */
+ public static int getOne_noCheck() {
+ return Impl.getOneStub();
+ }
+
+ private static class Impl {
+ @HostSideTestKeep
+ public static int getOneKeep() {
+ return 1;
+ }
+
+ @HostSideTestStub
+ public static int getOneStub() {
+ return 1;
+ }
+ }
+}
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations.java b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations.java
new file mode 100644
index 000000000000..ab387e0938c3
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2023 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.hoststubgen.test.tinyframework;
+
+import android.hosttest.annotation.HostSideTestClassLoadHook;
+import android.hosttest.annotation.HostSideTestKeep;
+import android.hosttest.annotation.HostSideTestRemove;
+import android.hosttest.annotation.HostSideTestStub;
+import android.hosttest.annotation.HostSideTestSubstitute;
+import android.hosttest.annotation.HostSideTestThrow;
+
+/**
+ * Test without class-wide annotations.
+ */
+@HostSideTestStub
+@HostSideTestClassLoadHook(
+ "com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook.onClassLoaded")
+public class TinyFrameworkClassAnnotations {
+ @HostSideTestStub
+ public TinyFrameworkClassAnnotations() {
+ }
+
+ @HostSideTestStub
+ public int stub = 1;
+
+ @HostSideTestKeep
+ public int keep = 2;
+
+ // Members will be deleted by default.
+ // Deleted fields cannot have an initial value, because otherwise .ctor will fail to set it at
+ // runtime.
+ public int remove;
+
+ @HostSideTestStub
+ public int addOne(int value) {
+ return addOneInner(value);
+ }
+
+ @HostSideTestKeep
+ public int addOneInner(int value) {
+ return value + 1;
+ }
+
+ @HostSideTestRemove // Explicitly remove
+ public void toBeRemoved(String foo) {
+ throw new RuntimeException();
+ }
+
+ @HostSideTestStub
+ @HostSideTestSubstitute(suffix = "_host")
+ public int addTwo(int value) {
+ throw new RuntimeException("not supported on host side");
+ }
+
+ public int addTwo_host(int value) {
+ return value + 2;
+ }
+
+ @HostSideTestStub
+ @HostSideTestSubstitute(suffix = "_host")
+ public static native int nativeAddThree(int value);
+
+ public static int nativeAddThree_host(int value) {
+ return value + 3;
+ }
+
+ @HostSideTestThrow
+ public String unsupportedMethod() {
+ return "This value shouldn't be seen on the host side.";
+ }
+
+ @HostSideTestStub
+ public String visibleButUsesUnsupportedMethod() {
+ return unsupportedMethod();
+ }
+}
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations.java b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations.java
new file mode 100644
index 000000000000..145b65a98d7b
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2023 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.hoststubgen.test.tinyframework;
+
+import android.hosttest.annotation.HostSideTestStub;
+import android.hosttest.annotation.HostSideTestSubstitute;
+import android.hosttest.annotation.HostSideTestWholeClassStub;
+
+@HostSideTestWholeClassStub
+public class TinyFrameworkClassClassWideAnnotations {
+ public TinyFrameworkClassClassWideAnnotations() {
+ }
+
+ public int stub = 1;
+
+ public int keep = 2;
+
+ // Cannot have an initial value, because otherwise .ctor will fail to set it at runtime.
+ public int remove;
+
+ // @Stub
+ public int addOne(int value) {
+ return addOneInner(value);
+ }
+
+ // @Keep
+ public int addOneInner(int value) {
+ return value + 1;
+ }
+
+ // @Remove
+ public void toBeRemoved(String foo) {
+ throw new RuntimeException();
+ }
+
+ @HostSideTestStub
+ @HostSideTestSubstitute(suffix = "_host")
+ public int addTwo(int value) {
+ throw new RuntimeException("not supported on host side");
+ }
+
+ public int addTwo_host(int value) {
+ return value + 2;
+ }
+
+ @HostSideTestStub
+ @HostSideTestSubstitute(suffix = "_host")
+ public static native int nativeAddThree(int value);
+
+ public static int nativeAddThree_host(int value) {
+ return value + 3;
+ }
+
+ public String unsupportedMethod() {
+ return "This value shouldn't be seen on the host side.";
+ }
+
+ public String visibleButUsesUnsupportedMethod() {
+ return unsupportedMethod();
+ }
+}
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassLoadHook.java b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassLoadHook.java
new file mode 100644
index 000000000000..98fc6349cdc9
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassLoadHook.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2023 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.hoststubgen.test.tinyframework;
+
+import android.hosttest.annotation.HostSideTestWholeClassStub;
+
+import java.util.HashSet;
+import java.util.Set;
+
+@HostSideTestWholeClassStub
+public class TinyFrameworkClassLoadHook {
+ private TinyFrameworkClassLoadHook() {
+ }
+
+ public static final Set<Class<?>> sLoadedClasses = new HashSet<>();
+
+ public static void onClassLoaded(Class<?> clazz) {
+ sLoadedClasses.add(clazz);
+ }
+}
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializer.java b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializer.java
new file mode 100644
index 000000000000..53cfdf6cd412
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializer.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2023 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.hoststubgen.test.tinyframework;
+
+import android.hosttest.annotation.HostSideTestClassLoadHook;
+import android.hosttest.annotation.HostSideTestWholeClassStub;
+
+@HostSideTestClassLoadHook(
+ "com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook.onClassLoaded")
+@HostSideTestWholeClassStub
+public class TinyFrameworkClassWithInitializer {
+ static {
+ sInitialized = true;
+ }
+
+ public static boolean sInitialized;
+}
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkExceptionTester.java b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkExceptionTester.java
new file mode 100644
index 000000000000..909d3b440f50
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkExceptionTester.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2023 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.hoststubgen.test.tinyframework;
+
+import android.hosttest.annotation.HostSideTestWholeClassStub;
+
+@HostSideTestWholeClassStub
+public class TinyFrameworkExceptionTester {
+ public static int testException() {
+ try {
+ throw new IllegalStateException("Inner exception");
+ } catch (Exception e) {
+ throw new RuntimeException("Outer exception", e);
+ }
+ }
+}
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy.java b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy.java
new file mode 100644
index 000000000000..bde7c35dc294
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2023 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.hoststubgen.test.tinyframework;
+
+/**
+ * Class for testing the "text policy" file.
+ */
+public class TinyFrameworkForTextPolicy {
+ public TinyFrameworkForTextPolicy() {
+ }
+
+ public int stub = 1;
+
+ public int keep = 2;
+
+ // Removed fields cannot have an initial value, because otherwise .ctor will fail to set it at
+ // runtime.
+ public int remove;
+
+ public int addOne(int value) {
+ return addOneInner(value);
+ }
+
+ public int addOneInner(int value) {
+ return value + 1;
+ }
+
+ public void toBeRemoved(String foo) {
+ throw new RuntimeException();
+ }
+
+ public int addTwo(int value) {
+ throw new RuntimeException("not supported on host side");
+ }
+
+ public int addTwo_host(int value) {
+ return value + 2;
+ }
+
+ public static native int nativeAddThree(int value);
+
+ public static int addThree_host(int value) {
+ return value + 3;
+ }
+
+ public String unsupportedMethod() {
+ return "This value shouldn't be seen on the host side.";
+ }
+
+ public String visibleButUsesUnsupportedMethod() {
+ return unsupportedMethod();
+ }
+}
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkNative.java b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkNative.java
new file mode 100644
index 000000000000..c151dcc9c90e
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkNative.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2023 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.hoststubgen.test.tinyframework;
+
+import android.hosttest.annotation.HostSideTestNativeSubstitutionClass;
+import android.hosttest.annotation.HostSideTestWholeClassStub;
+
+@HostSideTestWholeClassStub
+@HostSideTestNativeSubstitutionClass("TinyFrameworkNative_host")
+public class TinyFrameworkNative {
+ public static native int nativeAddTwo(int arg);
+
+ public static int nativeAddTwo_should_be_like_this(int arg) {
+ return TinyFrameworkNative_host.nativeAddTwo(arg);
+ }
+
+ public static native long nativeLongPlus(long arg1, long arg2);
+
+ public static long nativeLongPlus_should_be_like_this(long arg1, long arg2) {
+ return TinyFrameworkNative_host.nativeLongPlus(arg1, arg2);
+ }
+}
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.java b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.java
new file mode 100644
index 000000000000..48f7dea8c66c
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2023 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.hoststubgen.test.tinyframework;
+
+import android.hosttest.annotation.HostSideTestWholeClassKeep;
+
+// TODO: This annotation shouldn't be needed.
+// We should infer it from HostSideTestNativeSubstitutionClass.
+@HostSideTestWholeClassKeep
+public class TinyFrameworkNative_host {
+ public static int nativeAddTwo(int arg) {
+ return arg + 2;
+ }
+
+ public static long nativeLongPlus(long arg1, long arg2) {
+ return arg1 + arg2;
+ }
+}
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses.java b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses.java
new file mode 100644
index 000000000000..e1c48bb85563
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2023 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.hoststubgen.test.tinyframework;
+
+import android.hosttest.annotation.HostSideTestWholeClassStub;
+
+import java.util.function.Supplier;
+
+@HostSideTestWholeClassStub
+public class TinyFrameworkNestedClasses {
+ public final Supplier<Integer> mSupplier = new Supplier<Integer>() {
+ @Override
+ public Integer get() {
+ return 1;
+ }
+ };
+
+ public static final Supplier<Integer> sSupplier = new Supplier<Integer>() {
+ @Override
+ public Integer get() {
+ return 2;
+ }
+ };
+ public Supplier<Integer> getSupplier() {
+ return new Supplier<Integer>() {
+ @Override
+ public Integer get() {
+ return 3;
+ }
+ };
+ }
+
+ public static Supplier<Integer> getSupplier_static() {
+ return new Supplier<Integer>() {
+ @Override
+ public Integer get() {
+ return 4;
+ }
+ };
+ }
+
+ @HostSideTestWholeClassStub
+ public class InnerClass {
+ public int value = 5;
+ }
+
+ @HostSideTestWholeClassStub
+ public static class StaticNestedClass {
+ public int value = 6;
+
+ // Double-nest
+ public static Supplier<Integer> getSupplier_static() {
+ return new Supplier<Integer>() {
+ @Override
+ public Integer get() {
+ return 7;
+ }
+ };
+ }
+ }
+
+ public static class BaseClass {
+ public int value;
+ public BaseClass(int x) {
+ value = x;
+ }
+ }
+
+ public static class SubClass extends BaseClass {
+ public SubClass(int x) {
+ super(x);
+ }
+ }
+}
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-test/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkBenchmark.java b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-test/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkBenchmark.java
new file mode 100644
index 000000000000..6b5110ef2cef
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-test/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkBenchmark.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2023 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.hoststubgen.test.tinyframework;
+
+import org.junit.Test;
+
+import java.text.DecimalFormat;
+
+/**
+ * Contains simple micro-benchmarks.
+ */
+public class TinyFrameworkBenchmark {
+ private static final int MINIMAL_ITERATION = 1000;
+ private static final int MEASURE_SECONDS = 3;
+
+ private static final DecimalFormat sFormatter = new DecimalFormat("#,###");
+
+ private void doBenchmark(String name, Runnable r) {
+ // Worm up
+ for (int i = 0; i < MINIMAL_ITERATION; i++) {
+ r.run();
+ }
+
+ // Start measuring.
+ final long start = System.nanoTime();
+ final long end = start + MEASURE_SECONDS * 1_000_000_000L;
+
+ double iteration = 0;
+ while (System.nanoTime() <= end) {
+ for (int i = 0; i < MINIMAL_ITERATION; i++) {
+ r.run();
+ }
+ iteration += MINIMAL_ITERATION;
+ }
+
+ final long realEnd = System.nanoTime();
+
+ System.out.println(String.format("%s\t%s", name,
+ sFormatter.format((((double) realEnd - start)) / iteration)));
+ }
+
+ /**
+ * Micro-benchmark for a method without a non-stub caller check.
+ */
+ @Test
+ public void benchNoCallerCheck() {
+ doBenchmark("No caller check", TinyFrameworkCallerCheck::getOne_noCheck);
+ }
+
+ /**
+ * Micro-benchmark for a method with a non-stub caller check.
+ */
+ @Test
+ public void benchWithCallerCheck() {
+ doBenchmark("With caller check", TinyFrameworkCallerCheck::getOne_withCheck);
+ }
+}
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-test/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassTest.java b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-test/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassTest.java
new file mode 100644
index 000000000000..246d06526f5b
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-test/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassTest.java
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2023 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.hoststubgen.test.tinyframework;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses.SubClass;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+public class TinyFrameworkClassTest {
+ @Rule
+ public ExpectedException thrown = ExpectedException.none();
+
+ @Test
+ public void testSimple() {
+ TinyFrameworkForTextPolicy tfc = new TinyFrameworkForTextPolicy();
+ assertThat(tfc.addOne(1)).isEqualTo(2);
+ assertThat(tfc.stub).isEqualTo(1);
+ }
+
+// @Test
+// public void testDoesntCompile() {
+// TinyFrameworkClass tfc = new TinyFrameworkClass();
+//
+// tfc.addOneInner(1); // Shouldn't compile.
+// tfc.toBeRemoved("abc"); // Shouldn't compile.
+// tfc.unsupportedMethod(); // Shouldn't compile.
+// int a = tfc.keep; // Shouldn't compile
+// int b = tfc.remove; // Shouldn't compile
+// }
+
+ @Test
+ public void testSubstitute() {
+ TinyFrameworkForTextPolicy tfc = new TinyFrameworkForTextPolicy();
+ assertThat(tfc.addTwo(1)).isEqualTo(3);
+ }
+
+ @Test
+ public void testSubstituteNative() {
+ TinyFrameworkForTextPolicy tfc = new TinyFrameworkForTextPolicy();
+ assertThat(tfc.nativeAddThree(1)).isEqualTo(4);
+ }
+
+ @Test
+ public void testVisibleButUsesUnsupportedMethod() {
+ TinyFrameworkForTextPolicy tfc = new TinyFrameworkForTextPolicy();
+
+ thrown.expect(RuntimeException.class);
+ thrown.expectMessage("This method is not supported on the host side");
+ tfc.visibleButUsesUnsupportedMethod();
+ }
+
+ @Test
+ public void testNestedClass1() {
+ assertThat(new TinyFrameworkNestedClasses().mSupplier.get()).isEqualTo(1);
+ }
+
+ @Test
+ public void testNestedClass2() {
+ assertThat(TinyFrameworkNestedClasses.sSupplier.get()).isEqualTo(2);
+ }
+
+ @Test
+ public void testNestedClass3() {
+ assertThat(new TinyFrameworkNestedClasses().getSupplier().get()).isEqualTo(3);
+ }
+
+ @Test
+ public void testNestedClass4() {
+ assertThat(TinyFrameworkNestedClasses.getSupplier_static().get()).isEqualTo(4);
+ }
+
+ @Test
+ public void testNestedClass5() {
+ assertThat((new TinyFrameworkNestedClasses()).new InnerClass().value).isEqualTo(5);
+ }
+
+ @Test
+ public void testNestedClass6() {
+ assertThat(new TinyFrameworkNestedClasses.StaticNestedClass().value).isEqualTo(6);
+ }
+
+ @Test
+ public void testNestedClass7() {
+ assertThat(TinyFrameworkNestedClasses.StaticNestedClass.getSupplier_static().get())
+ .isEqualTo(7);
+ }
+
+ @Test
+ public void testNativeSubstitutionClass() {
+ assertThat(TinyFrameworkNative.nativeAddTwo(3)).isEqualTo(5);
+ }
+
+ @Test
+ public void testExitLog() {
+ thrown.expect(RuntimeException.class);
+ thrown.expectMessage("Outer exception");
+
+ TinyFrameworkExceptionTester.testException();
+
+ }
+
+ @Test
+ public void testMethodCallBeforeSuperCall() {
+ assertThat(new SubClass(3).value).isEqualTo(3);
+ }
+
+ @Test
+ public void testClassLoadHook() {
+ assertThat(TinyFrameworkClassWithInitializer.sInitialized).isTrue();
+
+ // Having this line before assertThat() will ensure these class are already loaded.
+ var classes = new Class[] {
+ TinyFrameworkClassWithInitializer.class,
+ TinyFrameworkClassAnnotations.class,
+ TinyFrameworkForTextPolicy.class,
+ };
+
+ // The following classes have a class load hook, so they should be registered.
+ assertThat(TinyFrameworkClassLoadHook.sLoadedClasses)
+ .containsAnyIn(classes);
+
+ // This class doesn't have a class load hook, so shouldn't be included.
+ assertThat(TinyFrameworkClassLoadHook.sLoadedClasses)
+ .doesNotContain(TinyFrameworkNestedClasses.class);
+ }
+}
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-test/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithAnnotTest.java b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-test/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithAnnotTest.java
new file mode 100644
index 000000000000..20cc2ec9d50d
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-test/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithAnnotTest.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2023 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.hoststubgen.test.tinyframework;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+public class TinyFrameworkClassWithAnnotTest {
+ @Rule
+ public ExpectedException thrown = ExpectedException.none();
+
+ @Test
+ public void testSimple() {
+ TinyFrameworkClassAnnotations tfc = new TinyFrameworkClassAnnotations();
+ assertThat(tfc.addOne(1)).isEqualTo(2);
+ assertThat(tfc.stub).isEqualTo(1);
+ }
+
+// @Test
+// public void testDoesntCompile() {
+// TinyFrameworkClassWithAnnot tfc = new TinyFrameworkClassWithAnnot();
+//
+// tfc.addOneInner(1); // Shouldn't compile.
+// tfc.toBeRemoved("abc"); // Shouldn't compile.
+// tfc.unsupportedMethod(); // Shouldn't compile.
+// int a = tfc.keep; // Shouldn't compile
+// int b = tfc.remove; // Shouldn't compile
+// }
+
+ @Test
+ public void testSubstitute() {
+ TinyFrameworkClassAnnotations tfc = new TinyFrameworkClassAnnotations();
+ assertThat(tfc.addTwo(1)).isEqualTo(3);
+ }
+
+ @Test
+ public void testSubstituteNative() {
+ TinyFrameworkClassAnnotations tfc = new TinyFrameworkClassAnnotations();
+ assertThat(tfc.nativeAddThree(1)).isEqualTo(4);
+ }
+
+ @Test
+ public void testVisibleButUsesUnsupportedMethod() {
+ TinyFrameworkClassAnnotations tfc = new TinyFrameworkClassAnnotations();
+
+ thrown.expect(RuntimeException.class);
+ thrown.expectMessage("This method is not supported on the host side");
+ tfc.visibleButUsesUnsupportedMethod();
+ }
+}
diff --git a/tools/hoststubgen/scripts/Android.bp b/tools/hoststubgen/scripts/Android.bp
new file mode 100644
index 000000000000..5da805e5640e
--- /dev/null
+++ b/tools/hoststubgen/scripts/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"],
+}
+
+sh_binary_host {
+ name: "dump-jar",
+ src: "dump-jar",
+ visibility: ["//visibility:public"],
+}
+
+genrule_defaults {
+ name: "hoststubgen-jar-dump-defaults",
+ tools: ["dump-jar"],
+ cmd: "$(location dump-jar) -s -o $(out) $(in)",
+}
+
+sh_binary_host {
+ name: "run-ravenwood-test",
+ src: "run-ravenwood-test",
+ visibility: ["//visibility:public"],
+}
diff --git a/tools/hoststubgen/scripts/build-framework-hostside-jars-and-extract.sh b/tools/hoststubgen/scripts/build-framework-hostside-jars-and-extract.sh
new file mode 100755
index 000000000000..72681234dad8
--- /dev/null
+++ b/tools/hoststubgen/scripts/build-framework-hostside-jars-and-extract.sh
@@ -0,0 +1,35 @@
+#!/bin/bash
+# Copyright (C) 2023 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.
+
+
+# Script to build `framework-host-stub` and `framework-host-impl`, and copy the
+# generated jars to $out, and unzip them. Useful for looking into the generated files.
+
+source "${0%/*}"/../common.sh
+
+out=framework-all-stub-out
+
+rm -fr $out
+mkdir -p $out
+
+# Build the jars with `m`.
+run m framework-all-hidden-api-host
+
+# Copy the jar to out/ and extract them.
+run cp \
+ $SOONG_INT/frameworks/base/tools/hoststubgen/hoststubgen/framework-all-hidden-api-host/linux_glibc_common/gen/* \
+ $out
+
+extract $out/*.jar
diff --git a/tools/hoststubgen/scripts/build-framework-hostside-jars-without-genrules.sh b/tools/hoststubgen/scripts/build-framework-hostside-jars-without-genrules.sh
new file mode 100755
index 000000000000..c3605a9ffaa5
--- /dev/null
+++ b/tools/hoststubgen/scripts/build-framework-hostside-jars-without-genrules.sh
@@ -0,0 +1,76 @@
+#!/bin/bash
+# Copyright (C) 2023 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.
+
+
+# Script to build hoststubgen and run it directly (without using the build rules)
+# on framework-all.jar.
+
+
+echo "THIS SCRIPT IS BROKEN DUE TO CHANGES TO FILE PATHS TO DEPENDENT FILES. FIX IT WHEN YOU NEED TO USE IT." 1>&2
+
+exit 99
+
+
+source "${0%/*}"/../common.sh
+
+out=out
+
+mkdir -p $out
+
+# Build the tool and target jar.
+run m hoststubgen framework-all
+
+base_args=(
+ @../hoststubgen/hoststubgen-standard-options.txt
+
+ --in-jar $ANDROID_BUILD_TOP/out/soong/.intermediates/frameworks/base/framework-all/android_common/combined/framework-all.jar
+ --policy-override-file ../hoststubgen/framework-policy-override.txt "${@}"
+
+ # This file will contain all classes as an annotation file, with "keep all" policy.
+ --gen-keep-all-file $out/framework-all-keep-all-policy.txt
+
+ # This file will contains dump of all classes in the input jar.
+ --gen-input-dump-file $out/framework-all-dump.txt
+)
+
+do_it() {
+ local out_file_stem="$1"
+ shift
+ local extra_args=("${@}")
+
+ run hoststubgen \
+ "${base_args[@]}" \
+ "${extra_args[@]}" \
+ --out-stub-jar ${out_file_stem}_stub.jar \
+ --out-impl-jar ${out_file_stem}_impl.jar \
+ $HOSTSTUBGEN_OPTS
+
+ # Extract the jar files, so we can look into them.
+ run extract ${out_file_stem}_*.jar
+}
+
+#-----------------------------------------------------------------------------
+# framework-all, with all hidden APIs.
+#-----------------------------------------------------------------------------
+
+# No extra args.
+do_it $out/framework-all_host
+
+#-----------------------------------------------------------------------------
+# framework-test-api, only public/system/test-APIs in the stub.
+#-----------------------------------------------------------------------------
+
+do_it $out/framework-test-api_host \
+ --intersect-stub-jar $SOONG_INT/frameworks/base/api/android_test_stubs_current/android_common/combined/*.jar
diff --git a/tools/hoststubgen/scripts/dump-jar b/tools/hoststubgen/scripts/dump-jar
new file mode 100755
index 000000000000..93729fb22caa
--- /dev/null
+++ b/tools/hoststubgen/scripts/dump-jar
@@ -0,0 +1,163 @@
+#!/bin/bash
+# Copyright (C) 2023 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.
+
+set -e
+
+
+help() {
+ cat <<'EOF'
+
+ dump-jar: Dump java classes in jar files
+
+ Usage:
+ dump-jar [-v] CLASS-FILE [...]
+
+ Dump a *.class file
+
+ dump-jar [-v] [-s] [-o OUTPUT-FILENAME] JAR-FILE[: filename regex] [...]
+
+ Dump a jar file.
+
+ If a filename contains a ':', then the following part
+ will be used to filter files in the jar file.
+
+ For example, "file.jar:/MyClass$" will only dump "MyClass" in file.jar.
+
+ Options:
+ -v: Enable verbose output.
+
+ -s: Simple output mode, used to check HostStubGen output jars.
+
+ -o: Write the output to a specified file.
+EOF
+}
+
+# Parse the options.
+
+verbose=0
+simple=0
+output=""
+while getopts "hvso:" opt; do
+case "$opt" in
+ h)
+ help
+ exit 0
+ ;;
+ v)
+ verbose=1
+ ;;
+ s)
+ simple=1
+ ;;
+ o)
+ output="$OPTARG"
+ ;;
+ '?')
+ help
+ exit 1
+ ;;
+esac
+done
+shift $(($OPTIND - 1))
+
+JAVAP_OPTS="${JAVAP_OPTS:--v -p -s -sysinfo -constants}"
+
+if (( $simple )) ; then
+ JAVAP_OPTS="-p -c -v"
+fi
+
+
+# Normalize a java class name.
+# Convert '.' to '/'
+# Remove the *.class suffix.
+normalize() {
+ local name="$1"
+ name="${name%.class}" # Remove the .class suffix.
+ echo "$name" | tr '.' '/'
+}
+
+# Convert the output for `-s` as needed.
+filter_output() {
+ if (( $simple )) ; then
+ # For "simple output" mode,
+ # - Normalize the constant numbers (replace with "#x")
+ # - Remove the constant pool
+ # - Remove the line number table
+ # - Some other transient lines
+ #
+ # `/PATTERN-1/,/PATTERN-1/{//!d}` is a trick to delete lines between two patterns, without
+ # the start and the end lines.
+ sed -e 's/#[0-9][0-9]*/#x/g' \
+ -e '/^Constant pool:/,/^[^ ]/{//!d}' \
+ -e '/^ *line *[0-9][0-9]*: *[0-9][0-9]*$/d' \
+ -e '/SHA-256 checksum/d' \
+ -e '/Last modified/d' \
+ -e '/^Classfile jar/d'
+ else
+ cat # Print as-is.
+ fi
+}
+
+# Write to the output file (specified with -o) as needed.
+write_to_out() {
+ if [[ -n "$output" ]] ; then
+ cat >"$output"
+ echo "Wrote output to $output" 1>&2
+ else
+ cat # print to stdout
+ fi
+}
+
+for file in "${@}"; do
+
+ # *.class?
+ if echo "$file" | grep -qE '\.class$' ; then
+ echo "# Class: $file" 1>&2
+ javap $dump_code_opt $JAVAP_OPTS $file
+
+ # *.jar?
+ elif echo "$file" | grep -qE '\.jar(:.*)?$' ; then
+ # Take the regex. Remove everything up to : in $file
+ regex=""
+ if [[ "$file" =~ : ]] ; then
+ regex="$(normalize "${file##*:}")"
+ fi
+
+ # Remove everything after ':', inclusively, in $file.
+ file="${file%:*}"
+
+ # Print the filename and the regex.
+ if ! (( $simple )) ; then
+ echo -n "# Jar: $file"
+ if [[ "$regex" != "" ]] ;then
+ echo -n " (regex: $regex)"
+ fi
+ echo
+ fi
+
+ jar tf "$file" | grep '\.class$' | sort | while read -r class ; do
+ if normalize "$class" | grep -q -- "$regex" ; then
+ echo "## Class: $class"
+ javap $dump_code_opt $JAVAP_OPTS -cp $file ${class%.class}
+ else
+ (( $verbose )) && echo "## Skipping class: $class"
+ fi
+ done
+
+ else
+ echo "Unknown file type: $file" 1>&2
+ exit 1
+ fi
+done | filter_output | write_to_out
diff --git a/tools/hoststubgen/scripts/run-all-tests.sh b/tools/hoststubgen/scripts/run-all-tests.sh
new file mode 100755
index 000000000000..6bc0ddb1a8dc
--- /dev/null
+++ b/tools/hoststubgen/scripts/run-all-tests.sh
@@ -0,0 +1,45 @@
+#!/bin/bash
+# Copyright (C) 2023 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.
+
+source "${0%/*}"/../common.sh
+
+# Move to the top directory of hoststubgen
+cd ..
+
+# These tests are known to pass.
+READY_TEST_MODULES=(
+ HostStubGenTest-framework-all-test-host-test
+ hoststubgen-test-tiny-test
+)
+
+# First, build all the test modules. This shouldn't fail.
+run m run-ravenwood-test ${READY_TEST_MODULES[*]} ${NOT_READY_TEST_MODULES[*]}
+
+# Next, run the golden check. This should always pass too.
+# The following scripts _should_ pass too, but they depend on the internal paths to soong generated
+# files, and they may fail when something changes in the build system.
+run ./hoststubgen/test-tiny-framework/diff-and-update-golden.sh
+
+run ./hoststubgen/test-framework/run-test-without-atest.sh
+run ./hoststubgen/test-tiny-framework/run-test-manually.sh
+run ./scripts/build-framework-hostside-jars-and-extract.sh
+
+# This script is already broken on goog/master
+# run ./scripts/build-framework-hostside-jars-without-genrules.sh
+
+# These tests should all pass.
+run-ravenwood-test ${READY_TEST_MODULES[*]}
+
+echo ""${0##*/}" finished, with no unexpected failures. Ready to submit!" \ No newline at end of file
diff --git a/tools/hoststubgen/scripts/run-ravenwood-test b/tools/hoststubgen/scripts/run-ravenwood-test
new file mode 100755
index 000000000000..9bbb859f5c3d
--- /dev/null
+++ b/tools/hoststubgen/scripts/run-ravenwood-test
@@ -0,0 +1,129 @@
+#!/bin/bash
+# Copyright (C) 2023 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.
+
+set -e
+
+# Script to run a "Ravenwood" host side test.
+#
+# A proper way to run these tests is to use `atest`, but `atest` has a known issue of loading
+# unrelated jar files as the class path, so for now we use this script to run host side tests.
+
+# Copy (with some changes) some functions from ../common.sh, so this script can be used without it.
+
+m() {
+ if (( $SKIP_BUILD )) ; then
+ echo "Skipping build: $*" 1>&2
+ return 0
+ fi
+ run ${ANDROID_BUILD_TOP}/build/soong/soong_ui.bash --make-mode "$@"
+}
+
+run() {
+ echo "Running: $*" 1>&2
+ "$@"
+}
+
+run_junit_test_jar() {
+ local jar="$1"
+ echo "Starting test: $jar ..."
+ run cd "${jar%/*}"
+
+ run ${JAVA:-java} $JAVA_OPTS \
+ -cp $jar \
+ org.junit.runner.JUnitCore \
+ com.android.hoststubgen.hosthelper.HostTestSuite || return 1
+ return 0
+}
+
+help() {
+ cat <<'EOF'
+
+ run-ravenwood-test -- Run Ravenwood host tests
+
+ Usage:
+ run-ravenwood-test [options] MODULE-NAME ...
+
+ Options:
+ -h: Help
+ -t: Run test only, without building
+ -b: Build only, without running
+
+ Example:
+ run-ravenwood-test HostStubGenTest-framework-test-host-test
+
+EOF
+}
+
+#-------------------------------------------------------------------------
+# Parse options
+#-------------------------------------------------------------------------
+build=0
+test=0
+
+while getopts "htb" opt; do
+ case "$opt" in
+ h) help; exit 0 ;;
+ t)
+ test=1
+ ;;
+ b)
+ build=1
+ ;;
+ esac
+done
+shift $(($OPTIND - 1))
+
+# If neither -t nor -b is provided, then build and run./
+if (( ( $build + $test ) == 0 )) ; then
+ build=1
+ test=1
+fi
+
+
+modules=("${@}")
+
+if (( "${#modules[@]}" == 0 )); then
+ help
+ exit 1
+fi
+
+#-------------------------------------------------------------------------
+# Build
+#-------------------------------------------------------------------------
+if (( $build )) ; then
+ run m "${modules[@]}"
+fi
+
+#-------------------------------------------------------------------------
+# Run
+#-------------------------------------------------------------------------
+
+failures=0
+if (( test )) ; then
+ for module in "${modules[@]}"; do
+ if run_junit_test_jar "$ANDROID_BUILD_TOP/out/host/linux-x86/testcases/${module}/${module}.jar"; then
+ : # passed.
+ else
+ failures=$(( failures + 1 ))
+ fi
+ done
+
+ if (( $failures > 0 )) ; then
+ echo "$failures test jar(s) failed." 1>&2
+ exit 2
+ fi
+fi
+
+exit 0 \ No newline at end of file