diff options
560 files changed, 25178 insertions, 5031 deletions
diff --git a/AconfigFlags.bp b/AconfigFlags.bp index a2994088cfb2..e18470498f39 100644 --- a/AconfigFlags.bp +++ b/AconfigFlags.bp @@ -100,7 +100,7 @@ aconfig_declarations_group { "com.android.media.flags.performance-aconfig-java", "com.android.media.flags.projection-aconfig-java", "com.android.net.thread.platform.flags-aconfig-java", - "com.android.ranging.flags.ranging-aconfig-java", + "com.android.ranging.flags.ranging-aconfig-java-export", "com.android.server.contextualsearch.flags-java", "com.android.server.flags.services-aconfig-java", "com.android.text.flags-aconfig-java", @@ -373,6 +373,11 @@ java_aconfig_library { name: "android.security.flags-aconfig-java-export", aconfig_declarations: "android.security.flags-aconfig", mode: "exported", + min_sdk_version: "30", + apex_available: [ + "//apex_available:platform", + "com.android.wifi", + ], defaults: ["framework-minus-apex-aconfig-java-defaults"], } @@ -1651,13 +1656,6 @@ java_aconfig_library { defaults: ["framework-minus-apex-aconfig-java-defaults"], } -// Ranging -java_aconfig_library { - name: "com.android.ranging.flags.ranging-aconfig-java", - aconfig_declarations: "ranging_aconfig_flags", - defaults: ["framework-minus-apex-aconfig-java-defaults"], -} - // System Server aconfig_declarations { name: "android.systemserver.flags-aconfig", diff --git a/boot/boot-image-profile-extra.txt b/boot/boot-image-profile-extra.txt index e31eb3a993f0..fd51f9cbcee1 100644 --- a/boot/boot-image-profile-extra.txt +++ b/boot/boot-image-profile-extra.txt @@ -23,4 +23,25 @@ HSPLandroid/graphics/Color;->luminance()F # For now, compile all methods in MessageQueue to avoid performance cliffs for # flagged/evolving hot code paths. See: b/338098106 HSPLandroid/os/MessageQueue;->* -HSPLandroid/os/MessageQueue$*;->* +HSPLandroid/os/MessageQueue$FileDescriptorRecord;->* +HSPLandroid/os/MessageQueue$IdleHandler;->* +HSPLandroid/os/MessageQueue$MessageCompare;->* +HSPLandroid/os/MessageQueue$MatchAllFutureMessages;->* +HSPLandroid/os/MessageQueue$MatchAllMessages;->* +HSPLandroid/os/MessageQueue$MatchBarrierToken;->* +HSPLandroid/os/MessageQueue$MatchDeliverableMessages;->* +HSPLandroid/os/MessageQueue$MatchHandler;->* +HSPLandroid/os/MessageQueue$MatchHandlerAndObject;->* +HSPLandroid/os/MessageQueue$MatchHandlerAndObjectEquals;->* +HSPLandroid/os/MessageQueue$MatchHandlerRunnableAndObject;->* +HSPLandroid/os/MessageQueue$MatchHandlerRunnableAndObjectEquals;->* +HSPLandroid/os/MessageQueue$MatchHandlerWhatAndObject;->* +HSPLandroid/os/MessageQueue$MatchHandlerWhatAndObjectEquals;->* +HSPLandroid/os/MessageQueue$MessageCounts;->* +HSPLandroid/os/MessageQueue$StackNode;->* +HSPLandroid/os/MessageQueue$MessageNode;->* +HSPLandroid/os/MessageQueue$OnFileDescriptorEventListener$Events;->* +HSPLandroid/os/MessageQueue$OnFileDescriptorEventListener;->* +HSPLandroid/os/MessageQueue$StackNodeType;->* +HSPLandroid/os/MessageQueue$StateNode;->* +HSPLandroid/os/MessageQueue$TimedParkStateNode;->* diff --git a/cmds/idmap2/idmap2/CreateMultiple.cpp b/cmds/idmap2/idmap2/CreateMultiple.cpp index 68800cde6101..2608c69be66f 100644 --- a/cmds/idmap2/idmap2/CreateMultiple.cpp +++ b/cmds/idmap2/idmap2/CreateMultiple.cpp @@ -99,7 +99,7 @@ Result<Unit> CreateMultiple(const std::vector<std::string>& args) { std::vector<std::string> idmap_paths; for (const std::string& overlay_apk_path : overlay_apk_paths) { - const std::string idmap_path = Idmap::CanonicalIdmapPathFor(idmap_dir, overlay_apk_path); + std::string idmap_path = Idmap::CanonicalIdmapPathFor(idmap_dir, overlay_apk_path); const uid_t uid = getuid(); if (!UidHasWriteAccessToPath(uid, idmap_path)) { LOG(WARNING) << "uid " << uid << "does not have write access to " << idmap_path.c_str(); @@ -111,7 +111,7 @@ Result<Unit> CreateMultiple(const std::vector<std::string>& args) { !ignore_overlayable)) { const auto overlay = OverlayResourceContainer::FromPath(overlay_apk_path); if (!overlay) { - LOG(WARNING) << "failed to load apk " << overlay_apk_path.c_str(); + LOG(WARNING) << "failed to load apk " << overlay_apk_path; continue; } @@ -138,7 +138,7 @@ Result<Unit> CreateMultiple(const std::vector<std::string>& args) { } } - idmap_paths.emplace_back(idmap_path); + idmap_paths.emplace_back(std::move(idmap_path)); } for (const std::string& idmap_path : idmap_paths) { diff --git a/core/api/current.txt b/core/api/current.txt index 45f6a3fbe0cb..3af8e7e17dbd 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -1502,6 +1502,7 @@ package android { field public static final int shadowRadius = 16843108; // 0x1010164 field public static final int shape = 16843162; // 0x101019a field public static final int shareInterpolator = 16843195; // 0x10101bb + field @FlaggedApi("android.nfc.nfc_associated_role_services") public static final int shareRolePriority; field @Deprecated public static final int sharedUserId = 16842763; // 0x101000b field @Deprecated public static final int sharedUserLabel = 16843361; // 0x1010261 field public static final int sharedUserMaxSdkVersion = 16844365; // 0x101064d @@ -2451,6 +2452,7 @@ package android { field public static final int primary = 16908300; // 0x102000c field public static final int progress = 16908301; // 0x102000d field public static final int redo = 16908339; // 0x1020033 + field @FlaggedApi("android.appwidget.flags.engagement_metrics") public static final int remoteViewsMetricsId; field public static final int replaceText = 16908340; // 0x1020034 field public static final int secondaryProgress = 16908303; // 0x102000f field public static final int selectAll = 16908319; // 0x102001f @@ -9892,6 +9894,8 @@ package android.appwidget { field public static final String ACTION_APPWIDGET_PICK = "android.appwidget.action.APPWIDGET_PICK"; field public static final String ACTION_APPWIDGET_RESTORED = "android.appwidget.action.APPWIDGET_RESTORED"; field public static final String ACTION_APPWIDGET_UPDATE = "android.appwidget.action.APPWIDGET_UPDATE"; + field @FlaggedApi("android.appwidget.flags.engagement_metrics") public static final String EVENT_CATEGORY_APPWIDGET = "android.appwidget"; + field @FlaggedApi("android.appwidget.flags.engagement_metrics") public static final String EVENT_TYPE_WIDGET_INTERACTION = "widget_interaction"; field public static final String EXTRA_APPWIDGET_ID = "appWidgetId"; field public static final String EXTRA_APPWIDGET_IDS = "appWidgetIds"; field public static final String EXTRA_APPWIDGET_OLD_IDS = "appWidgetOldIds"; @@ -9901,6 +9905,10 @@ package android.appwidget { field public static final String EXTRA_APPWIDGET_PROVIDER_PROFILE = "appWidgetProviderProfile"; field public static final String EXTRA_CUSTOM_EXTRAS = "customExtras"; field public static final String EXTRA_CUSTOM_INFO = "customInfo"; + field @FlaggedApi("android.appwidget.flags.engagement_metrics") public static final String EXTRA_EVENT_CLICKED_VIEWS = "android.appwidget.extra.EVENT_CLICKED_VIEWS"; + field @FlaggedApi("android.appwidget.flags.engagement_metrics") public static final String EXTRA_EVENT_DURATION_MS = "android.appwidget.extra.EVENT_DURATION_MS"; + field @FlaggedApi("android.appwidget.flags.engagement_metrics") public static final String EXTRA_EVENT_POSITION_RECT = "android.appwidget.extra.EVENT_POSITION_RECT"; + field @FlaggedApi("android.appwidget.flags.engagement_metrics") public static final String EXTRA_EVENT_SCROLLED_VIEWS = "android.appwidget.extra.EVENT_SCROLLED_VIEWS"; field public static final String EXTRA_HOST_ID = "hostId"; field public static final int INVALID_APPWIDGET_ID = 0; // 0x0 field public static final String META_DATA_APPWIDGET_PROVIDER = "android.appwidget.provider"; @@ -18954,6 +18962,7 @@ package android.hardware { method @FlaggedApi("android.hardware.flags.luts_api") @NonNull public int[] getSamplingKeys(); method @FlaggedApi("android.hardware.flags.luts_api") public int getSize(); field @FlaggedApi("android.hardware.flags.luts_api") public static final int ONE_DIMENSION = 1; // 0x1 + field @FlaggedApi("android.hardware.flags.luts_api") public static final int SAMPLING_KEY_CIE_Y = 2; // 0x2 field @FlaggedApi("android.hardware.flags.luts_api") public static final int SAMPLING_KEY_MAX_RGB = 1; // 0x1 field @FlaggedApi("android.hardware.flags.luts_api") public static final int SAMPLING_KEY_RGB = 0; // 0x0 field @FlaggedApi("android.hardware.flags.luts_api") public static final int THREE_DIMENSION = 3; // 0x3 @@ -24166,6 +24175,8 @@ package android.media { field public static final String KEY_OPERATING_RATE = "operating-rate"; field public static final String KEY_OUTPUT_REORDER_DEPTH = "output-reorder-depth"; field public static final String KEY_PCM_ENCODING = "pcm-encoding"; + field @FlaggedApi("android.media.tv.flags.apply_picture_profiles") public static final String KEY_PICTURE_PROFILE_ID = "picture-profile-id"; + field @FlaggedApi("android.media.tv.flags.apply_picture_profiles") public static final String KEY_PICTURE_PROFILE_INSTANCE = "picture-profile-instance"; field public static final String KEY_PICTURE_TYPE = "picture-type"; field public static final String KEY_PIXEL_ASPECT_RATIO_HEIGHT = "sar-height"; field public static final String KEY_PIXEL_ASPECT_RATIO_WIDTH = "sar-width"; @@ -25613,6 +25624,7 @@ package android.media { method public void addOnSpatializerStateChangedListener(@NonNull java.util.concurrent.Executor, @NonNull android.media.Spatializer.OnSpatializerStateChangedListener); method public boolean canBeSpatialized(@NonNull android.media.AudioAttributes, @NonNull android.media.AudioFormat); method public int getImmersiveAudioLevel(); + method @FlaggedApi("android.media.audio.spatializer_capabilities") @NonNull public java.util.List<java.lang.Integer> getSpatializedChannelMasks(); method public boolean isAvailable(); method public boolean isEnabled(); method public boolean isHeadTrackerAvailable(); @@ -51925,7 +51937,7 @@ package android.view { method public int getState(); method @FlaggedApi("com.android.server.display.feature.flags.enable_get_suggested_frame_rate") public float getSuggestedFrameRate(int); method public android.view.Display.Mode[] getSupportedModes(); - method @Deprecated public float[] getSupportedRefreshRates(); + method @FlaggedApi("com.android.server.display.feature.flags.enable_get_supported_refresh_rates") @NonNull public float[] getSupportedRefreshRates(); method @Deprecated public int getWidth(); method @FlaggedApi("com.android.server.display.feature.flags.enable_has_arr_support") public boolean hasArrSupport(); method public boolean isHdr(); @@ -56483,6 +56495,7 @@ package android.view.accessibility { method public float getMin(); method public int getType(); method @Deprecated public static android.view.accessibility.AccessibilityNodeInfo.RangeInfo obtain(int, float, float, float); + field @FlaggedApi("android.view.accessibility.indeterminate_range_info") @NonNull public static final android.view.accessibility.AccessibilityNodeInfo.RangeInfo INDETERMINATE; field public static final int RANGE_TYPE_FLOAT = 1; // 0x1 field @FlaggedApi("android.view.accessibility.indeterminate_range_info") public static final int RANGE_TYPE_INDETERMINATE = 3; // 0x3 field public static final int RANGE_TYPE_INT = 0; // 0x0 diff --git a/core/api/system-current.txt b/core/api/system-current.txt index e225bb4199e3..b7a82cde3e47 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -34,6 +34,7 @@ package android { field public static final String ACCESS_VIBRATOR_STATE = "android.permission.ACCESS_VIBRATOR_STATE"; field public static final String ACTIVITY_EMBEDDING = "android.permission.ACTIVITY_EMBEDDING"; field public static final String ADD_ALWAYS_UNLOCKED_DISPLAY = "android.permission.ADD_ALWAYS_UNLOCKED_DISPLAY"; + field @FlaggedApi("android.companion.virtualdevice.flags.enable_limited_vdm_role") public static final String ADD_MIRROR_DISPLAY = "android.permission.ADD_MIRROR_DISPLAY"; field public static final String ADD_TRUSTED_DISPLAY = "android.permission.ADD_TRUSTED_DISPLAY"; field public static final String ADJUST_RUNTIME_PERMISSIONS_POLICY = "android.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY"; field public static final String ALLOCATE_AGGRESSIVE = "android.permission.ALLOCATE_AGGRESSIVE"; @@ -4249,6 +4250,7 @@ package android.content.pm { method @RequiresPermission(android.Manifest.permission.INSTALL_PACKAGES) public void setPermissionsResult(int, boolean); field public static final String ACTION_CONFIRM_INSTALL = "android.content.pm.action.CONFIRM_INSTALL"; field public static final String ACTION_CONFIRM_PRE_APPROVAL = "android.content.pm.action.CONFIRM_PRE_APPROVAL"; + field @FlaggedApi("android.content.pm.sdk_dependency_installer") public static final String ACTION_INSTALL_DEPENDENCY = "android.content.pm.action.INSTALL_DEPENDENCY"; field public static final int DATA_LOADER_TYPE_INCREMENTAL = 2; // 0x2 field public static final int DATA_LOADER_TYPE_NONE = 0; // 0x0 field public static final int DATA_LOADER_TYPE_STREAMING = 1; // 0x1 @@ -5273,9 +5275,8 @@ package android.hardware.contexthub { } @FlaggedApi("android.chre.flags.offload_api") public final class HubServiceInfo implements android.os.Parcelable { - ctor public HubServiceInfo(@NonNull String, int, int, int, @NonNull android.os.ParcelableHolder); + ctor public HubServiceInfo(@NonNull String, int, int, int); method public int describeContents(); - method @NonNull public android.os.ParcelableHolder getExtendedInfo(); method public int getFormat(); method public int getMajorVersion(); method public int getMinorVersion(); @@ -5290,7 +5291,11 @@ package android.hardware.contexthub { public static final class HubServiceInfo.Builder { ctor public HubServiceInfo.Builder(@NonNull String, int, int, int); method @NonNull public android.hardware.contexthub.HubServiceInfo build(); - method @NonNull public android.hardware.contexthub.HubServiceInfo.Builder setExtendedInfo(@Nullable android.os.Parcelable); + } + + @FlaggedApi("android.chre.flags.offload_api") public interface IHubEndpointDiscoveryCallback { + method public void onEndpointsStarted(@NonNull java.util.List<android.hardware.contexthub.HubDiscoveryInfo>); + method public void onEndpointsStopped(@NonNull java.util.List<android.hardware.contexthub.HubDiscoveryInfo>); } @FlaggedApi("android.chre.flags.offload_api") public interface IHubEndpointLifecycleCallback { @@ -6315,11 +6320,16 @@ package android.hardware.location { method @Deprecated public int registerCallback(@NonNull android.hardware.location.ContextHubManager.Callback); method @Deprecated public int registerCallback(android.hardware.location.ContextHubManager.Callback, android.os.Handler); method @FlaggedApi("android.chre.flags.offload_api") @RequiresPermission(android.Manifest.permission.ACCESS_CONTEXT_HUB) public void registerEndpoint(@NonNull android.hardware.contexthub.HubEndpoint); + method @FlaggedApi("android.chre.flags.offload_api") @RequiresPermission(android.Manifest.permission.ACCESS_CONTEXT_HUB) public void registerEndpointDiscoveryCallback(long, @NonNull android.hardware.contexthub.IHubEndpointDiscoveryCallback); + method @FlaggedApi("android.chre.flags.offload_api") @RequiresPermission(android.Manifest.permission.ACCESS_CONTEXT_HUB) public void registerEndpointDiscoveryCallback(long, @NonNull android.hardware.contexthub.IHubEndpointDiscoveryCallback, @NonNull java.util.concurrent.Executor); + method @FlaggedApi("android.chre.flags.offload_api") @RequiresPermission(android.Manifest.permission.ACCESS_CONTEXT_HUB) public void registerEndpointDiscoveryCallback(@NonNull String, @NonNull android.hardware.contexthub.IHubEndpointDiscoveryCallback); + method @FlaggedApi("android.chre.flags.offload_api") @RequiresPermission(android.Manifest.permission.ACCESS_CONTEXT_HUB) public void registerEndpointDiscoveryCallback(@NonNull String, @NonNull android.hardware.contexthub.IHubEndpointDiscoveryCallback, @NonNull java.util.concurrent.Executor); method @Deprecated @RequiresPermission(android.Manifest.permission.ACCESS_CONTEXT_HUB) public int sendMessage(int, int, @NonNull android.hardware.location.ContextHubMessage); method @Deprecated @RequiresPermission(android.Manifest.permission.ACCESS_CONTEXT_HUB) public int unloadNanoApp(int); method @NonNull @RequiresPermission(android.Manifest.permission.ACCESS_CONTEXT_HUB) public android.hardware.location.ContextHubTransaction<java.lang.Void> unloadNanoApp(@NonNull android.hardware.location.ContextHubInfo, long); method @Deprecated public int unregisterCallback(@NonNull android.hardware.location.ContextHubManager.Callback); method @FlaggedApi("android.chre.flags.offload_api") @RequiresPermission(android.Manifest.permission.ACCESS_CONTEXT_HUB) public void unregisterEndpoint(@NonNull android.hardware.contexthub.HubEndpoint); + method @FlaggedApi("android.chre.flags.offload_api") @RequiresPermission(android.Manifest.permission.ACCESS_CONTEXT_HUB) public void unregisterEndpointDiscoveryCallback(@NonNull android.hardware.contexthub.IHubEndpointDiscoveryCallback); field public static final int AUTHORIZATION_DENIED = 0; // 0x0 field public static final int AUTHORIZATION_DENIED_GRACE_PERIOD = 1; // 0x1 field public static final int AUTHORIZATION_GRANTED = 2; // 0x2 @@ -11110,6 +11120,7 @@ package android.nfc.cardemulation { method @FlaggedApi("android.nfc.enable_nfc_mainline") public void setDynamicAidGroup(@NonNull android.nfc.cardemulation.AidGroup); method @FlaggedApi("android.nfc.enable_nfc_mainline") public void setOffHostSecureElement(@NonNull String); method @FlaggedApi("android.nfc.nfc_observe_mode") public void setShouldDefaultToObserveMode(boolean); + method @FlaggedApi("android.nfc.nfc_associated_role_services") public boolean shareRolePriority(); method @FlaggedApi("android.nfc.nfc_observe_mode") public boolean shouldDefaultToObserveMode(); method @FlaggedApi("android.nfc.enable_nfc_mainline") public void writeToParcel(@NonNull android.os.Parcel, int); field @FlaggedApi("android.nfc.enable_nfc_mainline") @NonNull public static final android.os.Parcelable.Creator<android.nfc.cardemulation.ApduServiceInfo> CREATOR; @@ -12865,6 +12876,30 @@ package android.security.authenticationpolicy { package android.security.intrusiondetection { + @FlaggedApi("android.security.afl_api") public final class IntrusionDetectionEvent implements android.os.Parcelable { + ctor public IntrusionDetectionEvent(@NonNull android.app.admin.SecurityLog.SecurityEvent); + ctor public IntrusionDetectionEvent(@NonNull android.app.admin.DnsEvent); + ctor public IntrusionDetectionEvent(@NonNull android.app.admin.ConnectEvent); + method @FlaggedApi("android.security.afl_api") public int describeContents(); + method @NonNull public android.app.admin.ConnectEvent getConnectEvent(); + method @NonNull public android.app.admin.DnsEvent getDnsEvent(); + method @NonNull public android.app.admin.SecurityLog.SecurityEvent getSecurityEvent(); + method @NonNull public int getType(); + method public void writeToParcel(@NonNull android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator<android.security.intrusiondetection.IntrusionDetectionEvent> CREATOR; + field public static final int NETWORK_EVENT_CONNECT = 2; // 0x2 + field public static final int NETWORK_EVENT_DNS = 1; // 0x1 + field public static final int SECURITY_EVENT = 0; // 0x0 + } + + @FlaggedApi("android.security.afl_api") public class IntrusionDetectionEventTransport { + ctor public IntrusionDetectionEventTransport(); + method public boolean addData(@NonNull java.util.List<android.security.intrusiondetection.IntrusionDetectionEvent>); + method @NonNull public android.os.IBinder getBinder(); + method public boolean initialize(); + method public boolean release(); + } + @FlaggedApi("android.security.afl_api") public class IntrusionDetectionManager { method @RequiresPermission(android.Manifest.permission.READ_INTRUSION_DETECTION_STATE) public void addStateCallback(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>); method @RequiresPermission(android.Manifest.permission.MANAGE_INTRUSION_DETECTION_STATE) public void disable(@NonNull java.util.concurrent.Executor, @NonNull android.security.intrusiondetection.IntrusionDetectionManager.CommandCallback); @@ -16196,6 +16231,7 @@ package android.telephony { method @Nullable @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS) public android.content.ComponentName getAndUpdateDefaultRespondViaMessageApplication(); method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void getCallForwarding(int, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.TelephonyManager.CallForwardingInfoCallback); method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void getCallWaitingStatus(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>); + method @FlaggedApi("com.android.internal.telephony.flags.carrier_id_from_carrier_identifier") @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) @WorkerThread public int getCarrierIdFromCarrierIdentifier(@NonNull android.service.carrier.CarrierIdentifier); method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public android.telephony.ImsiEncryptionInfo getCarrierInfoForImsiEncryption(int); method public java.util.List<java.lang.String> getCarrierPackageNamesForIntent(android.content.Intent); method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.List<java.lang.String> getCarrierPackageNamesForIntentAndPhone(android.content.Intent, int); diff --git a/core/api/test-current.txt b/core/api/test-current.txt index 1a97f7beb7fa..967f6194969e 100644 --- a/core/api/test-current.txt +++ b/core/api/test-current.txt @@ -3730,6 +3730,7 @@ package android.view { method @NonNull public android.view.Display.Mode getDefaultMode(); method public int getRemoveMode(); method @NonNull public int[] getReportedHdrTypes(); + method @NonNull public float[] getSupportedRefreshRatesLegacy(); method @NonNull public android.graphics.ColorSpace[] getSupportedWideColorGamut(); method @Nullable public android.view.Display.Mode getSystemPreferredDisplayMode(); method public int getType(); @@ -3752,6 +3753,7 @@ package android.view { public static final class Display.Mode implements android.os.Parcelable { ctor public Display.Mode(int, int, float); + method public float getVsyncRate(); method public boolean isSynthetic(); method public boolean matches(int, int, float); } diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java index d9f8d33f0545..eccb6ffb281c 100644 --- a/core/java/android/app/ActivityManagerInternal.java +++ b/core/java/android/app/ActivityManagerInternal.java @@ -1164,6 +1164,19 @@ public abstract class ActivityManagerInternal { @UserIdInt int userId, int notificationId); /** + * Notifies that a media service associated with a media session has transitioned to a + * "user-engaged" state. Upon receiving this notification, service will transition to the + * foreground state. It should only be called by + * {@link com.android.server.media.MediaSessionService} + * + * @param packageName The package name of the app running the media service. + * @param userId The user ID associated with the service. + * @param notificationId The ID of the media notification associated with the service. + */ + public abstract void notifyActiveMediaForegroundService(@NonNull String packageName, + @UserIdInt int userId, int notificationId); + + /** * Same as {@link android.app.IActivityManager#startProfile(int userId)}, but it would succeed * even if the profile is disabled - it should only be called by * {@link com.android.server.devicepolicy.DevicePolicyManagerService} when starting a profile diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index cb7b1153988a..f8186d68e210 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -8843,10 +8843,10 @@ public final class ActivityThread extends ClientTransactionHandler // Call per-process mainline module initialization. initializeMainlineModules(); - Process.setArgV0("<pre-initialized>"); - Looper.prepareMainLooper(); + Process.setArgV0("<pre-initialized>"); + // Find the value for {@link #PROC_START_SEQ_IDENT} if provided on the command line. // It will be in the format "seq=114" long startSeq = 0; diff --git a/core/java/android/app/ITaskStackListener.aidl b/core/java/android/app/ITaskStackListener.aidl index f2228f94ff01..4a9a28607796 100644 --- a/core/java/android/app/ITaskStackListener.aidl +++ b/core/java/android/app/ITaskStackListener.aidl @@ -178,6 +178,11 @@ oneway interface ITaskStackListener { void onRecentTaskListFrozenChanged(boolean frozen); /** + * Called when a task is removed from the recent tasks list as a result of adding a new task. + */ + void onRecentTaskRemovedForAddTask(int taskId); + + /** * Called when a task gets or loses focus. * * @param taskId id of the task. diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java index b84c91b8276b..0e68cce7a8f5 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -814,9 +814,9 @@ public class Notification implements Parcelable if (Flags.notificationsRedesignTemplates()) { return switch (layoutId) { case R.layout.notification_2025_template_collapsed_base, + R.layout.notification_2025_template_expanded_base, R.layout.notification_2025_template_heads_up_base, R.layout.notification_2025_template_header, - R.layout.notification_template_material_big_base, R.layout.notification_template_material_big_picture, R.layout.notification_template_material_big_text, R.layout.notification_template_material_inbox, @@ -3263,6 +3263,7 @@ public class Notification implements Parcelable public boolean hasPromotableCharacteristics() { return isColorizedRequested() && hasTitle() + && !isGroupSummary() && !containsCustomViews() && hasPromotableStyle(); } @@ -7545,7 +7546,11 @@ public class Notification implements Parcelable } private int getBigBaseLayoutResource() { - return R.layout.notification_template_material_big_base; + if (Flags.notificationsRedesignTemplates()) { + return R.layout.notification_2025_template_expanded_base; + } else { + return R.layout.notification_template_material_big_base; + } } private int getBigPictureLayoutResource() { diff --git a/core/java/android/app/TaskStackListener.java b/core/java/android/app/TaskStackListener.java index 36f61fd3ef59..b9b582a7d660 100644 --- a/core/java/android/app/TaskStackListener.java +++ b/core/java/android/app/TaskStackListener.java @@ -198,6 +198,10 @@ public abstract class TaskStackListener extends ITaskStackListener.Stub { } @Override + public void onRecentTaskRemovedForAddTask(int taskId) { + } + + @Override public void onTaskFocusChanged(int taskId, boolean focused) { } diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index e766ae2fce0d..42fa9e7d7994 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -14453,7 +14453,7 @@ public class DevicePolicyManager { * </ul> * <p> * The following methods are supported for the parent instance but can only be called by the - * profile owner of a managed profile that was created during the device provisioning flow: + * profile owner on an <a href="#organization-owned">organization owned</a> managed profile: * <ul> * <li>{@link #getPasswordComplexity}</li> * <li>{@link #setCameraDisabled}</li> @@ -14461,11 +14461,6 @@ public class DevicePolicyManager { * <li>{@link #setAccountManagementDisabled(ComponentName, String, boolean)}</li> * <li>{@link #setPermittedInputMethods}</li> * <li>{@link #getPermittedInputMethods}</li> - * </ul> - * - * <p>The following methods can be called by the profile owner of a managed profile - * on an organization-owned device: - * <ul> * <li>{@link #wipeData}</li> * </ul> * @@ -18177,4 +18172,4 @@ public class DevicePolicyManager { } return HEADLESS_DEVICE_OWNER_MODE_UNSUPPORTED; } -}
\ No newline at end of file +} diff --git a/core/java/android/app/background_install_control_manager.aconfig b/core/java/android/app/background_install_control_manager.aconfig index d29c5b58092d..39f10dc0647f 100644 --- a/core/java/android/app/background_install_control_manager.aconfig +++ b/core/java/android/app/background_install_control_manager.aconfig @@ -9,3 +9,10 @@ flag { is_fixed_read_only: true bug: "287507984" } + +flag { + name: "background_install_control_callback_api" + namespace: "preload_safety" + description: "Feature flag to enable the use of push API in background install control service" + bug: "369382811" +}
\ No newline at end of file diff --git a/core/java/android/appwidget/AppWidgetManager.java b/core/java/android/appwidget/AppWidgetManager.java index 8f20ea034cf6..40de2985f68a 100644 --- a/core/java/android/appwidget/AppWidgetManager.java +++ b/core/java/android/appwidget/AppWidgetManager.java @@ -31,6 +31,7 @@ import android.annotation.UiThread; import android.annotation.UserIdInt; import android.app.IServiceConnection; import android.app.PendingIntent; +import android.app.usage.UsageStatsManager; import android.appwidget.flags.Flags; import android.compat.annotation.UnsupportedAppUsage; import android.content.ComponentName; @@ -41,12 +42,14 @@ import android.content.ServiceConnection; import android.content.pm.PackageManager; import android.content.pm.ParceledListSlice; import android.content.pm.ShortcutInfo; +import android.graphics.Rect; import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.os.HandlerExecutor; import android.os.HandlerThread; import android.os.Looper; +import android.os.PersistableBundle; import android.os.Process; import android.os.RemoteException; import android.os.UserHandle; @@ -485,6 +488,67 @@ public class AppWidgetManager { public static final String ACTION_APPWIDGET_HOST_RESTORED = "android.appwidget.action.APPWIDGET_HOST_RESTORED"; + /** + * This is the value of {@link UsageStatsManager.EXTRA_EVENT_ACTION} in the event bundle for + * widget user interaction events. + * + * A single widget interaction event describes what user interactions happened during a single + * impression of the widget. + */ + @FlaggedApi(Flags.FLAG_ENGAGEMENT_METRICS) + public static final String EVENT_TYPE_WIDGET_INTERACTION = "widget_interaction"; + + /** + * This is the value of {@link UsageStatsManager.EXTRA_EVENT_CATEGORY} in the event bundle for + * widget user interaction events. + */ + @FlaggedApi(Flags.FLAG_ENGAGEMENT_METRICS) + public static final String EVENT_CATEGORY_APPWIDGET = "android.appwidget"; + + /** + * This bundle extra describes which views have been clicked during a single impression of the + * widget. It is an integer array of view IDs of the clicked views. + * + * Widget providers may set a different ID for event purposes by setting the + * {@link android.R.id.remoteViewsMetricsId} int tag on the view. + * + * @see android.views.RemoteViews.setIntTag + */ + @FlaggedApi(Flags.FLAG_ENGAGEMENT_METRICS) + public static final String EXTRA_EVENT_CLICKED_VIEWS = + "android.appwidget.extra.EVENT_CLICKED_VIEWS"; + + /** + * This bundle extra describes which views have been scrolled during a single impression of the + * widget. It is an integer array of view IDs of the scrolled views. + * + * Widget providers may set a different ID for event purposes by setting the + * {@link android.R.id.remoteViewsMetricsId} int tag on the view. + * + * @see android.views.RemoteViews.setIntTag + */ + @FlaggedApi(Flags.FLAG_ENGAGEMENT_METRICS) + public static final String EXTRA_EVENT_SCROLLED_VIEWS = + "android.appwidget.extra.EVENT_SCROLLED_VIEWS"; + + /** + * This bundle extra contains a long that represents the duration of time in milliseconds + * during which the widget was visible. + */ + @FlaggedApi(Flags.FLAG_ENGAGEMENT_METRICS) + public static final String EXTRA_EVENT_DURATION_MS = + "android.appwidget.extra.EVENT_DURATION_MS"; + + /** + * This bundle extra contains an integer array with 4 elements that describe the left, top, + * right, and bottom coordinates of the widget at the end of the interaction event. + * + * This Rect indicates the current position and size of the widget. + */ + @FlaggedApi(Flags.FLAG_ENGAGEMENT_METRICS) + public static final String EXTRA_EVENT_POSITION_RECT = + "android.appwidget.extra.EVENT_POSITION_RECT"; + private static final String TAG = "AppWidgetManager"; private static Executor sUpdateExecutor; @@ -1516,6 +1580,39 @@ public class AppWidgetManager { } } + /** + * Create a {@link PersistableBundle} that represents a single widget interaction event. + * + * @param appWidgetId App Widget ID of the widget. + * @param durationMs Duration of the impression in milliseconds + * @param position Current position of the widget. + * @param clickedIds IDs of views clicked during this event. + * @param scrolledIds IDs of views scrolled during this event. + * + * @hide + */ + @FlaggedApi(Flags.FLAG_ENGAGEMENT_METRICS) + @NonNull + public static PersistableBundle createWidgetInteractionEvent(int appWidgetId, long durationMs, + @Nullable Rect position, @Nullable int[] clickedIds, @Nullable int[] scrolledIds) { + PersistableBundle extras = new PersistableBundle(); + extras.putString(UsageStatsManager.EXTRA_EVENT_ACTION, EVENT_TYPE_WIDGET_INTERACTION); + extras.putString(UsageStatsManager.EXTRA_EVENT_CATEGORY, EVENT_CATEGORY_APPWIDGET); + extras.putInt(EXTRA_APPWIDGET_ID, appWidgetId); + extras.putLong(EXTRA_EVENT_DURATION_MS, durationMs); + if (position != null) { + extras.putIntArray(EXTRA_EVENT_POSITION_RECT, + new int[]{position.left, position.top, position.right, position.bottom}); + } + if (clickedIds != null && clickedIds.length > 0) { + extras.putIntArray(EXTRA_EVENT_CLICKED_VIEWS, clickedIds); + } + if (scrolledIds != null && scrolledIds.length > 0) { + extras.putIntArray(EXTRA_EVENT_SCROLLED_VIEWS, scrolledIds); + } + return extras; + } + @UiThread private static @NonNull Executor createUpdateExecutorIfNull() { diff --git a/core/java/android/appwidget/flags.aconfig b/core/java/android/appwidget/flags.aconfig index 4499a723cfb8..17bcdb013673 100644 --- a/core/java/android/appwidget/flags.aconfig +++ b/core/java/android/appwidget/flags.aconfig @@ -105,3 +105,10 @@ flag { purpose: PURPOSE_BUGFIX } } + +flag { + name: "engagement_metrics" + namespace: "app_widgets" + description: "Enable collection of widget engagement metrics" + bug: "364655296" +} diff --git a/core/java/android/companion/CompanionDeviceService.java b/core/java/android/companion/CompanionDeviceService.java index 5ad2348254e2..db080fcc7702 100644 --- a/core/java/android/companion/CompanionDeviceService.java +++ b/core/java/android/companion/CompanionDeviceService.java @@ -249,7 +249,7 @@ public abstract class CompanionDeviceService extends Service { // TODO(b/315163162) Add @Deprecated keyword after 24Q2 cut. /** - * Called by system whenever a device associated with this app is connected. + * Called by the system when an associated device is nearby or connected. * * @param associationInfo A record for the companion device. */ @@ -262,7 +262,7 @@ public abstract class CompanionDeviceService extends Service { // TODO(b/315163162) Add @Deprecated keyword after 24Q2 cut. /** - * Called by system whenever a device associated with this app is disconnected. + * Called by the system when an associated device is out of range or disconnected. * * @param associationInfo A record for the companion device. */ @@ -274,7 +274,7 @@ public abstract class CompanionDeviceService extends Service { } /** - * Called by the system during device events. + * Called by the system when an associated device's presence state changes. * * @see CompanionDeviceManager#startObservingDevicePresence(ObservingDevicePresenceRequest) */ diff --git a/core/java/android/companion/virtual/IVirtualDevice.aidl b/core/java/android/companion/virtual/IVirtualDevice.aidl index d3a1c25b74d5..367f1afc912b 100644 --- a/core/java/android/companion/virtual/IVirtualDevice.aidl +++ b/core/java/android/companion/virtual/IVirtualDevice.aidl @@ -90,11 +90,6 @@ interface IVirtualDevice { */ boolean hasCustomAudioInputSupport(); - /** - * Returns whether this device is allowed to create mirror displays. - */ - boolean canCreateMirrorDisplays(); - /* * Turns off all trusted non-mirror displays of the virtual device. */ diff --git a/core/java/android/companion/virtual/flags.aconfig b/core/java/android/companion/virtual/flags.aconfig index 3e6919bac5fa..46da4a3d99bc 100644 --- a/core/java/android/companion/virtual/flags.aconfig +++ b/core/java/android/companion/virtual/flags.aconfig @@ -81,14 +81,3 @@ flag { description: "Enable virtual stylus input" bug: "304829446" } - -flag { - name: "impulse_velocity_strategy_for_touch_navigation" - is_exported: true - namespace: "virtual_devices" - description: "Use impulse velocity strategy during conversion of touch navigation flings into Dpad events" - bug: "338426241" - metadata { - purpose: PURPOSE_BUGFIX - } -}
\ No newline at end of file diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java index cb665cd2053c..cd62573f6e4e 100644 --- a/core/java/android/content/pm/PackageInstaller.java +++ b/core/java/android/content/pm/PackageInstaller.java @@ -218,6 +218,17 @@ public class PackageInstaller { "android.content.pm.action.CONFIRM_PRE_APPROVAL"; /** + * Intent action to be sent to the implementer of + * {@link android.content.pm.dependencyinstaller.DependencyInstallerService}. + * + * @hide + */ + @FlaggedApi(Flags.FLAG_SDK_DEPENDENCY_INSTALLER) + @SystemApi + public static final String ACTION_INSTALL_DEPENDENCY = + "android.content.pm.action.INSTALL_DEPENDENCY"; + + /** * An integer session ID that an operation is working with. * * @see Intent#getIntExtra(String, int) diff --git a/core/java/android/content/pm/parsing/ApkLiteParseUtils.java b/core/java/android/content/pm/parsing/ApkLiteParseUtils.java index 72542036232c..18a45d8d442e 100644 --- a/core/java/android/content/pm/parsing/ApkLiteParseUtils.java +++ b/core/java/android/content/pm/parsing/ApkLiteParseUtils.java @@ -595,9 +595,6 @@ public class ApkLiteParseUtils { /*allowDuplicates=*/ true); break; case TAG_USES_STATIC_LIBRARY: - if (!android.content.pm.Flags.sdkDependencyInstaller()) { - break; - } String usesStaticLibName = parser.getAttributeValue( ANDROID_RES_NAMESPACE, "name"); long usesStaticLibVersion = parser.getAttributeIntValue( @@ -666,7 +663,7 @@ public class ApkLiteParseUtils { SharedLibraryInfo.TYPE_SDK_PACKAGE)); break; case TAG_STATIC_LIBRARY: - isSdkLibrary = true; + isStaticLibrary = true; // Mirrors ParsingPackageUtils#parseStaticLibrary until lite and full // parsing are combined String staticLibName = parser.getAttributeValue( diff --git a/core/java/android/hardware/DisplayLuts.java b/core/java/android/hardware/DisplayLuts.java index 6343ba19f569..0abb30f8c24d 100644 --- a/core/java/android/hardware/DisplayLuts.java +++ b/core/java/android/hardware/DisplayLuts.java @@ -177,6 +177,8 @@ public final class DisplayLuts { return "SAMPLING_KEY_RGB"; case LutProperties.SAMPLING_KEY_MAX_RGB: return "SAMPLING_KEY_MAX_RGB"; + case LutProperties.SAMPLING_KEY_CIE_Y: + return "SAMPLING_KEY_CIE_Y"; default: return ""; } diff --git a/core/java/android/hardware/LutProperties.java b/core/java/android/hardware/LutProperties.java index bf40a415b0f7..abb303adac15 100644 --- a/core/java/android/hardware/LutProperties.java +++ b/core/java/android/hardware/LutProperties.java @@ -44,7 +44,8 @@ public final class LutProperties { @Retention(RetentionPolicy.SOURCE) @IntDef(prefix = {"SAMPLING_KEY_"}, value = { SAMPLING_KEY_RGB, - SAMPLING_KEY_MAX_RGB + SAMPLING_KEY_MAX_RGB, + SAMPLING_KEY_CIE_Y }) public @interface SamplingKey { } @@ -57,6 +58,10 @@ public final class LutProperties { @FlaggedApi(Flags.FLAG_LUTS_API) public static final int SAMPLING_KEY_MAX_RGB = 1; + /** use y of CIE XYZ as the gain value of a lut */ + @FlaggedApi(Flags.FLAG_LUTS_API) + public static final int SAMPLING_KEY_CIE_Y = 2; + /** @hide */ @Retention(RetentionPolicy.SOURCE) @IntDef(value = { diff --git a/core/java/android/hardware/camera2/CameraExtensionCharacteristics.java b/core/java/android/hardware/camera2/CameraExtensionCharacteristics.java index 3cf508a6db00..58fe4774f178 100644 --- a/core/java/android/hardware/camera2/CameraExtensionCharacteristics.java +++ b/core/java/android/hardware/camera2/CameraExtensionCharacteristics.java @@ -1066,6 +1066,7 @@ public final class CameraExtensionCharacteristics { case ImageFormat.YUV_420_888: case ImageFormat.JPEG: case ImageFormat.JPEG_R: + case ImageFormat.DEPTH_JPEG: case ImageFormat.YCBCR_P010: break; default: @@ -1096,9 +1097,10 @@ public final class CameraExtensionCharacteristics { // processed YUV_420 buffers. return getSupportedSizes( extenders.second.getSupportedPostviewResolutions(sz), format); - } else if (format == ImageFormat.JPEG_R || format == ImageFormat.YCBCR_P010) { - // Jpeg_R/UltraHDR + YCBCR_P010 is currently not supported in the basic - // extension case + } else if (format == ImageFormat.JPEG_R || format == ImageFormat.YCBCR_P010 || + (Flags.depthJpegExtensions() && (format == ImageFormat.DEPTH_JPEG))) { + // DepthJpeg/Jpeg_R/UltraHDR + YCBCR_P010 is currently not supported in the + // basic extension case return new ArrayList<>(); } else { throw new IllegalArgumentException("Unsupported format: " + format); @@ -1194,8 +1196,8 @@ public final class CameraExtensionCharacteristics { * * <p>Device-specific extensions currently support at most three * multi-frame capture surface formats. ImageFormat.JPEG will be supported by all - * extensions while ImageFormat.YUV_420_888, ImageFormat.JPEG_R, or ImageFormat.YCBCR_P010 - * may or may not be supported.</p> + * extensions while ImageFormat.YUV_420_888, ImageFormat.JPEG_R, ImageFormat.YCBCR_P010 or + * ImageFormat.DEPTH_JPEG may or may not be supported.</p> * * @param extension the extension type * @param format device-specific extension output format @@ -1203,7 +1205,8 @@ public final class CameraExtensionCharacteristics { * supported. * @throws IllegalArgumentException in case of format different from ImageFormat.JPEG, * ImageFormat.YUV_420_888, ImageFormat.JPEG_R, - * ImageFormat.YCBCR_P010; or unsupported extension. + * ImageFormat.DEPTH_JPEG, ImageFormat.YCBCR_P010; or + * unsupported extension. */ public @NonNull List<Size> getExtensionSupportedSizes(@Extension int extension, int format) { @@ -1227,6 +1230,7 @@ public final class CameraExtensionCharacteristics { case ImageFormat.YUV_420_888: case ImageFormat.JPEG: case ImageFormat.JPEG_R: + case ImageFormat.DEPTH_JPEG: case ImageFormat.YCBCR_P010: break; default: @@ -1260,8 +1264,9 @@ public final class CameraExtensionCharacteristics { } else { return generateSupportedSizes(null, format, streamMap); } - } else if (format == ImageFormat.JPEG_R || format == ImageFormat.YCBCR_P010) { - // Jpeg_R/UltraHDR + YCBCR_P010 is currently not supported in the + } else if (format == ImageFormat.JPEG_R || format == ImageFormat.YCBCR_P010 || + (Flags.depthJpegExtensions() && (format == ImageFormat.DEPTH_JPEG))) { + // DepthJpeg/Jpeg_R/UltraHDR + YCBCR_P010 is currently not supported in the // basic extension case return new ArrayList<>(); } else { @@ -1292,7 +1297,8 @@ public final class CameraExtensionCharacteristics { * or null if no capture latency info can be provided * @throws IllegalArgumentException in case of format different from {@link ImageFormat#JPEG}, * {@link ImageFormat#YUV_420_888}, {@link ImageFormat#JPEG_R} - * {@link ImageFormat#YCBCR_P010}; + * {@link ImageFormat#YCBCR_P010}, + * {@link ImageFormat#DEPTH_JPEG}; * or unsupported extension. */ public @Nullable Range<Long> getEstimatedCaptureLatencyRangeMillis(@Extension int extension, @@ -1301,6 +1307,7 @@ public final class CameraExtensionCharacteristics { case ImageFormat.YUV_420_888: case ImageFormat.JPEG: case ImageFormat.JPEG_R: + case ImageFormat.DEPTH_JPEG: case ImageFormat.YCBCR_P010: //No op break; @@ -1349,8 +1356,9 @@ public final class CameraExtensionCharacteristics { // specific and cannot be estimated accurately enough. return null; } - if (format == ImageFormat.JPEG_R || format == ImageFormat.YCBCR_P010) { - // JpegR/UltraHDR + YCBCR_P010 is not supported for basic extensions + if (format == ImageFormat.JPEG_R || format == ImageFormat.YCBCR_P010 || + (Flags.depthJpegExtensions() && (format == ImageFormat.DEPTH_JPEG))) { + // DepthJpeg/JpegR/UltraHDR + YCBCR_P010 is not supported for basic extensions return null; } diff --git a/core/java/android/hardware/camera2/impl/CameraAdvancedExtensionSessionImpl.java b/core/java/android/hardware/camera2/impl/CameraAdvancedExtensionSessionImpl.java index fc03b517e6d4..d511e9f64c17 100644 --- a/core/java/android/hardware/camera2/impl/CameraAdvancedExtensionSessionImpl.java +++ b/core/java/android/hardware/camera2/impl/CameraAdvancedExtensionSessionImpl.java @@ -186,12 +186,12 @@ public final class CameraAdvancedExtensionSessionImpl extends CameraExtensionSes HashMap<Integer, List<Size>> supportedCaptureSizes = new HashMap<>(); - IntArray supportedCaptureOutputFormats = - new IntArray(CameraExtensionUtils.SUPPORTED_CAPTURE_OUTPUT_FORMATS.length); - supportedCaptureOutputFormats.addAll( - CameraExtensionUtils.SUPPORTED_CAPTURE_OUTPUT_FORMATS); - supportedCaptureOutputFormats.add(ImageFormat.YCBCR_P010); - for (int format : supportedCaptureOutputFormats.toArray()) { + Integer[] supportedCaptureOutputFormats = + new Integer[CameraExtensionUtils.SUPPORTED_CAPTURE_OUTPUT_FORMATS.size()]; + supportedCaptureOutputFormats = + CameraExtensionUtils.SUPPORTED_CAPTURE_OUTPUT_FORMATS.toArray( + supportedCaptureOutputFormats); + for (int format : supportedCaptureOutputFormats) { List<Size> supportedSizes = extensionChars.getExtensionSupportedSizes( config.getExtension(), format); if (supportedSizes != null) { @@ -230,7 +230,7 @@ public final class CameraAdvancedExtensionSessionImpl extends CameraExtensionSes Size burstCaptureSurfaceSize = new Size(burstCaptureSurfaceInfo.mWidth, burstCaptureSurfaceInfo.mHeight); HashMap<Integer, List<Size>> supportedPostviewSizes = new HashMap<>(); - for (int format : supportedCaptureOutputFormats.toArray()) { + for (int format : supportedCaptureOutputFormats) { List<Size> supportedSizesPostview = extensionChars.getPostviewSupportedSizes( config.getExtension(), burstCaptureSurfaceSize, format); if (supportedSizesPostview != null) { diff --git a/core/java/android/hardware/camera2/impl/CameraExtensionSessionImpl.java b/core/java/android/hardware/camera2/impl/CameraExtensionSessionImpl.java index ce1609dec4e6..ed73e624e242 100644 --- a/core/java/android/hardware/camera2/impl/CameraExtensionSessionImpl.java +++ b/core/java/android/hardware/camera2/impl/CameraExtensionSessionImpl.java @@ -186,12 +186,12 @@ public final class CameraExtensionSessionImpl extends CameraExtensionSession { } HashMap<Integer, List<Size>> supportedCaptureSizes = new HashMap<>(); - IntArray supportedCaptureOutputFormats = - new IntArray(CameraExtensionUtils.SUPPORTED_CAPTURE_OUTPUT_FORMATS.length); - supportedCaptureOutputFormats.addAll( - CameraExtensionUtils.SUPPORTED_CAPTURE_OUTPUT_FORMATS); - supportedCaptureOutputFormats.add(ImageFormat.YCBCR_P010); - for (int format : supportedCaptureOutputFormats.toArray()) { + Integer[] supportedCaptureOutputFormats = + new Integer[CameraExtensionUtils.SUPPORTED_CAPTURE_OUTPUT_FORMATS.size()]; + supportedCaptureOutputFormats = + CameraExtensionUtils.SUPPORTED_CAPTURE_OUTPUT_FORMATS.toArray( + supportedCaptureOutputFormats); + for (int format : supportedCaptureOutputFormats) { List<Size> supportedSizes = extensionChars.getExtensionSupportedSizes( config.getExtension(), format); if (supportedSizes != null) { @@ -223,7 +223,7 @@ public final class CameraExtensionSessionImpl extends CameraExtensionSession { Size burstCaptureSurfaceSize = new Size(burstCaptureSurfaceInfo.mWidth, burstCaptureSurfaceInfo.mHeight); HashMap<Integer, List<Size>> supportedPostviewSizes = new HashMap<>(); - for (int format : supportedCaptureOutputFormats.toArray()) { + for (int format : supportedCaptureOutputFormats) { List<Size> supportedSizesPostview = extensionChars.getPostviewSupportedSizes( config.getExtension(), burstCaptureSurfaceSize, format); if (supportedSizesPostview != null) { diff --git a/core/java/android/hardware/camera2/impl/CameraExtensionUtils.java b/core/java/android/hardware/camera2/impl/CameraExtensionUtils.java index f91d277d571f..212c909bcbba 100644 --- a/core/java/android/hardware/camera2/impl/CameraExtensionUtils.java +++ b/core/java/android/hardware/camera2/impl/CameraExtensionUtils.java @@ -32,11 +32,14 @@ import android.os.Handler; import android.util.IntArray; import android.util.Log; import android.util.Size; +import android.util.SparseIntArray; import android.view.Surface; import com.android.internal.camera.flags.Flags; +import java.util.Arrays; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.concurrent.Executor; @@ -48,11 +51,16 @@ public final class CameraExtensionUtils { public final static int JPEG_DEFAULT_QUALITY = 100; public final static int JPEG_DEFAULT_ROTATION = 0; - public static final int[] SUPPORTED_CAPTURE_OUTPUT_FORMATS = { - CameraExtensionCharacteristics.PROCESSING_INPUT_FORMAT, - ImageFormat.JPEG, - ImageFormat.JPEG_R - }; + public static HashSet<Integer> SUPPORTED_CAPTURE_OUTPUT_FORMATS = new HashSet<>(); + + static { + SUPPORTED_CAPTURE_OUTPUT_FORMATS.addAll(Arrays.asList( + CameraExtensionCharacteristics.PROCESSING_INPUT_FORMAT, ImageFormat.JPEG, + ImageFormat.YCBCR_P010, ImageFormat.JPEG_R )); + if (Flags.depthJpegExtensions()) { + SUPPORTED_CAPTURE_OUTPUT_FORMATS.add(ImageFormat.DEPTH_JPEG); + } + } public static class SurfaceInfo { public int mWidth = 0; @@ -101,6 +109,13 @@ public final class CameraExtensionUtils { surfaceInfo.mFormat = ImageFormat.JPEG_R; return surfaceInfo; } + if (Flags.depthJpegExtensions()) { + if ((nativeFormat == StreamConfigurationMap.HAL_PIXEL_FORMAT_BLOB) + && (dataspace == StreamConfigurationMap.HAL_DATASPACE_DYNAMIC_DEPTH)) { + surfaceInfo.mFormat = ImageFormat.DEPTH_JPEG; + return surfaceInfo; + } + } return surfaceInfo; } @@ -125,14 +140,14 @@ public final class CameraExtensionUtils { public static Surface getBurstCaptureSurface( @NonNull List<OutputConfiguration> outputConfigs, @NonNull HashMap<Integer, List<Size>> supportedCaptureSizes) { - IntArray supportedCaptureOutputFormats = - new IntArray(CameraExtensionUtils.SUPPORTED_CAPTURE_OUTPUT_FORMATS.length); - supportedCaptureOutputFormats.addAll( - CameraExtensionUtils.SUPPORTED_CAPTURE_OUTPUT_FORMATS); - supportedCaptureOutputFormats.add(ImageFormat.YCBCR_P010); + Integer[] supportedCaptureOutputFormats = + new Integer[CameraExtensionUtils.SUPPORTED_CAPTURE_OUTPUT_FORMATS.size()]; + supportedCaptureOutputFormats = + CameraExtensionUtils.SUPPORTED_CAPTURE_OUTPUT_FORMATS.toArray( + supportedCaptureOutputFormats); for (OutputConfiguration config : outputConfigs) { SurfaceInfo surfaceInfo = querySurface(config.getSurface()); - for (int supportedFormat : supportedCaptureOutputFormats.toArray()) { + for (int supportedFormat : supportedCaptureOutputFormats) { if (surfaceInfo.mFormat == supportedFormat) { Size captureSize = new Size(surfaceInfo.mWidth, surfaceInfo.mHeight); if (supportedCaptureSizes.containsKey(supportedFormat)) { diff --git a/core/java/android/hardware/contexthub/HubServiceInfo.java b/core/java/android/hardware/contexthub/HubServiceInfo.java index c7fe77c4a0f1..a1c52fb5864f 100644 --- a/core/java/android/hardware/contexthub/HubServiceInfo.java +++ b/core/java/android/hardware/contexthub/HubServiceInfo.java @@ -17,12 +17,10 @@ package android.hardware.contexthub; import android.annotation.FlaggedApi; import android.annotation.IntDef; -import android.annotation.Nullable; import android.annotation.SystemApi; import android.chre.flags.Flags; import android.os.Parcel; import android.os.Parcelable; -import android.os.ParcelableHolder; import androidx.annotation.NonNull; @@ -76,15 +74,12 @@ public final class HubServiceInfo implements Parcelable { private final int mMajorVersion; private final int mMinorVersion; - @NonNull private final ParcelableHolder mExtendedInfo; - /** @hide */ public HubServiceInfo(android.hardware.contexthub.Service service) { mServiceDescriptor = service.serviceDescriptor; mFormat = service.format; mMajorVersion = service.majorVersion; mMinorVersion = service.minorVersion; - mExtendedInfo = service.extendedInfo; } private HubServiceInfo(Parcel in) { @@ -92,20 +87,17 @@ public final class HubServiceInfo implements Parcelable { mFormat = in.readInt(); mMajorVersion = in.readInt(); mMinorVersion = in.readInt(); - mExtendedInfo = ParcelableHolder.CREATOR.createFromParcel(in); } public HubServiceInfo( @NonNull String serviceDescriptor, @ServiceFormat int format, int majorVersion, - int minorVersion, - @NonNull ParcelableHolder extendedInfo) { + int minorVersion) { mServiceDescriptor = serviceDescriptor; mFormat = format; mMajorVersion = majorVersion; mMinorVersion = minorVersion; - mExtendedInfo = extendedInfo; } /** Get the unique identifier of this service. See {@link Builder} for more information. */ @@ -134,17 +126,10 @@ public final class HubServiceInfo implements Parcelable { return mMinorVersion; } - /** Get the {@link ParcelableHolder} for the extended information about the service. */ - @NonNull - public ParcelableHolder getExtendedInfo() { - return mExtendedInfo; - } - /** Parcel implementation details */ @Override public int describeContents() { - // Passthrough describeContents flags for mExtendedInfo because we don't have FD otherwise. - return mExtendedInfo.describeContents(); + return 0; } /** Parcel implementation details */ @@ -154,7 +139,6 @@ public final class HubServiceInfo implements Parcelable { dest.writeInt(mFormat); dest.writeInt(mMajorVersion); dest.writeInt(mMinorVersion); - mExtendedInfo.writeToParcel(dest, flags); } /** Builder for a {@link HubServiceInfo} object. */ @@ -165,9 +149,6 @@ public final class HubServiceInfo implements Parcelable { private final int mMajorVersion; private final int mMinorVersion; - private final ParcelableHolder mExtendedInfo = - new ParcelableHolder(Parcelable.PARCELABLE_STABILITY_VINTF); - /** * Create a builder for {@link HubServiceInfo} with a service descriptor. * @@ -220,20 +201,6 @@ public final class HubServiceInfo implements Parcelable { } /** - * Set the extended information of this service. - * - * @param extendedInfo Parcelable with extended information about this service. The - * parcelable needs to have at least VINTF stability. Null can be used to clear a - * previously set value. - * @throws android.os.BadParcelableException if the parcelable cannot be used. - */ - @NonNull - public Builder setExtendedInfo(@Nullable Parcelable extendedInfo) { - mExtendedInfo.setParcelable(extendedInfo); - return this; - } - - /** * Build the {@link HubServiceInfo} object. * * @throws IllegalStateException if the Builder is missing required info. @@ -244,7 +211,7 @@ public final class HubServiceInfo implements Parcelable { throw new IllegalStateException("Major and minor version must be set."); } return new HubServiceInfo( - mServiceDescriptor, mFormat, mMajorVersion, mMinorVersion, mExtendedInfo); + mServiceDescriptor, mFormat, mMajorVersion, mMinorVersion); } } diff --git a/core/java/android/hardware/contexthub/IContextHubEndpointDiscoveryCallback.aidl b/core/java/android/hardware/contexthub/IContextHubEndpointDiscoveryCallback.aidl new file mode 100644 index 000000000000..85775c05bad9 --- /dev/null +++ b/core/java/android/hardware/contexthub/IContextHubEndpointDiscoveryCallback.aidl @@ -0,0 +1,36 @@ +/* + * Copyright 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.contexthub; + +import android.hardware.contexthub.HubEndpointInfo; + +/** + * @hide + */ +oneway interface IContextHubEndpointDiscoveryCallback { + /** + * Called when endpoint(s) start. + * @param hubEndpointInfoList The list of endpoints that started. + */ + void onEndpointsStarted(in HubEndpointInfo[] hubEndpointInfoList); + + /** + * Called when endpoint(s) stopped. + * @param hubEndpointInfoList The list of endpoints that started. + */ + void onEndpointsStopped(in HubEndpointInfo[] hubEndpointInfoList); +} diff --git a/core/java/android/hardware/contexthub/IHubEndpointDiscoveryCallback.java b/core/java/android/hardware/contexthub/IHubEndpointDiscoveryCallback.java new file mode 100644 index 000000000000..0b77ddb8cb0b --- /dev/null +++ b/core/java/android/hardware/contexthub/IHubEndpointDiscoveryCallback.java @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.contexthub; + +import android.annotation.FlaggedApi; +import android.annotation.NonNull; +import android.annotation.SystemApi; +import android.chre.flags.Flags; + +import java.util.List; + +/** + * Interface for listening to updates about endpoint availability. + * + * @hide + */ +@SystemApi +@FlaggedApi(Flags.FLAG_OFFLOAD_API) +public interface IHubEndpointDiscoveryCallback { + /** + * Called when a list of hub endpoints have started. + * + * @param discoveryInfoList The list containing hub discovery information. + */ + void onEndpointsStarted(@NonNull List<HubDiscoveryInfo> discoveryInfoList); + + /** + * Called when a list of hub endpoints have stopped. + * + * @param discoveryInfoList The list containing hub discovery information. + */ + // TODO(b/375487784): Add endpoint stop reason + void onEndpointsStopped(@NonNull List<HubDiscoveryInfo> discoveryInfoList); +} diff --git a/core/java/android/hardware/location/ContextHubManager.java b/core/java/android/hardware/location/ContextHubManager.java index 426cd69f76a0..5e8a18724cdf 100644 --- a/core/java/android/hardware/location/ContextHubManager.java +++ b/core/java/android/hardware/location/ContextHubManager.java @@ -38,6 +38,8 @@ import android.hardware.contexthub.HubDiscoveryInfo; import android.hardware.contexthub.HubEndpoint; import android.hardware.contexthub.HubEndpointInfo; import android.hardware.contexthub.HubServiceInfo; +import android.hardware.contexthub.IContextHubEndpointDiscoveryCallback; +import android.hardware.contexthub.IHubEndpointDiscoveryCallback; import android.hardware.contexthub.IHubEndpointLifecycleCallback; import android.os.Handler; import android.os.HandlerExecutor; @@ -49,7 +51,9 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.List; +import java.util.Map; import java.util.Objects; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.Executor; /** @@ -202,6 +206,10 @@ public final class ContextHubManager { private Callback mCallback; private Handler mCallbackHandler; + /** A map of endpoint discovery callbacks currently registered */ + private Map<IHubEndpointDiscoveryCallback, IContextHubEndpointDiscoveryCallback> + mDiscoveryCallbacks = new ConcurrentHashMap<>(); + /** * @deprecated Use {@code mCallback} instead. */ @@ -694,8 +702,6 @@ public final class ContextHubManager { @RequiresPermission(android.Manifest.permission.ACCESS_CONTEXT_HUB) @NonNull public List<HubDiscoveryInfo> findEndpoints(long endpointId) { - // TODO(b/379323274): Consider improving these getters to avoid racing with nano app load - // timing. try { List<HubEndpointInfo> endpointInfos = mService.findEndpoints(endpointId); List<HubDiscoveryInfo> results = new ArrayList<>(endpointInfos.size()); @@ -720,8 +726,6 @@ public final class ContextHubManager { @RequiresPermission(android.Manifest.permission.ACCESS_CONTEXT_HUB) @NonNull public List<HubDiscoveryInfo> findEndpoints(@NonNull String serviceDescriptor) { - // TODO(b/379323274): Consider improving these getters to avoid racing with nano app load - // timing. if (serviceDescriptor.isBlank()) { throw new IllegalArgumentException("Invalid service descriptor: " + serviceDescriptor); } @@ -744,6 +748,188 @@ public final class ContextHubManager { } /** + * Creates an interface to invoke endpoint discovery callbacks to send down to the service. + * + * @param callback the callback to invoke at the client process + * @param executor the executor to invoke callbacks for this client + * @return the callback interface + */ + private IContextHubEndpointDiscoveryCallback createDiscoveryCallback( + IHubEndpointDiscoveryCallback callback, + Executor executor, + @Nullable String serviceDescriptor) { + return new IContextHubEndpointDiscoveryCallback.Stub() { + @Override + public void onEndpointsStarted(HubEndpointInfo[] hubEndpointInfoList) { + if (hubEndpointInfoList.length == 0) { + Log.w(TAG, "onEndpointsStarted: received empty discovery list"); + return; + } + executor.execute( + () -> { + // TODO(b/380293951): Refactor + List<HubDiscoveryInfo> discoveryList = + new ArrayList<>(hubEndpointInfoList.length); + for (HubEndpointInfo info : hubEndpointInfoList) { + if (serviceDescriptor != null) { + for (HubServiceInfo sInfo : info.getServiceInfoCollection()) { + if (sInfo.getServiceDescriptor() + .equals(serviceDescriptor)) { + discoveryList.add(new HubDiscoveryInfo(info, sInfo)); + } + } + } else { + discoveryList.add(new HubDiscoveryInfo(info)); + } + } + if (discoveryList.isEmpty()) { + Log.w(TAG, "onEndpointsStarted: no matching service descriptor"); + } else { + callback.onEndpointsStarted(discoveryList); + } + }); + } + + @Override + public void onEndpointsStopped(HubEndpointInfo[] hubEndpointInfoList) { + if (hubEndpointInfoList.length == 0) { + Log.w(TAG, "onEndpointsStopped: received empty discovery list"); + return; + } + executor.execute( + () -> { + List<HubDiscoveryInfo> discoveryList = + new ArrayList<>(hubEndpointInfoList.length); + for (HubEndpointInfo info : hubEndpointInfoList) { + if (serviceDescriptor != null) { + for (HubServiceInfo sInfo : info.getServiceInfoCollection()) { + if (sInfo.getServiceDescriptor() + .equals(serviceDescriptor)) { + discoveryList.add(new HubDiscoveryInfo(info, sInfo)); + } + } + } else { + discoveryList.add(new HubDiscoveryInfo(info)); + } + } + if (discoveryList.isEmpty()) { + Log.w(TAG, "onEndpointsStopped: no matching service descriptor"); + } else { + callback.onEndpointsStopped(discoveryList); + } + }); + } + }; + } + + /** + * Equivalent to {@link #registerEndpointDiscoveryCallback(long, IHubEndpointDiscoveryCallback, + * Executor)} with the default executor in the main thread. + */ + @RequiresPermission(android.Manifest.permission.ACCESS_CONTEXT_HUB) + @FlaggedApi(Flags.FLAG_OFFLOAD_API) + public void registerEndpointDiscoveryCallback( + long endpointId, @NonNull IHubEndpointDiscoveryCallback callback) { + registerEndpointDiscoveryCallback( + endpointId, callback, new HandlerExecutor(Handler.getMain())); + } + + /** + * Registers a callback to be notified when the hub endpoint with the corresponding endpoint ID + * has started or stopped. + * + * @param endpointId The identifier of the hub endpoint. + * @param callback The callback to be invoked. + * @param executor The executor to invoke the callback on. + */ + @RequiresPermission(android.Manifest.permission.ACCESS_CONTEXT_HUB) + @FlaggedApi(Flags.FLAG_OFFLOAD_API) + public void registerEndpointDiscoveryCallback( + long endpointId, + @NonNull IHubEndpointDiscoveryCallback callback, + @NonNull Executor executor) { + Objects.requireNonNull(callback, "callback cannot be null"); + Objects.requireNonNull(executor, "executor cannot be null"); + IContextHubEndpointDiscoveryCallback iCallback = + createDiscoveryCallback(callback, executor, null); + try { + mService.registerEndpointDiscoveryCallbackId(endpointId, iCallback); + } catch (RemoteException e) { + e.rethrowFromSystemServer(); + } + + mDiscoveryCallbacks.put(callback, iCallback); + } + + /** + * Equivalent to {@link #registerEndpointDiscoveryCallback(String, + * IHubEndpointDiscoveryCallback, Executor)} with the default executor in the main thread. + */ + @RequiresPermission(android.Manifest.permission.ACCESS_CONTEXT_HUB) + @FlaggedApi(Flags.FLAG_OFFLOAD_API) + public void registerEndpointDiscoveryCallback( + @NonNull String serviceDescriptor, @NonNull IHubEndpointDiscoveryCallback callback) { + registerEndpointDiscoveryCallback( + serviceDescriptor, callback, new HandlerExecutor(Handler.getMain())); + } + + /** + * Registers a callback to be notified when the hub endpoint with the corresponding service + * descriptor has started or stopped. + * + * @param serviceDescriptor The service descriptor of the hub endpoint. + * @param callback The callback to be invoked. + * @param executor The executor to invoke the callback on. + * @throws IllegalArgumentException if the serviceDescriptor is empty. + */ + @RequiresPermission(android.Manifest.permission.ACCESS_CONTEXT_HUB) + @FlaggedApi(Flags.FLAG_OFFLOAD_API) + public void registerEndpointDiscoveryCallback( + @NonNull String serviceDescriptor, + @NonNull IHubEndpointDiscoveryCallback callback, + @NonNull Executor executor) { + Objects.requireNonNull(serviceDescriptor, "serviceDescriptor cannot be null"); + Objects.requireNonNull(callback, "callback cannot be null"); + Objects.requireNonNull(executor, "executor cannot be null"); + if (serviceDescriptor.isBlank()) { + throw new IllegalArgumentException("Invalid service descriptor: " + serviceDescriptor); + } + + IContextHubEndpointDiscoveryCallback iCallback = + createDiscoveryCallback(callback, executor, serviceDescriptor); + try { + mService.registerEndpointDiscoveryCallbackDescriptor(serviceDescriptor, iCallback); + } catch (RemoteException e) { + e.rethrowFromSystemServer(); + } + + mDiscoveryCallbacks.put(callback, iCallback); + } + + /** + * Unregisters a previously registered endpoint discovery callback. + * + * @param callback The callback previously registered. + * @throws IllegalArgumentException If the callback was not previously registered. + */ + @RequiresPermission(android.Manifest.permission.ACCESS_CONTEXT_HUB) + @FlaggedApi(Flags.FLAG_OFFLOAD_API) + public void unregisterEndpointDiscoveryCallback( + @NonNull IHubEndpointDiscoveryCallback callback) { + Objects.requireNonNull(callback, "callback cannot be null"); + IContextHubEndpointDiscoveryCallback iCallback = mDiscoveryCallbacks.remove(callback); + if (iCallback == null) { + throw new IllegalArgumentException("Callback not previously registered"); + } + + try { + mService.unregisterEndpointDiscoveryCallback(iCallback); + } catch (RemoteException e) { + e.rethrowFromSystemServer(); + } + } + + /** * Set a callback to receive messages from the context hub * * @param callback Callback object diff --git a/core/java/android/hardware/location/IContextHubService.aidl b/core/java/android/hardware/location/IContextHubService.aidl index f9f412446038..f14aadcab474 100644 --- a/core/java/android/hardware/location/IContextHubService.aidl +++ b/core/java/android/hardware/location/IContextHubService.aidl @@ -21,6 +21,7 @@ import android.app.PendingIntent; import android.hardware.contexthub.HubEndpointInfo; import android.hardware.contexthub.IContextHubEndpoint; import android.hardware.contexthub.IContextHubEndpointCallback; +import android.hardware.contexthub.IContextHubEndpointDiscoveryCallback; import android.hardware.location.ContextHubInfo; import android.hardware.location.ContextHubMessage; import android.hardware.location.HubInfo; @@ -137,4 +138,16 @@ interface IContextHubService { // Register an endpoint with the context hub @EnforcePermission("ACCESS_CONTEXT_HUB") IContextHubEndpoint registerEndpoint(in HubEndpointInfo pendingEndpointInfo, in IContextHubEndpointCallback callback); + + // Register an endpoint discovery callback (id) + @EnforcePermission("ACCESS_CONTEXT_HUB") + void registerEndpointDiscoveryCallbackId(long endpointId, in IContextHubEndpointDiscoveryCallback callback); + + // Register an endpoint discovery callback (descriptor) + @EnforcePermission("ACCESS_CONTEXT_HUB") + void registerEndpointDiscoveryCallbackDescriptor(String serviceDescriptor, in IContextHubEndpointDiscoveryCallback callback); + + // Unregister an endpoint with the context hub + @EnforcePermission("ACCESS_CONTEXT_HUB") + void unregisterEndpointDiscoveryCallback(in IContextHubEndpointDiscoveryCallback callback); } diff --git a/core/java/android/os/CombinedMessageQueue/MessageQueue.java b/core/java/android/os/CombinedMessageQueue/MessageQueue.java index 4c9f08d80d4b..3e4d74546adc 100644 --- a/core/java/android/os/CombinedMessageQueue/MessageQueue.java +++ b/core/java/android/os/CombinedMessageQueue/MessageQueue.java @@ -19,8 +19,6 @@ package android.os; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.TestApi; -import android.app.ActivityThread; -import android.app.Instrumentation; import android.compat.annotation.UnsupportedAppUsage; import android.os.Process; import android.os.UserHandle; @@ -88,14 +86,20 @@ public final class MessageQueue { // queue for async messages when inserting a message at the tail. private int mAsyncMessageCount; - /* + /** * Select between two implementations of message queue. The legacy implementation is used * by default as it provides maximum compatibility with applications and tests that * reach into MessageQueue via the mMessages field. The concurrent implemmentation is used for * system processes and provides a higher level of concurrency and higher enqueue throughput * than the legacy implementation. */ - private boolean mUseConcurrent; + private final boolean mUseConcurrent; + + /** + * Caches process-level checks that determine `mUseConcurrent`. + * This is to avoid redoing checks that shouldn't change during the process's lifetime. + */ + private static Boolean sIsProcessAllowedToUseConcurrent = null; @RavenwoodRedirect private native static long nativeInit(); @@ -112,32 +116,37 @@ public final class MessageQueue { private native static void nativeSetFileDescriptorEvents(long ptr, int fd, int events); MessageQueue(boolean quitAllowed) { - // Concurrent mode modifies behavior that is observable via reflection and is commonly used - // by tests. - // For now, we limit it to system processes to avoid breaking apps and their tests. - mUseConcurrent = UserHandle.isCore(Process.myUid()); - // Even then, we don't use it if instrumentation is loaded as it breaks some - // platform tests. - final Instrumentation instrumentation = getInstrumentation(); - mUseConcurrent &= instrumentation == null || !instrumentation.isInstrumenting(); - // We can lift this restriction in the future after we've made it possible for test authors - // to test Looper and MessageQueue without resorting to reflection. + if (sIsProcessAllowedToUseConcurrent == null) { + // Concurrent mode modifies behavior that is observable via reflection and is commonly + // used by tests. + // For now, we limit it to system processes to avoid breaking apps and their tests. + boolean useConcurrent = UserHandle.isCore(Process.myUid()); - mQuitAllowed = quitAllowed; - mPtr = nativeInit(); - } + // Some platform tests run in system UIDs. + // Use this awful heuristic to detect them. + if (useConcurrent) { + final String processName = Process.myProcessName(); + if (processName.contains("test") || processName.contains("Test")) { + useConcurrent = false; + } + } + + // We can lift this restriction in the future after we've made it possible for test + // authors to test Looper and MessageQueue without resorting to reflection. - @android.ravenwood.annotation.RavenwoodReplace(blockedBy = ActivityThread.class) - private static Instrumentation getInstrumentation() { - final ActivityThread activityThread = ActivityThread.currentActivityThread(); - if (activityThread != null) { - return activityThread.getInstrumentation(); + // Holdback study. + if (useConcurrent && Flags.messageQueueForceLegacy()) { + useConcurrent = false; + } + + sIsProcessAllowedToUseConcurrent = useConcurrent; + mUseConcurrent = useConcurrent; + } else { + mUseConcurrent = sIsProcessAllowedToUseConcurrent; } - return null; - } - private static Instrumentation getInstrumentation$ravenwood() { - return null; // Instrumentation not supported on Ravenwood yet. + mQuitAllowed = quitAllowed; + mPtr = nativeInit(); } @Override diff --git a/core/java/android/os/OWNERS b/core/java/android/os/OWNERS index e63b6648a9ef..94259d7cf819 100644 --- a/core/java/android/os/OWNERS +++ b/core/java/android/os/OWNERS @@ -89,6 +89,8 @@ per-file DdmSyncState.java = sanglardf@google.com, rpaquay@google.com per-file DdmSyncStageUpdater.java = sanglardf@google.com, rpaquay@google.com # PerformanceHintManager +per-file CpuHeadroom*.aidl = file:/ADPF_OWNERS +per-file GpuHeadroom*.aidl = file:/ADPF_OWNERS per-file PerformanceHintManager.java = file:/ADPF_OWNERS per-file WorkDuration.java = file:/ADPF_OWNERS per-file IHintManager.aidl = file:/ADPF_OWNERS diff --git a/core/java/android/os/flags.aconfig b/core/java/android/os/flags.aconfig index 5ac53f1bf39d..3001fbd4fafa 100644 --- a/core/java/android/os/flags.aconfig +++ b/core/java/android/os/flags.aconfig @@ -4,6 +4,15 @@ container: "system" # keep-sorted start block=yes newline_separated=yes flag { + # Holdback study for concurrent MessageQueue. + # Do not promote beyond trunkfood. + namespace: "system_performance" + name: "message_queue_force_legacy" + description: "Whether to holdback concurrent MessageQueue (force legacy)." + bug: "336880969" +} + +flag { name: "adpf_gpu_report_actual_work_duration" is_exported: true namespace: "game" @@ -222,6 +231,15 @@ flag { } flag { + name: "message_queue_testability" + namespace: "system_performance" + is_exported: true + description: "Whether MessageQueue implements test APIs." + bug: "379472827" + is_fixed_read_only: true +} + +flag { name: "network_time_uses_shared_memory" namespace: "system_performance" description: "SystemClock.currentNetworkTimeMillis() reads network time offset from shared memory" diff --git a/core/java/android/permission/flags.aconfig b/core/java/android/permission/flags.aconfig index 55ba4afc9c68..a653e0a493ee 100644 --- a/core/java/android/permission/flags.aconfig +++ b/core/java/android/permission/flags.aconfig @@ -58,7 +58,7 @@ flag { is_fixed_read_only: true namespace: "permissions" description: "enable enhanced confirmation incall apis" - bug: "310220212" + bug: "364535720" } flag { @@ -67,7 +67,7 @@ flag { is_fixed_read_only: true namespace: "permissions" description: "enable the blocking of certain app installs during an unknown call" - bug: "310220212" + bug: "364535720" } flag { diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 23f76299d8c4..d5b525884ac1 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -10999,6 +10999,25 @@ public final class Settings { "emergency_gesture_ui_last_started_millis"; /** + * Whether double tap the power button gesture is enabled. + * + * @hide + */ + @Readable + public static final String DOUBLE_TAP_POWER_BUTTON_GESTURE_ENABLED = + "double_tap_power_button_gesture_enabled"; + + /** + * Double tap power button gesture behavior. + * 0 = Camera launch + * 1 = Wallet launch + * @hide + */ + @Readable + public static final String DOUBLE_TAP_POWER_BUTTON_GESTURE = + "double_tap_power_button_gesture"; + + /** * Whether the camera launch gesture to double tap the power button when the screen is off * should be disabled. * diff --git a/core/java/android/security/intrusiondetection/IIntrusionDetectionEventTransport.aidl b/core/java/android/security/intrusiondetection/IIntrusionDetectionEventTransport.aidl index 8759f72ca08a..eab1c156b6be 100644 --- a/core/java/android/security/intrusiondetection/IIntrusionDetectionEventTransport.aidl +++ b/core/java/android/security/intrusiondetection/IIntrusionDetectionEventTransport.aidl @@ -15,6 +15,7 @@ */ package android.security.intrusiondetection; + import android.security.intrusiondetection.IntrusionDetectionEvent; import com.android.internal.infra.AndroidFuture; @@ -24,18 +25,20 @@ oneway interface IIntrusionDetectionEventTransport { /** * Initialize the server side. */ - void initialize(in AndroidFuture<int> resultFuture); + void initialize(in AndroidFuture<boolean> resultFuture); /** - * Send intrusiondetection logging data to the backup destination. + * Send intrusiondetection logging data to the transport destination. * The data is a list of IntrusionDetectionEvent. * The IntrusionDetectionEvent is an abstract class that represents - * different type of events. + * different types of events. */ - void addData(in List<IntrusionDetectionEvent> events, in AndroidFuture<int> resultFuture); + void addData( + in List<IntrusionDetectionEvent> events, + in AndroidFuture<boolean> resultFuture); /** * Release the binder to the server. */ - void release(in AndroidFuture<int> resultFuture); + void release(in AndroidFuture<boolean> resultFuture); } diff --git a/core/java/android/security/intrusiondetection/IntrusionDetectionEvent.java b/core/java/android/security/intrusiondetection/IntrusionDetectionEvent.java index 538acf99c9fe..b479ca7a0b6f 100644 --- a/core/java/android/security/intrusiondetection/IntrusionDetectionEvent.java +++ b/core/java/android/security/intrusiondetection/IntrusionDetectionEvent.java @@ -22,6 +22,7 @@ import android.annotation.NonNull; import android.app.admin.ConnectEvent; import android.app.admin.DnsEvent; import android.app.admin.SecurityLog.SecurityEvent; +import android.annotation.SystemApi; import android.os.Parcel; import android.os.Parcelable; import android.security.Flags; @@ -31,14 +32,36 @@ import java.lang.annotation.RetentionPolicy; /** * A class that represents a intrusiondetection event. + * * @hide */ +@SystemApi @FlaggedApi(Flags.FLAG_AFL_API) public final class IntrusionDetectionEvent implements Parcelable { private static final String TAG = "IntrusionDetectionEvent"; + /** + * Event type representing a security-related event. + * This type is associated with a {@link SecurityEvent} object. + * + * @see SecurityEvent + */ public static final int SECURITY_EVENT = 0; + + /** + * Event type representing a network DNS event. + * This type is associated with a {@link DnsEvent} object. + * + * @see DnsEvent + */ public static final int NETWORK_EVENT_DNS = 1; + + /** + * Event type representing a network connection event. + * This type is associated with a {@link ConnectEvent} object. + * + * @see ConnectEvent + */ public static final int NETWORK_EVENT_CONNECT = 2; /** @hide */ @@ -67,6 +90,12 @@ public final class IntrusionDetectionEvent implements Parcelable { } }; + /** + * Creates an IntrusionDetectionEvent object with a + * {@link SecurityEvent} object as the event source. + * + * @param securityEvent The SecurityEvent object. + */ public IntrusionDetectionEvent(@NonNull SecurityEvent securityEvent) { mType = SECURITY_EVENT; mSecurityEvent = securityEvent; @@ -74,6 +103,12 @@ public final class IntrusionDetectionEvent implements Parcelable { mNetworkEventConnect = null; } + /** + * Creates an IntrusionDetectionEvent object with a + * {@link DnsEvent} object as the event source. + * + * @param dnsEvent The DnsEvent object. + */ public IntrusionDetectionEvent(@NonNull DnsEvent dnsEvent) { mType = NETWORK_EVENT_DNS; mNetworkEventDns = dnsEvent; @@ -81,6 +116,12 @@ public final class IntrusionDetectionEvent implements Parcelable { mNetworkEventConnect = null; } + /** + * Creates an IntrusionDetectionEvent object with a + * {@link ConnectEvent} object as the event source. + * + * @param connectEvent The ConnectEvent object. + */ public IntrusionDetectionEvent(@NonNull ConnectEvent connectEvent) { mType = NETWORK_EVENT_CONNECT; mNetworkEventConnect = connectEvent; diff --git a/core/java/android/security/intrusiondetection/IntrusionDetectionEventTransport.java b/core/java/android/security/intrusiondetection/IntrusionDetectionEventTransport.java new file mode 100644 index 000000000000..2e2d0f7f2dd2 --- /dev/null +++ b/core/java/android/security/intrusiondetection/IntrusionDetectionEventTransport.java @@ -0,0 +1,145 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.security.intrusiondetection; + +import android.annotation.FlaggedApi; +import android.annotation.NonNull; +import android.annotation.SystemApi; +import android.annotation.SuppressLint; +import android.content.ComponentName; +import android.content.Context; +import android.os.IBinder; +import android.util.CloseGuard; + +import android.security.Flags; +import android.security.intrusiondetection.IntrusionDetectionEvent; +import android.security.intrusiondetection.IIntrusionDetectionEventTransport; + +import com.android.internal.infra.AndroidFuture; + +import java.lang.AutoCloseable; +import java.util.List; + +/** + * A class that provides a stable API for transporting intrusion detection events + * to a transport location, such as a file or a network endpoint. + * + * This class acts as a bridge between the {@link IIntrusionDetectionEventTransport} + * interface and its implementations. It allows system components to add intrusion + * detection events ({@link IntrusionDetectionEvent}) to a transport queue, + * which will then be delivered to the specified location. + * + * Usage: + * 1. Obtain an instance of {@link IntrusionDetectionEventTransport} using the constructor. + * 2. Initialize the transport by calling {@link #initialize()}. + * 3. Add events to the transport queue using {@link #addData(List)}. + * 4. Release the transport when finished by calling {@link #release()}. + * + * Key Components: + * - {@link IIntrusionDetectionEventTransport}: The underlying AIDL interface + * for interacting with transport implementations. + * - {@link IntrusionDetectionEvent}: Represents a single event. + * + * @hide + */ +@SystemApi +@FlaggedApi(Flags.FLAG_AFL_API) +@SuppressLint("NotCloseable") +public class IntrusionDetectionEventTransport { + IIntrusionDetectionEventTransport mBinderImpl = new TransportImpl(); + + /** + * Returns the binder interface for this transport. + */ + @NonNull + public IBinder getBinder() { + return mBinderImpl.asBinder(); + } + + /** + * Initializes the transport. + * + * @return whether the initialization was successful. + */ + public boolean initialize() { + return false; + } + + /** + * Adds data to the transport. + * + * @param events the events to add. + * @return whether the addition was successful. + */ + public boolean addData(@NonNull List<IntrusionDetectionEvent> events) { + return false; + } + + /** + * Releases the transport. + * + * The release() method is a callback implemented by the concrete transport + * endpoint. + * The "SuppressLint" annotation is used to allow the release() method to be + * included in the API without requiring the class to implement AutoCloseable. + * + * @return whether the release was successful. + */ + public boolean release() { + return false; + } + + /** + * Bridge between the actual IIntrusionDetectionEventTransport implementation + * and the stable API. If the binder interface needs to change, we use this + * layer to translate so that we can decouple those framework-side changes + * from the IntrusionDetectionEventTransport implementations. + */ + class TransportImpl extends IIntrusionDetectionEventTransport.Stub { + @Override + public void initialize(AndroidFuture<Boolean> resultFuture) { + try { + boolean result = IntrusionDetectionEventTransport.this.initialize(); + resultFuture.complete(result); + } catch (RuntimeException e) { + resultFuture.cancel(/* mayInterruptIfRunning */ true); + } + } + + @Override + public void addData( + List<IntrusionDetectionEvent> events, + AndroidFuture<Boolean> resultFuture) { + try { + boolean result = IntrusionDetectionEventTransport.this.addData(events); + resultFuture.complete(result); + } catch (RuntimeException e) { + resultFuture.cancel(/* mayInterruptIfRunning */ true); + } + } + + @Override + public void release(AndroidFuture<Boolean> resultFuture) { + try { + boolean result = IntrusionDetectionEventTransport.this.release(); + resultFuture.complete(result); + } catch (RuntimeException e) { + resultFuture.cancel(/* mayInterruptIfRunning */ true); + } + } + } +}
\ No newline at end of file diff --git a/core/java/android/service/notification/SystemZenRules.java b/core/java/android/service/notification/SystemZenRules.java index ebb8569ead49..f11ce1621f93 100644 --- a/core/java/android/service/notification/SystemZenRules.java +++ b/core/java/android/service/notification/SystemZenRules.java @@ -122,17 +122,16 @@ public final class SystemZenRules { @Nullable public static String getTriggerDescriptionForScheduleTime(Context context, @NonNull ScheduleInfo schedule) { - final StringBuilder sb = new StringBuilder(); String daysSummary = getDaysOfWeekShort(context, schedule); if (daysSummary == null) { // no use outputting times without dates return null; } - sb.append(daysSummary); - sb.append(context.getString(R.string.zen_mode_trigger_summary_divider_text)); - sb.append(getTimeSummary(context, schedule)); - - return sb.toString(); + return context.getString( + R.string.zen_mode_trigger_summary_combined, + daysSummary, + getTimeSummary(context, schedule) + ); } /** diff --git a/core/java/android/service/quickaccesswallet/flags.aconfig b/core/java/android/service/quickaccesswallet/flags.aconfig index 75a93091eec3..7225f27c4555 100644 --- a/core/java/android/service/quickaccesswallet/flags.aconfig +++ b/core/java/android/service/quickaccesswallet/flags.aconfig @@ -6,4 +6,11 @@ flag { namespace: "wallet_integration" description: "Option to launch the Wallet app on double-tap of the power button" bug: "378469025" +} + +flag { + name: "launch_selected_card_from_qs_tile" + namespace: "wallet_integration" + description: "When the wallet QS tile is tapped, launch the selected card pending intent instead of the home screen pending intent." + bug: "378469025" }
\ No newline at end of file diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java index 09a78e5ebb4e..c9d560c3424b 100644 --- a/core/java/android/view/Display.java +++ b/core/java/android/view/Display.java @@ -20,6 +20,7 @@ import static android.Manifest.permission.CONFIGURE_DISPLAY_COLOR_MODE; import static android.Manifest.permission.CONTROL_DISPLAY_BRIGHTNESS; import static android.hardware.flags.Flags.FLAG_OVERLAYPROPERTIES_CLASS_API; +import static com.android.server.display.feature.flags.Flags.FLAG_ENABLE_GET_SUPPORTED_REFRESH_RATES; import static com.android.server.display.feature.flags.Flags.FLAG_HIGHEST_HDR_SDR_RATIO_API; import static com.android.server.display.feature.flags.Flags.FLAG_ENABLE_HAS_ARR_SUPPORT; import static com.android.server.display.feature.flags.Flags.FLAG_ENABLE_GET_SUGGESTED_FRAME_RATE; @@ -63,6 +64,7 @@ import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.Objects; import java.util.concurrent.Executor; import java.util.function.Consumer; @@ -1207,17 +1209,36 @@ public final class Display { /** * Get the supported refresh rates of this display in frames per second. - * <p> - * This method only returns refresh rates for the display's default modes. For more options, use - * {@link #getSupportedModes()}. * - * @deprecated use {@link #getSupportedModes()} instead + * <ul> + * <li> Android version {@link Build.VERSION_CODES#BAKLAVA} and above: + * returns display supported render rates. + * <li> Android version {@link Build.VERSION_CODES#VANILLA_ICE_CREAM} and below: + * This method only returns refresh rates for the display's default modes. For more options, + * use {@link #getSupportedModes()}. + * </ul> */ - @Deprecated - public float[] getSupportedRefreshRates() { + @FlaggedApi(FLAG_ENABLE_GET_SUPPORTED_REFRESH_RATES) + public @NonNull float[] getSupportedRefreshRates() { synchronized (mLock) { updateDisplayInfoLocked(); - return mDisplayInfo.getDefaultRefreshRates(); + final float[] refreshRates = mDisplayInfo.getDefaultRefreshRates(); + Objects.requireNonNull(refreshRates); + return refreshRates; + } + } + + /** + * @hide + */ + @TestApi + @SuppressLint({"UnflaggedApi"}) // Usage in the CTS to test backward compatibility. + public @NonNull float[] getSupportedRefreshRatesLegacy() { + synchronized (mLock) { + updateDisplayInfoLocked(); + final float[] refreshRates = mDisplayInfo.getDefaultRefreshRatesLegacy(); + Objects.requireNonNull(refreshRates); + return refreshRates; } } @@ -2449,6 +2470,8 @@ public final class Display { * constrained by the system. * @hide */ + @SuppressWarnings("UnflaggedApi") // For testing only + @TestApi public float getVsyncRate() { return mVsyncRate; } diff --git a/core/java/android/view/DisplayInfo.java b/core/java/android/view/DisplayInfo.java index 4ff04d5c1fa6..8b6458a54c43 100644 --- a/core/java/android/view/DisplayInfo.java +++ b/core/java/android/view/DisplayInfo.java @@ -210,6 +210,11 @@ public final class DisplayInfo implements Parcelable { public FrameRateCategoryRate frameRateCategoryRate; /** + * All the refresh rates supported in the active mode. + */ + public float[] supportedRefreshRates = new float[0]; + + /** * The default display mode. */ public int defaultModeId; @@ -449,6 +454,7 @@ public final class DisplayInfo implements Parcelable { && modeId == other.modeId && hasArrSupport == other.hasArrSupport && Objects.equals(frameRateCategoryRate, other.frameRateCategoryRate) + && Arrays.equals(supportedRefreshRates, other.supportedRefreshRates) && defaultModeId == other.defaultModeId && userPreferredModeId == other.userPreferredModeId && Arrays.equals(supportedModes, other.supportedModes) @@ -512,6 +518,8 @@ public final class DisplayInfo implements Parcelable { renderFrameRate = other.renderFrameRate; hasArrSupport = other.hasArrSupport; frameRateCategoryRate = other.frameRateCategoryRate; + supportedRefreshRates = Arrays.copyOf( + other.supportedRefreshRates, other.supportedRefreshRates.length); defaultModeId = other.defaultModeId; userPreferredModeId = other.userPreferredModeId; supportedModes = Arrays.copyOf(other.supportedModes, other.supportedModes.length); @@ -571,6 +579,11 @@ public final class DisplayInfo implements Parcelable { hasArrSupport = source.readBoolean(); frameRateCategoryRate = source.readParcelable(null, android.view.FrameRateCategoryRate.class); + int numOfSupportedRefreshRates = source.readInt(); + supportedRefreshRates = new float[numOfSupportedRefreshRates]; + for (int i = 0; i < numOfSupportedRefreshRates; i++) { + supportedRefreshRates[i] = source.readFloat(); + } defaultModeId = source.readInt(); userPreferredModeId = source.readInt(); int nModes = source.readInt(); @@ -646,6 +659,10 @@ public final class DisplayInfo implements Parcelable { dest.writeFloat(renderFrameRate); dest.writeBoolean(hasArrSupport); dest.writeParcelable(frameRateCategoryRate, flags); + dest.writeInt(supportedRefreshRates.length); + for (float supportedRefreshRate : supportedRefreshRates) { + dest.writeFloat(supportedRefreshRate); + } dest.writeInt(defaultModeId); dest.writeInt(userPreferredModeId); dest.writeInt(supportedModes.length); @@ -750,9 +767,19 @@ public final class DisplayInfo implements Parcelable { } /** - * Returns the list of supported refresh rates in the default mode. + * Returns the list of supported refresh rates in the active mode. */ public float[] getDefaultRefreshRates() { + if (supportedRefreshRates.length == 0) { + return getDefaultRefreshRatesLegacy(); + } + return Arrays.copyOf(supportedRefreshRates, supportedRefreshRates.length); + } + + /** + * Returns the list of supported refresh rates in the default mode. + */ + public float[] getDefaultRefreshRatesLegacy() { Display.Mode[] modes = appsSupportedModes; ArraySet<Float> rates = new ArraySet<>(); Display.Mode defaultMode = getDefaultMode(); @@ -898,6 +925,8 @@ public final class DisplayInfo implements Parcelable { sb.append(hasArrSupport); sb.append(", frameRateCategoryRate "); sb.append(frameRateCategoryRate); + sb.append(", supportedRefreshRates "); + sb.append(Arrays.toString(supportedRefreshRates)); sb.append(", defaultMode "); sb.append(defaultModeId); sb.append(", userPreferredModeId "); diff --git a/core/java/android/view/InputWindowHandle.java b/core/java/android/view/InputWindowHandle.java index 58ef5efe846f..6cd4a4033adf 100644 --- a/core/java/android/view/InputWindowHandle.java +++ b/core/java/android/view/InputWindowHandle.java @@ -260,6 +260,15 @@ public final class InputWindowHandle { touchableRegionSurfaceControl = new WeakReference<>(bounds); } + /** + * Resize the window touchable region. + * @param rect new touchable region rectangle. + */ + public void setTouchableRegion(Rect rect) { + touchableRegion.set(rect); + } + + public void setWindowToken(IBinder iwindow) { windowToken = iwindow; } diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java index 68674dd402b4..dd9a95e58bd1 100644 --- a/core/java/android/view/SurfaceControl.java +++ b/core/java/android/view/SurfaceControl.java @@ -1932,6 +1932,7 @@ public final class SurfaceControl implements Parcelable { public float renderFrameRate; public boolean hasArrSupport; public FrameRateCategoryRate frameRateCategoryRate; + public float[] supportedRefreshRates; public int[] supportedColorModes; public int activeColorMode; @@ -1951,6 +1952,7 @@ public final class SurfaceControl implements Parcelable { + ", renderFrameRate=" + renderFrameRate + ", hasArrSupport=" + hasArrSupport + ", frameRateCategoryRate=" + frameRateCategoryRate + + ", supportedRefreshRates=" + Arrays.toString(supportedRefreshRates) + ", supportedColorModes=" + Arrays.toString(supportedColorModes) + ", activeColorMode=" + activeColorMode + ", hdrCapabilities=" + hdrCapabilities @@ -1972,14 +1974,15 @@ public final class SurfaceControl implements Parcelable { && Objects.equals(hdrCapabilities, that.hdrCapabilities) && preferredBootDisplayMode == that.preferredBootDisplayMode && hasArrSupport == that.hasArrSupport - && Objects.equals(frameRateCategoryRate, that.frameRateCategoryRate); + && Objects.equals(frameRateCategoryRate, that.frameRateCategoryRate) + && Arrays.equals(supportedRefreshRates, that.supportedRefreshRates); } @Override public int hashCode() { return Objects.hash(Arrays.hashCode(supportedDisplayModes), activeDisplayModeId, renderFrameRate, activeColorMode, hdrCapabilities, hasArrSupport, - frameRateCategoryRate); + frameRateCategoryRate, Arrays.hashCode(supportedRefreshRates)); } } diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 072a835eb664..b6e114b3a3ca 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -8876,11 +8876,6 @@ public final class ViewRootImpl implements ViewParent, SyntheticTouchNavigationHandler() { super(true); - int gestureDetectorVelocityStrategy = - android.companion.virtual.flags.Flags - .impulseVelocityStrategyForTouchNavigation() - ? VelocityTracker.VELOCITY_TRACKER_STRATEGY_IMPULSE - : VelocityTracker.VELOCITY_TRACKER_STRATEGY_DEFAULT; mGestureDetector = new GestureDetector(mContext, new GestureDetector.OnGestureListener() { @Override @@ -8920,7 +8915,7 @@ public final class ViewRootImpl implements ViewParent, } }, /* handler= */ null, - gestureDetectorVelocityStrategy); + VelocityTracker.VELOCITY_TRACKER_STRATEGY_IMPULSE); } public void process(MotionEvent event) { diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java index b4b0687eb498..1e8cad61381c 100644 --- a/core/java/android/view/WindowManager.java +++ b/core/java/android/view/WindowManager.java @@ -1426,8 +1426,9 @@ public interface WindowManager extends ViewManager { "android.window.PROPERTY_COMPAT_ALLOW_USER_ASPECT_RATIO_FULLSCREEN_OVERRIDE"; /** - * Activity-level {@link android.content.pm.PackageManager.Property PackageManager.Property} - * that specifies whether this activity can declare or request + * Application or Activity level + * {@link android.content.pm.PackageManager.Property PackageManager.Property} + * that specifies whether this package or activity can declare or request * {@link android.R.attr#screenOrientation fixed orientation}, * {@link android.R.attr#minAspectRatio max aspect ratio}, * {@link android.R.attr#maxAspectRatio min aspect ratio} @@ -1438,6 +1439,13 @@ public interface WindowManager extends ViewManager { * * <p><b>Syntax:</b> * <pre> + * <application> + * <property + * android:name="android.window.PROPERTY_COMPAT_ALLOW_USER_ASPECT_RATIO_FULLSCREEN_OVERRIDE" + * android:value="false"/> + * </application> + * </pre>or + * <pre> * <activity> * <property * android:name="android.window.PROPERTY_COMPAT_ALLOW_RESTRICTED_RESIZABILITY" @@ -1446,7 +1454,7 @@ public interface WindowManager extends ViewManager { * </pre> * @hide */ - // TODO(b/357141415): Make this public API. + // TODO(b/357141415): Remove this from sdk 37 String PROPERTY_COMPAT_ALLOW_RESTRICTED_RESIZABILITY = "android.window.PROPERTY_COMPAT_ALLOW_RESTRICTED_RESIZABILITY"; diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java index 0204517e869a..df0c5a34e992 100644 --- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java +++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java @@ -6551,15 +6551,23 @@ public class AccessibilityNodeInfo implements Parcelable { /** * Range type: indeterminate. * + * When using this type, the {@code min}, {@code max}, and {@code current} values used to + * construct an instance may be ignored. + * + * @see #INDETERMINATE + */ + @FlaggedApi(Flags.FLAG_INDETERMINATE_RANGE_INFO) + public static final int RANGE_TYPE_INDETERMINATE = 3; + + /** * A {@link RangeInfo} type used to represent a node which may typically expose range * information but is presently in an indeterminate state, such as a {@link * android.widget.ProgressBar} representing a loading operation of unknown duration. - * When using this type, the {@code min}, {@code max}, and {@code current} values used to - * construct an instance may be ignored. It is recommended to use {@code Float.NaN} for - * these values. */ + @NonNull @FlaggedApi(Flags.FLAG_INDETERMINATE_RANGE_INFO) - public static final int RANGE_TYPE_INDETERMINATE = 3; + public static final RangeInfo INDETERMINATE = new RangeInfo(RANGE_TYPE_INDETERMINATE, 0.0f, + 0.0f, 0.0f); private int mType; private float mMin; diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java index 80d39d1f9a1c..595eb260f998 100644 --- a/core/java/android/widget/RemoteViews.java +++ b/core/java/android/widget/RemoteViews.java @@ -9333,7 +9333,11 @@ public class RemoteViews implements Parcelable, Filter { Set<Integer> bitmapIdSet = getBitmapIdsUsedByActions(new HashSet<>()); int result = 0; for (int bitmapId: bitmapIdSet) { - result += mBitmapCache.getBitmapForId(bitmapId).getAllocationByteCount(); + Bitmap currentBitmap = mBitmapCache.getBitmapForId(bitmapId); + if (currentBitmap == null) { + continue; + } + result += currentBitmap.getAllocationByteCount(); } return result; diff --git a/core/java/android/window/WindowTokenClient.java b/core/java/android/window/WindowTokenClient.java index 15adc80add01..6e76d8d345b2 100644 --- a/core/java/android/window/WindowTokenClient.java +++ b/core/java/android/window/WindowTokenClient.java @@ -19,6 +19,8 @@ import static android.window.ConfigurationHelper.freeTextLayoutCachesIfNeeded; import static android.window.ConfigurationHelper.isDifferentDisplay; import static android.window.ConfigurationHelper.shouldUpdateResources; +import static com.android.internal.annotations.VisibleForTesting.Visibility.PACKAGE; + import android.annotation.AnyThread; import android.annotation.MainThread; import android.annotation.NonNull; @@ -104,7 +106,7 @@ public class WindowTokenClient extends Binder { * @param newConfig the updated {@link Configuration} * @param newDisplayId the updated {@link android.view.Display} ID */ - @VisibleForTesting + @VisibleForTesting(visibility = PACKAGE) @MainThread public void onConfigurationChanged(Configuration newConfig, int newDisplayId) { onConfigurationChanged(newConfig, newDisplayId, true /* shouldReportConfigChange */); @@ -113,7 +115,7 @@ public class WindowTokenClient extends Binder { /** * Posts an {@link #onConfigurationChanged} to the main thread. */ - @VisibleForTesting + @VisibleForTesting(visibility = PACKAGE) public void postOnConfigurationChanged(@NonNull Configuration newConfig, int newDisplayId) { mHandler.post(PooledLambda.obtainRunnable(this::onConfigurationChanged, newConfig, newDisplayId, true /* shouldReportConfigChange */).recycleOnUse()); @@ -232,7 +234,7 @@ public class WindowTokenClient extends Binder { /** * Called when the attached window is removed from the display. */ - @VisibleForTesting + @VisibleForTesting(visibility = PACKAGE) @MainThread public void onWindowTokenRemoved() { final Context context = mContextRef.get(); diff --git a/core/java/android/window/WindowTokenClientController.java b/core/java/android/window/WindowTokenClientController.java index abf7bb15b3d8..fa345956ec4d 100644 --- a/core/java/android/window/WindowTokenClientController.java +++ b/core/java/android/window/WindowTokenClientController.java @@ -28,7 +28,7 @@ import android.content.Context; import android.os.Bundle; import android.os.IBinder; import android.os.RemoteException; -import android.util.ArrayMap; +import android.util.ArraySet; import android.util.Log; import android.view.IWindowManager; import android.view.WindowManagerGlobal; @@ -50,9 +50,9 @@ public class WindowTokenClientController { private final IApplicationThread mAppThread = ActivityThread.currentActivityThread() .getApplicationThread(); - /** Mapping from a client defined token to the {@link WindowTokenClient} it represents. */ + /** Attached {@link WindowTokenClient}. */ @GuardedBy("mLock") - private final ArrayMap<IBinder, WindowTokenClient> mWindowTokenClientMap = new ArrayMap<>(); + private final ArraySet<WindowTokenClient> mWindowTokenClients = new ArraySet<>(); /** Gets the singleton controller. */ @NonNull @@ -85,11 +85,15 @@ public class WindowTokenClientController { /** Gets the {@link WindowContext} instance for the token. */ @Nullable public Context getWindowContext(@NonNull IBinder clientToken) { - final WindowTokenClient windowTokenClient; + if (!(clientToken instanceof WindowTokenClient windowTokenClient)) { + return null; + } synchronized (mLock) { - windowTokenClient = mWindowTokenClientMap.get(clientToken); + if (!mWindowTokenClients.contains(windowTokenClient)) { + return null; + } } - return windowTokenClient != null ? windowTokenClient.getContext() : null; + return windowTokenClient.getContext(); } /** @@ -126,8 +130,14 @@ public class WindowTokenClientController { */ public boolean attachToDisplayContent(@NonNull WindowTokenClient client, int displayId) { final IWindowManager wms = getWindowManagerService(); - // #createSystemUiContext may call this method before WindowManagerService is initialized. if (wms == null) { + // #createSystemUiContext may call this method before WindowManagerService is + // initialized. + // Regardless of whether or not it is ready, keep track of the token so that when WMS + // is initialized later, the SystemUiContext will start reporting from + // DisplayContent#registerSystemUiContext, and WindowTokenClientController can report + // the Configuration to the correct client. + recordWindowContextToken(client); return false; } final WindowContextInfo info; @@ -170,12 +180,18 @@ public class WindowTokenClientController { /** Detaches a {@link WindowTokenClient} from associated WindowContainer if there's one. */ public void detachIfNeeded(@NonNull WindowTokenClient client) { synchronized (mLock) { - if (mWindowTokenClientMap.remove(client) == null) { + if (!mWindowTokenClients.remove(client)) { return; } } + final IWindowManager wms = getWindowManagerService(); + if (wms == null) { + // #createSystemUiContext may call this method before WindowManagerService is + // initialized. If it is GC'ed before WMS is initialized, skip calling into WMS. + return; + } try { - getWindowManagerService().detachWindowContext(client); + wms.detachWindowContext(client); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -183,9 +199,7 @@ public class WindowTokenClientController { private void onWindowContextTokenAttached(@NonNull WindowTokenClient client, @NonNull WindowContextInfo info, boolean shouldReportConfigChange) { - synchronized (mLock) { - mWindowTokenClientMap.put(client, client); - } + recordWindowContextToken(client); if (shouldReportConfigChange) { // Should trigger an #onConfigurationChanged callback to the WindowContext. Post the // dispatch in the next loop to prevent the callback from being dispatched before @@ -199,10 +213,16 @@ public class WindowTokenClientController { } } + private void recordWindowContextToken(@NonNull WindowTokenClient client) { + synchronized (mLock) { + mWindowTokenClients.add(client); + } + } + /** Called when receives {@link WindowContextInfoChangeItem}. */ public void onWindowContextInfoChanged(@NonNull IBinder clientToken, @NonNull WindowContextInfo info) { - final WindowTokenClient windowTokenClient = getWindowTokenClient(clientToken); + final WindowTokenClient windowTokenClient = getWindowTokenClientIfAttached(clientToken); if (windowTokenClient != null) { windowTokenClient.onConfigurationChanged(info.getConfiguration(), info.getDisplayId()); } @@ -210,20 +230,23 @@ public class WindowTokenClientController { /** Called when receives {@link WindowContextWindowRemovalItem}. */ public void onWindowContextWindowRemoved(@NonNull IBinder clientToken) { - final WindowTokenClient windowTokenClient = getWindowTokenClient(clientToken); + final WindowTokenClient windowTokenClient = getWindowTokenClientIfAttached(clientToken); if (windowTokenClient != null) { windowTokenClient.onWindowTokenRemoved(); } } @Nullable - private WindowTokenClient getWindowTokenClient(@NonNull IBinder clientToken) { - final WindowTokenClient windowTokenClient; - synchronized (mLock) { - windowTokenClient = mWindowTokenClientMap.get(clientToken); + private WindowTokenClient getWindowTokenClientIfAttached(@NonNull IBinder clientToken) { + if (!(clientToken instanceof WindowTokenClient windowTokenClient)) { + Log.e(TAG, "getWindowTokenClient failed for non-window token " + clientToken); + return null; } - if (windowTokenClient == null) { - Log.w(TAG, "Can't find attached WindowTokenClient for " + clientToken); + synchronized (mLock) { + if (!mWindowTokenClients.contains(windowTokenClient)) { + Log.w(TAG, "Can't find attached WindowTokenClient for " + clientToken); + return null; + } } return windowTokenClient; } diff --git a/core/java/android/window/flags/lse_desktop_experience.aconfig b/core/java/android/window/flags/lse_desktop_experience.aconfig index eebdeadcdeb2..8019e6791cf1 100644 --- a/core/java/android/window/flags/lse_desktop_experience.aconfig +++ b/core/java/android/window/flags/lse_desktop_experience.aconfig @@ -242,6 +242,13 @@ flag { } flag { + name: "enable_desktop_windowing_app_handle_education_integration" + namespace: "lse_desktop_experience" + description: "Enables desktop windowing app handle education and integrates new APIs" + bug: "380272815" +} + +flag { name: "enable_desktop_windowing_transitions" namespace: "lse_desktop_experience" description: "Enables desktop windowing transition & motion polish changes" @@ -256,6 +263,16 @@ flag { } flag { + name: "enable_desktop_windowing_enter_transition_bugfix" + namespace: "lse_desktop_experience" + description: "Enables enter desktop windowing transition & motion polish changes" + bug: "380224875" + metadata { + purpose: PURPOSE_BUGFIX + } +} + +flag { name: "enable_desktop_windowing_exit_transitions" namespace: "lse_desktop_experience" description: "Enables exit desktop windowing transition & motion polish changes" @@ -263,6 +280,16 @@ flag { } flag { + name: "enable_desktop_windowing_exit_transitions_bugfix" + namespace: "lse_desktop_experience" + description: "Enables exit desktop windowing transition & motion polish changes" + bug: "380224768" + metadata { + purpose: PURPOSE_BUGFIX + } +} + +flag { name: "enable_compat_ui_visibility_status" namespace: "lse_desktop_experience" description: "Enables the tracking of the status for compat ui elements." @@ -346,6 +373,16 @@ flag { } flag { + name: "enable_desktop_app_launch_alttab_transitions_bugfix" + namespace: "lse_desktop_experience" + description: "Enables custom transitions for alt-tab app launches in Desktop Mode." + bug: "380225486" + metadata { + purpose: PURPOSE_BUGFIX + } +} + +flag { name: "enable_desktop_app_launch_transitions" namespace: "lse_desktop_experience" description: "Enables custom transitions for app launches in Desktop Mode." @@ -353,6 +390,16 @@ flag { } flag { + name: "enable_desktop_app_launch_transitions_bugfix" + namespace: "lse_desktop_experience" + description: "Enables custom transitions for app launches in Desktop Mode." + bug: "380224832" + metadata { + purpose: PURPOSE_BUGFIX + } +} + +flag { name: "enable_desktop_system_dialogs_transitions" namespace: "lse_desktop_experience" description: "Enables custom transitions for system dialogs in Desktop Mode." diff --git a/core/java/android/window/flags/windowing_frontend.aconfig b/core/java/android/window/flags/windowing_frontend.aconfig index 86bbeb827703..ebbe4830009c 100644 --- a/core/java/android/window/flags/windowing_frontend.aconfig +++ b/core/java/android/window/flags/windowing_frontend.aconfig @@ -441,3 +441,11 @@ flag { description: "Enable Predictive Back Animation for 3-button-nav" bug: "373544911" } + +flag { + name: "predictive_back_default_enable_sdk_36" + namespace: "systemui" + description: "Enable Predictive Back by default with targetSdk>=36" + is_fixed_read_only: true + bug: "376407910" +} diff --git a/core/java/com/android/internal/pm/pkg/parsing/ParsingPackageUtils.java b/core/java/com/android/internal/pm/pkg/parsing/ParsingPackageUtils.java index 8a6e6be1abbf..5fc1276dd9f9 100644 --- a/core/java/com/android/internal/pm/pkg/parsing/ParsingPackageUtils.java +++ b/core/java/com/android/internal/pm/pkg/parsing/ParsingPackageUtils.java @@ -2377,6 +2377,7 @@ public class ParsingPackageUtils { * Flags are separated by type and by default value. They are sorted alphabetically within each * section. */ + @SuppressWarnings("AndroidFrameworkCompatChange") private void parseBaseAppBasicFlags(ParsingPackage pkg, TypedArray sa) { int targetSdk = pkg.getTargetSdkVersion(); //@formatter:off @@ -2414,12 +2415,20 @@ public class ParsingPackageUtils { .setResetEnabledSettingsOnAppDataCleared(bool(false, R.styleable.AndroidManifestApplication_resetEnabledSettingsOnAppDataCleared, sa)) - .setOnBackInvokedCallbackEnabled(bool(false, R.styleable.AndroidManifestApplication_enableOnBackInvokedCallback, sa)) // targetSdkVersion gated .setAllowAudioPlaybackCapture(bool(targetSdk >= Build.VERSION_CODES.Q, R.styleable.AndroidManifestApplication_allowAudioPlaybackCapture, sa)) .setHardwareAccelerated(bool(targetSdk >= Build.VERSION_CODES.ICE_CREAM_SANDWICH, R.styleable.AndroidManifestApplication_hardwareAccelerated, sa)) .setRequestLegacyExternalStorage(bool(targetSdk < Build.VERSION_CODES.Q, R.styleable.AndroidManifestApplication_requestLegacyExternalStorage, sa)) .setCleartextTrafficAllowed(bool(targetSdk < Build.VERSION_CODES.P, R.styleable.AndroidManifestApplication_usesCleartextTraffic, sa)) + // CompatChange.isChangeEnabled() can't be used here because this is called during + // PackageManagerService initialization. PlatformCompat can't be used because this + // code is not guaranteed to be called from the system_server process. Therefore + // accessing Build.VERSION_CODES directly and suppressing + // AndroidFrameworkCompatChange warning + .setOnBackInvokedCallbackEnabled(bool( + com.android.window.flags.Flags.predictiveBackDefaultEnableSdk36() + && targetSdk > Build.VERSION_CODES.VANILLA_ICE_CREAM, + R.styleable.AndroidManifestApplication_enableOnBackInvokedCallback, sa)) // Ints Default 0 .setUiOptions(anInt(R.styleable.AndroidManifestApplication_uiOptions, sa)) // Ints diff --git a/core/java/com/android/internal/vibrator/persistence/SerializedCompositionPrimitive.java b/core/java/com/android/internal/vibrator/persistence/SerializedCompositionPrimitive.java index 862f7cb1d476..5eedec6a63e4 100644 --- a/core/java/com/android/internal/vibrator/persistence/SerializedCompositionPrimitive.java +++ b/core/java/com/android/internal/vibrator/persistence/SerializedCompositionPrimitive.java @@ -17,6 +17,7 @@ package com.android.internal.vibrator.persistence; import static com.android.internal.vibrator.persistence.XmlConstants.ATTRIBUTE_DELAY_MS; +import static com.android.internal.vibrator.persistence.XmlConstants.ATTRIBUTE_DELAY_TYPE; import static com.android.internal.vibrator.persistence.XmlConstants.ATTRIBUTE_NAME; import static com.android.internal.vibrator.persistence.XmlConstants.ATTRIBUTE_SCALE; import static com.android.internal.vibrator.persistence.XmlConstants.NAMESPACE; @@ -25,9 +26,11 @@ import static com.android.internal.vibrator.persistence.XmlConstants.TAG_PRIMITI import android.annotation.NonNull; import android.annotation.Nullable; import android.os.VibrationEffect; +import android.os.vibrator.Flags; import android.os.vibrator.PrimitiveSegment; import com.android.internal.vibrator.persistence.SerializedComposedEffect.SerializedSegment; +import com.android.internal.vibrator.persistence.XmlConstants.PrimitiveDelayType; import com.android.internal.vibrator.persistence.XmlConstants.PrimitiveEffectName; import com.android.modules.utils.TypedXmlPullParser; import com.android.modules.utils.TypedXmlSerializer; @@ -46,17 +49,26 @@ final class SerializedCompositionPrimitive implements SerializedSegment { private final PrimitiveEffectName mPrimitiveName; private final float mPrimitiveScale; private final int mPrimitiveDelayMs; + @Nullable + private final PrimitiveDelayType mDelayType; - SerializedCompositionPrimitive(PrimitiveEffectName primitiveName, float scale, int delayMs) { + SerializedCompositionPrimitive(PrimitiveEffectName primitiveName, float scale, int delayMs, + @Nullable PrimitiveDelayType delayType) { mPrimitiveName = primitiveName; mPrimitiveScale = scale; mPrimitiveDelayMs = delayMs; + mDelayType = delayType; } @Override public void deserializeIntoComposition(@NonNull VibrationEffect.Composition composition) { - composition.addPrimitive(mPrimitiveName.getPrimitiveId(), mPrimitiveScale, - mPrimitiveDelayMs); + if (Flags.primitiveCompositionAbsoluteDelay() && mDelayType != null) { + composition.addPrimitive(mPrimitiveName.getPrimitiveId(), mPrimitiveScale, + mPrimitiveDelayMs, mDelayType.getDelayType()); + } else { + composition.addPrimitive(mPrimitiveName.getPrimitiveId(), mPrimitiveScale, + mPrimitiveDelayMs); + } } @Override @@ -72,6 +84,12 @@ final class SerializedCompositionPrimitive implements SerializedSegment { serializer.attributeInt(NAMESPACE, ATTRIBUTE_DELAY_MS, mPrimitiveDelayMs); } + if (Flags.primitiveCompositionAbsoluteDelay() && mDelayType != null) { + if (mDelayType.getDelayType() != PrimitiveSegment.DEFAULT_DELAY_TYPE) { + serializer.attribute(NAMESPACE, ATTRIBUTE_DELAY_TYPE, mDelayType.toString()); + } + } + serializer.endTag(NAMESPACE, TAG_PRIMITIVE_EFFECT); } @@ -81,6 +99,7 @@ final class SerializedCompositionPrimitive implements SerializedSegment { + "name=" + mPrimitiveName + ", scale=" + mPrimitiveScale + ", delayMs=" + mPrimitiveDelayMs + + ", delayType=" + mDelayType + '}'; } @@ -91,8 +110,14 @@ final class SerializedCompositionPrimitive implements SerializedSegment { static SerializedCompositionPrimitive parseNext(@NonNull TypedXmlPullParser parser) throws XmlParserException, IOException { XmlValidator.checkStartTag(parser, TAG_PRIMITIVE_EFFECT); - XmlValidator.checkTagHasNoUnexpectedAttributes(parser, - ATTRIBUTE_NAME, ATTRIBUTE_DELAY_MS, ATTRIBUTE_SCALE); + + if (Flags.primitiveCompositionAbsoluteDelay()) { + XmlValidator.checkTagHasNoUnexpectedAttributes(parser, + ATTRIBUTE_NAME, ATTRIBUTE_DELAY_MS, ATTRIBUTE_SCALE, ATTRIBUTE_DELAY_TYPE); + } else { + XmlValidator.checkTagHasNoUnexpectedAttributes(parser, + ATTRIBUTE_NAME, ATTRIBUTE_DELAY_MS, ATTRIBUTE_SCALE); + } PrimitiveEffectName primitiveName = parsePrimitiveName( parser.getAttributeValue(NAMESPACE, ATTRIBUTE_NAME)); @@ -100,11 +125,13 @@ final class SerializedCompositionPrimitive implements SerializedSegment { parser, ATTRIBUTE_SCALE, 0, 1, PrimitiveSegment.DEFAULT_SCALE); int delayMs = XmlReader.readAttributeIntNonNegative( parser, ATTRIBUTE_DELAY_MS, PrimitiveSegment.DEFAULT_DELAY_MILLIS); + PrimitiveDelayType delayType = parseDelayType( + parser.getAttributeValue(NAMESPACE, ATTRIBUTE_DELAY_TYPE)); // Consume tag XmlReader.readEndTag(parser); - return new SerializedCompositionPrimitive(primitiveName, scale, delayMs); + return new SerializedCompositionPrimitive(primitiveName, scale, delayMs, delayType); } @NonNull @@ -119,5 +146,21 @@ final class SerializedCompositionPrimitive implements SerializedSegment { } return effectName; } + + @Nullable + private static PrimitiveDelayType parseDelayType(@Nullable String name) + throws XmlParserException { + if (name == null) { + return null; + } + if (!Flags.primitiveCompositionAbsoluteDelay()) { + throw new XmlParserException("Unexpected primitive delay type " + name); + } + PrimitiveDelayType delayType = PrimitiveDelayType.findByName(name); + if (delayType == null) { + throw new XmlParserException("Unexpected primitive delay type " + name); + } + return delayType; + } } } diff --git a/core/java/com/android/internal/vibrator/persistence/VibrationEffectXmlSerializer.java b/core/java/com/android/internal/vibrator/persistence/VibrationEffectXmlSerializer.java index d74a23d47f4a..cb834a5eac7e 100644 --- a/core/java/com/android/internal/vibrator/persistence/VibrationEffectXmlSerializer.java +++ b/core/java/com/android/internal/vibrator/persistence/VibrationEffectXmlSerializer.java @@ -27,6 +27,7 @@ import android.os.vibrator.VibrationEffectSegment; import com.android.internal.vibrator.persistence.SerializedComposedEffect.SerializedSegment; import com.android.internal.vibrator.persistence.XmlConstants.PredefinedEffectName; +import com.android.internal.vibrator.persistence.XmlConstants.PrimitiveDelayType; import com.android.internal.vibrator.persistence.XmlConstants.PrimitiveEffectName; import java.util.List; @@ -170,8 +171,20 @@ public final class VibrationEffectXmlSerializer { XmlValidator.checkSerializerCondition(primitiveName != null, "Unsupported primitive effect id %s", primitive.getPrimitiveId()); + PrimitiveDelayType delayType = null; + + if (Flags.primitiveCompositionAbsoluteDelay()) { + delayType = PrimitiveDelayType.findByType(primitive.getDelayType()); + XmlValidator.checkSerializerCondition(delayType != null, + "Unsupported primitive delay type %s", primitive.getDelayType()); + } else { + XmlValidator.checkSerializerCondition( + primitive.getDelayType() == PrimitiveSegment.DEFAULT_DELAY_TYPE, + "Unsupported primitive delay type %s", primitive.getDelayType()); + } + return new SerializedCompositionPrimitive( - primitiveName, primitive.getScale(), primitive.getDelay()); + primitiveName, primitive.getScale(), primitive.getDelay(), delayType); } private static int toAmplitudeInt(float amplitude) { diff --git a/core/java/com/android/internal/vibrator/persistence/XmlConstants.java b/core/java/com/android/internal/vibrator/persistence/XmlConstants.java index 2a55d999bc0f..4122215a2b04 100644 --- a/core/java/com/android/internal/vibrator/persistence/XmlConstants.java +++ b/core/java/com/android/internal/vibrator/persistence/XmlConstants.java @@ -20,6 +20,7 @@ import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.os.VibrationEffect; +import android.os.VibrationEffect.Composition.DelayType; import android.os.VibrationEffect.Composition.PrimitiveType; import java.lang.annotation.Retention; @@ -51,6 +52,7 @@ public final class XmlConstants { public static final String ATTRIBUTE_AMPLITUDE = "amplitude"; public static final String ATTRIBUTE_SCALE = "scale"; public static final String ATTRIBUTE_DELAY_MS = "delayMs"; + public static final String ATTRIBUTE_DELAY_TYPE = "delayType"; public static final String VALUE_AMPLITUDE_DEFAULT = "default"; @@ -87,7 +89,7 @@ public final class XmlConstants { /** * Return the {@link PrimitiveEffectName} that represents given primitive id, or null if - * none of the available names maps to the given id. + * none of the available names map to the given id. */ @Nullable public static PrimitiveEffectName findById(int primitiveId) { @@ -200,4 +202,53 @@ public final class XmlConstants { return name().toLowerCase(Locale.ROOT); } } + + /** Represent supported values for attribute delay type in {@link #TAG_PRIMITIVE_EFFECT} */ + public enum PrimitiveDelayType { + PAUSE(VibrationEffect.Composition.DELAY_TYPE_PAUSE), + RELATIVE_START_OFFSET(VibrationEffect.Composition.DELAY_TYPE_RELATIVE_START_OFFSET); + + @DelayType private final int mDelayType; + + PrimitiveDelayType(@DelayType int type) { + mDelayType = type; + } + + /** + * Return the {@link PrimitiveEffectName} that represents given primitive id, or null if + * none of the available names maps to the given id. + */ + @Nullable + public static PrimitiveDelayType findByType(int delayType) { + for (PrimitiveDelayType type : PrimitiveDelayType.values()) { + if (type.mDelayType == delayType) { + return type; + } + } + return null; + } + + /** + * Return the {@link PrimitiveEffectName} that represents given primitive name, or null if + * none of the available names maps to the given name. + */ + @Nullable + public static PrimitiveDelayType findByName(@NonNull String delayType) { + try { + return PrimitiveDelayType.valueOf(delayType.toUpperCase(Locale.ROOT)); + } catch (IllegalArgumentException e) { + return null; + } + } + + @DelayType + public int getDelayType() { + return mDelayType; + } + + @Override + public String toString() { + return name().toLowerCase(Locale.ROOT); + } + } } diff --git a/core/jni/android_content_res_ApkAssets.cpp b/core/jni/android_content_res_ApkAssets.cpp index ded1a9949ef8..1e7bfe32ba79 100644 --- a/core/jni/android_content_res_ApkAssets.cpp +++ b/core/jni/android_content_res_ApkAssets.cpp @@ -36,6 +36,8 @@ using ::android::base::unique_fd; namespace android { +static constexpr bool kLogWeakReachableDeletedAssets = false; + static struct overlayableinfo_offsets_t { jclass classObject; jmethodID constructor; @@ -97,7 +99,7 @@ static void DeleteGuardedApkAssets(Guarded<AssetManager2::ApkAssetsPtr>& apk_ass if (useCount > 1) { ALOGW("ApkAssets: Deleting an object '%s' with %d > 1 strong and %d weak references", (*assets)->GetDebugName().c_str(), int(useCount), int(weakCount)); - } else if (weakCount > 0) { + } else if constexpr (kLogWeakReachableDeletedAssets) if (weakCount > 0) { ALOGW("ApkAssets: Deleting an ApkAssets object '%s' with %d weak references", (*assets)->GetDebugName().c_str(), int(weakCount)); } diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp index 68e642086636..0c243d1dc185 100644 --- a/core/jni/android_view_SurfaceControl.cpp +++ b/core/jni/android_view_SurfaceControl.cpp @@ -119,6 +119,7 @@ static struct { jfieldID renderFrameRate; jfieldID hasArrSupport; jfieldID frameRateCategoryRate; + jfieldID supportedRefreshRates; jfieldID supportedColorModes; jfieldID activeColorMode; jfieldID hdrCapabilities; @@ -1508,6 +1509,21 @@ static jobject nativeGetDynamicDisplayInfo(JNIEnv* env, jclass clazz, jlong disp env->SetBooleanField(object, gDynamicDisplayInfoClassInfo.hasArrSupport, info.hasArrSupport); env->SetObjectField(object, gDynamicDisplayInfoClassInfo.frameRateCategoryRate, convertFrameRateCategoryRateToJavaObject(env, info.frameRateCategoryRate)); + + jfloatArray supportedRefreshRatesArray = env->NewFloatArray(info.supportedRefreshRates.size()); + if (supportedRefreshRatesArray == NULL) { + jniThrowException(env, "java/lang/OutOfMemoryError", NULL); + return NULL; + } + jfloat* supportedRefreshRatesArrayValues = + env->GetFloatArrayElements(supportedRefreshRatesArray, 0); + for (size_t i = 0; i < info.supportedRefreshRates.size(); i++) { + supportedRefreshRatesArrayValues[i] = static_cast<jfloat>(info.supportedRefreshRates[i]); + } + env->ReleaseFloatArrayElements(supportedRefreshRatesArray, supportedRefreshRatesArrayValues, 0); + env->SetObjectField(object, gDynamicDisplayInfoClassInfo.supportedRefreshRates, + supportedRefreshRatesArray); + jintArray colorModesArray = env->NewIntArray(info.supportedColorModes.size()); if (colorModesArray == NULL) { jniThrowException(env, "java/lang/OutOfMemoryError", NULL); @@ -2766,6 +2782,8 @@ int register_android_view_SurfaceControl(JNIEnv* env) gFrameRateCategoryRateClassInfo.ctor = GetMethodIDOrDie(env, frameRateCategoryRateClazz, "<init>", "(FF)V"); + gDynamicDisplayInfoClassInfo.supportedRefreshRates = + GetFieldIDOrDie(env, dynamicInfoClazz, "supportedRefreshRates", "[F"); gDynamicDisplayInfoClassInfo.supportedColorModes = GetFieldIDOrDie(env, dynamicInfoClazz, "supportedColorModes", "[I"); gDynamicDisplayInfoClassInfo.activeColorMode = diff --git a/core/proto/android/providers/settings/secure.proto b/core/proto/android/providers/settings/secure.proto index 6af742fb23f4..2e0fe9eb13d9 100644 --- a/core/proto/android/providers/settings/secure.proto +++ b/core/proto/android/providers/settings/secure.proto @@ -256,6 +256,12 @@ message SecureSettingsProto { } optional Display display = 100; + message DoubleTapPowerButton { + optional SettingProto gesture_enabled = 1 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto gesture = 2 [ (android.privacy).dest = DEST_AUTOMATIC ]; + } + optional DoubleTapPowerButton double_tap_power_button = 103; + message Doze { option (android.msg_privacy).dest = DEST_EXPLICIT; @@ -737,5 +743,5 @@ message SecureSettingsProto { // Please insert fields in alphabetical order and group them into messages // if possible (to avoid reaching the method limit). - // Next tag = 103; + // Next tag = 104; } diff --git a/core/res/Android.bp b/core/res/Android.bp index 8042b30df4dc..aacd8699c202 100644 --- a/core/res/Android.bp +++ b/core/res/Android.bp @@ -160,6 +160,7 @@ android_app { "android.app.contextualsearch.flags-aconfig", "android.app.flags-aconfig", "android.appwidget.flags-aconfig", + "android.companion.virtualdevice.flags-aconfig", "android.content.pm.flags-aconfig", "android.media.audio-aconfig", "android.provider.flags-aconfig", diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index cedcd2feafc3..7c2a30da4923 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -848,10 +848,10 @@ <protected-broadcast android:name="android.app.action.CONSOLIDATED_NOTIFICATION_POLICY_CHANGED" /> <protected-broadcast android:name="android.intent.action.MAIN_USER_LOCKSCREEN_KNOWLEDGE_FACTOR_CHANGED" /> <protected-broadcast android:name="com.android.uwb.uwbcountrycode.GEOCODE_RETRY" /> - <protected-broadcast android:name="android.telephony.action.ACTION_SATELLITE_SUBSCRIBER_ID_LIST_CHANGED" /> + <protected-broadcast android:name="android.telephony.satellite.action.SATELLITE_SUBSCRIBER_ID_LIST_CHANGED" /> <protected-broadcast android:name="android.service.ondeviceintelligence.MODEL_LOADED" /> <protected-broadcast android:name="android.service.ondeviceintelligence.MODEL_UNLOADED" /> - <protected-broadcast android:name="android.telephony.action.ACTION_SATELLITE_START_NON_EMERGENCY_SESSION" /> + <protected-broadcast android:name="android.telephony.satellite.action.SATELLITE_START_NON_EMERGENCY_SESSION" /> <!-- ====================================================================== --> @@ -8060,6 +8060,13 @@ <permission android:name="android.permission.ADD_ALWAYS_UNLOCKED_DISPLAY" android:protectionLevel="signature|role"/> + <!-- Allows an application to create displays that mirror other displays' content. + @FlaggedApi(android.companion.virtualdevice.flags.Flags.FLAG_ENABLE_LIMITED_VDM_ROLE) + @hide @SystemApi --> + <permission android:name="android.permission.ADD_MIRROR_DISPLAY" + android:protectionLevel="internal|role" + android:featureFlag="android.companion.virtualdevice.flags.enable_limited_vdm_role" /> + <!-- @hide @SystemApi Allows an application to access locusId events in the usage stats. --> <permission android:name="android.permission.ACCESS_LOCUS_ID_USAGE_STATS" android:protectionLevel="signature|role" /> @@ -9344,6 +9351,17 @@ </intent-filter> </service> + <service android:name="com.android.ecm.EnhancedConfirmationCallTrackerService" + android:permission="android.permission.BIND_INCALL_SERVICE" + android:featureFlag="android.permission.flags.enhanced_confirmation_in_call_apis_enabled" + android:exported="true"> + <meta-data android:name="android.telecom.INCLUDE_SELF_MANAGED_CALLS" + android:value="true" /> + <intent-filter> + <action android:name="android.telecom.InCallService"/> + </intent-filter> + </service> + <service android:name="com.android.server.companion.datatransfer.contextsync.CallMetadataSyncConnectionService" android:permission="android.permission.BIND_TELECOM_CONNECTION_SERVICE" android:exported="true"> diff --git a/core/res/res/drawable-watch-v36/dialog_alert_button_background_negative.xml b/core/res/res/drawable-watch-v36/dialog_alert_button_background_negative.xml index b6b8eac3a547..0314bbec2b55 100644 --- a/core/res/res/drawable-watch-v36/dialog_alert_button_background_negative.xml +++ b/core/res/res/drawable-watch-v36/dialog_alert_button_background_negative.xml @@ -18,7 +18,7 @@ <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle"> <solid android:color="@color/btn_material_filled_tonal_background_color"/> - <corners android:radius="@dimen/config_bottomDialogCornerRadius" /> + <corners android:radius="@dimen/config_wearMaterial3_bottomDialogCornerRadius" /> <size android:width="@dimen/dialog_btn_negative_width" android:height="@dimen/dialog_btn_negative_height" /> diff --git a/core/res/res/layout-sw600dp/preference_list_content_single.xml b/core/res/res/layout-sw600dp/preference_list_content_single.xml index 88b1aa8d4d00..ebe4eca1b156 100644 --- a/core/res/res/layout-sw600dp/preference_list_content_single.xml +++ b/core/res/res/layout-sw600dp/preference_list_content_single.xml @@ -19,6 +19,7 @@ <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" + android:fitsSystemWindows="true" android:layout_height="match_parent" android:layout_width="match_parent"> diff --git a/core/res/res/layout-watch-v36/alert_dialog_icon_button_wear_material3.xml b/core/res/res/layout-watch-v36/alert_dialog_icon_button_wear_material3.xml new file mode 100644 index 000000000000..407ec7a42740 --- /dev/null +++ b/core/res/res/layout-watch-v36/alert_dialog_icon_button_wear_material3.xml @@ -0,0 +1,123 @@ +<!-- + ~ Copyright (C) 2024 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> + +<!-- This layout is the AlertDialog template. It overrides the system layout with the same name. + Make sure to include all the existing id of the overridden alert_dialog_material.--> +<com.android.internal.widget.WatchListDecorLayout + xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/parentPanel" + android:layout_width="match_parent" + android:layout_height="match_parent"> + <ScrollView + android:id="@+id/scrollView" + android:fillViewport="true" + android:layout_width="match_parent" + android:layout_height="match_parent"> + <LinearLayout + android:orientation="vertical" + android:layout_width="match_parent" + android:layout_height="wrap_content"> + <!-- Top Panel --> + <FrameLayout + android:paddingLeft="?dialogPreferredPadding" + android:paddingRight="?dialogPreferredPadding" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:id="@+id/topPanel" + android:minHeight="@dimen/dialog_list_padding_top_no_title"> + <include android:id="@+id/title_template" + android:layout_width="match_parent" + android:layout_height="wrap_content" + layout="@layout/alert_dialog_title_material"/> + </FrameLayout> + + <!-- Content Panel --> + <FrameLayout android:id="@+id/contentPanel" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:clipToPadding="false"> + <TextView android:id="@+id/message" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:gravity="center_horizontal|top" + android:textAppearance="@style/TextAppearance.DeviceDefault.Body1" + android:paddingStart="?dialogPreferredPadding" + android:paddingEnd="?dialogPreferredPadding" + android:paddingTop="8dip" + android:paddingBottom="8dip"/> + </FrameLayout> + + <!-- Custom Panel, to replace content panel if needed --> + <FrameLayout android:id="@+id/customPanel" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:minHeight="64dp"> + <FrameLayout android:id="@+android:id/custom" + android:layout_width="match_parent" + android:layout_height="wrap_content" /> + </FrameLayout> + + <!-- Button Panel --> + <FrameLayout + android:id="@+id/buttonPanel" + android:minHeight="@dimen/dialog_list_padding_bottom_no_buttons" + android:layout_weight="1" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center"> + <LinearLayout + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="bottom" + android:orientation="horizontal" + android:paddingBottom="?dialogPreferredPadding" + style="?android:attr/buttonBarStyle" + android:measureWithLargestChild="true"> + <Button android:id="@+id/button2" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center" + android:gravity="center" + android:layout_weight="1" + style="@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog.WearMaterial3.Negative" /> + <Button android:id="@+id/button3" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center" + android:gravity="center" + android:layout_weight="1" + style="?android:attr/buttonBarButtonStyle"/> + <FrameLayout + android:layout_width="wrap_content" + android:layout_height="wrap_content"> + <Button android:id="@+id/button1" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:layout_gravity="center" + android:gravity="center" + android:layout_weight="1" + style="@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog.WearMaterial3.Confirm" /> + <!-- This works as background. --> + <ImageView + android:layout_width="match_parent" + android:layout_height="match_parent" + android:src="@drawable/dialog_alert_button_positive"/> + </FrameLayout> + </LinearLayout> + </FrameLayout> + </LinearLayout> + </ScrollView> +</com.android.internal.widget.WatchListDecorLayout> diff --git a/core/res/res/layout-watch-v36/alert_dialog_material.xml b/core/res/res/layout-watch-v36/alert_dialog_material.xml index 900102f379d9..8f7545690142 100644 --- a/core/res/res/layout-watch-v36/alert_dialog_material.xml +++ b/core/res/res/layout-watch-v36/alert_dialog_material.xml @@ -82,9 +82,8 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="bottom" - android:orientation="horizontal" + android:orientation="vertical" android:paddingBottom="?dialogPreferredPadding" - style="?android:attr/buttonBarStyle" android:measureWithLargestChild="true"> <Button android:id="@+id/button2" android:layout_width="wrap_content" @@ -92,7 +91,7 @@ android:layout_gravity="center" android:gravity="center" android:layout_weight="1" - style="@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog.Negative" /> + style="@*android:style/Widget.DeviceDefault.Button.WearMaterial3"/> <Button android:id="@+id/button3" android:layout_width="wrap_content" android:layout_height="wrap_content" @@ -100,22 +99,13 @@ android:gravity="center" android:layout_weight="1" style="?android:attr/buttonBarButtonStyle"/> - <FrameLayout - android:layout_width="wrap_content" - android:layout_height="wrap_content"> - <Button android:id="@+id/button1" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:layout_gravity="center" - android:gravity="center" - android:layout_weight="1" - style="@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog.Confirm"/> - <!-- This works as background. --> - <ImageView + <Button android:id="@+id/button1" android:layout_width="match_parent" android:layout_height="match_parent" - android:src="@drawable/dialog_alert_button_positive"/> - </FrameLayout> + android:layout_gravity="center" + android:gravity="center" + android:layout_weight="1" + style="@*android:style/Widget.DeviceDefault.Button.Filled"/> </LinearLayout> </FrameLayout> </LinearLayout> diff --git a/core/res/res/layout/notification_2025_reply_container.xml b/core/res/res/layout/notification_2025_reply_container.xml new file mode 100644 index 000000000000..6923b59f34dc --- /dev/null +++ b/core/res/res/layout/notification_2025_reply_container.xml @@ -0,0 +1,79 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2024 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License + --> + +<!-- Note: this layout is included from a view stub; layout attributes will be overridden. --> +<LinearLayout + xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/notification_material_reply_container" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical" + android:paddingStart="@dimen/notification_2025_content_margin_start"> + + <ImageView + android:layout_width="match_parent" + android:layout_height="1dip" + android:id="@+id/action_divider" + android:layout_marginTop="@dimen/notification_content_margin" + android:layout_marginBottom="@dimen/notification_content_margin" + android:layout_marginEnd="@dimen/notification_content_margin_end" + android:background="@drawable/notification_template_divider" /> + + <TextView + android:id="@+id/notification_material_reply_text_3" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginEnd="@dimen/notification_content_margin_end" + android:visibility="gone" + android:textAppearance="@style/TextAppearance.DeviceDefault.Notification.Reply" + android:singleLine="true" /> + + <TextView + android:id="@+id/notification_material_reply_text_2" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginEnd="@dimen/notification_content_margin_end" + android:visibility="gone" + android:textAppearance="@style/TextAppearance.DeviceDefault.Notification.Reply" + android:singleLine="true" /> + + <LinearLayout + android:id="@+id/notification_material_reply_text_1_container" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="horizontal" + android:layout_marginEnd="@dimen/notification_content_margin_end"> + <TextView + android:id="@+id/notification_material_reply_text_1" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_weight="1" + android:layout_marginEnd="@dimen/notification_content_margin_end" + android:layout_gravity="center" + android:textAppearance="@style/TextAppearance.DeviceDefault.Notification.Reply" + android:singleLine="true" /> + <ProgressBar + android:id="@+id/notification_material_reply_progress" + android:layout_height="@dimen/messaging_group_sending_progress_size" + android:layout_width="@dimen/messaging_group_sending_progress_size" + android:layout_marginStart="@dimen/notification_2025_content_margin_start" + android:layout_gravity="center" + android:indeterminate="true" + style="?android:attr/progressBarStyleSmall" /> + </LinearLayout> + +</LinearLayout> diff --git a/core/res/res/layout/notification_2025_template_expanded_base.xml b/core/res/res/layout/notification_2025_template_expanded_base.xml new file mode 100644 index 000000000000..e480fe5eef1e --- /dev/null +++ b/core/res/res/layout/notification_2025_template_expanded_base.xml @@ -0,0 +1,86 @@ +<?xml version="1.0" encoding="utf-8"?><!-- + ~ Copyright (C) 2024 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License + --> +<FrameLayout + xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/status_bar_latest_event_content" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical" + android:clipChildren="false" + android:tag="big" + > + + <LinearLayout + android:id="@+id/notification_action_list_margin_target" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginBottom="@dimen/notification_content_margin" + android:orientation="vertical" + > + + <FrameLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_weight="1" + android:layout_gravity="top" + > + + <include layout="@layout/notification_2025_template_header" /> + + <LinearLayout + android:id="@+id/notification_main_column" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginStart="@dimen/notification_2025_content_margin_start" + android:layout_marginEnd="@dimen/notification_content_margin_end" + android:layout_marginTop="@dimen/notification_content_margin_top" + android:orientation="vertical" + > + + <include layout="@layout/notification_template_part_line1" /> + + <include layout="@layout/notification_template_text_multiline" /> + + <include + android:layout_width="match_parent" + android:layout_height="@dimen/notification_progress_bar_height" + android:layout_marginTop="@dimen/notification_progress_margin_top" + layout="@layout/notification_template_progress" + /> + </LinearLayout> + + <include layout="@layout/notification_template_right_icon" /> + </FrameLayout> + + <ViewStub + android:layout="@layout/notification_2025_reply_container" + android:id="@+id/notification_material_reply_container" + android:layout_width="match_parent" + android:layout_height="wrap_content" + /> + + <include + layout="@layout/notification_template_smart_reply_container" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginStart="@dimen/notification_2025_content_margin_start" + android:layout_marginEnd="@dimen/notification_content_margin_end" + android:layout_marginTop="@dimen/notification_content_margin" + /> + + <include layout="@layout/notification_material_action_list" /> + </LinearLayout> +</FrameLayout> diff --git a/core/res/res/layout/notification_template_header.xml b/core/res/res/layout/notification_template_header.xml index 565d584875ac..57959361bd48 100644 --- a/core/res/res/layout/notification_template_header.xml +++ b/core/res/res/layout/notification_template_header.xml @@ -13,7 +13,7 @@ ~ See the License for the specific language governing permissions and ~ limitations under the License --> -<!-- extends FrameLayout --> +<!-- extends RelativeLayout --> <NotificationHeaderView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/notification_header" @@ -62,7 +62,7 @@ android:layout_height="match_parent" android:layout_alignParentStart="true" android:layout_centerVertical="true" - android:layout_toStartOf="@id/notification_buttons_column" + android:layout_toStartOf="@id/expand_button" android:layout_alignWithParentIfMissing="true" android:clipChildren="false" android:gravity="center_vertical" @@ -83,28 +83,17 @@ android:focusable="false" /> - <LinearLayout - android:id="@+id/notification_buttons_column" + <include layout="@layout/notification_expand_button" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_alignParentEnd="true" - android:orientation="vertical" - > - - <include layout="@layout/notification_close_button" - android:layout_width="@dimen/notification_close_button_size" - android:layout_height="@dimen/notification_close_button_size" - android:layout_gravity="end" - android:layout_marginEnd="20dp" - /> - - <include layout="@layout/notification_expand_button" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_alignParentEnd="true" - android:layout_centerVertical="true" - /> + android:layout_centerVertical="true" + android:layout_alignParentEnd="true" /> - </LinearLayout> + <include layout="@layout/notification_close_button" + android:id="@+id/close_button" + android:layout_width="@dimen/notification_close_button_size" + android:layout_height="@dimen/notification_close_button_size" + android:layout_alignParentTop="true" + android:layout_alignParentEnd="true" /> </NotificationHeaderView> diff --git a/core/res/res/layout/notification_template_material_base.xml b/core/res/res/layout/notification_template_material_base.xml index 29f14a4a93fc..227f84bb2eed 100644 --- a/core/res/res/layout/notification_template_material_base.xml +++ b/core/res/res/layout/notification_template_material_base.xml @@ -157,39 +157,27 @@ android:maxDrawableHeight="@dimen/notification_right_icon_size" /> - <LinearLayout - android:id="@+id/notification_buttons_column" + <FrameLayout + android:id="@+id/expand_button_touch_container" android:layout_width="wrap_content" android:layout_height="match_parent" - android:layout_alignParentEnd="true" - android:orientation="vertical" + android:minWidth="@dimen/notification_content_margin_end" > - <include layout="@layout/notification_close_button" - android:layout_width="@dimen/notification_close_button_size" - android:layout_height="@dimen/notification_close_button_size" - android:layout_gravity="end" - android:layout_marginEnd="20dp" - /> - - <FrameLayout - android:id="@+id/expand_button_touch_container" + <include layout="@layout/notification_expand_button" android:layout_width="wrap_content" - android:layout_height="0dp" - android:layout_weight="1" - android:minWidth="@dimen/notification_content_margin_end" - > - - <include layout="@layout/notification_expand_button" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="center_vertical|end" - /> - - </FrameLayout> + android:layout_height="wrap_content" + android:layout_gravity="center_vertical|end" + /> - </LinearLayout> + </FrameLayout> </LinearLayout> + <include layout="@layout/notification_close_button" + android:id="@+id/close_button" + android:layout_width="@dimen/notification_close_button_size" + android:layout_height="@dimen/notification_close_button_size" + android:layout_gravity="top|end" /> + </FrameLayout> diff --git a/core/res/res/layout/notification_template_material_media.xml b/core/res/res/layout/notification_template_material_media.xml index 6e9d17fc31d4..5459fa895f82 100644 --- a/core/res/res/layout/notification_template_material_media.xml +++ b/core/res/res/layout/notification_template_material_media.xml @@ -15,6 +15,7 @@ ~ limitations under the License --> +<!-- extends FrameLayout --> <com.android.internal.widget.MediaNotificationView android:id="@+id/status_bar_latest_event_content" xmlns:android="http://schemas.android.com/apk/res/android" @@ -191,4 +192,11 @@ </FrameLayout> </LinearLayout> + + <include layout="@layout/notification_close_button" + android:id="@+id/close_button" + android:layout_width="@dimen/notification_close_button_size" + android:layout_height="@dimen/notification_close_button_size" + android:layout_gravity="top|end" /> + </com.android.internal.widget.MediaNotificationView> diff --git a/core/res/res/layout/notification_template_material_messaging.xml b/core/res/res/layout/notification_template_material_messaging.xml index 1eae41da1e81..2b3b7d873f4f 100644 --- a/core/res/res/layout/notification_template_material_messaging.xml +++ b/core/res/res/layout/notification_template_material_messaging.xml @@ -195,6 +195,12 @@ </LinearLayout> + <include layout="@layout/notification_close_button" + android:id="@+id/close_button" + android:layout_width="@dimen/notification_close_button_size" + android:layout_height="@dimen/notification_close_button_size" + android:layout_gravity="top|end" /> + </com.android.internal.widget.NotificationMaxHeightFrameLayout> <LinearLayout diff --git a/core/res/res/layout/preference_list_content.xml b/core/res/res/layout/preference_list_content.xml index bed80edf0ee7..7a2fb0b3b822 100644 --- a/core/res/res/layout/preference_list_content.xml +++ b/core/res/res/layout/preference_list_content.xml @@ -20,6 +20,7 @@ <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" + android:fitsSystemWindows="true" android:layout_height="match_parent" android:layout_width="match_parent"> diff --git a/core/res/res/layout/preference_list_content_material.xml b/core/res/res/layout/preference_list_content_material.xml index 37b411918ef6..23c82509b6b0 100644 --- a/core/res/res/layout/preference_list_content_material.xml +++ b/core/res/res/layout/preference_list_content_material.xml @@ -20,6 +20,7 @@ <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" + android:fitsSystemWindows="true" android:layout_height="match_parent" android:layout_width="match_parent"> diff --git a/core/res/res/layout/preference_list_content_single.xml b/core/res/res/layout/preference_list_content_single.xml index 726ce78b281f..4f072da99546 100644 --- a/core/res/res/layout/preference_list_content_single.xml +++ b/core/res/res/layout/preference_list_content_single.xml @@ -19,6 +19,7 @@ <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" + android:fitsSystemWindows="true" android:layout_height="match_parent" android:layout_width="match_parent"> diff --git a/core/res/res/layout/preference_list_fragment.xml b/core/res/res/layout/preference_list_fragment.xml index c43975e4ad3c..44a5df9b60be 100644 --- a/core/res/res/layout/preference_list_fragment.xml +++ b/core/res/res/layout/preference_list_fragment.xml @@ -19,6 +19,7 @@ <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" + android:fitsSystemWindows="true" android:layout_height="match_parent" android:layout_width="match_parent" android:background="@android:color/transparent" diff --git a/core/res/res/layout/preference_list_fragment_material.xml b/core/res/res/layout/preference_list_fragment_material.xml index db2fe7d038e0..4df76029e606 100644 --- a/core/res/res/layout/preference_list_fragment_material.xml +++ b/core/res/res/layout/preference_list_fragment_material.xml @@ -19,6 +19,7 @@ <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" + android:fitsSystemWindows="true" android:layout_height="match_parent" android:layout_width="match_parent" android:background="@android:color/transparent" diff --git a/core/res/res/values-watch-v36/config.xml b/core/res/res/values-watch-v36/config.xml index 1143ae30fe9d..679dc709ec35 100644 --- a/core/res/res/values-watch-v36/config.xml +++ b/core/res/res/values-watch-v36/config.xml @@ -16,5 +16,5 @@ <resources> <dimen name="config_wearMaterial3_buttonCornerRadius">26dp</dimen> - <dimen name="config_bottomDialogCornerRadius">18dp</dimen> + <dimen name="config_wearMaterial3_bottomDialogCornerRadius">18dp</dimen> </resources> diff --git a/core/res/res/values-watch-v36/styles_material.xml b/core/res/res/values-watch-v36/styles_material.xml index 00f3f092b768..7da7435930b1 100644 --- a/core/res/res/values-watch-v36/styles_material.xml +++ b/core/res/res/values-watch-v36/styles_material.xml @@ -57,7 +57,7 @@ </style> <!-- AlertDialog Styles --> - <style name="Widget.DeviceDefault.Button.ButtonBar.AlertDialog" parent="Widget.DeviceDefault.Button"> + <style name="Widget.DeviceDefault.Button.ButtonBar.AlertDialog.WearMaterial3" parent="Widget.DeviceDefault.Button"> <item name="android:textSize">0sp</item> <item name="android:gravity">center</item> <item name="android:paddingStart">0dp</item> @@ -65,14 +65,14 @@ <item name="android:drawablePadding">0dp</item> </style> - <style name="Widget.DeviceDefault.Button.ButtonBar.AlertDialog.Confirm" parent="Widget.DeviceDefault.Button.ButtonBar.AlertDialog"> + <style name="Widget.DeviceDefault.Button.ButtonBar.AlertDialog.WearMaterial3.Confirm"> <!-- Use a ImageView as background --> <item name="background">@android:color/transparent</item> <item name="minWidth">@dimen/dialog_btn_confirm_width</item> <item name="minHeight">@dimen/dialog_btn_confirm_height</item> </style> - <style name="Widget.DeviceDefault.Button.ButtonBar.AlertDialog.Negative" parent="Widget.DeviceDefault.Button.ButtonBar.AlertDialog"> + <style name="Widget.DeviceDefault.Button.ButtonBar.AlertDialog.WearMaterial3.Negative"> <item name="background">@drawable/dialog_alert_button_negative</item> <item name="minWidth">@dimen/dialog_btn_negative_width</item> <item name="minHeight">@dimen/dialog_btn_negative_height</item> diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml index f6590b1360f8..8c46ccc84f39 100644 --- a/core/res/res/values/attrs.xml +++ b/core/res/res/values/attrs.xml @@ -4808,6 +4808,12 @@ <!-- Whether the device should default to observe mode when this service is default or in the foreground. --> <attr name="shouldDefaultToObserveMode" format="boolean"/> + <!-- Whether this service should share the same AID routing priority as the role + owner. This package and the role owner must have the same signature, and the + role owner must opt into this behavior by using the property named by + {@link android.nfc.cardemulation.CardEmulation.PROPERTY_ALLOW_SHARED_ROLE_PRIORITY } + in the <code><application&rt;</code> tag. --> + <attr name="shareRolePriority" format="boolean"/> </declare-styleable> <!-- Use <code>offhost-apdu-service</code> as the root tag of the XML resource that @@ -4835,6 +4841,7 @@ <!-- Whether the device should default to observe mode when this service is default or in the foreground. --> <attr name="shouldDefaultToObserveMode"/> + <attr name="shareRolePriority"/> </declare-styleable> <!-- Specify one or more <code>aid-group</code> elements inside a diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index 7f2c816e5654..38ebda733270 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -2731,6 +2731,8 @@ </string-array> <!-- The list of supported dream complications --> <integer-array name="config_supportedDreamComplications"> + <!-- COMPLICATION_TYPE_TIME --> + <item>1</item> </integer-array> <!-- Are we allowed to dream while not plugged in? --> diff --git a/core/res/res/values/ids.xml b/core/res/res/values/ids.xml index e71277dc0414..3b39a65b6795 100644 --- a/core/res/res/values/ids.xml +++ b/core/res/res/values/ids.xml @@ -290,4 +290,7 @@ <!-- View tag associating a view with its overridden id, to ensure valid recycling only. --> <item type="id" name="remote_views_override_id" /> + + <!-- View tag associating a view with its id for widget metrics. --> + <item type="id" name="remoteViewsMetricsId" /> </resources> diff --git a/core/res/res/values/public-staging.xml b/core/res/res/values/public-staging.xml index b0b87d1dead6..e75371d6bf46 100644 --- a/core/res/res/values/public-staging.xml +++ b/core/res/res/values/public-staging.xml @@ -133,9 +133,13 @@ <public name="alternateLauncherLabels"/> <!-- @FlaggedApi(android.content.pm.Flags.FLAG_APP_COMPAT_OPTION_16KB) --> <public name="pageSizeCompat" /> + <!-- @FlaggedApi(android.nfc.Flags.FLAG_NFC_ASSOCIATED_ROLE_SERVICES) --> + <public name="shareRolePriority"/> </staging-public-group> <staging-public-group type="id" first-id="0x01b60000"> + <!-- @FlaggedApi(android.appwidget.flags.Flags.FLAG_ENGAGEMENT_METRICS) --> + <public name="remoteViewsMetricsId"/> </staging-public-group> <staging-public-group type="style" first-id="0x01b50000"> diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index c13fdb17dfe3..413f0c3e0c58 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -5357,6 +5357,8 @@ <string name="zen_mode_trigger_summary_range_symbol_combination"><xliff:g id="start" example="Sun">%1$s</xliff:g> - <xliff:g id="end" example="Thu">%2$s</xliff:g></string> <!-- [CHAR LIMIT=40] General template for a start - end range in a text summary, used for the trigger description of a Zen mode --> <string name="zen_mode_trigger_summary_range_words"><xliff:g id="start" example="Sunday">%1$s</xliff:g> to <xliff:g id="end" example="Thursday">%2$s</xliff:g></string> + <!-- [CHAR LIMIT=NONE] General template for combining a days of week start-end range with a time-based start-end range, for example: "Sun-Thurs, 10:00 PM - 7:00 AM" --> + <string name="zen_mode_trigger_summary_combined"><xliff:g id="days" example="Sat-Thurs">%1$s</xliff:g>,\u0020<xliff:g id="times" example="10:00 PM - 7:00 AM">%2$s</xliff:g></string> <!-- [CHAR LIMIT=40] Event-based rule calendar option value for any calendar, used for the trigger description of a Zen mode --> <string name="zen_mode_trigger_event_calendar_any">Any calendar</string> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index b49e142e4cee..fc24f4599b25 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -2390,6 +2390,7 @@ <java-symbol type="layout" name="notification_material_action_list" /> <java-symbol type="layout" name="notification_material_action_tombstone" /> <java-symbol type="layout" name="notification_2025_template_collapsed_base" /> + <java-symbol type="layout" name="notification_2025_template_expanded_base" /> <java-symbol type="layout" name="notification_2025_template_heads_up_base" /> <java-symbol type="layout" name="notification_2025_template_header" /> <java-symbol type="layout" name="notification_template_material_base" /> @@ -2666,6 +2667,7 @@ <java-symbol type="string" name="zen_mode_trigger_summary_divider_text" /> <java-symbol type="string" name="zen_mode_trigger_summary_range_symbol_combination" /> <java-symbol type="string" name="zen_mode_trigger_summary_range_words" /> + <java-symbol type="string" name="zen_mode_trigger_summary_combined" /> <java-symbol type="string" name="zen_mode_trigger_event_calendar_any" /> <java-symbol type="string" name="display_rotation_camera_compat_toast_after_rotation" /> @@ -5109,7 +5111,6 @@ <java-symbol type="layout" name="notification_expand_button"/> <java-symbol type="id" name="close_button" /> <java-symbol type="layout" name="notification_close_button"/> - <java-symbol type="id" name="notification_buttons_column" /> <java-symbol type="bool" name="config_supportsMicToggle" /> <java-symbol type="bool" name="config_supportsCamToggle" /> diff --git a/core/tests/coretests/Android.bp b/core/tests/coretests/Android.bp index f39508d6de15..49425572b256 100644 --- a/core/tests/coretests/Android.bp +++ b/core/tests/coretests/Android.bp @@ -152,6 +152,7 @@ android_test { ":HelloWorldUsingSdkMalformedNegativeVersion", ":CtsStaticSharedLibConsumerApp1", ":CtsStaticSharedLibConsumerApp3", + ":CtsStaticSharedLibProviderApp1", ], } diff --git a/core/tests/coretests/AndroidTest.xml b/core/tests/coretests/AndroidTest.xml index 5d8ff87eca24..bada7512a8e9 100644 --- a/core/tests/coretests/AndroidTest.xml +++ b/core/tests/coretests/AndroidTest.xml @@ -43,6 +43,8 @@ value="/data/local/tmp/tests/coretests/pm/CtsStaticSharedLibConsumerApp1.apk"/> <option name="push-file" key="CtsStaticSharedLibConsumerApp3.apk" value="/data/local/tmp/tests/coretests/pm/CtsStaticSharedLibConsumerApp3.apk"/> + <option name="push-file" key="CtsStaticSharedLibProviderApp1.apk" + value="/data/local/tmp/tests/coretests/pm/CtsStaticSharedLibProviderApp1.apk"/> </target_preparer> <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer"> diff --git a/core/tests/coretests/src/android/app/NotificationTest.java b/core/tests/coretests/src/android/app/NotificationTest.java index 23a09857032c..63e678d9ee53 100644 --- a/core/tests/coretests/src/android/app/NotificationTest.java +++ b/core/tests/coretests/src/android/app/NotificationTest.java @@ -467,7 +467,6 @@ public class NotificationTest { .setStyle(new Notification.BigTextStyle().setBigContentTitle("BIG")) .setColor(Color.WHITE) .setColorized(true) - .setFlag(FLAG_CAN_COLORIZE, true) .build(); assertThat(n.hasPromotableCharacteristics()).isTrue(); } @@ -481,7 +480,6 @@ public class NotificationTest { .setContentTitle("TITLE") .setColor(Color.WHITE) .setColorized(true) - .setFlag(FLAG_CAN_COLORIZE, true) .build(); assertThat(n.hasPromotableCharacteristics()).isFalse(); } @@ -505,7 +503,20 @@ public class NotificationTest { .setStyle(new Notification.BigTextStyle()) .setColor(Color.WHITE) .setColorized(true) - .setFlag(FLAG_CAN_COLORIZE, true) + .build(); + assertThat(n.hasPromotableCharacteristics()).isFalse(); + } + + @Test + @EnableFlags(Flags.FLAG_UI_RICH_ONGOING) + public void testHasPromotableCharacteristics_groupSummary() { + Notification n = new Notification.Builder(mContext, "test") + .setSmallIcon(android.R.drawable.sym_def_app_icon) + .setStyle(new Notification.BigTextStyle().setBigContentTitle("BIG")) + .setColor(Color.WHITE) + .setColorized(true) + .setGroup("someGroup") + .setGroupSummary(true) .build(); assertThat(n.hasPromotableCharacteristics()).isFalse(); } diff --git a/core/tests/coretests/src/android/appwidget/AppWidgetEventsTest.kt b/core/tests/coretests/src/android/appwidget/AppWidgetEventsTest.kt new file mode 100644 index 000000000000..ea1158c88055 --- /dev/null +++ b/core/tests/coretests/src/android/appwidget/AppWidgetEventsTest.kt @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.appwidget + +import android.graphics.Rect +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.google.common.truth.Truth.assertThat +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class AppWidgetEventsTest { + @Test + fun createWidgetInteractionEvent() { + val appWidgetId = 1 + val durationMs = 1000L + val position = Rect(1, 2, 3, 4) + val clicked = intArrayOf(1, 2, 3) + val scrolled = intArrayOf(4, 5, 6) + val bundle = AppWidgetManager.createWidgetInteractionEvent( + appWidgetId, + durationMs, + position, + clicked, + scrolled + ) + + assertThat(bundle.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID)).isEqualTo(appWidgetId) + assertThat(bundle.getLong(AppWidgetManager.EXTRA_EVENT_DURATION_MS)).isEqualTo(durationMs) + assertThat(bundle.getIntArray(AppWidgetManager.EXTRA_EVENT_POSITION_RECT)) + .asList().containsExactly(position.left, position.top, position.right, position.bottom) + assertThat(bundle.getIntArray(AppWidgetManager.EXTRA_EVENT_CLICKED_VIEWS)) + .asList().containsExactly(clicked[0], clicked[1], clicked[2]) + assertThat(bundle.getIntArray(AppWidgetManager.EXTRA_EVENT_SCROLLED_VIEWS)) + .asList().containsExactly(scrolled[0], scrolled[1], scrolled[2]) + } +} diff --git a/core/tests/coretests/src/android/appwidget/OWNERS b/core/tests/coretests/src/android/appwidget/OWNERS new file mode 100644 index 000000000000..d724cac4aa3e --- /dev/null +++ b/core/tests/coretests/src/android/appwidget/OWNERS @@ -0,0 +1 @@ +include /core/java/android/appwidget/OWNERS diff --git a/core/tests/coretests/src/android/content/pm/parsing/ApkLiteParseUtilsTest.java b/core/tests/coretests/src/android/content/pm/parsing/ApkLiteParseUtilsTest.java index ecacdb2bde0b..6d2dd5355ff0 100644 --- a/core/tests/coretests/src/android/content/pm/parsing/ApkLiteParseUtilsTest.java +++ b/core/tests/coretests/src/android/content/pm/parsing/ApkLiteParseUtilsTest.java @@ -73,6 +73,7 @@ public class ApkLiteParseUtilsTest { private static final String TEST_APP_USING_SDK1_AND_SDK1 = "HelloWorldUsingSdk1AndSdk1.apk"; private static final String TEST_APP_USING_SDK_MALFORMED_VERSION = "HelloWorldUsingSdkMalformedNegativeVersion.apk"; + private static final String TEST_STATIC_LIB_APP = "CtsStaticSharedLibProviderApp1.apk"; private static final String TEST_APP_USING_STATIC_LIB = "CtsStaticSharedLibConsumerApp1.apk"; private static final String TEST_APP_USING_STATIC_LIB_TWO_CERTS = "CtsStaticSharedLibConsumerApp3.apk"; @@ -207,6 +208,17 @@ public class ApkLiteParseUtilsTest { assertThat(liteCerts).isEqualTo(pkgCerts); } + @Test + public void testParseApkLite_isIsStaticLibrary() throws Exception { + File apkFile = copyApkToTmpDir(TEST_STATIC_LIB_APP); + ParseResult<ApkLite> result = ApkLiteParseUtils + .parseApkLite(ParseTypeImpl.forDefaultParsing().reset(), apkFile, 0); + assertThat(result.isError()).isFalse(); + ApkLite baseApk = result.getResult(); + + assertThat(baseApk.isIsStaticLibrary()).isTrue(); + } + @SuppressLint("CheckResult") @Test public void testParseApkLite_malformedUsesSdkLibrary_duplicate() throws Exception { diff --git a/core/tests/coretests/src/android/window/WindowTokenClientControllerTest.java b/core/tests/coretests/src/android/window/WindowTokenClientControllerTest.java index a3725af04ba6..bb2fe1bcfc64 100644 --- a/core/tests/coretests/src/android/window/WindowTokenClientControllerTest.java +++ b/core/tests/coretests/src/android/window/WindowTokenClientControllerTest.java @@ -162,6 +162,22 @@ public class WindowTokenClientControllerTest { } @Test + public void testAttachToDisplayContent_keepTrackWithoutWMS() { + // WMS is not initialized + doReturn(null).when(mController).getWindowManagerService(); + + assertFalse(mController.attachToDisplayContent(mWindowTokenClient, DEFAULT_DISPLAY)); + + // Can report config change + mController.onWindowContextInfoChanged(mWindowTokenClient, mWindowContextInfo); + + verify(mWindowTokenClient).onConfigurationChanged(mConfiguration, DEFAULT_DISPLAY); + + // No crash to detach even if WMS is not initialized. + mController.detachIfNeeded(mWindowTokenClient); + } + + @Test public void testAttachToWindowToken() throws RemoteException { doReturn(null).when(mWindowManagerService).attachWindowContextToWindowToken( any(), any(), any()); diff --git a/core/tests/vibrator/src/android/os/vibrator/persistence/VibrationEffectXmlSerializationTest.java b/core/tests/vibrator/src/android/os/vibrator/persistence/VibrationEffectXmlSerializationTest.java index 1cc38ded1c2c..40710577b154 100644 --- a/core/tests/vibrator/src/android/os/vibrator/persistence/VibrationEffectXmlSerializationTest.java +++ b/core/tests/vibrator/src/android/os/vibrator/persistence/VibrationEffectXmlSerializationTest.java @@ -16,6 +16,8 @@ package android.os.vibrator.persistence; +import static android.os.VibrationEffect.Composition.DELAY_TYPE_PAUSE; +import static android.os.VibrationEffect.Composition.DELAY_TYPE_RELATIVE_START_OFFSET; import static android.os.VibrationEffect.Composition.PRIMITIVE_CLICK; import static android.os.VibrationEffect.Composition.PRIMITIVE_LOW_TICK; import static android.os.VibrationEffect.Composition.PRIMITIVE_SPIN; @@ -31,6 +33,7 @@ import android.os.PersistableBundle; import android.os.VibrationEffect; import android.os.vibrator.Flags; import android.os.vibrator.PrebakedSegment; +import android.os.vibrator.PrimitiveSegment; import android.platform.test.annotations.DisableFlags; import android.platform.test.annotations.EnableFlags; import android.platform.test.flag.junit.SetFlagsRule; @@ -437,7 +440,7 @@ public class VibrationEffectXmlSerializationTest { @Test @EnableFlags(Flags.FLAG_VENDOR_VIBRATION_EFFECTS) - public void testVendorEffect_featureFlagEnabled_allSucceed() throws Exception { + public void testVendorEffect_allSucceed() throws Exception { PersistableBundle vendorData = new PersistableBundle(); vendorData.putInt("id", 1); vendorData.putDouble("scale", 0.5); @@ -476,7 +479,7 @@ public class VibrationEffectXmlSerializationTest { @Test @EnableFlags(Flags.FLAG_VENDOR_VIBRATION_EFFECTS) - public void testInvalidVendorEffect_featureFlagEnabled_allFail() throws IOException { + public void testInvalidVendorEffect_allFail() throws IOException { String emptyTag = "<vibration-effect><vendor-effect/></vibration-effect>"; assertPublicApisParserFails(emptyTag); assertHiddenApisParserFails(emptyTag); @@ -526,6 +529,81 @@ public class VibrationEffectXmlSerializationTest { assertHiddenApisSerializerFails(vendorEffect); } + @Test + @EnableFlags(Flags.FLAG_PRIMITIVE_COMPOSITION_ABSOLUTE_DELAY) + public void testPrimitiveDelayType_allSucceed() throws Exception { + VibrationEffect effect = VibrationEffect.startComposition() + .addPrimitive(PRIMITIVE_TICK, 1.0f, 0, DELAY_TYPE_RELATIVE_START_OFFSET) + .addPrimitive(PRIMITIVE_CLICK, 0.123f, 10, DELAY_TYPE_PAUSE) + .compose(); + String xml = """ + <vibration-effect> + <primitive-effect name="tick" delayType="relative_start_offset"/> + <primitive-effect name="click" scale="0.123" delayMs="10"/> + </vibration-effect> + """; + + assertPublicApisParserSucceeds(xml, effect); + assertPublicApisSerializerSucceeds(effect, "tick", "click"); + // Delay type pause is not serialized, as it's the default one + assertPublicApisSerializerSucceeds(effect, "relative_start_offset", "click"); + assertPublicApisRoundTrip(effect); + + assertHiddenApisParserSucceeds(xml, effect); + assertHiddenApisSerializerSucceeds(effect, "tick", "click"); + assertHiddenApisRoundTrip(effect); + + // Check PersistableBundle from round-trip + VibrationEffect.Composed parsedEffect = ((VibrationEffect.Composed) parseVibrationEffect( + serialize(effect), /* flags= */ 0)); + assertThat(parsedEffect.getRepeatIndex()).isEqualTo(-1); + assertThat(parsedEffect.getSegments()).containsExactly( + new PrimitiveSegment(PRIMITIVE_TICK, 1.0f, 0, DELAY_TYPE_RELATIVE_START_OFFSET), + new PrimitiveSegment(PRIMITIVE_CLICK, 0.123f, 10, DELAY_TYPE_PAUSE)) + .inOrder(); + } + + @Test + @EnableFlags(Flags.FLAG_PRIMITIVE_COMPOSITION_ABSOLUTE_DELAY) + public void testPrimitiveInvalidDelayType_allFail() { + String emptyAttribute = """ + <vibration-effect> + <primitive-effect name="tick" delayType=""/> + </vibration-effect> + """; + assertPublicApisParserFails(emptyAttribute); + assertHiddenApisParserFails(emptyAttribute); + + String invalidString = """ + <vibration-effect> + <primitive-effect name="tick" delayType="invalid"/> + </vibration-effect> + """; + assertPublicApisParserFails(invalidString); + assertHiddenApisParserFails(invalidString); + } + + @Test + @DisableFlags(Flags.FLAG_PRIMITIVE_COMPOSITION_ABSOLUTE_DELAY) + public void testPrimitiveDelayType_featureFlagDisabled_allFail() { + VibrationEffect effect = VibrationEffect.startComposition() + .addPrimitive(PRIMITIVE_TICK, 1.0f, 0, DELAY_TYPE_RELATIVE_START_OFFSET) + .addPrimitive(PRIMITIVE_CLICK, 0.123f, 10, DELAY_TYPE_PAUSE) + .compose(); + String xml = """ + <vibration-effect> + <primitive-effect name="tick" delayType="relative_start_offset"/> + <primitive-effect name="click" scale="0.123" delayMs="10" delayType="pause"/> + </vibration-effect> + """; + + assertPublicApisParserFails(xml); + assertPublicApisSerializerFails(effect); + + assertHiddenApisParserFails(xml); + assertHiddenApisSerializerFails(effect); + } + private void assertPublicApisParserFails(String xml) { assertThrows("Expected parseVibrationEffect to fail for " + xml, VibrationXmlParser.ParseFailedException.class, diff --git a/core/xsd/permission.xsd b/core/xsd/permission.xsd index 0ec8f7d4f2ae..0a0ca7c2248b 100644 --- a/core/xsd/permission.xsd +++ b/core/xsd/permission.xsd @@ -43,6 +43,7 @@ <xs:element name="disabled-until-used-preinstalled-carrier-app" type="disabled-until-used-preinstalled-carrier-app"/> <xs:element name="privapp-permissions" type="privapp-permissions"/> <xs:element name="oem-permissions" type="oem-permissions"/> + <xs:element name="signature-permissions" type="signature-permissions"/> <xs:element name="hidden-api-whitelisted-app" type="hidden-api-whitelisted-app"/> <xs:element name="allow-association" type="allow-association"/> <xs:element name="bugreport-whitelisted" type="bugreport-whitelisted"/> @@ -156,6 +157,21 @@ </xs:sequence> <xs:attribute name="package" type="xs:string"/> </xs:complexType> + <xs:complexType name="signature-permissions"> + <xs:sequence> + <xs:element name="permission" minOccurs="0" maxOccurs="unbounded"> + <xs:complexType> + <xs:attribute name="name" type="xs:string"/> + </xs:complexType> + </xs:element> + <xs:element name="deny-permission" minOccurs="0" maxOccurs="unbounded"> + <xs:complexType> + <xs:attribute name="name" type="xs:string"/> + </xs:complexType> + </xs:element> + </xs:sequence> + <xs:attribute name="package" type="xs:string"/> + </xs:complexType> <xs:complexType name="hidden-api-whitelisted-app"> <xs:attribute name="package" type="xs:string"/> </xs:complexType> diff --git a/core/xsd/schema/current.txt b/core/xsd/schema/current.txt index f3beea1b96a9..cdec6ab6e014 100644 --- a/core/xsd/schema/current.txt +++ b/core/xsd/schema/current.txt @@ -183,6 +183,7 @@ package com.android.xml.permission.configfile { method public java.util.List<com.android.xml.permission.configfile.OemPermissions> getOemPermissions_optional(); method public java.util.List<com.android.xml.permission.configfile.Permission> getPermission_optional(); method public java.util.List<com.android.xml.permission.configfile.PrivappPermissions> getPrivappPermissions_optional(); + method public java.util.List<com.android.xml.permission.configfile.SignaturePermissions> getSignaturePermissions_optional(); method public java.util.List<com.android.xml.permission.configfile.SplitPermission> getSplitPermission_optional(); method public java.util.List<com.android.xml.permission.configfile.SystemUserBlacklistedApp> getSystemUserBlacklistedApp_optional(); method public java.util.List<com.android.xml.permission.configfile.SystemUserWhitelistedApp> getSystemUserWhitelistedApp_optional(); @@ -209,6 +210,26 @@ package com.android.xml.permission.configfile { method public void setName(String); } + public class SignaturePermissions { + ctor public SignaturePermissions(); + method public java.util.List<com.android.xml.permission.configfile.SignaturePermissions.DenyPermission> getDenyPermission(); + method public java.util.List<com.android.xml.permission.configfile.SignaturePermissions.Permission> getPermission(); + method public String get_package(); + method public void set_package(String); + } + + public static class SignaturePermissions.DenyPermission { + ctor public SignaturePermissions.DenyPermission(); + method public String getName(); + method public void setName(String); + } + + public static class SignaturePermissions.Permission { + ctor public SignaturePermissions.Permission(); + method public String getName(); + method public void setName(String); + } + public class SplitPermission { ctor public SplitPermission(); method public java.util.List<com.android.xml.permission.configfile.SplitPermission.Library> getLibrary(); diff --git a/core/xsd/vibrator/vibration/schema/current.txt b/core/xsd/vibrator/vibration/schema/current.txt index 280b40516b7e..b4148d657b0d 100644 --- a/core/xsd/vibrator/vibration/schema/current.txt +++ b/core/xsd/vibrator/vibration/schema/current.txt @@ -15,12 +15,20 @@ package com.android.internal.vibrator.persistence { enum_constant public static final com.android.internal.vibrator.persistence.PredefinedEffectName tick; } + public enum PrimitiveDelayType { + method public String getRawName(); + enum_constant public static final com.android.internal.vibrator.persistence.PrimitiveDelayType pause; + enum_constant public static final com.android.internal.vibrator.persistence.PrimitiveDelayType relative_start_offset; + } + public class PrimitiveEffect { ctor public PrimitiveEffect(); method public java.math.BigInteger getDelayMs(); + method public com.android.internal.vibrator.persistence.PrimitiveDelayType getDelayType(); method public com.android.internal.vibrator.persistence.PrimitiveEffectName getName(); method public float getScale(); method public void setDelayMs(java.math.BigInteger); + method public void setDelayType(com.android.internal.vibrator.persistence.PrimitiveDelayType); method public void setName(com.android.internal.vibrator.persistence.PrimitiveEffectName); method public void setScale(float); } diff --git a/core/xsd/vibrator/vibration/vibration-plus-hidden-apis.xsd b/core/xsd/vibrator/vibration/vibration-plus-hidden-apis.xsd index 21a6facad242..910a9b700b5c 100644 --- a/core/xsd/vibrator/vibration/vibration-plus-hidden-apis.xsd +++ b/core/xsd/vibrator/vibration/vibration-plus-hidden-apis.xsd @@ -147,6 +147,7 @@ <xs:attribute name="name" type="PrimitiveEffectName" use="required"/> <xs:attribute name="scale" type="PrimitiveScale"/> <xs:attribute name="delayMs" type="xs:nonNegativeInteger"/> + <xs:attribute name="delayType" type="PrimitiveDelayType"/> </xs:complexType> <!-- Primitive names as defined by VibrationEffect.Composition.PRIMITIVE_* --> @@ -171,4 +172,12 @@ </xs:restriction> </xs:simpleType> + <!-- Primitive delay types VibrationEffect.Composition.DELAY_TYPE_* --> + <xs:simpleType name="PrimitiveDelayType"> + <xs:restriction base="xs:string"> + <xs:enumeration value="pause"/> + <xs:enumeration value="relative_start_offset"/> + </xs:restriction> + </xs:simpleType> + </xs:schema> diff --git a/core/xsd/vibrator/vibration/vibration.xsd b/core/xsd/vibrator/vibration/vibration.xsd index d35d777d4450..3c8e01605659 100644 --- a/core/xsd/vibrator/vibration/vibration.xsd +++ b/core/xsd/vibrator/vibration/vibration.xsd @@ -124,6 +124,7 @@ <xs:attribute name="name" type="PrimitiveEffectName" use="required"/> <xs:attribute name="scale" type="PrimitiveScale"/> <xs:attribute name="delayMs" type="xs:nonNegativeInteger"/> + <xs:attribute name="delayType" type="PrimitiveDelayType"/> </xs:complexType> <!-- Primitive names as defined by VibrationEffect.Composition.PRIMITIVE_* --> @@ -148,4 +149,12 @@ </xs:restriction> </xs:simpleType> + <!-- Primitive delay types VibrationEffect.Composition.DELAY_TYPE_* --> + <xs:simpleType name="PrimitiveDelayType"> + <xs:restriction base="xs:string"> + <xs:enumeration value="pause"/> + <xs:enumeration value="relative_start_offset"/> + </xs:restriction> + </xs:simpleType> + </xs:schema> diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml index af690f4449af..897fc543517e 100644 --- a/data/etc/privapp-permissions-platform.xml +++ b/data/etc/privapp-permissions-platform.xml @@ -677,8 +677,4 @@ applications that come with the platform <permission name="android.permission.BATTERY_STATS"/> <permission name="android.permission.ENTER_TRADE_IN_MODE"/> </privapp-permissions> - - <privapp-permissions package="com.android.multiuser"> - <permission name="android.permission.MANAGE_USERS"/> - </privapp-permissions> </permissions> diff --git a/graphics/java/android/graphics/RuntimeColorFilter.java b/graphics/java/android/graphics/RuntimeColorFilter.java index d112f7153fca..a64acfe767a9 100644 --- a/graphics/java/android/graphics/RuntimeColorFilter.java +++ b/graphics/java/android/graphics/RuntimeColorFilter.java @@ -280,7 +280,8 @@ public class RuntimeColorFilter extends ColorFilter { if (colorFilter == null) { throw new NullPointerException("The colorFilter parameter must not be null"); } - nativeUpdateChild(getNativeInstance(), filterName, colorFilter.getNativeInstance()); + nativeUpdateInputColorFilter(getNativeInstance(), filterName, + colorFilter.getNativeInstance()); } /** @@ -318,5 +319,6 @@ public class RuntimeColorFilter extends ColorFilter { long colorFilter, String uniformName, int value1, int value2, int value3, int value4, int count); private static native void nativeUpdateChild(long colorFilter, String childName, long child); - + private static native void nativeUpdateInputColorFilter(long colorFilter, String childName, + long inputFilter); } diff --git a/graphics/java/android/graphics/RuntimeShader.java b/graphics/java/android/graphics/RuntimeShader.java index 6316c1fb8b47..3543e991924e 100644 --- a/graphics/java/android/graphics/RuntimeShader.java +++ b/graphics/java/android/graphics/RuntimeShader.java @@ -264,6 +264,9 @@ public class RuntimeShader extends Shader { * enable better heap tracking & tooling support */ private ArrayMap<String, Shader> mShaderUniforms = new ArrayMap<>(); + private ArrayMap<String, ColorFilter> mColorFilterUniforms = new ArrayMap<>(); + private ArrayMap<String, RuntimeXfermode> mXfermodeUniforms = new ArrayMap<>(); + /** * Creates a new RuntimeShader. @@ -544,8 +547,10 @@ public class RuntimeShader extends Shader { if (colorFilter == null) { throw new NullPointerException("The colorFilter parameter must not be null"); } - nativeUpdateChild(mNativeInstanceRuntimeShaderBuilder, filterName, + mColorFilterUniforms.put(filterName, colorFilter); + nativeUpdateColorFilter(mNativeInstanceRuntimeShaderBuilder, filterName, colorFilter.getNativeInstance()); + discardNativeInstance(); } /** @@ -563,8 +568,10 @@ public class RuntimeShader extends Shader { if (xfermode == null) { throw new NullPointerException("The xfermode parameter must not be null"); } + mXfermodeUniforms.put(xfermodeName, xfermode); nativeUpdateChild(mNativeInstanceRuntimeShaderBuilder, xfermodeName, xfermode.createNativeInstance()); + discardNativeInstance(); } @@ -594,6 +601,8 @@ public class RuntimeShader extends Shader { int value4, int count); private static native void nativeUpdateShader( long shaderBuilder, String shaderName, long shader); + private static native void nativeUpdateColorFilter( + long shaderBuilder, String colorFilterName, long colorFilter); private static native void nativeUpdateChild( long shaderBuilder, String childName, long child); } diff --git a/graphics/java/android/graphics/RuntimeXfermode.java b/graphics/java/android/graphics/RuntimeXfermode.java index 51d97a4b7487..c8a0b1a11339 100644 --- a/graphics/java/android/graphics/RuntimeXfermode.java +++ b/graphics/java/android/graphics/RuntimeXfermode.java @@ -285,7 +285,8 @@ public class RuntimeXfermode extends Xfermode { if (colorFilter == null) { throw new NullPointerException("The colorFilter parameter must not be null"); } - nativeUpdateChild(mBuilderNativeInstance, filterName, colorFilter.getNativeInstance()); + nativeUpdateColorFilter(mBuilderNativeInstance, filterName, + colorFilter.getNativeInstance()); } /** @@ -325,5 +326,6 @@ public class RuntimeXfermode extends Xfermode { long builder, String uniformName, int value1, int value2, int value3, int value4, int count); private static native void nativeUpdateChild(long builder, String childName, long child); + private static native void nativeUpdateColorFilter(long builder, String childName, long filter); } diff --git a/libs/WindowManager/Jetpack/src/androidx/window/common/DeviceStateManagerFoldingFeatureProducer.java b/libs/WindowManager/Jetpack/src/androidx/window/common/DeviceStateManagerFoldingFeatureProducer.java index 089613853555..5ea38431829e 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/common/DeviceStateManagerFoldingFeatureProducer.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/common/DeviceStateManagerFoldingFeatureProducer.java @@ -30,8 +30,6 @@ import android.text.TextUtils; import android.util.Log; import android.util.SparseIntArray; -import androidx.annotation.BinderThread; -import androidx.annotation.GuardedBy; import androidx.annotation.MainThread; import androidx.annotation.NonNull; import androidx.annotation.VisibleForTesting; @@ -39,14 +37,12 @@ import androidx.window.common.layout.CommonFoldingFeature; import androidx.window.common.layout.DisplayFoldFeatureCommon; import com.android.internal.R; -import com.android.window.flags.Flags; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Objects; import java.util.Optional; -import java.util.concurrent.Executor; import java.util.function.Consumer; /** @@ -70,20 +66,8 @@ public final class DeviceStateManagerFoldingFeatureProducer * "rear display". Concurrent mode for example is activated via public API and can be active in * both the "open" and "half folded" device states. */ - // TODO: b/337820752 - Add @GuardedBy("mCurrentDeviceStateLock") after flag cleanup. private DeviceState mCurrentDeviceState = INVALID_DEVICE_STATE; - /** - * Lock to synchronize access to {@link #mCurrentDeviceState}. - * - * <p>This lock is used to ensure thread-safety when accessing and modifying the - * {@link #mCurrentDeviceState} field. It is acquired by both the binder thread (if - * {@link Flags#wlinfoOncreate()} is enabled) and the main thread (if - * {@link Flags#wlinfoOncreate()} is disabled) to prevent race conditions and - * ensure data consistency. - */ - private final Object mCurrentDeviceStateLock = new Object(); - @NonNull private final RawFoldingFeatureProducer mRawFoldSupplier; @@ -95,15 +79,12 @@ public final class DeviceStateManagerFoldingFeatureProducer // The GuardedBy analysis is intra-procedural, meaning it doesn’t consider the getData() // implementation. See https://errorprone.info/bugpattern/GuardedBy for limitations. @SuppressWarnings("GuardedBy") - @BinderThread // When Flags.wlinfoOncreate() is enabled. - @MainThread // When Flags.wlinfoOncreate() is disabled. + @MainThread @Override public void onDeviceStateChanged(@NonNull DeviceState state) { - synchronized (mCurrentDeviceStateLock) { - mCurrentDeviceState = state; - mRawFoldSupplier.getData(DeviceStateManagerFoldingFeatureProducer.this - ::notifyFoldingFeatureChangeLocked); - } + mCurrentDeviceState = state; + mRawFoldSupplier.getData(DeviceStateManagerFoldingFeatureProducer.this + ::notifyFoldingFeatureChangeLocked); } }; @@ -115,10 +96,8 @@ public final class DeviceStateManagerFoldingFeatureProducer new DeviceStateMapper(context, deviceStateManager.getSupportedDeviceStates()); if (!mDeviceStateMapper.isDeviceStateToPostureMapEmpty()) { - final Executor executor = - Flags.wlinfoOncreate() ? Runnable::run : context.getMainExecutor(); Objects.requireNonNull(deviceStateManager) - .registerCallback(executor, mDeviceStateCallback); + .registerCallback(context.getMainExecutor(), mDeviceStateCallback); } } @@ -145,21 +124,17 @@ public final class DeviceStateManagerFoldingFeatureProducer @Override protected void onListenersChanged() { super.onListenersChanged(); - synchronized (mCurrentDeviceStateLock) { - if (hasListeners()) { - mRawFoldSupplier.addDataChangedCallback(this::notifyFoldingFeatureChangeLocked); - } else { - mCurrentDeviceState = INVALID_DEVICE_STATE; - mRawFoldSupplier.removeDataChangedCallback(this::notifyFoldingFeatureChangeLocked); - } + if (hasListeners()) { + mRawFoldSupplier.addDataChangedCallback(this::notifyFoldingFeatureChangeLocked); + } else { + mCurrentDeviceState = INVALID_DEVICE_STATE; + mRawFoldSupplier.removeDataChangedCallback(this::notifyFoldingFeatureChangeLocked); } } @NonNull private DeviceState getCurrentDeviceState() { - synchronized (mCurrentDeviceStateLock) { - return mCurrentDeviceState; - } + return mCurrentDeviceState; } @NonNull @@ -231,7 +206,6 @@ public final class DeviceStateManagerFoldingFeatureProducer }); } - @GuardedBy("mCurrentDeviceStateLock") private void notifyFoldingFeatureChangeLocked(String displayFeaturesString) { final DeviceState state = mCurrentDeviceState; if (!mDeviceStateMapper.isDeviceStateValid(state)) { @@ -252,29 +226,16 @@ public final class DeviceStateManagerFoldingFeatureProducer return parseListFromString(displayFeaturesString, hingeState); } - /** - * Internal class to map device states to corresponding postures. - * - * <p>This class encapsulates the logic for mapping device states to postures. The mapping is - * immutable after initialization to ensure thread safety. - */ + /** Internal class to map device states to corresponding postures. */ private static class DeviceStateMapper { /** * Emulated device state * {@link DeviceStateManager.DeviceStateCallback#onDeviceStateChanged(DeviceState)} to * {@link CommonFoldingFeature.State} map. - * - * <p>This map must be immutable after initialization to ensure thread safety, as it may be - * accessed from multiple threads. Modifications should only occur during object - * construction. */ private final SparseIntArray mDeviceStateToPostureMap = new SparseIntArray(); - /** - * The list of device states that are supported. - * - * <p>This list must be immutable after initialization to ensure thread safety. - */ + /** The list of device states that are supported. */ @NonNull private final List<DeviceState> mSupportedStates; diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/common/DeviceStateManagerFoldingFeatureProducerTest.kt b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/common/DeviceStateManagerFoldingFeatureProducerTest.kt index 90887a747a6f..fb01cd88158c 100644 --- a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/common/DeviceStateManagerFoldingFeatureProducerTest.kt +++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/common/DeviceStateManagerFoldingFeatureProducerTest.kt @@ -20,9 +20,6 @@ import android.content.Context import android.content.res.Resources import android.hardware.devicestate.DeviceState import android.hardware.devicestate.DeviceStateManager -import android.platform.test.annotations.DisableFlags -import android.platform.test.annotations.EnableFlags -import android.platform.test.flag.junit.SetFlagsRule import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.window.common.layout.CommonFoldingFeature import androidx.window.common.layout.CommonFoldingFeature.COMMON_STATE_FLAT @@ -34,15 +31,11 @@ import androidx.window.common.layout.DisplayFoldFeatureCommon import androidx.window.common.layout.DisplayFoldFeatureCommon.DISPLAY_FOLD_FEATURE_PROPERTY_SUPPORTS_HALF_OPENED import androidx.window.common.layout.DisplayFoldFeatureCommon.DISPLAY_FOLD_FEATURE_TYPE_SCREEN_FOLD_IN import com.android.internal.R -import com.android.window.flags.Flags import com.google.common.truth.Truth.assertThat import java.util.Optional -import java.util.concurrent.Executor import java.util.function.Consumer -import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith -import org.mockito.ArgumentCaptor import org.mockito.kotlin.any import org.mockito.kotlin.doAnswer import org.mockito.kotlin.doReturn @@ -60,9 +53,6 @@ import org.mockito.kotlin.verify */ @RunWith(AndroidJUnit4::class) class DeviceStateManagerFoldingFeatureProducerTest { - @get:Rule - val setFlagsRule: SetFlagsRule = SetFlagsRule() - private val mMockDeviceStateManager = mock<DeviceStateManager>() private val mMockResources = mock<Resources> { on { getStringArray(R.array.config_device_state_postures) } doReturn DEVICE_STATE_POSTURES @@ -79,8 +69,7 @@ class DeviceStateManagerFoldingFeatureProducerTest { } @Test - @DisableFlags(Flags.FLAG_WLINFO_ONCREATE) - fun testRegisterCallback_whenWlinfoOncreateIsDisabled_usesMainExecutor() { + fun testRegisterCallback_usesMainExecutor() { DeviceStateManagerFoldingFeatureProducer( mMockContext, mRawFoldSupplier, @@ -91,23 +80,6 @@ class DeviceStateManagerFoldingFeatureProducerTest { } @Test - @EnableFlags(Flags.FLAG_WLINFO_ONCREATE) - fun testRegisterCallback_whenWlinfoOncreateIsEnabled_usesRunnableRun() { - val executorCaptor = ArgumentCaptor.forClass(Executor::class.java) - val runnable = mock<Runnable>() - - DeviceStateManagerFoldingFeatureProducer( - mMockContext, - mRawFoldSupplier, - mMockDeviceStateManager, - ) - - verify(mMockDeviceStateManager).registerCallback(executorCaptor.capture(), any()) - executorCaptor.value.execute(runnable) - verify(runnable).run() - } - - @Test fun testGetCurrentData_validCurrentState_returnsFoldingFeatureWithState() { val ffp = DeviceStateManagerFoldingFeatureProducer( mMockContext, diff --git a/libs/WindowManager/Shell/Android.bp b/libs/WindowManager/Shell/Android.bp index a354bf78bb39..4c75ea4777da 100644 --- a/libs/WindowManager/Shell/Android.bp +++ b/libs/WindowManager/Shell/Android.bp @@ -182,6 +182,7 @@ android_library { "kotlinx-coroutines-core", "//frameworks/libs/systemui:com_android_systemui_shared_flags_lib", "//frameworks/libs/systemui:iconloader_base", + "com_android_launcher3_flags_lib", "com_android_wm_shell_flags_lib", "PlatformAnimationLib", "WindowManager-Shell-proto", diff --git a/libs/WindowManager/Shell/multivalentTests/src/com/android/wm/shell/bubbles/bar/BubbleBarExpandedViewTest.kt b/libs/WindowManager/Shell/multivalentTests/src/com/android/wm/shell/bubbles/bar/BubbleBarExpandedViewTest.kt index 6ac36a3319c9..1bf6af8d1f6d 100644 --- a/libs/WindowManager/Shell/multivalentTests/src/com/android/wm/shell/bubbles/bar/BubbleBarExpandedViewTest.kt +++ b/libs/WindowManager/Shell/multivalentTests/src/com/android/wm/shell/bubbles/bar/BubbleBarExpandedViewTest.kt @@ -17,6 +17,7 @@ package com.android.wm.shell.bubbles.bar import android.app.ActivityManager +import android.content.ComponentName import android.content.Context import android.content.pm.ShortcutInfo import android.graphics.Insets @@ -24,6 +25,7 @@ import android.graphics.Rect import android.view.LayoutInflater import android.view.View import android.view.WindowManager +import android.widget.FrameLayout import androidx.test.core.app.ApplicationProvider import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest @@ -110,9 +112,9 @@ class BubbleBarExpandedViewTest { regionSamplingProvider = TestRegionSamplingProvider() - bubbleExpandedView = (inflater.inflate( + bubbleExpandedView = inflater.inflate( R.layout.bubble_bar_expanded_view, null, false /* attachToRoot */ - ) as BubbleBarExpandedView) + ) as BubbleBarExpandedView bubbleExpandedView.initialize( expandedViewManager, positioner, @@ -124,11 +126,11 @@ class BubbleBarExpandedViewTest { regionSamplingProvider, ) - getInstrumentation().runOnMainSync(Runnable { + getInstrumentation().runOnMainSync { bubbleExpandedView.onAttachedToWindow() // Helper should be created once attached to window testableRegionSamplingHelper = regionSamplingProvider!!.helper - }) + } bubble = Bubble( "key", @@ -254,6 +256,93 @@ class BubbleBarExpandedViewTest { assertThat(uiEventLoggerFake.logs[0]).hasBubbleInfo(bubble) } + @Test + fun animateExpansion_waitsUntilTaskCreated() { + var animated = false + bubbleExpandedView.animateExpansionWhenTaskViewVisible { animated = true } + assertThat(animated).isFalse() + bubbleExpandedView.onTaskCreated() + assertThat(animated).isTrue() + } + + @Test + fun animateExpansion_taskViewAttachedAndVisible() { + val inflater = LayoutInflater.from(context) + val expandedView = inflater.inflate( + R.layout.bubble_bar_expanded_view, null, false /* attachToRoot */ + ) as BubbleBarExpandedView + val taskView = FakeBubbleTaskViewFactory().create() + val taskViewParent = FrameLayout(context) + taskViewParent.addView(taskView.taskView) + taskView.listener.onTaskCreated(666, ComponentName(context, "BubbleBarExpandedViewTest")) + assertThat(taskView.isVisible).isTrue() + + expandedView.initialize( + expandedViewManager, + positioner, + BubbleLogger(uiEventLoggerFake), + false /* isOverflow */, + taskView, + mainExecutor, + bgExecutor, + regionSamplingProvider, + ) + + // the task view should be removed from its parent + assertThat(taskView.taskView.parent).isNull() + + var animated = false + expandedView.animateExpansionWhenTaskViewVisible { animated = true } + assertThat(animated).isFalse() + + // send an invisible signal to simulate the surface getting destroyed + expandedView.onContentVisibilityChanged(false) + + // send a visible signal to simulate a new surface getting created + expandedView.onContentVisibilityChanged(true) + + assertThat(taskView.taskView.parent).isEqualTo(expandedView) + assertThat(animated).isTrue() + } + + @Test + fun animateExpansion_taskViewAttachedAndInvisible() { + val inflater = LayoutInflater.from(context) + val expandedView = inflater.inflate( + R.layout.bubble_bar_expanded_view, null, false /* attachToRoot */ + ) as BubbleBarExpandedView + val taskView = FakeBubbleTaskViewFactory().create() + val taskViewParent = FrameLayout(context) + taskViewParent.addView(taskView.taskView) + taskView.listener.onTaskCreated(666, ComponentName(context, "BubbleBarExpandedViewTest")) + assertThat(taskView.isVisible).isTrue() + taskView.listener.onTaskVisibilityChanged(666, false) + assertThat(taskView.isVisible).isFalse() + + expandedView.initialize( + expandedViewManager, + positioner, + BubbleLogger(uiEventLoggerFake), + false /* isOverflow */, + taskView, + mainExecutor, + bgExecutor, + regionSamplingProvider, + ) + + // the task view should be added to the expanded view + assertThat(taskView.taskView.parent).isEqualTo(expandedView) + + var animated = false + expandedView.animateExpansionWhenTaskViewVisible { animated = true } + assertThat(animated).isFalse() + + // send a visible signal to simulate a new surface getting created + expandedView.onContentVisibilityChanged(true) + + assertThat(animated).isTrue() + } + private fun BubbleBarExpandedView.menuView(): BubbleBarMenuView { return findViewByPredicate { it is BubbleBarMenuView } } diff --git a/libs/WindowManager/Shell/multivalentTests/src/com/android/wm/shell/bubbles/bar/BubbleBarLayerViewTest.kt b/libs/WindowManager/Shell/multivalentTests/src/com/android/wm/shell/bubbles/bar/BubbleBarLayerViewTest.kt index 22597ac6ab67..7280f8aa07a6 100644 --- a/libs/WindowManager/Shell/multivalentTests/src/com/android/wm/shell/bubbles/bar/BubbleBarLayerViewTest.kt +++ b/libs/WindowManager/Shell/multivalentTests/src/com/android/wm/shell/bubbles/bar/BubbleBarLayerViewTest.kt @@ -253,6 +253,7 @@ class BubbleBarLayerViewTest { getInstrumentation().runOnMainSync { bubbleBarLayerView.showExpandedView(bubble) + bubble.bubbleBarExpandedView!!.onContentVisibilityChanged(true) } waitForExpandedViewAnimation() @@ -276,6 +277,7 @@ class BubbleBarLayerViewTest { getInstrumentation().runOnMainSync { bubbleBarLayerView.showExpandedView(bubble) + bubble.bubbleBarExpandedView!!.onContentVisibilityChanged(true) } waitForExpandedViewAnimation() diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/back/CrossActivityBackAnimation.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/back/CrossActivityBackAnimation.kt index 37339307f5b0..7e5a82e640cc 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/back/CrossActivityBackAnimation.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/back/CrossActivityBackAnimation.kt @@ -39,6 +39,8 @@ import android.view.animation.DecelerateInterpolator import android.view.animation.Interpolator import android.view.animation.Transformation import android.window.BackEvent +import android.window.BackEvent.EDGE_LEFT +import android.window.BackEvent.EDGE_RIGHT import android.window.BackMotionEvent import android.window.BackNavigationInfo import android.window.BackProgressAnimator @@ -50,6 +52,7 @@ import com.android.internal.jank.Cuj import com.android.internal.policy.ScreenDecorationsUtils import com.android.internal.policy.SystemBarUtils import com.android.internal.protolog.ProtoLog +import com.android.window.flags.Flags.predictiveBackTimestampApi import com.android.wm.shell.R import com.android.wm.shell.RootTaskDisplayAreaOrganizer import com.android.wm.shell.protolog.ShellProtoLogGroup @@ -118,7 +121,9 @@ abstract class CrossActivityBackAnimation( private val postCommitFlingSpring = SpringForce(SPRING_SCALE) .setStiffness(SpringForce.STIFFNESS_LOW) .setDampingRatio(SpringForce.DAMPING_RATIO_LOW_BOUNCY) + private var swipeEdge = EDGE_LEFT protected var gestureProgress = 0f + private val velocityTracker = ProgressVelocityTracker() /** Background color to be used during the animation, also see [getBackgroundColor] */ protected var customizedBackgroundColor = 0 @@ -175,6 +180,7 @@ abstract class CrossActivityBackAnimation( ) return } + swipeEdge = backMotionEvent.swipeEdge triggerBack = backMotionEvent.triggerBack initialTouchPos.set(backMotionEvent.touchX, backMotionEvent.touchY) @@ -241,6 +247,9 @@ abstract class CrossActivityBackAnimation( ) applyTransaction() background.customizeStatusBarAppearance(currentClosingRect.top.toInt()) + if (predictiveBackTimestampApi()) { + velocityTracker.addPosition(backEvent.frameTimeMillis, progress) + } } private fun getYOffset(centeredRect: RectF, touchY: Float): Float { @@ -272,10 +281,19 @@ abstract class CrossActivityBackAnimation( // kick off spring animation with the current velocity from the pre-commit phase, this // affects the scaling of the closing and/or opening activity during post-commit - val startVelocity = - if (gestureProgress < 0.1f) -DEFAULT_FLING_VELOCITY else -velocity * SPRING_SCALE + + var startVelocity = if (predictiveBackTimestampApi()) { + // pronounce fling animation more for gestures + val velocityFactor = if (swipeEdge == EDGE_LEFT || swipeEdge == EDGE_RIGHT) 2f else 1f + velocity * SPRING_SCALE * (1f - MAX_SCALE) * velocityFactor + } else { + velocity * SPRING_SCALE + } + if (gestureProgress < 0.1f) { + startVelocity = startVelocity.coerceAtLeast(DEFAULT_FLING_VELOCITY) + } val flingAnimation = SpringAnimation(postCommitFlingScale, SPRING_SCALE) - .setStartVelocity(startVelocity.coerceIn(-MAX_FLING_VELOCITY, 0f)) + .setStartVelocity(-startVelocity.coerceIn(0f, MAX_FLING_VELOCITY)) .setStartValue(SPRING_SCALE) .setSpring(postCommitFlingSpring) flingAnimation.start() @@ -338,6 +356,7 @@ abstract class CrossActivityBackAnimation( lastPostCommitFlingScale = SPRING_SCALE gestureProgress = 0f triggerBack = false + velocityTracker.resetTracking() } protected fun applyTransform( @@ -520,7 +539,11 @@ abstract class CrossActivityBackAnimation( override fun onBackInvoked() { triggerBack = true progressAnimator.reset() - onGestureCommitted(progressAnimator.velocity) + if (predictiveBackTimestampApi()) { + onGestureCommitted(velocityTracker.calculateVelocity()) + } else { + onGestureCommitted(progressAnimator.velocity) + } } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/back/CrossTaskBackAnimation.java b/libs/WindowManager/Shell/src/com/android/wm/shell/back/CrossTaskBackAnimation.java index dc50fdbd1af3..f48b3ffcd598 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/back/CrossTaskBackAnimation.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/back/CrossTaskBackAnimation.java @@ -16,7 +16,6 @@ package com.android.wm.shell.back; -import static android.view.MotionEvent.ACTION_MOVE; import static android.view.RemoteAnimationTarget.MODE_CLOSING; import static android.view.RemoteAnimationTarget.MODE_OPENING; import static android.window.BackEvent.EDGE_RIGHT; @@ -43,10 +42,8 @@ import android.util.TimeUtils; import android.view.Choreographer; import android.view.IRemoteAnimationFinishedCallback; import android.view.IRemoteAnimationRunner; -import android.view.MotionEvent; import android.view.RemoteAnimationTarget; import android.view.SurfaceControl; -import android.view.VelocityTracker; import android.view.animation.DecelerateInterpolator; import android.view.animation.Interpolator; import android.window.BackEvent; @@ -132,9 +129,8 @@ public class CrossTaskBackAnimation extends ShellBackAnimation { private final SpringForce mPostCommitFlingSpring = new SpringForce(SPRING_SCALE) .setStiffness(FLING_SPRING_STIFFNESS) .setDampingRatio(1f); - private final VelocityTracker mVelocityTracker = VelocityTracker.obtain(); + private final ProgressVelocityTracker mVelocityTracker = new ProgressVelocityTracker(); private float mGestureProgress = 0f; - private long mDownTime = 0L; @Inject public CrossTaskBackAnimation(Context context, BackAnimationBackground background, @@ -316,8 +312,7 @@ public class CrossTaskBackAnimation extends ShellBackAnimation { mClosingCurrentRect.setEmpty(); mInitialTouchPos.set(0, 0); mGestureProgress = 0; - mDownTime = 0; - mVelocityTracker.clear(); + mVelocityTracker.resetTracking(); if (mFinishCallback != null) { try { @@ -333,22 +328,13 @@ public class CrossTaskBackAnimation extends ShellBackAnimation { private void onGestureProgress(@NonNull BackEvent backEvent) { if (!mBackInProgress) { mBackInProgress = true; - mDownTime = backEvent.getFrameTimeMillis(); } float progress = backEvent.getProgress(); mTouchPos.set(backEvent.getTouchX(), backEvent.getTouchY()); float interpolatedProgress = getInterpolatedProgress(progress); if (predictiveBackTimestampApi()) { - mVelocityTracker.addMovement( - MotionEvent.obtain( - /* downTime */ mDownTime, - /* eventTime */ backEvent.getFrameTimeMillis(), - /* action */ ACTION_MOVE, - /* x */ interpolatedProgress * SPRING_SCALE, - /* y */ 0f, - /* metaState */ 0 - ) - ); + mVelocityTracker.addPosition(backEvent.getFrameTimeMillis(), + interpolatedProgress * SPRING_SCALE); } updateGestureBackProgress(interpolatedProgress, backEvent); } @@ -362,9 +348,8 @@ public class CrossTaskBackAnimation extends ShellBackAnimation { if (predictiveBackTimestampApi()) { // kick off spring animation with the current velocity from the pre-commit phase, this // affects the scaling of the closing and/or opening task during post-commit - mVelocityTracker.computeCurrentVelocity(1000); float startVelocity = mGestureProgress < 0.1f - ? -DEFAULT_FLING_VELOCITY : -mVelocityTracker.getXVelocity(); + ? -DEFAULT_FLING_VELOCITY : -mVelocityTracker.calculateVelocity(); SpringAnimation flingAnimation = new SpringAnimation(mPostCommitFlingScale, SPRING_SCALE) .setStartVelocity(Math.max(-MAX_FLING_VELOCITY, Math.min(0f, startVelocity))) diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/back/ProgressVelocityTracker.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/back/ProgressVelocityTracker.kt new file mode 100644 index 000000000000..6bbda0fd7b19 --- /dev/null +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/back/ProgressVelocityTracker.kt @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.wm.shell.back + +import android.view.MotionEvent +import android.view.VelocityTracker + +internal class ProgressVelocityTracker { + private val velocityTracker: VelocityTracker = VelocityTracker.obtain() + private var downTime = -1L + + fun addPosition(timeMillis: Long, position: Float) { + if (downTime == -1L) downTime = timeMillis + velocityTracker.addMovement( + MotionEvent.obtain( + /* downTime */ downTime, + /* eventTime */ timeMillis, + /* action */ MotionEvent.ACTION_MOVE, + /* x */ position, + /* y */ 0f, + /* metaState */0 + ) + ) + } + + /** calculates current velocity (unit: progress per second) */ + fun calculateVelocity(): Float { + velocityTracker.computeCurrentVelocity(1000) + return velocityTracker.xVelocity + } + + fun resetTracking() { + velocityTracker.clear() + downTime = -1L + } +}
\ No newline at end of file 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 294569190f68..dc2025bb2dce 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 @@ -898,7 +898,10 @@ public class BubbleData { Bubble oldest = mOverflowBubbles.get(mOverflowBubbles.size() - 1); ProtoLog.d(WM_SHELL_BUBBLES, "overflow full, remove=%s", oldest.getKey()); mStateChange.bubbleRemoved(oldest, Bubbles.DISMISS_OVERFLOW_MAX_REACHED); - mLogger.log(bubble, BubbleLogger.Event.BUBBLE_OVERFLOW_REMOVE_MAX_REACHED); + if (!mPositioner.isShowingInBubbleBar()) { + // Only logged for bubbles in stack view + mLogger.log(bubble, BubbleLogger.Event.BUBBLE_OVERFLOW_REMOVE_MAX_REACHED); + } mOverflowBubbles.remove(oldest); mStateChange.removedOverflowBubble = oldest; } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleTaskView.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleTaskView.kt index 68fc0c99abee..a517a2d550b9 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleTaskView.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleTaskView.kt @@ -42,6 +42,16 @@ class BubbleTaskView(val taskView: TaskView, executor: Executor) { var componentName: ComponentName? = null private set + /** + * Whether the task view is visible and has a surface. Note that this does not check the alpha + * value of the task view. + * + * When this is `true` it is safe to start showing the task view. Otherwise if this is `false` + * callers should wait for it to be visible which will be indicated either by a call to + * [TaskView.Listener.onTaskCreated] or [TaskView.Listener.onTaskVisibilityChanged]. */ + var isVisible = false + private set + /** [TaskView.Listener] for users of this class. */ var delegateListener: TaskView.Listener? = null @@ -61,9 +71,12 @@ class BubbleTaskView(val taskView: TaskView, executor: Executor) { this@BubbleTaskView.taskId = taskId isCreated = true componentName = name + // when the task is created it is visible + isVisible = true } override fun onTaskVisibilityChanged(taskId: Int, visible: Boolean) { + this@BubbleTaskView.isVisible = visible delegateListener?.onTaskVisibilityChanged(taskId, visible) } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarAnimationHelper.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarAnimationHelper.java index 74c3748dccaf..a313bd004a51 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarAnimationHelper.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarAnimationHelper.java @@ -161,6 +161,7 @@ public class BubbleBarAnimationHelper { updateExpandedView(); bbev.setAnimating(true); + bbev.setSurfaceZOrderedOnTop(true); bbev.setContentVisibility(false); bbev.setAlpha(0f); bbev.setTaskViewAlpha(0f); @@ -171,28 +172,29 @@ public class BubbleBarAnimationHelper { bbev.setAnimationMatrix(mExpandedViewContainerMatrix); - mExpandedViewAlphaAnimator.start(); - - PhysicsAnimator.getInstance(mExpandedViewContainerMatrix).cancel(); - PhysicsAnimator.getInstance(mExpandedViewContainerMatrix) - .spring(AnimatableScaleMatrix.SCALE_X, - AnimatableScaleMatrix.getAnimatableValueForScaleFactor(1f), - mScaleInSpringConfig) - .spring(AnimatableScaleMatrix.SCALE_Y, - AnimatableScaleMatrix.getAnimatableValueForScaleFactor(1f), - mScaleInSpringConfig) - .addUpdateListener((target, values) -> { - bbev.setAnimationMatrix(mExpandedViewContainerMatrix); - }) - .withEndActions(() -> { - bbev.setAnimationMatrix(null); - updateExpandedView(); - bbev.setSurfaceZOrderedOnTop(false); - if (afterAnimation != null) { - afterAnimation.run(); - } - }) - .start(); + bbev.animateExpansionWhenTaskViewVisible(() -> { + mExpandedViewAlphaAnimator.start(); + + PhysicsAnimator.getInstance(mExpandedViewContainerMatrix).cancel(); + PhysicsAnimator.getInstance(mExpandedViewContainerMatrix) + .spring(AnimatableScaleMatrix.SCALE_X, + AnimatableScaleMatrix.getAnimatableValueForScaleFactor(1f), + mScaleInSpringConfig) + .spring(AnimatableScaleMatrix.SCALE_Y, + AnimatableScaleMatrix.getAnimatableValueForScaleFactor(1f), + mScaleInSpringConfig) + .addUpdateListener((target, values) -> { + bbev.setAnimationMatrix(mExpandedViewContainerMatrix); + }) + .withEndActions(() -> { + bbev.setAnimationMatrix(null); + updateExpandedView(); + if (afterAnimation != null) { + afterAnimation.run(); + } + }) + .start(); + }); } /** diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarExpandedView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarExpandedView.java index 3764bcd42ac6..ed49417ad3bd 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarExpandedView.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarExpandedView.java @@ -131,6 +131,11 @@ public class BubbleBarExpandedView extends FrameLayout implements BubbleTaskView /** Current corner radius */ private float mCurrentCornerRadius = 0f; + /** A runnable to start the expansion animation as soon as the task view is made visible. */ + @Nullable + private Runnable mAnimateExpansion = null; + private TaskViewVisibilityState mVisibilityState = TaskViewVisibilityState.INVISIBLE; + /** * Whether we want the {@code TaskView}'s content to be visible (alpha = 1f). If * {@link #mIsAnimating} is true, this may not reflect the {@code TaskView}'s actual alpha @@ -140,6 +145,18 @@ public class BubbleBarExpandedView extends FrameLayout implements BubbleTaskView private boolean mIsAnimating; private boolean mIsDragging; + /** An enum value that tracks the visibility state of the task view */ + private enum TaskViewVisibilityState { + /** The task view is going away, and we're waiting for the surface to be destroyed. */ + PENDING_INVISIBLE, + /** The task view is invisible and does not have a surface. */ + INVISIBLE, + /** The task view is in the process of being added to a surface. */ + PENDING_VISIBLE, + /** The task view is visible and has a surface. */ + VISIBLE + } + public BubbleBarExpandedView(Context context) { this(context, null); } @@ -206,16 +223,27 @@ public class BubbleBarExpandedView extends FrameLayout implements BubbleTaskView mBubbleTaskViewHelper = new BubbleTaskViewHelper(mContext, expandedViewManager, /* listener= */ this, bubbleTaskView, /* viewParent= */ this); + + // if the task view is already attached to a parent we need to remove it if (mTaskView.getParent() != null) { + // it's possible that the task view is visible, e.g. if we're unfolding, in which + // case removing it will trigger a visibility change. we have to wait for that + // signal before we can add it to this expanded view, otherwise the signal will be + // incorrect because the task view will have a surface. + // if the task view is not visible, then it has no surface and removing it will not + // trigger any visibility change signals. + if (bubbleTaskView.isVisible()) { + mVisibilityState = TaskViewVisibilityState.PENDING_INVISIBLE; + } ((ViewGroup) mTaskView.getParent()).removeView(mTaskView); } - FrameLayout.LayoutParams lp = - new FrameLayout.LayoutParams(MATCH_PARENT, MATCH_PARENT); - addView(mTaskView, lp); - mTaskView.setEnableSurfaceClipping(true); - mTaskView.setCornerRadius(mCurrentCornerRadius); - mTaskView.setVisibility(VISIBLE); - mTaskView.setCaptionInsets(Insets.of(0, mCaptionHeight, 0, 0)); + + // if we're invisible it's safe to setup the task view and then await on the visibility + // signal. + if (mVisibilityState == TaskViewVisibilityState.INVISIBLE) { + mVisibilityState = TaskViewVisibilityState.PENDING_VISIBLE; + setupTaskView(); + } // Handle view needs to draw on top of task view. bringChildToFront(mHandleView); @@ -269,6 +297,16 @@ public class BubbleBarExpandedView extends FrameLayout implements BubbleTaskView }); } + private void setupTaskView() { + FrameLayout.LayoutParams lp = + new FrameLayout.LayoutParams(MATCH_PARENT, MATCH_PARENT); + addView(mTaskView, lp); + mTaskView.setEnableSurfaceClipping(true); + mTaskView.setCornerRadius(mCurrentCornerRadius); + mTaskView.setVisibility(VISIBLE); + mTaskView.setCaptionInsets(Insets.of(0, mCaptionHeight, 0, 0)); + } + public BubbleBarHandleView getHandleView() { return mHandleView; } @@ -326,15 +364,28 @@ public class BubbleBarExpandedView extends FrameLayout implements BubbleTaskView @Override public void onTaskCreated() { - setContentVisibility(true); + if (mTaskView != null) { + mTaskView.setAlpha(0); + } if (mListener != null) { mListener.onTaskCreated(); } + // when the task is created we're visible + onTaskViewVisible(); } @Override public void onContentVisibilityChanged(boolean visible) { - setContentVisibility(visible); + if (mVisibilityState == TaskViewVisibilityState.PENDING_INVISIBLE && !visible) { + // the surface is now destroyed. set up the task view and wait for the visibility + // signal. + mVisibilityState = TaskViewVisibilityState.PENDING_VISIBLE; + setupTaskView(); + return; + } + if (visible) { + onTaskViewVisible(); + } } @Override @@ -350,6 +401,25 @@ public class BubbleBarExpandedView extends FrameLayout implements BubbleTaskView mListener.onBackPressed(); } + void animateExpansionWhenTaskViewVisible(Runnable animateExpansion) { + if (mVisibilityState == TaskViewVisibilityState.VISIBLE || mIsOverflow) { + animateExpansion.run(); + } else { + mAnimateExpansion = animateExpansion; + } + } + + private void onTaskViewVisible() { + // if we're waiting to be visible, start the expansion animation if it's pending. + if (mVisibilityState == TaskViewVisibilityState.PENDING_VISIBLE) { + mVisibilityState = TaskViewVisibilityState.VISIBLE; + if (mAnimateExpansion != null) { + mAnimateExpansion.run(); + mAnimateExpansion = null; + } + } + } + /** * Set whether this view is currently being dragged. * diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/TaskStackListenerCallback.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/TaskStackListenerCallback.java index 9abf0f678179..de5c834f3120 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/TaskStackListenerCallback.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/TaskStackListenerCallback.java @@ -33,6 +33,9 @@ public interface TaskStackListenerCallback { default void onRecentTaskListFrozenChanged(boolean frozen) { } + /** A task is removed from recents as a result of another task being added to recent tasks. */ + default void onRecentTaskRemovedForAddTask(int taskId) { } + @BinderThread default void onTaskStackChangedBackground() { } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/TaskStackListenerImpl.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/TaskStackListenerImpl.java index d8859bac471f..4e1dec60d956 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/TaskStackListenerImpl.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/TaskStackListenerImpl.java @@ -59,6 +59,7 @@ public class TaskStackListenerImpl extends TaskStackListener implements Handler. private static final int ON_TASK_LIST_FROZEN_UNFROZEN = 18; private static final int ON_TASK_DESCRIPTION_CHANGED = 19; private static final int ON_ACTIVITY_ROTATION = 20; + private static final int ON_RECENT_TASK_REMOVED_FOR_ADD_TASK = 21; /** * List of {@link TaskStackListenerCallback} registered from {@link #addListener}. @@ -132,6 +133,11 @@ public class TaskStackListenerImpl extends TaskStackListener implements Handler. } @Override + public void onRecentTaskRemovedForAddTask(int taskId) { + mMainHandler.obtainMessage(ON_RECENT_TASK_REMOVED_FOR_ADD_TASK, taskId).sendToTarget(); + } + + @Override public void onTaskStackChanged() { // Call the task changed callback for the non-ui thread listeners first. Copy to a set // of temp listeners so that we don't lock on mTaskStackListeners while calling all the @@ -408,6 +414,13 @@ public class TaskStackListenerImpl extends TaskStackListener implements Handler. } break; } + case ON_RECENT_TASK_REMOVED_FOR_ADD_TASK: { + final int taskId = (int) msg.obj; + for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) { + mTaskStackListeners.get(i).onRecentTaskRemovedForAddTask(taskId); + } + break; + } case ON_TASK_DESCRIPTION_CHANGED: { final ActivityManager.RunningTaskInfo info = (ActivityManager.RunningTaskInfo) msg.obj; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java index fbf68ff97f08..0f636588476a 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java @@ -29,6 +29,7 @@ import android.annotation.Nullable; import android.app.KeyguardManager; import android.content.Context; import android.content.pm.LauncherApps; +import android.content.pm.PackageManager; import android.hardware.input.InputManager; import android.os.Handler; import android.os.UserManager; @@ -702,6 +703,7 @@ public abstract class WMShellModule { InputManager inputManager, FocusTransitionObserver focusTransitionObserver, DesktopModeEventLogger desktopModeEventLogger, + DesktopModeUiEventLogger desktopModeUiEventLogger, DesktopTilingDecorViewModel desktopTilingDecorViewModel) { return new DesktopTasksController( context, @@ -732,6 +734,7 @@ public abstract class WMShellModule { interactionJankMonitor, mainHandler, desktopModeEventLogger, + desktopModeUiEventLogger, desktopTilingDecorViewModel); } @@ -893,7 +896,8 @@ public abstract class WMShellModule { WindowDecorCaptionHandleRepository windowDecorCaptionHandleRepository, Optional<DesktopActivityOrientationChangeHandler> activityOrientationChangeHandler, FocusTransitionObserver focusTransitionObserver, - DesktopModeEventLogger desktopModeEventLogger + DesktopModeEventLogger desktopModeEventLogger, + DesktopModeUiEventLogger desktopModeUiEventLogger ) { if (!DesktopModeStatus.canEnterDesktopModeOrShowAppHandle(context)) { return Optional.empty(); @@ -906,7 +910,7 @@ public abstract class WMShellModule { assistContentRequester, multiInstanceHelper, desktopTasksLimiter, appHandleEducationController, appToWebEducationController, windowDecorCaptionHandleRepository, activityOrientationChangeHandler, - focusTransitionObserver, desktopModeEventLogger)); + focusTransitionObserver, desktopModeEventLogger, desktopModeUiEventLogger)); } @WMSingleton @@ -1234,9 +1238,10 @@ public abstract class WMShellModule { @WMSingleton @Provides static DesktopModeUiEventLogger provideDesktopUiEventLogger( - UiEventLogger uiEventLogger + UiEventLogger uiEventLogger, + PackageManager packageManager ) { - return new DesktopModeUiEventLogger(uiEventLogger); + return new DesktopModeUiEventLogger(uiEventLogger, packageManager); } // diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeEventLogger.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeEventLogger.kt index b4eac7a7b2d3..dc23128b7b2a 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeEventLogger.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeEventLogger.kt @@ -446,6 +446,7 @@ class DesktopModeEventLogger { val displayArea: Int?, ) + @JvmStatic fun getInputMethodFromMotionEvent(e: MotionEvent?): InputMethod { if (e == null) return InputMethod.UNKNOWN_INPUT_METHOD diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeKeyGestureHandler.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeKeyGestureHandler.kt index 114563aa18bb..6cb23b81f1e4 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeKeyGestureHandler.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeKeyGestureHandler.kt @@ -94,7 +94,7 @@ class DesktopModeKeyGestureHandler( desktopTasksController.get().toggleDesktopTaskSize( it, ResizeTrigger.MAXIMIZE_MENU, - null, + DesktopModeEventLogger.Companion.InputMethod.KEYBOARD, ) } return true diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeUiEventLogger.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeUiEventLogger.kt index dff56c13e03a..d0e01625a3aa 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeUiEventLogger.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeUiEventLogger.kt @@ -16,6 +16,8 @@ package com.android.wm.shell.desktopmode +import android.app.ActivityManager.RunningTaskInfo +import android.content.pm.PackageManager import com.android.internal.logging.InstanceId import com.android.internal.logging.InstanceIdSequence import com.android.internal.logging.UiEvent @@ -27,6 +29,7 @@ import com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE /** Log Aster UIEvents for desktop windowing mode. */ class DesktopModeUiEventLogger( private val uiEventLogger: UiEventLogger, + private val packageManager: PackageManager, ) { private val instanceIdSequence = InstanceIdSequence(Integer.MAX_VALUE) @@ -45,6 +48,17 @@ class DesktopModeUiEventLogger( uiEventLogger.log(event, uid, packageName) } + /** Logs an event for a CUI on a particular task. */ + fun log(taskInfo: RunningTaskInfo, event: DesktopUiEventEnum) { + val packageName = taskInfo.baseActivity?.packageName + if (packageName == null) { + logD("Skip logging due to null base activity") + return + } + val uid = getUid(packageName, taskInfo.userId) + log(uid, packageName, event) + } + /** Retrieves a new instance id for a new interaction. */ fun getNewInstanceId(): InstanceId = instanceIdSequence.newInstanceId() @@ -70,6 +84,12 @@ class DesktopModeUiEventLogger( uiEventLogger.logWithInstanceId(event, uid, packageName, instanceId) } + private fun getUid(packageName: String, userId: Int): Int = try { + packageManager.getApplicationInfoAsUser(packageName, /* flags= */ 0, userId).uid + } catch (e: PackageManager.NameNotFoundException) { + INVALID_PACKAGE_UID + } + private fun logD(msg: String, vararg arguments: Any?) { ProtoLog.d(WM_SHELL_DESKTOP_MODE, "%s: $msg", TAG, *arguments) } @@ -84,12 +104,33 @@ class DesktopModeUiEventLogger( @UiEvent(doc = "Tap on the window header maximize button in desktop windowing mode") DESKTOP_WINDOW_MAXIMIZE_BUTTON_TAP(1723), @UiEvent(doc = "Double tap on window header to maximize it in desktop windowing mode") - DESKTOP_WINDOW_HEADER_DOUBLE_TAP_TO_MAXIMIZE(1724); + DESKTOP_WINDOW_HEADER_DOUBLE_TAP_TO_MAXIMIZE(1724), + @UiEvent(doc = "Tap on the window Handle to open the Handle Menu") + DESKTOP_WINDOW_APP_HANDLE_TAP(1998), + @UiEvent(doc = "Tap on the desktop mode option under app handle menu") + DESKTOP_WINDOW_APP_HANDLE_MENU_TAP_TO_DESKTOP_MODE(1999), + @UiEvent(doc = "Tap on the split screen option under app handle menu") + DESKTOP_WINDOW_APP_HANDLE_MENU_TAP_TO_SPLIT_SCREEN(2000), + @UiEvent(doc = "Tap on the full screen option under app handle menu") + DESKTOP_WINDOW_APP_HANDLE_MENU_TAP_TO_FULL_SCREEN(2001), + @UiEvent(doc = "When user successfully drags the app handle to desktop mode") + DESKTOP_WINDOW_APP_HANDLE_DRAG_TO_DESKTOP_MODE(2002), + @UiEvent(doc = "When user successfully drags the app handle to split screen") + DESKTOP_WINDOW_APP_HANDLE_DRAG_TO_SPLIT_SCREEN(2003), + @UiEvent(doc = "When user successfully drags the app handle to full screen") + DESKTOP_WINDOW_APP_HANDLE_DRAG_TO_FULL_SCREEN(2004), + @UiEvent(doc = "Drag the window header to the top to switch to full screen mode") + DESKTOP_WINDOW_APP_HEADER_DRAG_TO_FULL_SCREEN(2005), + @UiEvent(doc = "Drag the window header to an edge to tile it to the left side") + DESKTOP_WINDOW_APP_HEADER_DRAG_TO_TILE_TO_LEFT(2006), + @UiEvent(doc = "Drag the window header to an edge to tile it to the right side") + DESKTOP_WINDOW_APP_HEADER_DRAG_TO_TILE_TO_RIGHT(2007); override fun getId(): Int = mId } companion object { private const val TAG = "DesktopModeUiEventLogger" + private const val INVALID_PACKAGE_UID = -1 } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt index ccbc9204ad9d..3e3dd74ae4b4 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt @@ -130,6 +130,7 @@ import java.util.concurrent.Executor import java.util.function.Consumer import com.android.wm.shell.desktopmode.DesktopModeEventLogger.Companion.InputMethod import com.android.wm.shell.desktopmode.DesktopModeEventLogger.Companion.ResizeTrigger +import com.android.wm.shell.desktopmode.DesktopModeUiEventLogger.DesktopUiEventEnum import com.android.wm.shell.desktopmode.DragToDesktopTransitionHandler.Companion.DRAG_TO_DESKTOP_FINISH_ANIM_DURATION_MS import com.android.wm.shell.desktopmode.EnterDesktopTaskTransitionHandler.FREEFORM_ANIMATION_DURATION import com.android.wm.shell.desktopmode.ExitDesktopTaskTransitionHandler.FULLSCREEN_ANIMATION_DURATION @@ -166,6 +167,7 @@ class DesktopTasksController( private val interactionJankMonitor: InteractionJankMonitor, @ShellMainThread private val handler: Handler, private val desktopModeEventLogger: DesktopModeEventLogger, + private val desktopModeUiEventLogger: DesktopModeUiEventLogger, private val desktopTilingDecorViewModel: DesktopTilingDecorViewModel, ) : RemoteCallable<DesktopTasksController>, @@ -819,12 +821,12 @@ class DesktopTasksController( fun toggleDesktopTaskSize( taskInfo: RunningTaskInfo, resizeTrigger: ResizeTrigger, - motionEvent: MotionEvent?, + inputMethod: InputMethod, ) { val currentTaskBounds = taskInfo.configuration.windowConfiguration.bounds desktopModeEventLogger.logTaskResizingStarted( resizeTrigger, - DesktopModeEventLogger.getInputMethodFromMotionEvent(motionEvent), + inputMethod, taskInfo, currentTaskBounds.width(), currentTaskBounds.height(), @@ -877,7 +879,7 @@ class DesktopTasksController( taskbarDesktopTaskListener?.onTaskbarCornerRoundingUpdate(doesAnyTaskRequireTaskbarRounding) val wct = WindowContainerTransaction().setBounds(taskInfo.token, destinationBounds) desktopModeEventLogger.logTaskResizingEnded( - resizeTrigger, DesktopModeEventLogger.getInputMethodFromMotionEvent(motionEvent), + resizeTrigger, inputMethod, taskInfo, destinationBounds.width(), destinationBounds.height(), displayController ) @@ -909,7 +911,11 @@ class DesktopTasksController( return } - toggleDesktopTaskSize(taskInfo, ResizeTrigger.DRAG_TO_TOP_RESIZE_TRIGGER, motionEvent) + toggleDesktopTaskSize( + taskInfo, + ResizeTrigger.DRAG_TO_TOP_RESIZE_TRIGGER, + DesktopModeEventLogger.getInputMethodFromMotionEvent(motionEvent) + ) } private fun getMaximizeBounds(taskInfo: RunningTaskInfo, stableBounds: Rect): Rect { @@ -2083,6 +2089,10 @@ class DesktopTasksController( if (DesktopModeStatus.shouldMaximizeWhenDragToTopEdge(context)) { dragToMaximizeDesktopTask(taskInfo, taskSurface, currentDragBounds, motionEvent) } else { + desktopModeUiEventLogger.log( + taskInfo, + DesktopUiEventEnum.DESKTOP_WINDOW_APP_HEADER_DRAG_TO_FULL_SCREEN + ) moveToFullscreenWithAnimation( taskInfo, position, @@ -2091,6 +2101,10 @@ class DesktopTasksController( } } IndicatorType.TO_SPLIT_LEFT_INDICATOR -> { + desktopModeUiEventLogger.log( + taskInfo, + DesktopUiEventEnum.DESKTOP_WINDOW_APP_HEADER_DRAG_TO_TILE_TO_LEFT + ) handleSnapResizingTaskOnDrag( taskInfo, SnapPosition.LEFT, @@ -2102,6 +2116,10 @@ class DesktopTasksController( ) } IndicatorType.TO_SPLIT_RIGHT_INDICATOR -> { + desktopModeUiEventLogger.log( + taskInfo, + DesktopUiEventEnum.DESKTOP_WINDOW_APP_HEADER_DRAG_TO_TILE_TO_RIGHT + ) handleSnapResizingTaskOnDrag( taskInfo, SnapPosition.RIGHT, @@ -2188,16 +2206,32 @@ class DesktopTasksController( // Start a new jank interaction for the drag release to desktop window animation. interactionJankMonitor.begin(taskSurface, context, handler, CUJ_DESKTOP_MODE_ENTER_APP_HANDLE_DRAG_RELEASE, "to_desktop") + desktopModeUiEventLogger.log( + taskInfo, + DesktopUiEventEnum.DESKTOP_WINDOW_APP_HANDLE_DRAG_TO_DESKTOP_MODE + ) finalizeDragToDesktop(taskInfo) } IndicatorType.NO_INDICATOR, IndicatorType.TO_FULLSCREEN_INDICATOR -> { + desktopModeUiEventLogger.log( + taskInfo, + DesktopUiEventEnum.DESKTOP_WINDOW_APP_HANDLE_DRAG_TO_FULL_SCREEN + ) cancelDragToDesktop(taskInfo) } IndicatorType.TO_SPLIT_LEFT_INDICATOR -> { + desktopModeUiEventLogger.log( + taskInfo, + DesktopUiEventEnum.DESKTOP_WINDOW_APP_HANDLE_DRAG_TO_SPLIT_SCREEN + ) requestSplit(taskInfo, leftOrTop = true) } IndicatorType.TO_SPLIT_RIGHT_INDICATOR -> { + desktopModeUiEventLogger.log( + taskInfo, + DesktopUiEventEnum.DESKTOP_WINDOW_APP_HANDLE_DRAG_TO_SPLIT_SCREEN + ) requestSplit(taskInfo, leftOrTop = false) } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopWallpaperActivity.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopWallpaperActivity.kt index e835b2fec232..909a06604382 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopWallpaperActivity.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopWallpaperActivity.kt @@ -17,12 +17,10 @@ package com.android.wm.shell.desktopmode import android.app.Activity -import android.app.ActivityManager +import android.app.TaskInfo import android.content.ComponentName import android.os.Bundle import android.view.WindowManager -import com.android.internal.protolog.ProtoLog -import com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE /** * A transparent activity used in the desktop mode to show the wallpaper under the freeform windows. @@ -42,11 +40,12 @@ class DesktopWallpaperActivity : Activity() { companion object { private const val SYSTEM_UI_PACKAGE_NAME = "com.android.systemui" - private val wallpaperActivityComponent = + @JvmStatic + val wallpaperActivityComponent = ComponentName(SYSTEM_UI_PACKAGE_NAME, DesktopWallpaperActivity::class.java.name) @JvmStatic - fun isWallpaperTask(taskInfo: ActivityManager.RunningTaskInfo) = + fun isWallpaperTask(taskInfo: TaskInfo) = taskInfo.baseIntent.component?.let(::isWallpaperComponent) ?: false @JvmStatic diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/education/AppHandleEducationController.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/education/AppHandleEducationController.kt index e01c448be8e5..de9c79ab34fd 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/education/AppHandleEducationController.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/education/AppHandleEducationController.kt @@ -82,9 +82,9 @@ class AppHandleEducationController( runIfEducationFeatureEnabled { applicationCoroutineScope.launch { // Central block handling the app handle's educational flow end-to-end. - isEducationViewedFlow() - .flatMapLatest { isEducationViewed -> - if (isEducationViewed) { + isAppHandleHintViewedFlow() + .flatMapLatest { isAppHandleHintViewed -> + if (isAppHandleHintViewed) { // If the education is viewed then return emptyFlow() that completes immediately. // This will help us to not listen to [captionHandleStateFlow] after the education // has been viewed already. @@ -106,12 +106,12 @@ class AppHandleEducationController( showEducation(captionState, tooltipColorScheme) // After showing first tooltip, mark education as viewed - appHandleEducationDatastoreRepository.updateEducationViewedTimestampMillis(true) + appHandleEducationDatastoreRepository.updateAppHandleHintViewedTimestampMillis(true) } } applicationCoroutineScope.launch { - if (isFeatureUsed()) return@launch + if (isAppHandleHintUsed()) return@launch windowDecorCaptionHandleRepository.captionStateFlow .filter { captionState -> captionState is CaptionState.AppHandle && captionState.isHandleMenuExpanded @@ -119,8 +119,8 @@ class AppHandleEducationController( .take(1) .flowOn(backgroundDispatcher) .collect { - // If user expands app handle, mark user has used the feature - appHandleEducationDatastoreRepository.updateFeatureUsedTimestampMillis(true) + // If user expands app handle, mark user has used the app handle hint + appHandleEducationDatastoreRepository.updateAppHandleHintUsedTimestampMillis(true) } } } @@ -323,25 +323,25 @@ class AppHandleEducationController( } /** - * Listens to the changes to [WindowingEducationProto#hasEducationViewedTimestampMillis()] in + * Listens to the changes to [WindowingEducationProto#hasAppHandleHintViewedTimestampMillis()] in * datastore proto object. * * If [SHOULD_OVERRIDE_EDUCATION_CONDITIONS] is true, this flow will always emit false. That means - * it will emit education has not been viewed yet always. + * it will always emit app handle hint has not been viewed yet. */ - private fun isEducationViewedFlow(): Flow<Boolean> = + private fun isAppHandleHintViewedFlow(): Flow<Boolean> = appHandleEducationDatastoreRepository.dataStoreFlow .map { preferences -> - preferences.hasEducationViewedTimestampMillis() && !SHOULD_OVERRIDE_EDUCATION_CONDITIONS + preferences.hasAppHandleHintViewedTimestampMillis() && !SHOULD_OVERRIDE_EDUCATION_CONDITIONS } .distinctUntilChanged() /** - * Listens to the changes to [WindowingEducationProto#hasFeatureUsedTimestampMillis()] in + * Listens to the changes to [WindowingEducationProto#hasAppHandleHintUsedTimestampMillis()] in * datastore proto object. */ - private suspend fun isFeatureUsed(): Boolean = - appHandleEducationDatastoreRepository.dataStoreFlow.first().hasFeatureUsedTimestampMillis() + private suspend fun isAppHandleHintUsed(): Boolean = + appHandleEducationDatastoreRepository.dataStoreFlow.first().hasAppHandleHintUsedTimestampMillis() private fun getSize(@DimenRes resourceId: Int): Int { if (resourceId == Resources.ID_NULL) return 0 diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/education/AppHandleEducationFilter.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/education/AppHandleEducationFilter.kt index 144370d76060..7a7829334fb6 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/education/AppHandleEducationFilter.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/education/AppHandleEducationFilter.kt @@ -54,8 +54,8 @@ class AppHandleEducationFilter( return isFocusAppInAllowlist(focusAppPackageName) && !isOtherEducationShowing() && hasSufficientTimeSinceSetup() && - !isEducationViewedBefore(windowingEducationProto) && - !isFeatureUsedBefore(windowingEducationProto) && + !isAppHandleHintViewedBefore(windowingEducationProto) && + !isAppHandleHintUsedBefore(windowingEducationProto) && hasMinAppUsage(windowingEducationProto, focusAppPackageName) } @@ -76,11 +76,11 @@ class AppHandleEducationFilter( convertIntegerResourceToDuration( R.integer.desktop_windowing_education_required_time_since_setup_seconds) - private fun isEducationViewedBefore(windowingEducationProto: WindowingEducationProto): Boolean = - windowingEducationProto.hasEducationViewedTimestampMillis() + private fun isAppHandleHintViewedBefore(windowingEducationProto: WindowingEducationProto): Boolean = + windowingEducationProto.hasAppHandleHintViewedTimestampMillis() - private fun isFeatureUsedBefore(windowingEducationProto: WindowingEducationProto): Boolean = - windowingEducationProto.hasFeatureUsedTimestampMillis() + private fun isAppHandleHintUsedBefore(windowingEducationProto: WindowingEducationProto): Boolean = + windowingEducationProto.hasAppHandleHintUsedTimestampMillis() private suspend fun hasMinAppUsage( windowingEducationProto: WindowingEducationProto, diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/education/data/AppHandleEducationDatastoreRepository.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/education/data/AppHandleEducationDatastoreRepository.kt index d21b208df482..5e0c0007e2eb 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/education/data/AppHandleEducationDatastoreRepository.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/education/data/AppHandleEducationDatastoreRepository.kt @@ -71,32 +71,34 @@ constructor(private val dataStore: DataStore<WindowingEducationProto>) { suspend fun windowingEducationProto(): WindowingEducationProto = dataStoreFlow.first() /** - * Updates [WindowingEducationProto.educationViewedTimestampMillis_] field in datastore with - * current timestamp if [isViewed] is true, if not then clears the field. + * Updates [WindowingEducationProto.appHandleHintViewedTimestampMillis_] field + * in datastore with current timestamp if [isViewed] is true, if not then + * clears the field. */ - suspend fun updateEducationViewedTimestampMillis(isViewed: Boolean) { + suspend fun updateAppHandleHintViewedTimestampMillis(isViewed: Boolean) { dataStore.updateData { preferences -> if (isViewed) { preferences .toBuilder() - .setEducationViewedTimestampMillis(System.currentTimeMillis()) + .setAppHandleHintViewedTimestampMillis(System.currentTimeMillis()) .build() } else { - preferences.toBuilder().clearEducationViewedTimestampMillis().build() + preferences.toBuilder().clearAppHandleHintViewedTimestampMillis().build() } } } /** - * Updates [WindowingEducationProto.featureUsedTimestampMillis_] field in datastore with current - * timestamp if [isViewed] is true, if not then clears the field. + * Updates [WindowingEducationProto.appHandleHintUsedTimestampMillis_] field + * in datastore with current timestamp if [isViewed] is true, if not then + * clears the field. */ - suspend fun updateFeatureUsedTimestampMillis(isViewed: Boolean) { + suspend fun updateAppHandleHintUsedTimestampMillis(isViewed: Boolean) { dataStore.updateData { preferences -> if (isViewed) { - preferences.toBuilder().setFeatureUsedTimestampMillis(System.currentTimeMillis()).build() + preferences.toBuilder().setAppHandleHintUsedTimestampMillis(System.currentTimeMillis()).build() } else { - preferences.toBuilder().clearFeatureUsedTimestampMillis().build() + preferences.toBuilder().clearAppHandleHintUsedTimestampMillis().build() } } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/education/data/proto/windowing_education.proto b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/education/data/proto/windowing_education.proto index 4cddd01ee96b..0c4d562b8d55 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/education/data/proto/windowing_education.proto +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/education/data/proto/windowing_education.proto @@ -22,9 +22,19 @@ option java_multiple_files = true; // Desktop Windowing education data message WindowingEducationProto { // Timestamp in milliseconds of when the education was last viewed. - optional int64 education_viewed_timestamp_millis = 1; + optional int64 education_viewed_timestamp_millis = 1 [deprecated=true]; // Timestamp in milliseconds of when the feature was last used. - optional int64 feature_used_timestamp_millis = 2; + optional int64 feature_used_timestamp_millis = 2 [deprecated=true]; + + // Timestamp in milliseconds of when the app handle hint was last viewed. + optional int64 app_handle_hint_viewed_timestamp_millis = 5; + // Timestamp in milliseconds of when the app handle hint was last used. + optional int64 app_handle_hint_used_timestamp_millis = 6; + // Timestamp in milliseconds of when the enter desktop mode hint was last viewed. + optional int64 enter_desktop_mode_hint_viewed_timestamp_millis = 7; + // Timestamp in milliseconds of when the exit desktop mode hint was last viewed. + optional int64 exit_desktop_mode_hint_viewed_timestamp_millis = 8; + oneof education_data { // Fields specific to app handle education AppHandleEducation app_handle_education = 3; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java index f7aed4401247..72c1ef06806a 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java @@ -73,6 +73,7 @@ import com.android.wm.shell.common.pip.PipBoundsState; import com.android.wm.shell.common.pip.PipDisplayLayoutState; import com.android.wm.shell.common.pip.PipMenuController; import com.android.wm.shell.common.pip.PipUtils; +import com.android.wm.shell.common.split.SplitScreenUtils; import com.android.wm.shell.protolog.ShellProtoLogGroup; import com.android.wm.shell.shared.TransitionUtil; import com.android.wm.shell.shared.pip.PipContentOverlay; @@ -1346,6 +1347,13 @@ public class PipTransition extends PipTransitionController { return true; } + @Override + public boolean isPackageActiveInPip(@Nullable String packageName) { + final TaskInfo inPipTask = mPipOrganizer.getTaskInfo(); + return packageName != null && inPipTask != null && mPipOrganizer.isInPip() + && packageName.equals(SplitScreenUtils.getPackageName(inPipTask.baseIntent)); + } + private void updatePipForUnhandledTransition(@NonNull TransitionInfo.Change pipChange, @NonNull SurfaceControl.Transaction startTransaction, @NonNull SurfaceControl.Transaction finishTransaction) { diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransitionController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransitionController.java index 79a9ce5212c6..a273822759f6 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransitionController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransitionController.java @@ -312,9 +312,8 @@ public abstract class PipTransitionController implements Transitions.TransitionH /** Whether a particular package is same as current pip package. */ public boolean isPackageActiveInPip(@Nullable String packageName) { - return packageName != null - && mPipBoundsState.getLastPipComponentName() != null - && packageName.equals(mPipBoundsState.getLastPipComponentName().getPackageName()); + // No-op, to be handled differently in PIP1 and PIP2 + return false; } /** Add PiP-related changes to `outWCT` for the given request. */ diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTransition.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTransition.java index 2bcbe3013397..8ee087b33609 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTransition.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTransition.java @@ -371,7 +371,9 @@ public class PipTransition extends PipTransitionController implements // Update the src-rect-hint in params in place, to set up initial animator transform. Rect sourceRectHint = getAdjustedSourceRectHint(info, pipChange, pipActivityChange); - pipChange.getTaskInfo().pictureInPictureParams.getSourceRectHint().set(sourceRectHint); + final PictureInPictureParams params = getPipParams(pipChange); + params.copyOnlySet( + new PictureInPictureParams.Builder().setSourceRectHint(sourceRectHint).build()); // Config-at-end transitions need to have their activities transformed before starting // the animation; this makes the buffer seem like it's been updated to final size. @@ -416,9 +418,7 @@ public class PipTransition extends PipTransitionController implements final SurfaceControl pipLeash = getLeash(pipChange); final Rect startBounds = pipChange.getStartAbsBounds(); final Rect endBounds = pipChange.getEndAbsBounds(); - final PictureInPictureParams params = pipChange.getTaskInfo().pictureInPictureParams != null - ? pipChange.getTaskInfo().pictureInPictureParams - : new PictureInPictureParams.Builder().build(); + final PictureInPictureParams params = getPipParams(pipChange); final Rect adjustedSourceRectHint = getAdjustedSourceRectHint(info, pipChange, pipActivityChange); @@ -598,10 +598,10 @@ public class PipTransition extends PipTransitionController implements PictureInPictureParams params = null; if (pipChange.getTaskInfo() != null) { // single activity - params = pipChange.getTaskInfo().pictureInPictureParams; + params = getPipParams(pipChange); } else if (parentBeforePip != null && parentBeforePip.getTaskInfo() != null) { // multi activity - params = parentBeforePip.getTaskInfo().pictureInPictureParams; + params = getPipParams(parentBeforePip); } final Rect sourceRectHint = PipBoundsAlgorithm.getValidSourceHintRect(params, endBounds, startBounds); @@ -842,19 +842,25 @@ public class PipTransition extends PipTransitionController implements initActivityPos.y); } } + void cacheAndStartTransitionAnimator(@NonNull ValueAnimator animator) { + mTransitionAnimator = animator; + mTransitionAnimator.start(); + } + + @NonNull + private static PictureInPictureParams getPipParams(@NonNull TransitionInfo.Change pipChange) { + return pipChange.getTaskInfo().pictureInPictureParams != null + ? pipChange.getTaskInfo().pictureInPictureParams + : new PictureInPictureParams.Builder().build(); + } @NonNull - private SurfaceControl getLeash(TransitionInfo.Change change) { + private static SurfaceControl getLeash(TransitionInfo.Change change) { SurfaceControl leash = change.getLeash(); Preconditions.checkNotNull(leash, "Leash is null for change=" + change); return leash; } - void cacheAndStartTransitionAnimator(@NonNull ValueAnimator animator) { - mTransitionAnimator = animator; - mTransitionAnimator.start(); - } - // // Miscellaneous callbacks and listeners // @@ -904,9 +910,21 @@ public class PipTransition extends PipTransitionController implements "Unexpected bundle for " + mPipTransitionState); break; case PipTransitionState.EXITED_PIP: + // Save the PiP bounds in case, we re-enter the PiP with the same component. + float snapFraction = mPipBoundsAlgorithm.getSnapFraction( + mPipBoundsState.getBounds()); + mPipBoundsState.saveReentryState(snapFraction); + mPipTransitionState.setPipTaskToken(null); mPipTransitionState.setPinnedTaskLeash(null); break; } } + + @Override + public boolean isPackageActiveInPip(@Nullable String packageName) { + return packageName != null + && mPipBoundsState.getLastPipComponentName() != null + && packageName.equals(mPipBoundsState.getLastPipComponentName().getPackageName()); + } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentTasksController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentTasksController.java index d917f937b16c..363c95fcf010 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentTasksController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentTasksController.java @@ -19,8 +19,10 @@ package com.android.wm.shell.recents; import static android.app.ActivityTaskManager.INVALID_TASK_ID; import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; import static android.content.pm.PackageManager.FEATURE_PC; +import static android.view.Display.INVALID_DISPLAY; import static com.android.wm.shell.Flags.enableShellTopTaskTracking; +import static com.android.wm.shell.desktopmode.DesktopWallpaperActivity.isWallpaperTask; import static com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_TASK_OBSERVER; import static com.android.wm.shell.shared.ShellSharedConstants.KEY_EXTRA_SHELL_RECENT_TASKS; @@ -53,6 +55,7 @@ import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; import com.android.internal.protolog.ProtoLog; +import com.android.launcher3.Flags; import com.android.wm.shell.common.ExternalInterfaceBinder; import com.android.wm.shell.common.RemoteCallable; import com.android.wm.shell.common.ShellExecutor; @@ -282,6 +285,17 @@ public class RecentTasksController implements TaskStackListenerCallback, notifyRecentTasksChanged(); } + /** + * This method only gets notified when a task is removed from recents as a result of another + * task being added to recent tasks. + */ + @Override + public void onRecentTaskRemovedForAddTask(int taskId) { + mDesktopRepository.ifPresent( + repo -> repo.removeFreeformTask(INVALID_DISPLAY, taskId) + ); + } + public void onTaskAdded(RunningTaskInfo taskInfo) { notifyRunningTaskAppeared(taskInfo); } @@ -530,6 +544,10 @@ public class RecentTasksController implements TaskStackListenerCallback, groupedTasks.add(GroupedTaskInfo.forSplitTasks(taskInfo, pairedTaskInfo, mTaskSplitBoundsMap.get(pairedTaskId))); } else { + if (Flags.enableRefactorTaskThumbnail() && isWallpaperTask(taskInfo)) { + // Don't add the wallpaper task as an entry in grouped tasks + continue; + } // TODO(346588978): Consolidate multiple visible fullscreen tasks into the same // grouped task groupedTasks.add(GroupedTaskInfo.forFullscreenTasks(taskInfo)); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java index 43ed23b3b52a..f48226930871 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java @@ -108,6 +108,8 @@ import com.android.wm.shell.common.SyncTransactionQueue; import com.android.wm.shell.compatui.CompatUIController; import com.android.wm.shell.desktopmode.DesktopActivityOrientationChangeHandler; import com.android.wm.shell.desktopmode.DesktopModeEventLogger; +import com.android.wm.shell.desktopmode.DesktopModeUiEventLogger; +import com.android.wm.shell.desktopmode.DesktopModeUiEventLogger.DesktopUiEventEnum; import com.android.wm.shell.desktopmode.DesktopModeVisualIndicator; import com.android.wm.shell.desktopmode.DesktopRepository; import com.android.wm.shell.desktopmode.DesktopTasksController; @@ -228,6 +230,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel, private final TaskPositionerFactory mTaskPositionerFactory; private final FocusTransitionObserver mFocusTransitionObserver; private final DesktopModeEventLogger mDesktopModeEventLogger; + private final DesktopModeUiEventLogger mDesktopModeUiEventLogger; public DesktopModeWindowDecorViewModel( Context context, @@ -257,7 +260,8 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel, WindowDecorCaptionHandleRepository windowDecorCaptionHandleRepository, Optional<DesktopActivityOrientationChangeHandler> activityOrientationChangeHandler, FocusTransitionObserver focusTransitionObserver, - DesktopModeEventLogger desktopModeEventLogger) { + DesktopModeEventLogger desktopModeEventLogger, + DesktopModeUiEventLogger desktopModeUiEventLogger) { this( context, shellExecutor, @@ -292,7 +296,8 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel, activityOrientationChangeHandler, new TaskPositionerFactory(), focusTransitionObserver, - desktopModeEventLogger); + desktopModeEventLogger, + desktopModeUiEventLogger); } @VisibleForTesting @@ -330,7 +335,8 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel, Optional<DesktopActivityOrientationChangeHandler> activityOrientationChangeHandler, TaskPositionerFactory taskPositionerFactory, FocusTransitionObserver focusTransitionObserver, - DesktopModeEventLogger desktopModeEventLogger) { + DesktopModeEventLogger desktopModeEventLogger, + DesktopModeUiEventLogger desktopModeUiEventLogger) { mContext = context; mMainExecutor = shellExecutor; mMainHandler = mainHandler; @@ -393,6 +399,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel, mTaskPositionerFactory = taskPositionerFactory; mFocusTransitionObserver = focusTransitionObserver; mDesktopModeEventLogger = desktopModeEventLogger; + mDesktopModeUiEventLogger = desktopModeUiEventLogger; shellInit.addInitCallback(this::onInit, this); } @@ -577,7 +584,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel, decoration.mTaskSurface, mContext, mMainHandler, Cuj.CUJ_DESKTOP_MODE_MAXIMIZE_WINDOW, source); mDesktopTasksController.toggleDesktopTaskSize(decoration.mTaskInfo, resizeTrigger, - motionEvent); + DesktopModeEventLogger.getInputMethodFromMotionEvent(motionEvent)); decoration.closeHandleMenu(); decoration.closeMaximizeMenu(); } @@ -637,6 +644,11 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel, decoration.addCaptionInset(wct); mDesktopTasksController.moveTaskToDesktop(taskId, wct, source); decoration.closeHandleMenu(); + + if (source == DesktopModeTransitionSource.APP_HANDLE_MENU_BUTTON) { + mDesktopModeUiEventLogger.log(decoration.mTaskInfo, + DesktopUiEventEnum.DESKTOP_WINDOW_APP_HANDLE_MENU_TAP_TO_DESKTOP_MODE); + } } private void onToFullscreen(int taskId) { @@ -652,6 +664,8 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel, mDesktopTasksController.moveToFullscreen(taskId, DesktopModeTransitionSource.APP_HANDLE_MENU_BUTTON); } + mDesktopModeUiEventLogger.log(decoration.mTaskInfo, + DesktopUiEventEnum.DESKTOP_WINDOW_APP_HANDLE_MENU_TAP_TO_FULL_SCREEN); } private void onToSplitScreen(int taskId) { @@ -664,6 +678,8 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel, // we shouldn't receive input for it any longer. decoration.disposeStatusBarInputLayer(); mDesktopTasksController.requestSplit(decoration.mTaskInfo, false /* leftOrTop */); + mDesktopModeUiEventLogger.log(decoration.mTaskInfo, + DesktopUiEventEnum.DESKTOP_WINDOW_APP_HANDLE_MENU_TAP_TO_SPLIT_SCREEN); } private void onNewWindow(int taskId) { @@ -803,6 +819,11 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel, } else if (id == R.id.back_button) { mTaskOperations.injectBackKey(mDisplayId); } else if (id == R.id.caption_handle || id == R.id.open_menu_button) { + if (id == R.id.caption_handle && !decoration.mTaskInfo.isFreeform()) { + // Clicking the App Handle. + mDesktopModeUiEventLogger.log(decoration.mTaskInfo, + DesktopUiEventEnum.DESKTOP_WINDOW_APP_HANDLE_TAP); + } if (!decoration.isHandleMenuActive()) { moveTaskToFront(decoration.mTaskInfo); openHandleMenu(mTaskId); @@ -1554,8 +1575,6 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel, final DesktopModeTouchEventListener touchEventListener = new DesktopModeTouchEventListener(taskInfo, taskPositioner); - InputMethod inputMethod = DesktopModeEventLogger.Companion.getInputMethodFromMotionEvent( - touchEventListener.mMotionEvent); windowDecoration.setOnMaximizeOrRestoreClickListener(() -> { onMaximizeOrRestore(taskInfo.taskId, "maximize_menu", ResizeTrigger.MAXIMIZE_MENU, touchEventListener.mMotionEvent); @@ -1566,11 +1585,15 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel, return Unit.INSTANCE; }); windowDecoration.setOnLeftSnapClickListener(() -> { - onSnapResize(taskInfo.taskId, /* isLeft= */ true, inputMethod); + onSnapResize(taskInfo.taskId, /* isLeft= */ true, + DesktopModeEventLogger.getInputMethodFromMotionEvent( + touchEventListener.mMotionEvent)); return Unit.INSTANCE; }); windowDecoration.setOnRightSnapClickListener(() -> { - onSnapResize(taskInfo.taskId, /* isLeft= */ false, inputMethod); + onSnapResize(taskInfo.taskId, /* isLeft= */ false, + DesktopModeEventLogger.getInputMethodFromMotionEvent( + touchEventListener.mMotionEvent)); return Unit.INSTANCE; }); windowDecoration.setOnToDesktopClickListener(desktopModeTransitionSource -> { diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java index b6fa059e891d..d57044a4d27c 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java @@ -1417,7 +1417,6 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin mHandleMenu.show( /* onToDesktopClickListener= */ () -> { mOnToDesktopClickListener.accept(APP_HANDLE_MENU_BUTTON); - mOnToDesktopClickListener.accept(APP_HANDLE_MENU_BUTTON); return Unit.INSTANCE; }, /* onToFullscreenClickListener= */ mOnToFullscreenClickListener, diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragResizeInputListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragResizeInputListener.java index b3213996b868..a6d503d0d991 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragResizeInputListener.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragResizeInputListener.java @@ -460,7 +460,7 @@ class DragResizeInputListener implements AutoCloseable { || ctrlType == CTRL_TYPE_RIGHT || ctrlType == CTRL_TYPE_LEFT) ? ResizeTrigger.EDGE : ResizeTrigger.CORNER; mDesktopModeEventLogger.logTaskResizingStarted(mResizeTrigger, - DesktopModeEventLogger.Companion.getInputMethodFromMotionEvent(e), + DesktopModeEventLogger.getInputMethodFromMotionEvent(e), mTaskInfo, mDragStartTaskBounds.width(), mDragStartTaskBounds.height(), /* displayController= */ null, /* displayLayoutSize= */ mDisplayLayoutSizeSupplier.get()); @@ -514,7 +514,7 @@ class DragResizeInputListener implements AutoCloseable { } mDesktopModeEventLogger.logTaskResizingEnded(mResizeTrigger, - DesktopModeEventLogger.Companion.getInputMethodFromMotionEvent( + DesktopModeEventLogger.getInputMethodFromMotionEvent( mLastMotionEventOnDown), mTaskInfo, taskBounds.width(), taskBounds.height(), /* displayController= */ null, diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragResizeWindowGeometry.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragResizeWindowGeometry.java index 6f72d34eb0ae..c8aff78cbb36 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragResizeWindowGeometry.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragResizeWindowGeometry.java @@ -74,8 +74,7 @@ public final class DragResizeWindowGeometry { mFineTaskCorners = new TaskCorners(mTaskSize, fineCornerSize, disabledEdge); // Save touch areas for each edge. - mTaskEdges = new TaskEdges(mTaskSize, mResizeHandleEdgeOutset, mResizeHandleEdgeInset, - mDisabledEdge); + mTaskEdges = new TaskEdges(mTaskSize, mResizeHandleEdgeOutset, mDisabledEdge); } /** @@ -459,7 +458,7 @@ public final class DragResizeWindowGeometry { private final @NonNull DisabledEdge mDisabledEdge; private TaskEdges(@NonNull Size taskSize, int resizeHandleThickness, - int resizeHandleEdgeInset, DisabledEdge disabledEdge) { + DisabledEdge disabledEdge) { // Save touch areas for each edge. mDisabledEdge = disabledEdge; // Save touch areas for each edge. @@ -471,16 +470,16 @@ public final class DragResizeWindowGeometry { mLeftEdgeBounds = new Rect( -resizeHandleThickness, 0, - resizeHandleEdgeInset, + resizeHandleThickness, taskSize.getHeight()); mRightEdgeBounds = new Rect( - taskSize.getWidth() - resizeHandleEdgeInset, + taskSize.getWidth() - resizeHandleThickness, 0, taskSize.getWidth() + resizeHandleThickness, taskSize.getHeight()); mBottomEdgeBounds = new Rect( -resizeHandleThickness, - taskSize.getHeight() - resizeHandleEdgeInset, + taskSize.getHeight() - resizeHandleThickness, taskSize.getWidth() + resizeHandleThickness, taskSize.getHeight() + resizeHandleThickness); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/tiling/DesktopTilingDividerWindowManager.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/tiling/DesktopTilingDividerWindowManager.kt index 6cdc517c9cb7..583282247f58 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/tiling/DesktopTilingDividerWindowManager.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/tiling/DesktopTilingDividerWindowManager.kt @@ -18,10 +18,12 @@ package com.android.wm.shell.windowdecor.tiling import android.content.Context import android.content.res.Configuration +import android.graphics.Path import android.graphics.PixelFormat import android.graphics.Rect import android.graphics.Region import android.os.Binder +import android.util.Size import android.view.LayoutInflater import android.view.MotionEvent import android.view.RoundedCorner @@ -40,7 +42,6 @@ import android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER import android.view.WindowlessWindowManager import com.android.wm.shell.R import com.android.wm.shell.common.SyncTransactionQueue -import com.android.wm.shell.desktopmode.DesktopModeEventLogger import java.util.function.Supplier /** @@ -48,7 +49,7 @@ import java.util.function.Supplier * when two tasks are tiled on left and right to resize them simultaneously. */ class DesktopTilingDividerWindowManager( - private val config: Configuration, + config: Configuration, private val windowName: String, private val context: Context, private val leash: SurfaceControl, @@ -61,7 +62,11 @@ class DesktopTilingDividerWindowManager( private lateinit var viewHost: SurfaceControlViewHost private var tilingDividerView: TilingDividerView? = null private var dividerShown = false - private var handleRegionWidth: Int = -1 + private var handleRegionSize: Size = + Size( + context.resources.getDimensionPixelSize(R.dimen.split_divider_handle_region_width), + context.resources.getDimensionPixelSize(R.dimen.split_divider_handle_region_height), + ) private var setTouchRegion = true private val maxRoundedCornerRadius = getMaxRoundedCornerRadius() @@ -74,9 +79,62 @@ class DesktopTilingDividerWindowManager( rect.set(dividerBounds) } - /** Sets the touch region for the SurfaceControlViewHost. */ - fun setTouchRegion(region: Rect) { - setTouchRegion(viewHost.windowToken.asBinder(), Region(region)) + /** + * Sets the touch region for the SurfaceControlViewHost. + * + * The region includes the area around the handle (for accessibility), the divider itself and + * the rounded corners (to prevent click reaching windows behind). + */ + fun setTouchRegion(handle: Rect, divider: Rect, cornerRadius: Float) { + val path = Path() + path.fillType = Path.FillType.WINDING + // The UI starts on the top-left corner, the region will be: + // + // cornerLeft cornerRight + // c1Top +--------+ + // |corners | + // c1Bottom +--+ +--+ + // | | + // handleLeft| | handleRight + // handleTop +----+ +----+ + // | handle | + // handleBot +----+ +----+ + // | | + // | | + // c2Top +--+ +--+ + // |corners | + // c2Bottom +--------+ + val cornerLeft = 0f + val centerX = cornerRadius + divider.width() / 2f + val centerY = divider.height() + val cornerRight = divider.width() + 2 * cornerRadius + val handleLeft = centerX - handle.width() / 2f + val handleRight = handleLeft + handle.width() + val dividerLeft = centerY - divider.width() / 2f + val dividerRight = dividerLeft + divider.width() + + val c1Top = 0f + val c1Bottom = cornerRadius + val handleTop = centerY - handle.height() / 2f + val handleBottom = handleTop + handle.height() + val c2Top = divider.height() - cornerRadius + val c2Bottom = divider.height().toFloat() + + // Top corners + path.addRect(cornerLeft, c1Top, cornerRight, c1Bottom, Path.Direction.CCW) + // Bottom corners + path.addRect(cornerLeft, c1Top, cornerRight, c2Bottom, Path.Direction.CCW) + // Handle + path.addRect(handleLeft, handleTop, handleRight, handleBottom, Path.Direction.CCW) + // Divider + path.addRect(dividerLeft, c2Top, dividerRight, c2Bottom, Path.Direction.CCW) + + val clip = Rect(handleLeft.toInt(), c1Top.toInt(), handleRight.toInt(), c2Bottom.toInt()) + + val region = Region() + region.setPath(path, Region(clip)) + + setTouchRegion(viewHost.windowToken.asBinder(), region) } /** @@ -96,7 +154,7 @@ class DesktopTilingDividerWindowManager( surfaceControlViewHost.setView(dividerView, lp) val tmpDividerBounds = Rect() getDividerBounds(tmpDividerBounds) - dividerView.setup(this, tmpDividerBounds) + dividerView.setup(this, tmpDividerBounds, handleRegionSize) t.setRelativeLayer(leash, relativeLeash, 1) .setPosition( leash, @@ -112,7 +170,7 @@ class DesktopTilingDividerWindowManager( viewHost = surfaceControlViewHost dividerView.addOnLayoutChangeListener(this) tilingDividerView = dividerView - handleRegionWidth = dividerView.handleRegionWidth + updateTouchRegion() } /** Hides the divider bar. */ @@ -176,8 +234,8 @@ class DesktopTilingDividerWindowManager( private fun getWindowManagerParams(): WindowManager.LayoutParams { val lp = WindowManager.LayoutParams( - dividerBounds.width() + 2 * maxRoundedCornerRadius, - dividerBounds.height(), + /* w= */ dividerBounds.width() + 2 * maxRoundedCornerRadius, + /* h= */ dividerBounds.height(), TYPE_DOCK_DIVIDER, FLAG_NOT_FOCUSABLE or FLAG_NOT_TOUCH_MODAL or @@ -216,13 +274,16 @@ class DesktopTilingDividerWindowManager( ) { if (!setTouchRegion) return - val startX = (dividerBounds.width() - handleRegionWidth) / 2 - val startY = 0 - val tempRect = Rect(startX, startY, startX + handleRegionWidth, dividerBounds.height()) - setTouchRegion(tempRect) + updateTouchRegion() setTouchRegion = false } + private fun updateTouchRegion() { + val startX = -handleRegionSize.width / 2 + val handle = Rect(startX, 0, startX + handleRegionSize.width, dividerBounds.height()) + setTouchRegion(handle, dividerBounds, maxRoundedCornerRadius.toFloat()) + } + private fun setSlippery(slippery: Boolean) { val lp = tilingDividerView?.layoutParams as WindowManager.LayoutParams val isSlippery = (lp.flags and FLAG_SLIPPERY) != 0 diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/tiling/DesktopTilingWindowDecoration.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/tiling/DesktopTilingWindowDecoration.kt index bc7576c91da2..3b5c6ca2e58a 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/tiling/DesktopTilingWindowDecoration.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/tiling/DesktopTilingWindowDecoration.kt @@ -492,9 +492,8 @@ class DesktopTilingWindowDecoration( // Only called if [taskInfo] relates to a focused task private fun isTilingRefocused(taskInfo: RunningTaskInfo): Boolean { - return !isTilingFocused && - (taskInfo.taskId == leftTaskResizingHelper?.taskInfo?.taskId || - taskInfo.taskId == rightTaskResizingHelper?.taskInfo?.taskId) + return taskInfo.taskId == leftTaskResizingHelper?.taskInfo?.taskId || + taskInfo.taskId == rightTaskResizingHelper?.taskInfo?.taskId } private fun buildTiledTasksMoveToFront(leftOnTop: Boolean): WindowContainerTransaction { diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/tiling/TilingDividerView.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/tiling/TilingDividerView.kt index 111e28e450bd..b8e3b0fdb8d8 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/tiling/TilingDividerView.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/tiling/TilingDividerView.kt @@ -21,8 +21,10 @@ import android.graphics.Paint import android.graphics.Rect import android.provider.DeviceConfig import android.util.AttributeSet +import android.util.Size import android.view.MotionEvent import android.view.PointerIcon +import android.view.RoundedCorner import android.view.View import android.view.ViewConfiguration import android.widget.FrameLayout @@ -42,6 +44,7 @@ class TilingDividerView : FrameLayout, View.OnTouchListener, DragDetector.Motion private lateinit var callback: DividerMoveCallback private lateinit var handle: DividerHandleView private lateinit var corners: DividerRoundedCorner + private var cornersRadius: Int = 0 private var touchElevation = 0 private var moving = false @@ -49,8 +52,7 @@ class TilingDividerView : FrameLayout, View.OnTouchListener, DragDetector.Motion var handleRegionWidth: Int = 0 private var handleRegionHeight = 0 private var lastAcceptedPos = 0 - @VisibleForTesting var handleStartY = 0 - @VisibleForTesting var handleEndY = 0 + @VisibleForTesting var handleY: IntRange = 0..0 private var canResize = false private var resized = false /** @@ -79,16 +81,19 @@ class TilingDividerView : FrameLayout, View.OnTouchListener, DragDetector.Motion ) : super(context, attrs, defStyleAttr, defStyleRes) /** Sets up essential dependencies of the divider bar. */ - fun setup(dividerMoveCallback: DividerMoveCallback, dividerBounds: Rect) { + fun setup( + dividerMoveCallback: DividerMoveCallback, + dividerBounds: Rect, + handleRegionSize: Size, + ) { callback = dividerMoveCallback this.dividerBounds.set(dividerBounds) handle.setIsLeftRightSplit(true) corners.setIsLeftRightSplit(true) - handleRegionHeight = - resources.getDimensionPixelSize(R.dimen.split_divider_handle_region_width) - - handleRegionWidth = - resources.getDimensionPixelSize(R.dimen.split_divider_handle_region_height) + handleRegionHeight = handleRegionSize.height + handleRegionWidth = handleRegionSize.width + cornersRadius = + context.display.getRoundedCorner(RoundedCorner.POSITION_TOP_LEFT)?.radius ?: 0 initHandleYCoordinates() dragDetector = DragDetector( @@ -241,17 +246,17 @@ class TilingDividerView : FrameLayout, View.OnTouchListener, DragDetector.Motion return true } - private fun isWithinHandleRegion(touchYPos: Int): Boolean { - return touchYPos in handleStartY..handleEndY - } + private fun isWithinHandleRegion(touchYPos: Int): Boolean = touchYPos in handleY private fun initHandleYCoordinates() { - handleStartY = (dividerBounds.height() - handleRegionHeight) / 2 - handleEndY = handleStartY + handleRegionHeight + val handleStartY = (dividerBounds.height() - handleRegionHeight) / 2 + val handleEndY = handleStartY + handleRegionHeight + handleY = handleStartY..handleEndY } companion object { const val TOUCH_ANIMATION_DURATION: Long = 150 const val TOUCH_RELEASE_ANIMATION_DURATION: Long = 200 + private val TAG = TilingDividerView::class.java.simpleName } } diff --git a/libs/WindowManager/Shell/tests/e2e/desktopmode/flicker-service/src/com/android/wm/shell/flicker/DesktopModeFlickerScenarios.kt b/libs/WindowManager/Shell/tests/e2e/desktopmode/flicker-service/src/com/android/wm/shell/flicker/DesktopModeFlickerScenarios.kt index 0cc8b0c7ba8d..d9c36cc70790 100644 --- a/libs/WindowManager/Shell/tests/e2e/desktopmode/flicker-service/src/com/android/wm/shell/flicker/DesktopModeFlickerScenarios.kt +++ b/libs/WindowManager/Shell/tests/e2e/desktopmode/flicker-service/src/com/android/wm/shell/flicker/DesktopModeFlickerScenarios.kt @@ -25,6 +25,7 @@ import android.tools.flicker.assertors.assertions.AppLayerIsVisibleAlways import android.tools.flicker.assertors.assertions.AppLayerIsVisibleAtStart import android.tools.flicker.assertors.assertions.AppWindowAlignsWithOnlyOneDisplayCornerAtEnd import android.tools.flicker.assertors.assertions.AppWindowBecomesInvisible +import android.tools.flicker.assertors.assertions.AppWindowBecomesPinned import android.tools.flicker.assertors.assertions.AppWindowBecomesTopWindow import android.tools.flicker.assertors.assertions.AppWindowBecomesVisible import android.tools.flicker.assertors.assertions.AppWindowCoversLeftHalfScreenAtEnd @@ -465,5 +466,25 @@ class DesktopModeFlickerScenarios { AppWindowIsVisibleAlways(SIMPLE_APP) ).associateBy({ it }, { AssertionInvocationGroup.BLOCKING }), ) + + val MINIMIZE_AUTO_PIP_APP = + FlickerConfigEntry( + scenarioId = ScenarioId("MINIMIZE_AUTO_PIP_APP"), + extractor = + ShellTransitionScenarioExtractor( + transitionMatcher = + object : ITransitionMatcher { + override fun findAll( + transitions: Collection<Transition> + ): Collection<Transition> = + transitions.filter { it.type == TransitionType.PIP } + } + ), + assertions = + AssertionTemplates.COMMON_ASSERTIONS + + listOf( + AppWindowBecomesPinned(DESKTOP_MODE_APP), + ).associateBy({ it }, { AssertionInvocationGroup.BLOCKING }) + ) } } diff --git a/libs/WindowManager/Shell/tests/e2e/desktopmode/flicker-service/src/com/android/wm/shell/flicker/MinimizeAutoPipAppWindow.kt b/libs/WindowManager/Shell/tests/e2e/desktopmode/flicker-service/src/com/android/wm/shell/flicker/MinimizeAutoPipAppWindow.kt new file mode 100644 index 000000000000..b10db689e5bd --- /dev/null +++ b/libs/WindowManager/Shell/tests/e2e/desktopmode/flicker-service/src/com/android/wm/shell/flicker/MinimizeAutoPipAppWindow.kt @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.wm.shell.flicker + +import android.tools.flicker.FlickerConfig +import android.tools.flicker.annotation.ExpectedScenarios +import android.tools.flicker.annotation.FlickerConfigProvider +import android.tools.flicker.config.FlickerConfig +import android.tools.flicker.config.FlickerServiceConfig +import android.tools.flicker.junit.FlickerServiceJUnit4ClassRunner +import com.android.wm.shell.flicker.DesktopModeFlickerScenarios.Companion.MINIMIZE_AUTO_PIP_APP +import com.android.wm.shell.scenarios.MinimizeAutoPipAppWindow +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(FlickerServiceJUnit4ClassRunner::class) +class MinimizeAutoPipAppWindow : MinimizeAutoPipAppWindow() { + @ExpectedScenarios(["MINIMIZE_AUTO_PIP_APP"]) + @Test + override fun minimizePipAppWindow() = super.minimizePipAppWindow() + + companion object { + @JvmStatic + @FlickerConfigProvider + fun flickerConfigProvider(): FlickerConfig = + FlickerConfig().use(FlickerServiceConfig.DEFAULT).use(MINIMIZE_AUTO_PIP_APP) + } +} diff --git a/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/DragAppWindowMultiWindowAndPip.kt b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/DragAppWindowMultiWindowAndPip.kt index c43a57594fb3..bb812ad51135 100644 --- a/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/DragAppWindowMultiWindowAndPip.kt +++ b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/DragAppWindowMultiWindowAndPip.kt @@ -45,9 +45,9 @@ open class DragAppWindowMultiWindowAndPip : DragAppWindowScenarioTestBase() @Before fun setup() { Assume.assumeTrue(Flags.enableDesktopWindowingMode() && tapl.isTablet) + testApp.enterDesktopMode(wmHelper, device) // Set string extra to ensure the app is on PiP mode at launch pipApp.launchViaIntentAndWaitForPip(wmHelper, stringExtras = mapOf("enter_pip" to "true")) - testApp.enterDesktopMode(wmHelper, device) mailApp.launchViaIntent(wmHelper) newTasksApp.launchViaIntent(wmHelper) imeApp.launchViaIntent(wmHelper) diff --git a/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/ResizeAppCornerMultiWindowAndPip.kt b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/ResizeAppCornerMultiWindowAndPip.kt index 0226eb35de14..41452c3bdd9f 100644 --- a/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/ResizeAppCornerMultiWindowAndPip.kt +++ b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/ResizeAppCornerMultiWindowAndPip.kt @@ -63,9 +63,9 @@ constructor(val rotation: Rotation = Rotation.ROTATION_0, Assume.assumeTrue(Flags.enableDesktopWindowingMode() && tapl.isTablet) tapl.setEnableRotation(true) tapl.setExpectedRotation(rotation.value) + testApp.enterDesktopMode(wmHelper, device) // Set string extra to ensure the app is on PiP mode at launch pipApp.launchViaIntentAndWaitForPip(wmHelper, stringExtras = mapOf("enter_pip" to "true")) - testApp.enterDesktopMode(wmHelper, device) mailApp.launchViaIntent(wmHelper) newTasksApp.launchViaIntent(wmHelper) imeApp.launchViaIntent(wmHelper) diff --git a/libs/WindowManager/Shell/tests/e2e/splitscreen/flicker-legacy/Android.bp b/libs/WindowManager/Shell/tests/e2e/splitscreen/flicker-legacy/Android.bp index 176020ffc3b9..6d12b00a61e6 100644 --- a/libs/WindowManager/Shell/tests/e2e/splitscreen/flicker-legacy/Android.bp +++ b/libs/WindowManager/Shell/tests/e2e/splitscreen/flicker-legacy/Android.bp @@ -49,6 +49,7 @@ java_library { "wm-flicker-common-assertions", "launcher-helper-lib", "launcher-aosp-tapl", + "com_android_wm_shell_flags_lib", ], } diff --git a/libs/WindowManager/Shell/tests/e2e/splitscreen/flicker-legacy/src/com/android/wm/shell/flicker/splitscreen/DismissSplitScreenByGoHome.kt b/libs/WindowManager/Shell/tests/e2e/splitscreen/flicker-legacy/src/com/android/wm/shell/flicker/splitscreen/DismissSplitScreenByGoHome.kt index 6d396ea6e9d4..9c71510df8a0 100644 --- a/libs/WindowManager/Shell/tests/e2e/splitscreen/flicker-legacy/src/com/android/wm/shell/flicker/splitscreen/DismissSplitScreenByGoHome.kt +++ b/libs/WindowManager/Shell/tests/e2e/splitscreen/flicker-legacy/src/com/android/wm/shell/flicker/splitscreen/DismissSplitScreenByGoHome.kt @@ -17,12 +17,16 @@ package com.android.wm.shell.flicker.splitscreen import android.platform.test.annotations.Presubmit +import android.platform.test.annotations.RequiresFlagsDisabled +import android.platform.test.flag.junit.CheckFlagsRule +import android.platform.test.flag.junit.DeviceFlagsValueProvider import android.tools.flicker.junit.FlickerParametersRunnerFactory import android.tools.flicker.legacy.FlickerBuilder import android.tools.flicker.legacy.LegacyFlickerTest import android.tools.flicker.legacy.LegacyFlickerTestFactory import androidx.test.filters.FlakyTest import androidx.test.filters.RequiresDevice +import com.android.wm.shell.Flags import com.android.wm.shell.flicker.splitscreen.benchmark.DismissSplitScreenByGoHomeBenchmark import com.android.wm.shell.flicker.utils.ICommonAssertions import com.android.wm.shell.flicker.utils.appWindowBecomesInvisible @@ -30,6 +34,7 @@ import com.android.wm.shell.flicker.utils.layerBecomesInvisible import com.android.wm.shell.flicker.utils.splitAppLayerBoundsBecomesInvisible import com.android.wm.shell.flicker.utils.splitScreenDividerBecomesInvisible import org.junit.FixMethodOrder +import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith import org.junit.runners.MethodSorters @@ -44,8 +49,13 @@ import org.junit.runners.Parameterized @RunWith(Parameterized::class) @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class) @FixMethodOrder(MethodSorters.NAME_ASCENDING) +@RequiresFlagsDisabled(Flags.FLAG_ENABLE_PIP2) class DismissSplitScreenByGoHome(override val flicker: LegacyFlickerTest) : DismissSplitScreenByGoHomeBenchmark(flicker), ICommonAssertions { + @JvmField + @Rule + val checkFlagsRule: CheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule() + override val transition: FlickerBuilder.() -> Unit get() = { defaultSetup(this) diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/TestRunningTaskInfoBuilder.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/TestRunningTaskInfoBuilder.java index 9c31b46a80e5..310c2d725c09 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/TestRunningTaskInfoBuilder.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/TestRunningTaskInfoBuilder.java @@ -26,6 +26,7 @@ import static org.mockito.Mockito.mock; import android.annotation.NonNull; import android.app.ActivityManager; import android.app.WindowConfiguration; +import android.content.ComponentName; import android.content.Intent; import android.graphics.Point; import android.graphics.Rect; @@ -42,7 +43,9 @@ public final class TestRunningTaskInfoBuilder { private int mParentTaskId = INVALID_TASK_ID; private int mUid = INVALID_TASK_ID; private int mTaskId = INVALID_TASK_ID; + private int mUserId = -1; private Intent mBaseIntent = new Intent(); + private ComponentName mBaseActivity = null; private @WindowConfiguration.ActivityType int mActivityType = ACTIVITY_TYPE_STANDARD; private @WindowConfiguration.WindowingMode int mWindowingMode = WINDOWING_MODE_UNDEFINED; private @WindowConfiguration.ActivityType int mTopActivityType = ACTIVITY_TYPE_STANDARD; @@ -88,6 +91,12 @@ public final class TestRunningTaskInfoBuilder { return this; } + /** Sets the task info's user id. */ + public TestRunningTaskInfoBuilder setUserId(int userId) { + mUserId = userId; + return this; + } + /** * Set {@link ActivityManager.RunningTaskInfo#baseIntent} for the task info, by default * an empty intent is assigned @@ -97,6 +106,14 @@ public final class TestRunningTaskInfoBuilder { return this; } + /** + * Set {@link ActivityManager.RunningTaskInfo#baseActivity} for the task info. + */ + public TestRunningTaskInfoBuilder setBaseActivity(@NonNull ComponentName activity) { + mBaseActivity = activity; + return this; + } + public TestRunningTaskInfoBuilder setActivityType( @WindowConfiguration.ActivityType int activityType) { mActivityType = activityType; @@ -172,6 +189,8 @@ public final class TestRunningTaskInfoBuilder { info.isTopActivityTransparent = mIsTopActivityTransparent; info.numActivities = mNumActivities; info.lastActiveTime = mLastActiveTime; + info.userId = mUserId; + info.baseActivity = mBaseActivity; return info; } } diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/AppCompatUtilsTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/AppCompatUtilsTest.kt index 803e5d4442a9..1d390007d470 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/AppCompatUtilsTest.kt +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/AppCompatUtilsTest.kt @@ -21,7 +21,7 @@ import android.testing.AndroidTestingRunner import androidx.test.filters.SmallTest import com.android.internal.R import com.android.wm.shell.ShellTestCase -import com.android.wm.shell.desktopmode.DesktopTestHelpers.Companion.createFreeformTask +import com.android.wm.shell.desktopmode.DesktopTestHelpers.createFreeformTask import org.junit.Assert.assertFalse import org.junit.Assert.assertTrue import org.junit.Test diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopActivityOrientationChangeHandlerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopActivityOrientationChangeHandlerTest.kt index aabd973fce90..2ea0379e3bf7 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopActivityOrientationChangeHandlerTest.kt +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopActivityOrientationChangeHandlerTest.kt @@ -39,8 +39,8 @@ import com.android.wm.shell.ShellTaskOrganizer import com.android.wm.shell.ShellTestCase import com.android.wm.shell.common.ShellExecutor import com.android.wm.shell.common.TaskStackListenerImpl -import com.android.wm.shell.desktopmode.DesktopTestHelpers.Companion.createFreeformTask -import com.android.wm.shell.desktopmode.DesktopTestHelpers.Companion.createFullscreenTask +import com.android.wm.shell.desktopmode.DesktopTestHelpers.createFreeformTask +import com.android.wm.shell.desktopmode.DesktopTestHelpers.createFullscreenTask import com.android.wm.shell.desktopmode.persistence.Desktop import com.android.wm.shell.desktopmode.persistence.DesktopPersistentRepository import com.android.wm.shell.desktopmode.persistence.DesktopRepositoryInitializer diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopImmersiveControllerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopImmersiveControllerTest.kt index 4666276c2fae..b57c55c4c45a 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopImmersiveControllerTest.kt +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopImmersiveControllerTest.kt @@ -43,7 +43,7 @@ import com.android.wm.shell.TestShellExecutor import com.android.wm.shell.common.DisplayController import com.android.wm.shell.common.DisplayLayout import com.android.wm.shell.desktopmode.DesktopImmersiveController.ExitReason.USER_INTERACTION -import com.android.wm.shell.desktopmode.DesktopTestHelpers.Companion.createFreeformTask +import com.android.wm.shell.desktopmode.DesktopTestHelpers.createFreeformTask import com.android.wm.shell.sysui.ShellInit import com.android.wm.shell.transition.Transitions import com.android.wm.shell.util.StubTransaction diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeKeyGestureHandlerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeKeyGestureHandlerTest.kt index 7adc339c010d..887bdc259f54 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeKeyGestureHandlerTest.kt +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeKeyGestureHandlerTest.kt @@ -38,7 +38,7 @@ import com.android.wm.shell.MockToken import com.android.wm.shell.RootTaskDisplayAreaOrganizer import com.android.wm.shell.ShellTaskOrganizer import com.android.wm.shell.ShellTestCase -import com.android.wm.shell.desktopmode.DesktopTestHelpers.Companion.createFreeformTask +import com.android.wm.shell.desktopmode.DesktopTestHelpers.createFreeformTask import com.android.wm.shell.transition.FocusTransitionObserver import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.ExperimentalCoroutinesApi @@ -266,7 +266,7 @@ class DesktopModeKeyGestureHandlerTest : ShellTestCase() { verify(desktopTasksController).toggleDesktopTaskSize( task, ResizeTrigger.MAXIMIZE_MENU, - null + DesktopModeEventLogger.Companion.InputMethod.KEYBOARD ) } diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeUiEventLoggerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeUiEventLoggerTest.kt index a8b2811e46be..94698e2fc0fb 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeUiEventLoggerTest.kt +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeUiEventLoggerTest.kt @@ -17,16 +17,22 @@ package com.android.wm.shell.desktopmode +import android.content.ComponentName +import android.content.pm.ApplicationInfo +import android.content.pm.PackageManager import android.testing.AndroidTestingRunner import androidx.test.filters.SmallTest import com.android.internal.logging.InstanceId import com.android.internal.logging.testing.UiEventLoggerFake import com.android.wm.shell.ShellTestCase +import com.android.wm.shell.TestRunningTaskInfoBuilder import com.android.wm.shell.desktopmode.DesktopModeUiEventLogger.DesktopUiEventEnum.DESKTOP_WINDOW_EDGE_DRAG_RESIZE import com.google.common.truth.Truth.assertThat import org.junit.Before import org.junit.Test import org.junit.runner.RunWith +import org.mockito.kotlin.mock +import org.mockito.kotlin.whenever /** * Test class for [DesktopModeUiEventLogger] @@ -39,11 +45,12 @@ class DesktopModeUiEventLoggerTest : ShellTestCase() { private lateinit var uiEventLoggerFake: UiEventLoggerFake private lateinit var logger: DesktopModeUiEventLogger + private val mockPackageManager: PackageManager = mock<PackageManager>() @Before fun setUp() { uiEventLoggerFake = UiEventLoggerFake() - logger = DesktopModeUiEventLogger(uiEventLoggerFake) + logger = DesktopModeUiEventLogger(uiEventLoggerFake, mockPackageManager) } @Test @@ -100,10 +107,28 @@ class DesktopModeUiEventLoggerTest : ShellTestCase() { assertThat(uiEventLoggerFake[0].packageName).isEqualTo(PACKAGE_NAME) } + @Test + fun logWithTaskInfo_eventLogged() { + val event = + DESKTOP_WINDOW_EDGE_DRAG_RESIZE + val taskInfo = TestRunningTaskInfoBuilder() + .setUserId(USER_ID) + .setBaseActivity(ComponentName(PACKAGE_NAME, "test")) + .build() + whenever(mockPackageManager.getApplicationInfoAsUser(PACKAGE_NAME, /* flags= */ 0, USER_ID)) + .thenReturn(ApplicationInfo().apply { uid = UID }) + logger.log(taskInfo, event) + assertThat(uiEventLoggerFake.numLogs()).isEqualTo(1) + assertThat(uiEventLoggerFake.eventId(0)).isEqualTo(event.id) + assertThat(uiEventLoggerFake[0].instanceId).isNull() + assertThat(uiEventLoggerFake[0].uid).isEqualTo(UID) + assertThat(uiEventLoggerFake[0].packageName).isEqualTo(PACKAGE_NAME) + } companion object { private val INSTANCE_ID = InstanceId.fakeInstanceId(0) private const val UID = 10 + private const val USER_ID = 2 private const val PACKAGE_NAME = "com.foo" } } diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTaskChangeListenerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTaskChangeListenerTest.kt index e977966a45fe..8e323acc4e66 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTaskChangeListenerTest.kt +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTaskChangeListenerTest.kt @@ -23,8 +23,8 @@ import android.testing.AndroidTestingRunner import androidx.test.filters.SmallTest import com.android.window.flags.Flags.FLAG_ENABLE_DESKTOP_WINDOWING_BACK_NAVIGATION import com.android.wm.shell.ShellTestCase -import com.android.wm.shell.desktopmode.DesktopTestHelpers.Companion.createFreeformTask -import com.android.wm.shell.desktopmode.DesktopTestHelpers.Companion.createFullscreenTask +import com.android.wm.shell.desktopmode.DesktopTestHelpers.createFreeformTask +import com.android.wm.shell.desktopmode.DesktopTestHelpers.createFullscreenTask import org.junit.Before import org.junit.Rule import org.junit.Test diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt index a8cfef7c1262..fc31d08b4571 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt @@ -99,10 +99,10 @@ import com.android.wm.shell.desktopmode.DesktopModeEventLogger.Companion.ResizeT import com.android.wm.shell.desktopmode.DesktopTasksController.DesktopModeEntryExitTransitionListener import com.android.wm.shell.desktopmode.DesktopTasksController.SnapPosition import com.android.wm.shell.desktopmode.DesktopTasksController.TaskbarDesktopTaskListener -import com.android.wm.shell.desktopmode.DesktopTestHelpers.Companion.createFreeformTask -import com.android.wm.shell.desktopmode.DesktopTestHelpers.Companion.createFullscreenTask -import com.android.wm.shell.desktopmode.DesktopTestHelpers.Companion.createHomeTask -import com.android.wm.shell.desktopmode.DesktopTestHelpers.Companion.createSplitScreenTask +import com.android.wm.shell.desktopmode.DesktopTestHelpers.createFreeformTask +import com.android.wm.shell.desktopmode.DesktopTestHelpers.createFullscreenTask +import com.android.wm.shell.desktopmode.DesktopTestHelpers.createHomeTask +import com.android.wm.shell.desktopmode.DesktopTestHelpers.createSplitScreenTask import com.android.wm.shell.desktopmode.EnterDesktopTaskTransitionHandler.FREEFORM_ANIMATION_DURATION import com.android.wm.shell.desktopmode.ExitDesktopTaskTransitionHandler.FULLSCREEN_ANIMATION_DURATION import com.android.wm.shell.desktopmode.minimize.DesktopWindowLimitRemoteHandler @@ -220,6 +220,7 @@ class DesktopTasksControllerTest : ShellTestCase() { @Mock private lateinit var freeformTaskTransitionStarter: FreeformTaskTransitionStarter @Mock private lateinit var mockHandler: Handler @Mock private lateinit var desktopModeEventLogger: DesktopModeEventLogger + @Mock private lateinit var desktopModeUiEventLogger: DesktopModeUiEventLogger @Mock lateinit var persistentRepository: DesktopPersistentRepository @Mock lateinit var motionEvent: MotionEvent @Mock lateinit var repositoryInitializer: DesktopRepositoryInitializer @@ -346,6 +347,7 @@ class DesktopTasksControllerTest : ShellTestCase() { mockInteractionJankMonitor, mockHandler, desktopModeEventLogger, + desktopModeUiEventLogger, desktopTilingDecorViewModel, ) } @@ -375,12 +377,12 @@ class DesktopTasksControllerTest : ShellTestCase() { val task1 = setUpFreeformTask() val argumentCaptor = ArgumentCaptor.forClass(Boolean::class.java) - controller.toggleDesktopTaskSize(task1, ResizeTrigger.MAXIMIZE_BUTTON, motionEvent) + controller.toggleDesktopTaskSize(task1, ResizeTrigger.MAXIMIZE_BUTTON, InputMethod.TOUCH) verify(taskbarDesktopTaskListener).onTaskbarCornerRoundingUpdate(argumentCaptor.capture()) verify(desktopModeEventLogger, times(1)).logTaskResizingEnded( ResizeTrigger.MAXIMIZE_BUTTON, - InputMethod.UNKNOWN_INPUT_METHOD, + InputMethod.TOUCH, task1, STABLE_BOUNDS.width(), STABLE_BOUNDS.height(), @@ -402,12 +404,12 @@ class DesktopTasksControllerTest : ShellTestCase() { val task1 = setUpFreeformTask(bounds = stableBounds, active = true) val argumentCaptor = ArgumentCaptor.forClass(Boolean::class.java) - controller.toggleDesktopTaskSize(task1, ResizeTrigger.MAXIMIZE_BUTTON, motionEvent) + controller.toggleDesktopTaskSize(task1, ResizeTrigger.MAXIMIZE_BUTTON, InputMethod.TOUCH) verify(taskbarDesktopTaskListener).onTaskbarCornerRoundingUpdate(argumentCaptor.capture()) verify(desktopModeEventLogger, times(1)).logTaskResizingEnded( ResizeTrigger.MAXIMIZE_BUTTON, - InputMethod.UNKNOWN_INPUT_METHOD, + InputMethod.TOUCH, task1, 0, 0, @@ -3357,14 +3359,14 @@ class DesktopTasksControllerTest : ShellTestCase() { val bounds = Rect(0, 0, 100, 100) val task = setUpFreeformTask(DEFAULT_DISPLAY, bounds) - controller.toggleDesktopTaskSize(task, ResizeTrigger.MAXIMIZE_BUTTON, motionEvent) + controller.toggleDesktopTaskSize(task, ResizeTrigger.MAXIMIZE_BUTTON, InputMethod.TOUCH) // Assert bounds set to stable bounds val wct = getLatestToggleResizeDesktopTaskWct() assertThat(findBoundsChange(wct, task)).isEqualTo(STABLE_BOUNDS) verify(desktopModeEventLogger, times(1)).logTaskResizingEnded( ResizeTrigger.MAXIMIZE_BUTTON, - InputMethod.UNKNOWN_INPUT_METHOD, + InputMethod.TOUCH, task, STABLE_BOUNDS.width(), STABLE_BOUNDS.height(), @@ -3582,14 +3584,14 @@ class DesktopTasksControllerTest : ShellTestCase() { // Bounds should be 1000 x 500, vertically centered in the 1000 x 1000 stable bounds val expectedBounds = Rect(STABLE_BOUNDS.left, 250, STABLE_BOUNDS.right, 750) - controller.toggleDesktopTaskSize(task, ResizeTrigger.MAXIMIZE_BUTTON, motionEvent) + controller.toggleDesktopTaskSize(task, ResizeTrigger.MAXIMIZE_BUTTON, InputMethod.TOUCH) // Assert bounds set to stable bounds val wct = getLatestToggleResizeDesktopTaskWct() assertThat(findBoundsChange(wct, task)).isEqualTo(expectedBounds) verify(desktopModeEventLogger, times(1)).logTaskResizingEnded( ResizeTrigger.MAXIMIZE_BUTTON, - InputMethod.UNKNOWN_INPUT_METHOD, + InputMethod.TOUCH, task, expectedBounds.width(), expectedBounds.height(), @@ -3602,7 +3604,7 @@ class DesktopTasksControllerTest : ShellTestCase() { val bounds = Rect(0, 0, 100, 100) val task = setUpFreeformTask(DEFAULT_DISPLAY, bounds) - controller.toggleDesktopTaskSize(task, ResizeTrigger.MAXIMIZE_BUTTON, motionEvent) + controller.toggleDesktopTaskSize(task, ResizeTrigger.MAXIMIZE_BUTTON, InputMethod.TOUCH) assertThat(taskRepository.removeBoundsBeforeMaximize(task.taskId)).isEqualTo(bounds) verify(desktopModeEventLogger, never()).logTaskResizingEnded( any(), any(), any(), any(), @@ -3616,18 +3618,18 @@ class DesktopTasksControllerTest : ShellTestCase() { val task = setUpFreeformTask(DEFAULT_DISPLAY, boundsBeforeMaximize) // Maximize - controller.toggleDesktopTaskSize(task, ResizeTrigger.MAXIMIZE_BUTTON, motionEvent) + controller.toggleDesktopTaskSize(task, ResizeTrigger.MAXIMIZE_BUTTON, InputMethod.TOUCH) task.configuration.windowConfiguration.bounds.set(STABLE_BOUNDS) // Restore - controller.toggleDesktopTaskSize(task, ResizeTrigger.MAXIMIZE_BUTTON, motionEvent) + controller.toggleDesktopTaskSize(task, ResizeTrigger.MAXIMIZE_BUTTON, InputMethod.TOUCH) // Assert bounds set to last bounds before maximize val wct = getLatestToggleResizeDesktopTaskWct() assertThat(findBoundsChange(wct, task)).isEqualTo(boundsBeforeMaximize) verify(desktopModeEventLogger, times(1)).logTaskResizingEnded( ResizeTrigger.MAXIMIZE_BUTTON, - InputMethod.UNKNOWN_INPUT_METHOD, + InputMethod.TOUCH, task, boundsBeforeMaximize.width(), boundsBeforeMaximize.height(), @@ -3643,19 +3645,19 @@ class DesktopTasksControllerTest : ShellTestCase() { } // Maximize - controller.toggleDesktopTaskSize(task, ResizeTrigger.MAXIMIZE_BUTTON, motionEvent) + controller.toggleDesktopTaskSize(task, ResizeTrigger.MAXIMIZE_BUTTON, InputMethod.TOUCH) task.configuration.windowConfiguration.bounds.set(STABLE_BOUNDS.left, boundsBeforeMaximize.top, STABLE_BOUNDS.right, boundsBeforeMaximize.bottom) // Restore - controller.toggleDesktopTaskSize(task, ResizeTrigger.MAXIMIZE_BUTTON, motionEvent) + controller.toggleDesktopTaskSize(task, ResizeTrigger.MAXIMIZE_BUTTON, InputMethod.TOUCH) // Assert bounds set to last bounds before maximize val wct = getLatestToggleResizeDesktopTaskWct() assertThat(findBoundsChange(wct, task)).isEqualTo(boundsBeforeMaximize) verify(desktopModeEventLogger, times(1)).logTaskResizingEnded( ResizeTrigger.MAXIMIZE_BUTTON, - InputMethod.UNKNOWN_INPUT_METHOD, + InputMethod.TOUCH, task, boundsBeforeMaximize.width(), boundsBeforeMaximize.height(), @@ -3671,19 +3673,19 @@ class DesktopTasksControllerTest : ShellTestCase() { } // Maximize - controller.toggleDesktopTaskSize(task, ResizeTrigger.MAXIMIZE_BUTTON, motionEvent) + controller.toggleDesktopTaskSize(task, ResizeTrigger.MAXIMIZE_BUTTON, InputMethod.TOUCH) task.configuration.windowConfiguration.bounds.set(boundsBeforeMaximize.left, STABLE_BOUNDS.top, boundsBeforeMaximize.right, STABLE_BOUNDS.bottom) // Restore - controller.toggleDesktopTaskSize(task, ResizeTrigger.MAXIMIZE_BUTTON, motionEvent) + controller.toggleDesktopTaskSize(task, ResizeTrigger.MAXIMIZE_BUTTON, InputMethod.TOUCH) // Assert bounds set to last bounds before maximize val wct = getLatestToggleResizeDesktopTaskWct() assertThat(findBoundsChange(wct, task)).isEqualTo(boundsBeforeMaximize) verify(desktopModeEventLogger, times(1)).logTaskResizingEnded( ResizeTrigger.MAXIMIZE_BUTTON, - InputMethod.UNKNOWN_INPUT_METHOD, + InputMethod.TOUCH, task, boundsBeforeMaximize.width(), boundsBeforeMaximize.height(), @@ -3697,17 +3699,17 @@ class DesktopTasksControllerTest : ShellTestCase() { val task = setUpFreeformTask(DEFAULT_DISPLAY, boundsBeforeMaximize) // Maximize - controller.toggleDesktopTaskSize(task, ResizeTrigger.MAXIMIZE_BUTTON, motionEvent) + controller.toggleDesktopTaskSize(task, ResizeTrigger.MAXIMIZE_BUTTON, InputMethod.TOUCH) task.configuration.windowConfiguration.bounds.set(STABLE_BOUNDS) // Restore - controller.toggleDesktopTaskSize(task, ResizeTrigger.MAXIMIZE_BUTTON, motionEvent) + controller.toggleDesktopTaskSize(task, ResizeTrigger.MAXIMIZE_BUTTON, InputMethod.TOUCH) // Assert last bounds before maximize removed after use assertThat(taskRepository.removeBoundsBeforeMaximize(task.taskId)).isNull() verify(desktopModeEventLogger, times(1)).logTaskResizingEnded( ResizeTrigger.MAXIMIZE_BUTTON, - InputMethod.UNKNOWN_INPUT_METHOD, + InputMethod.TOUCH, task, boundsBeforeMaximize.width(), boundsBeforeMaximize.height(), diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksLimiterTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksLimiterTest.kt index 456b50da095b..797b12505ef2 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksLimiterTest.kt +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksLimiterTest.kt @@ -42,7 +42,7 @@ import com.android.window.flags.Flags.FLAG_ENABLE_DESKTOP_WINDOWING_BACK_NAVIGAT import com.android.wm.shell.ShellTaskOrganizer import com.android.wm.shell.ShellTestCase import com.android.wm.shell.common.ShellExecutor -import com.android.wm.shell.desktopmode.DesktopTestHelpers.Companion.createFreeformTask +import com.android.wm.shell.desktopmode.DesktopTestHelpers.createFreeformTask import com.android.wm.shell.desktopmode.persistence.DesktopPersistentRepository import com.android.wm.shell.desktopmode.persistence.DesktopRepositoryInitializer import com.android.wm.shell.shared.desktopmode.DesktopModeStatus diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTestHelpers.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTestHelpers.kt index 2134f3bb35cc..866d1b3880b0 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTestHelpers.kt +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTestHelpers.kt @@ -27,78 +27,56 @@ import android.view.Display.DEFAULT_DISPLAY import com.android.wm.shell.MockToken import com.android.wm.shell.TestRunningTaskInfoBuilder -class DesktopTestHelpers { - companion object { - /** Create a task that has windowing mode set to [WINDOWING_MODE_FREEFORM] */ - @JvmStatic - @JvmOverloads - fun createFreeformTask( - displayId: Int = DEFAULT_DISPLAY, - bounds: Rect? = null - ): RunningTaskInfo { - return TestRunningTaskInfoBuilder() - .setDisplayId(displayId) - .setToken(MockToken().token()) - .setActivityType(ACTIVITY_TYPE_STANDARD) - .setWindowingMode(WINDOWING_MODE_FREEFORM) - .setLastActiveTime(100) - .apply { bounds?.let { setBounds(it) }} - .build() - } +object DesktopTestHelpers { + /** Create a task that has windowing mode set to [WINDOWING_MODE_FREEFORM] */ + fun createFreeformTask( + displayId: Int = DEFAULT_DISPLAY, + bounds: Rect? = null, + ): RunningTaskInfo = + TestRunningTaskInfoBuilder() + .setDisplayId(displayId) + .setToken(MockToken().token()) + .setActivityType(ACTIVITY_TYPE_STANDARD) + .setWindowingMode(WINDOWING_MODE_FREEFORM) + .setLastActiveTime(100) + .apply { bounds?.let { setBounds(it) } } + .build() - /** Create a task builder that has windowing mode set to [WINDOWING_MODE_FULLSCREEN] */ - @JvmStatic - @JvmOverloads - fun createFullscreenTaskBuilder(displayId: Int = DEFAULT_DISPLAY): TestRunningTaskInfoBuilder { - return TestRunningTaskInfoBuilder() - .setDisplayId(displayId) - .setToken(MockToken().token()) - .setActivityType(ACTIVITY_TYPE_STANDARD) - .setWindowingMode(WINDOWING_MODE_FULLSCREEN) - .setLastActiveTime(100) - } + fun createFullscreenTaskBuilder(displayId: Int = DEFAULT_DISPLAY): TestRunningTaskInfoBuilder = + TestRunningTaskInfoBuilder() + .setDisplayId(displayId) + .setToken(MockToken().token()) + .setActivityType(ACTIVITY_TYPE_STANDARD) + .setWindowingMode(WINDOWING_MODE_FULLSCREEN) + .setLastActiveTime(100) - /** Create a task that has windowing mode set to [WINDOWING_MODE_FULLSCREEN] */ - @JvmStatic - @JvmOverloads - fun createFullscreenTask(displayId: Int = DEFAULT_DISPLAY): RunningTaskInfo { - return createFullscreenTaskBuilder(displayId).build() - } + /** Create a task that has windowing mode set to [WINDOWING_MODE_FULLSCREEN] */ + fun createFullscreenTask(displayId: Int = DEFAULT_DISPLAY): RunningTaskInfo = + createFullscreenTaskBuilder(displayId).build() - /** Create a task that has windowing mode set to [WINDOWING_MODE_MULTI_WINDOW] */ - @JvmStatic - @JvmOverloads - fun createSplitScreenTask(displayId: Int = DEFAULT_DISPLAY): RunningTaskInfo { - return TestRunningTaskInfoBuilder() - .setDisplayId(displayId) - .setToken(MockToken().token()) - .setActivityType(ACTIVITY_TYPE_STANDARD) - .setWindowingMode(WINDOWING_MODE_MULTI_WINDOW) - .setLastActiveTime(100) - .build() - } + /** Create a task that has windowing mode set to [WINDOWING_MODE_MULTI_WINDOW] */ + fun createSplitScreenTask(displayId: Int = DEFAULT_DISPLAY): RunningTaskInfo = + TestRunningTaskInfoBuilder() + .setDisplayId(displayId) + .setToken(MockToken().token()) + .setActivityType(ACTIVITY_TYPE_STANDARD) + .setWindowingMode(WINDOWING_MODE_MULTI_WINDOW) + .setLastActiveTime(100) + .build() - /** Create a new home task */ - @JvmStatic - @JvmOverloads - fun createHomeTask(displayId: Int = DEFAULT_DISPLAY): RunningTaskInfo { - return TestRunningTaskInfoBuilder() - .setDisplayId(displayId) - .setToken(MockToken().token()) - .setActivityType(ACTIVITY_TYPE_HOME) - .setWindowingMode(WINDOWING_MODE_FULLSCREEN) - .setLastActiveTime(100) - .build() - } + fun createHomeTask(displayId: Int = DEFAULT_DISPLAY): RunningTaskInfo = + TestRunningTaskInfoBuilder() + .setDisplayId(displayId) + .setToken(MockToken().token()) + .setActivityType(ACTIVITY_TYPE_HOME) + .setWindowingMode(WINDOWING_MODE_FULLSCREEN) + .setLastActiveTime(100) + .build() - /** Create a new System Modal task, i.e. a task with a single transparent activity. */ - @JvmStatic - @JvmOverloads - fun createSystemModalTask(displayId: Int = DEFAULT_DISPLAY): RunningTaskInfo { - return createFullscreenTaskBuilder(displayId) - .setTopActivityTransparent(true) - .setNumActivities(1) - .build() - } - } -}
\ No newline at end of file + /** Create a new System Modal task, i.e. a task with a single transparent activity. */ + fun createSystemModalTask(displayId: Int = DEFAULT_DISPLAY): RunningTaskInfo = + createFullscreenTaskBuilder(displayId) + .setTopActivityTransparent(true) + .setNumActivities(1) + .build() +} diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/compatui/SystemModalsTransitionHandlerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/compatui/SystemModalsTransitionHandlerTest.kt index 79d90838cecc..226e974d2875 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/compatui/SystemModalsTransitionHandlerTest.kt +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/compatui/SystemModalsTransitionHandlerTest.kt @@ -26,9 +26,9 @@ import androidx.test.filters.SmallTest import com.android.wm.shell.ShellTestCase import com.android.wm.shell.common.ShellExecutor import com.android.wm.shell.desktopmode.DesktopRepository -import com.android.wm.shell.desktopmode.DesktopTestHelpers.Companion.createFullscreenTask -import com.android.wm.shell.desktopmode.DesktopTestHelpers.Companion.createFullscreenTaskBuilder -import com.android.wm.shell.desktopmode.DesktopTestHelpers.Companion.createSystemModalTask +import com.android.wm.shell.desktopmode.DesktopTestHelpers.createFullscreenTask +import com.android.wm.shell.desktopmode.DesktopTestHelpers.createFullscreenTaskBuilder +import com.android.wm.shell.desktopmode.DesktopTestHelpers.createSystemModalTask import com.android.wm.shell.sysui.ShellInit import com.android.wm.shell.transition.TransitionInfoBuilder import com.android.wm.shell.transition.Transitions diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/education/AppHandleEducationControllerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/education/AppHandleEducationControllerTest.kt index d94186c8284e..9c00c0cee8b1 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/education/AppHandleEducationControllerTest.kt +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/education/AppHandleEducationControllerTest.kt @@ -175,13 +175,13 @@ class AppHandleEducationControllerTest : ShellTestCase() { @Test @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_APP_HANDLE_EDUCATION) - fun init_educationViewedAlready_shouldNotCallShowEducationTooltip() = + fun init_appHandleHintViewedAlready_shouldNotCallShowEducationTooltip() = testScope.runTest { - // App handle is visible but education has been viewed before. Should not show education - // tooltip. - // Mark education viewed. + // App handle is visible but app handle hint has been viewed before, + // should not show education tooltip. + // Mark app handle hint viewed. testDataStoreFlow.value = - createWindowingEducationProto(educationViewedTimestampMillis = 123L) + createWindowingEducationProto(appHandleHintViewedTimestampMillis = 123L) setShouldShowAppHandleEducation(true) // Simulate app handle visible. @@ -194,13 +194,14 @@ class AppHandleEducationControllerTest : ShellTestCase() { @Test @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_APP_HANDLE_EDUCATION) - fun overridePrerequisite_educationViewedAlready_shouldCallShowEducationTooltip() = + fun overridePrerequisite_appHandleHintViewedAlready_shouldCallShowEducationTooltip() = testScope.runTest { - // App handle is visible but education has been viewed before. But as we are overriding - // prerequisite conditions, we should show education tooltip. - // Mark education viewed. + // App handle is visible but app handle hint has been viewed before. + // But as we are overriding prerequisite conditions, we should show app + // handle tooltip. + // Mark app handle hint viewed. testDataStoreFlow.value = - createWindowingEducationProto(educationViewedTimestampMillis = 123L) + createWindowingEducationProto(appHandleHintViewedTimestampMillis = 123L) val systemPropertiesKey = "persist.desktop_windowing_app_handle_education_override_conditions" whenever(SystemProperties.getBoolean(eq(systemPropertiesKey), anyBoolean())) @@ -217,7 +218,7 @@ class AppHandleEducationControllerTest : ShellTestCase() { @Test @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_APP_HANDLE_EDUCATION) - fun init_appHandleExpanded_shouldMarkFeatureViewed() = + fun init_appHandleExpanded_shouldMarkAppHandleHintUsed() = testScope.runTest { setShouldShowAppHandleEducation(false) @@ -226,12 +227,12 @@ class AppHandleEducationControllerTest : ShellTestCase() { // Wait for some time before verifying waitForBufferDelay() - verify(mockDataStoreRepository, times(1)).updateFeatureUsedTimestampMillis(eq(true)) + verify(mockDataStoreRepository, times(1)).updateAppHandleHintUsedTimestampMillis(eq(true)) } @Test @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_APP_HANDLE_EDUCATION) - fun init_showFirstTooltip_shouldMarkEducationViewed() = + fun init_showFirstTooltip_shouldMarkAppHandleHintViewed() = testScope.runTest { // App handle is visible. Should show education tooltip. setShouldShowAppHandleEducation(true) @@ -241,7 +242,7 @@ class AppHandleEducationControllerTest : ShellTestCase() { // Wait for first tooltip to showup. waitForBufferDelay() - verify(mockDataStoreRepository, times(1)).updateEducationViewedTimestampMillis(eq(true)) + verify(mockDataStoreRepository, times(1)).updateAppHandleHintViewedTimestampMillis(eq(true)) } @Test diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/education/AppHandleEducationDatastoreRepositoryTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/education/AppHandleEducationDatastoreRepositoryTest.kt index c2865441d7a6..963890d1caa4 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/education/AppHandleEducationDatastoreRepositoryTest.kt +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/education/AppHandleEducationDatastoreRepositoryTest.kt @@ -81,8 +81,8 @@ class AppHandleEducationDatastoreRepositoryTest { runTest(StandardTestDispatcher()) { val windowingEducationProto = createWindowingEducationProto( - educationViewedTimestampMillis = 123L, - featureUsedTimestampMillis = 124L, + appHandleHintViewedTimestampMillis = 123L, + appHandleHintUsedTimestampMillis = 124L, appUsageStats = mapOf(GMAIL_PACKAGE_NAME to 2), appUsageStatsLastUpdateTimestampMillis = 125L) testDatastore.updateData { windowingEducationProto } @@ -110,20 +110,20 @@ class AppHandleEducationDatastoreRepositoryTest { } @Test - fun updateEducationViewedTimestampMillis_updatesDatastoreProto() = + fun updateAppHandleHintViewedTimestampMillis_updatesDatastoreProto() = runTest(StandardTestDispatcher()) { - datastoreRepository.updateEducationViewedTimestampMillis(true) + datastoreRepository.updateAppHandleHintViewedTimestampMillis(true) - val result = testDatastore.data.first().hasEducationViewedTimestampMillis() + val result = testDatastore.data.first().hasAppHandleHintViewedTimestampMillis() assertThat(result).isEqualTo(true) } @Test - fun updateFeatureUsedTimestampMillis_updatesDatastoreProto() = + fun updateAppHandleHintUsedTimestampMillis_updatesDatastoreProto() = runTest(StandardTestDispatcher()) { - datastoreRepository.updateFeatureUsedTimestampMillis(true) + datastoreRepository.updateAppHandleHintUsedTimestampMillis(true) - val result = testDatastore.data.first().hasFeatureUsedTimestampMillis() + val result = testDatastore.data.first().hasAppHandleHintUsedTimestampMillis() assertThat(result).isEqualTo(true) } diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/education/AppHandleEducationFilterTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/education/AppHandleEducationFilterTest.kt index a3e74e8aed5d..e5edd69155b5 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/education/AppHandleEducationFilterTest.kt +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/education/AppHandleEducationFilterTest.kt @@ -134,12 +134,12 @@ class AppHandleEducationFilterTest : ShellTestCase() { } @Test - fun shouldShowAppHandleEducation_educationViewedBefore_returnsFalse() = runTest { - // Education has been viewed before, hence #shouldShowAppHandleEducation should return false + fun shouldShowAppHandleEducation_appHandleHintViewedBefore_returnsFalse() = runTest { + // App handle hint has been viewed before, hence #shouldShowAppHandleEducation should return false val windowingEducationProto = createWindowingEducationProto( appUsageStats = mapOf(GMAIL_PACKAGE_NAME to 4), - educationViewedTimestampMillis = 123L, + appHandleHintViewedTimestampMillis = 123L, appUsageStatsLastUpdateTimestampMillis = Long.MAX_VALUE) `when`(datastoreRepository.windowingEducationProto()).thenReturn(windowingEducationProto) @@ -149,12 +149,12 @@ class AppHandleEducationFilterTest : ShellTestCase() { } @Test - fun shouldShowAppHandleEducation_featureUsedBefore_returnsFalse() = runTest { - // Feature has been used before, hence #shouldShowAppHandleEducation should return false + fun shouldShowAppHandleEducation_appHandleHintUsedBefore_returnsFalse() = runTest { + // App handle hint has been used before, hence #shouldShowAppHandleEducation should return false val windowingEducationProto = createWindowingEducationProto( appUsageStats = mapOf(GMAIL_PACKAGE_NAME to 4), - featureUsedTimestampMillis = 123L, + appHandleHintUsedTimestampMillis = 123L, appUsageStatsLastUpdateTimestampMillis = Long.MAX_VALUE) `when`(datastoreRepository.windowingEducationProto()).thenReturn(windowingEducationProto) diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/RecentTasksControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/RecentTasksControllerTest.java index 12c397868f5a..68c8aab8849d 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/RecentTasksControllerTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/RecentTasksControllerTest.java @@ -22,6 +22,7 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW; import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession; +import static com.android.launcher3.Flags.FLAG_ENABLE_REFACTOR_TASK_THUMBNAIL; import static com.android.window.flags.Flags.FLAG_ENABLE_DESKTOP_WINDOWING_PERSISTENCE; import static com.android.wm.shell.shared.split.SplitScreenConstants.SNAP_TO_2_50_50; @@ -51,6 +52,7 @@ import android.app.ActivityTaskManager; import android.app.KeyguardManager; import android.content.ComponentName; import android.content.Context; +import android.content.Intent; import android.content.pm.PackageManager; import android.graphics.Point; import android.graphics.Rect; @@ -72,6 +74,7 @@ import com.android.wm.shell.TestShellExecutor; import com.android.wm.shell.common.DisplayInsetsController; import com.android.wm.shell.common.TaskStackListenerImpl; import com.android.wm.shell.desktopmode.DesktopRepository; +import com.android.wm.shell.desktopmode.DesktopWallpaperActivity; import com.android.wm.shell.shared.GroupedTaskInfo; import com.android.wm.shell.shared.ShellSharedConstants; import com.android.wm.shell.shared.desktopmode.DesktopModeStatus; @@ -237,6 +240,19 @@ public class RecentTasksControllerTest extends ShellTestCase { t3.taskId, -1); } + @EnableFlags(FLAG_ENABLE_REFACTOR_TASK_THUMBNAIL) + @Test + public void testGetRecentTasks_removesDesktopWallpaperActivity() { + RecentTaskInfo t1 = makeTaskInfo(1); + RecentTaskInfo desktopWallpaperTaskInfo = makeDesktopWallpaperTaskInfo(2); + RecentTaskInfo t3 = makeTaskInfo(3); + setRawList(t1, desktopWallpaperTaskInfo, t3); + + ArrayList<GroupedTaskInfo> recentTasks = + mRecentTasksController.getRecentTasks(MAX_VALUE, RECENT_IGNORE_UNAVAILABLE, 0); + assertGroupedTasksListEquals(recentTasks, t1.taskId, -1, t3.taskId, -1); + } + @Test public void testGetRecentTasks_withPairs() { RecentTaskInfo t1 = makeTaskInfo(1); @@ -691,11 +707,25 @@ public class RecentTasksControllerTest extends ShellTestCase { private RecentTaskInfo makeTaskInfo(int taskId) { RecentTaskInfo info = new RecentTaskInfo(); info.taskId = taskId; + + Intent intent = new Intent(); + intent.setComponent(new ComponentName("com." + taskId, "Activity" + taskId)); + info.baseIntent = intent; + info.lastNonFullscreenBounds = new Rect(); return info; } /** + * Helper to create a desktop wallpaper activity with a given task id. + */ + private RecentTaskInfo makeDesktopWallpaperTaskInfo(int taskId) { + RecentTaskInfo info = makeTaskInfo(taskId); + info.baseIntent.setComponent(DesktopWallpaperActivity.getWallpaperActivityComponent()); + return info; + } + + /** * Helper to create a running task with a given task id. */ private ActivityManager.RunningTaskInfo makeRunningTaskInfo(int taskId) { diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/util/WindowingEducationTestUtils.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/util/WindowingEducationTestUtils.kt index 99e82959fcd6..b9d91e7895db 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/util/WindowingEducationTestUtils.kt +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/util/WindowingEducationTestUtils.kt @@ -78,18 +78,18 @@ fun createTaskInfo( * Any fields without corresponding parameters will retain their default values. */ fun createWindowingEducationProto( - educationViewedTimestampMillis: Long? = null, - featureUsedTimestampMillis: Long? = null, + appHandleHintViewedTimestampMillis: Long? = null, + appHandleHintUsedTimestampMillis: Long? = null, appUsageStats: Map<String, Int>? = null, appUsageStatsLastUpdateTimestampMillis: Long? = null ): WindowingEducationProto = WindowingEducationProto.newBuilder() .apply { - if (educationViewedTimestampMillis != null) { - setEducationViewedTimestampMillis(educationViewedTimestampMillis) + if (appHandleHintViewedTimestampMillis != null) { + setAppHandleHintViewedTimestampMillis(appHandleHintViewedTimestampMillis) } - if (featureUsedTimestampMillis != null) { - setFeatureUsedTimestampMillis(featureUsedTimestampMillis) + if (appHandleHintUsedTimestampMillis != null) { + setAppHandleHintUsedTimestampMillis(appHandleHintUsedTimestampMillis) } setAppHandleEducation( createAppHandleEducationProto(appUsageStats, appUsageStatsLastUpdateTimestampMillis)) diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.kt index 7bb8e891e33b..b873162e6fe3 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.kt +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.kt @@ -399,7 +399,7 @@ class DesktopModeWindowDecorViewModelTests : DesktopModeWindowDecorViewModelTest verify(mockDesktopTasksController).toggleDesktopTaskSize( decor.mTaskInfo, ResizeTrigger.MAXIMIZE_MENU, - null + InputMethod.UNKNOWN_INPUT_METHOD ) } @@ -1033,7 +1033,11 @@ class DesktopModeWindowDecorViewModelTests : DesktopModeWindowDecorViewModelTest onClickListenerCaptor.value.onClick(view) verify(mockDesktopTasksController) - .toggleDesktopTaskSize(decor.mTaskInfo, ResizeTrigger.MAXIMIZE_BUTTON, null) + .toggleDesktopTaskSize( + decor.mTaskInfo, + ResizeTrigger.MAXIMIZE_BUTTON, + InputMethod.UNKNOWN_INPUT_METHOD + ) } @Test diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTestsBase.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTestsBase.kt index 91eaadaf1f18..1670f2a6815b 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTestsBase.kt +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTestsBase.kt @@ -55,6 +55,7 @@ import com.android.wm.shell.common.MultiInstanceHelper import com.android.wm.shell.common.SyncTransactionQueue import com.android.wm.shell.desktopmode.DesktopActivityOrientationChangeHandler import com.android.wm.shell.desktopmode.DesktopModeEventLogger +import com.android.wm.shell.desktopmode.DesktopModeUiEventLogger import com.android.wm.shell.desktopmode.DesktopRepository import com.android.wm.shell.desktopmode.DesktopTasksController import com.android.wm.shell.desktopmode.DesktopTasksLimiter @@ -199,7 +200,8 @@ open class DesktopModeWindowDecorViewModelTestsBase : ShellTestCase() { Optional.of(mockActivityOrientationChangeHandler), mockTaskPositionerFactory, mockFocusTransitionObserver, - desktopModeEventLogger + desktopModeEventLogger, + mock<DesktopModeUiEventLogger>() ) desktopModeWindowDecorViewModel.setSplitScreenController(mockSplitScreenController) whenever(mockDisplayController.getDisplayLayout(any())).thenReturn(mockDisplayLayout) diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DragResizeWindowGeometryTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DragResizeWindowGeometryTests.java index e7d328e28297..479f1567ed31 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DragResizeWindowGeometryTests.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DragResizeWindowGeometryTests.java @@ -63,6 +63,7 @@ public class DragResizeWindowGeometryTests extends ShellTestCase { private static final int EDGE_RESIZE_HANDLE_INSET = 4; private static final int FINE_CORNER_SIZE = EDGE_RESIZE_THICKNESS * 2 + 10; private static final int LARGE_CORNER_SIZE = FINE_CORNER_SIZE + 10; + private static final int SMALL_OFFSET = 10; private static final DragResizeWindowGeometry GEOMETRY = new DragResizeWindowGeometry( TASK_CORNER_RADIUS, TASK_SIZE, EDGE_RESIZE_THICKNESS, EDGE_RESIZE_HANDLE_INSET, FINE_CORNER_SIZE, LARGE_CORNER_SIZE, DragResizeWindowGeometry.DisabledEdge.NONE); @@ -147,15 +148,19 @@ public class DragResizeWindowGeometryTests extends ShellTestCase { assertThat(region.contains(point.x + EDGE_RESIZE_THICKNESS, point.y)).isTrue(); assertThat(region.contains(point.x - EDGE_RESIZE_THICKNESS, point.y)).isTrue(); // Vertically along the edge is not contained. - assertThat(region.contains(point.x, point.y - EDGE_RESIZE_THICKNESS)).isFalse(); - assertThat(region.contains(point.x, point.y + EDGE_RESIZE_THICKNESS + 10)).isFalse(); + assertThat( + region.contains(point.x, point.y - EDGE_RESIZE_THICKNESS - SMALL_OFFSET)).isFalse(); + assertThat( + region.contains(point.x, point.y + EDGE_RESIZE_THICKNESS + SMALL_OFFSET)).isFalse(); } private static void verifyVerticalEdge(@NonNull Region region, @NonNull Point point) { assertThat(region.contains(point.x, point.y)).isTrue(); // Horizontally along the edge is not contained. - assertThat(region.contains(point.x + EDGE_RESIZE_THICKNESS, point.y)).isFalse(); - assertThat(region.contains(point.x - EDGE_RESIZE_THICKNESS, point.y)).isFalse(); + assertThat( + region.contains(point.x + EDGE_RESIZE_THICKNESS + SMALL_OFFSET, point.y)).isFalse(); + assertThat( + region.contains(point.x - EDGE_RESIZE_THICKNESS - SMALL_OFFSET, point.y)).isFalse(); // Vertically along the edge is contained. assertThat(region.contains(point.x, point.y - EDGE_RESIZE_THICKNESS)).isTrue(); assertThat(region.contains(point.x, point.y + EDGE_RESIZE_THICKNESS)).isTrue(); diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/tiling/DesktopTilingDecorViewModelTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/tiling/DesktopTilingDecorViewModelTest.kt index d8c1a11de452..d29002199f9d 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/tiling/DesktopTilingDecorViewModelTest.kt +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/tiling/DesktopTilingDecorViewModelTest.kt @@ -27,7 +27,7 @@ import com.android.wm.shell.common.SyncTransactionQueue import com.android.wm.shell.desktopmode.DesktopModeEventLogger import com.android.wm.shell.desktopmode.DesktopRepository import com.android.wm.shell.desktopmode.DesktopTasksController -import com.android.wm.shell.desktopmode.DesktopTestHelpers.Companion.createFreeformTask +import com.android.wm.shell.desktopmode.DesktopTestHelpers.createFreeformTask import com.android.wm.shell.desktopmode.ReturnToDragStartAnimator import com.android.wm.shell.desktopmode.ToggleResizeDesktopTaskTransitionHandler import com.android.wm.shell.transition.Transitions diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/tiling/DesktopTilingDividerWindowManagerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/tiling/DesktopTilingDividerWindowManagerTest.kt index 3143946fa828..121e0e915d08 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/tiling/DesktopTilingDividerWindowManagerTest.kt +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/tiling/DesktopTilingDividerWindowManagerTest.kt @@ -122,6 +122,6 @@ class DesktopTilingDividerWindowManagerTest : ShellTestCase() { companion object { private val BOUNDS = Rect(1, 2, 3, 4) - private val CORNER_RADIUS = 28 + private const val CORNER_RADIUS = 28 } } diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/tiling/DesktopTilingWindowDecorationTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/tiling/DesktopTilingWindowDecorationTest.kt index ad6fdf4d5c59..3b39f1e4a25a 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/tiling/DesktopTilingWindowDecorationTest.kt +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/tiling/DesktopTilingWindowDecorationTest.kt @@ -38,7 +38,7 @@ import com.android.wm.shell.desktopmode.DesktopModeEventLogger import com.android.wm.shell.desktopmode.DesktopModeEventLogger.Companion.ResizeTrigger import com.android.wm.shell.desktopmode.DesktopRepository import com.android.wm.shell.desktopmode.DesktopTasksController -import com.android.wm.shell.desktopmode.DesktopTestHelpers.Companion.createFreeformTask +import com.android.wm.shell.desktopmode.DesktopTestHelpers.createFreeformTask import com.android.wm.shell.desktopmode.ReturnToDragStartAnimator import com.android.wm.shell.desktopmode.ToggleResizeDesktopTaskTransitionHandler import com.android.wm.shell.transition.Transitions @@ -124,7 +124,7 @@ class DesktopTilingWindowDecorationTest : ShellTestCase() { @Test fun taskTiled_toCorrectBounds_leftTile() { - val task1 = createFreeformTask() + val task1 = createVisibleTask() val stableBounds = STABLE_BOUNDS_MOCK whenever(displayController.getDisplayLayout(any())).thenReturn(displayLayout) whenever(displayLayout.getStableBounds(any())).thenAnswer { i -> @@ -151,7 +151,7 @@ class DesktopTilingWindowDecorationTest : ShellTestCase() { @Test fun taskTiled_toCorrectBounds_rightTile() { // Setup - val task1 = createFreeformTask() + val task1 = createVisibleTask() val stableBounds = STABLE_BOUNDS_MOCK whenever(displayController.getDisplayLayout(any())).thenReturn(displayLayout) whenever(displayLayout.getStableBounds(any())).thenAnswer { i -> @@ -177,7 +177,7 @@ class DesktopTilingWindowDecorationTest : ShellTestCase() { @Test fun taskTiled_notAnimated_whenTilingPositionNotChange() { - val task1 = createFreeformTask() + val task1 = createVisibleTask() val stableBounds = STABLE_BOUNDS_MOCK whenever(displayController.getDisplayLayout(any())).thenReturn(displayLayout) whenever(displayLayout.getStableBounds(any())).thenAnswer { i -> @@ -213,8 +213,8 @@ class DesktopTilingWindowDecorationTest : ShellTestCase() { @Test fun taskNotTiled_notBroughtToFront_tilingNotInitialised() { - val task1 = createFreeformTask() - val task2 = createFreeformTask() + val task1 = createVisibleTask() + val task2 = createVisibleTask() val stableBounds = STABLE_BOUNDS_MOCK whenever(displayController.getDisplayLayout(any())).thenReturn(displayLayout) whenever(displayLayout.getStableBounds(any())).thenAnswer { i -> @@ -236,9 +236,9 @@ class DesktopTilingWindowDecorationTest : ShellTestCase() { @Test fun taskNotTiled_notBroughtToFront_taskNotTiled() { - val task1 = createFreeformTask() - val task2 = createFreeformTask() - val task3 = createFreeformTask() + val task1 = createVisibleTask() + val task2 = createVisibleTask() + val task3 = createVisibleTask() val stableBounds = STABLE_BOUNDS_MOCK whenever(displayController.getDisplayLayout(any())).thenReturn(displayLayout) whenever(displayLayout.getStableBounds(any())).thenAnswer { i -> @@ -265,9 +265,9 @@ class DesktopTilingWindowDecorationTest : ShellTestCase() { } @Test - fun taskTiled_broughtToFront_alreadyInFrontNoAction() { - val task1 = createFreeformTask() - val task2 = createFreeformTask() + fun taskTiled_broughtToFront_alreadyInFrontStillReorder() { + val task1 = createVisibleTask() + val task2 = createVisibleTask() val stableBounds = STABLE_BOUNDS_MOCK whenever(displayController.getDisplayLayout(any())).thenReturn(displayLayout) whenever(displayLayout.getStableBounds(any())).thenAnswer { i -> @@ -275,6 +275,8 @@ class DesktopTilingWindowDecorationTest : ShellTestCase() { } whenever(context.resources).thenReturn(resources) whenever(resources.getDimensionPixelSize(any())).thenReturn(split_divider_width) + whenever(desktopRepository.isVisibleTask(eq(task1.taskId))).thenReturn(true) + whenever(desktopRepository.isVisibleTask(eq(task2.taskId))).thenReturn(true) tilingDecoration.onAppTiled( task1, @@ -290,15 +292,15 @@ class DesktopTilingWindowDecorationTest : ShellTestCase() { ) task1.isFocused = true - assertThat(tilingDecoration.moveTiledPairToFront(task1)).isFalse() - verify(transitions, never()).startTransition(any(), any(), any()) + assertThat(tilingDecoration.moveTiledPairToFront(task1, isTaskFocused = true)).isTrue() + verify(transitions, times(1)).startTransition(eq(TRANSIT_TO_FRONT), any(), eq(null)) } @Test fun taskTiled_broughtToFront_bringToFront() { - val task1 = createFreeformTask() - val task2 = createFreeformTask() - val task3 = createFreeformTask() + val task1 = createVisibleTask() + val task2 = createVisibleTask() + val task3 = createVisibleTask() val stableBounds = STABLE_BOUNDS_MOCK whenever(displayLayout.getStableBounds(any())).thenAnswer { i -> (i.arguments.first() as Rect).set(stableBounds) @@ -329,9 +331,9 @@ class DesktopTilingWindowDecorationTest : ShellTestCase() { @Test fun taskTiled_broughtToFront_taskInfoNotUpdated_bringToFront() { - val task1 = createFreeformTask() - val task2 = createFreeformTask() - val task3 = createFreeformTask() + val task1 = createVisibleTask() + val task2 = createVisibleTask() + val task3 = createVisibleTask() val stableBounds = STABLE_BOUNDS_MOCK whenever(displayLayout.getStableBounds(any())).thenAnswer { i -> (i.arguments.first() as Rect).set(stableBounds) @@ -361,8 +363,8 @@ class DesktopTilingWindowDecorationTest : ShellTestCase() { @Test fun taskTiledTasks_NotResized_BeforeTouchEndArrival() { // Setup - val task1 = createFreeformTask() - val task2 = createFreeformTask() + val task1 = createVisibleTask() + val task2 = createVisibleTask() val stableBounds = STABLE_BOUNDS_MOCK whenever(displayController.getDisplayLayout(any())).thenReturn(displayLayout) whenever(displayLayout.getStableBounds(any())).thenAnswer { i -> @@ -428,8 +430,8 @@ class DesktopTilingWindowDecorationTest : ShellTestCase() { @Test fun tiledTasksResizedUsingDividerHandle_shouldLogResizingEvents() { // Setup - val task1 = createFreeformTask() - val task2 = createFreeformTask() + val task1 = createVisibleTask() + val task2 = createVisibleTask() val stableBounds = STABLE_BOUNDS_MOCK whenever(displayController.getDisplayLayout(any())).thenReturn(displayLayout) whenever(displayLayout.getStableBounds(any())).thenAnswer { i -> @@ -487,7 +489,7 @@ class DesktopTilingWindowDecorationTest : ShellTestCase() { @Test fun taskTiled_shouldBeRemoved_whenTileBroken() { - val task1 = createFreeformTask() + val task1 = createVisibleTask() val stableBounds = STABLE_BOUNDS_MOCK whenever(displayController.getDisplayLayout(any())).thenReturn(displayLayout) whenever(displayLayout.getStableBounds(any())).thenAnswer { i -> @@ -516,8 +518,8 @@ class DesktopTilingWindowDecorationTest : ShellTestCase() { @Test fun taskNotTiled_shouldNotBeRemoved_whenNotTiled() { - val task1 = createFreeformTask() - val task2 = createFreeformTask() + val task1 = createVisibleTask() + val task2 = createVisibleTask() val stableBounds = STABLE_BOUNDS_MOCK whenever(displayController.getDisplayLayout(any())).thenReturn(displayLayout) whenever(displayLayout.getStableBounds(any())).thenAnswer { i -> @@ -545,8 +547,8 @@ class DesktopTilingWindowDecorationTest : ShellTestCase() { @Test fun tasksTiled_shouldBeRemoved_whenSessionDestroyed() { - val task1 = createFreeformTask() - val task2 = createFreeformTask() + val task1 = createVisibleTask() + val task2 = createVisibleTask() val stableBounds = STABLE_BOUNDS_MOCK whenever(displayController.getDisplayLayout(any())).thenReturn(displayLayout) whenever(displayLayout.getStableBounds(any())).thenAnswer { i -> @@ -610,6 +612,11 @@ class DesktopTilingWindowDecorationTest : ShellTestCase() { return Rect(stableBounds.left, stableBounds.top, rightBound, stableBounds.bottom) } + private fun createVisibleTask() = + createFreeformTask().also { + whenever(desktopRepository.isVisibleTask(eq(it.taskId))).thenReturn(true) + } + companion object { private val NON_STABLE_BOUNDS_MOCK = Rect(50, 55, 100, 100) private val STABLE_BOUNDS_MOCK = Rect(0, 0, 100, 100) diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/tiling/TilingDividerViewTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/tiling/TilingDividerViewTest.kt index 734815cdd915..9a9d05a72442 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/tiling/TilingDividerViewTest.kt +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/tiling/TilingDividerViewTest.kt @@ -19,9 +19,12 @@ package com.android.wm.shell.windowdecor.tiling import android.graphics.Rect import android.os.SystemClock import android.testing.AndroidTestingRunner +import android.util.Size +import android.view.Display import android.view.InputDevice import android.view.LayoutInflater import android.view.MotionEvent +import android.view.RoundedCorner import android.view.View import androidx.test.annotation.UiThreadTest import androidx.test.filters.SmallTest @@ -46,16 +49,19 @@ class TilingDividerViewTest : ShellTestCase() { private val dividerMoveCallbackMock = mock<DividerMoveCallback>() private val viewMock = mock<View>() + private val display = mock<Display>() + private val roundedCorner = mock<RoundedCorner>() @Before @UiThreadTest fun setUp() { + whenever(display.getRoundedCorner(any())).thenReturn(roundedCorner) + whenever(roundedCorner.radius).thenReturn(CORNER_RADIUS) tilingDividerView = LayoutInflater.from(mContext).inflate(R.layout.tiling_split_divider, /* root= */ null) as TilingDividerView - tilingDividerView.setup(dividerMoveCallbackMock, BOUNDS) - tilingDividerView.handleStartY = 0 - tilingDividerView.handleEndY = 1500 + tilingDividerView.setup(dividerMoveCallbackMock, DIVIDER_BOUNDS, HANDLE_SIZE) + tilingDividerView.handleY = 0..1500 } @Test @@ -130,6 +136,8 @@ class TilingDividerViewTest : ShellTestCase() { } companion object { - private val BOUNDS = Rect(0, 0, 1500, 1500) + private val DIVIDER_BOUNDS = Rect(15, 0, 35, 1500) + private val HANDLE_SIZE = Size(800, 300) + private const val CORNER_RADIUS = 15 } } diff --git a/libs/hwui/jni/ColorFilter.cpp b/libs/hwui/jni/ColorFilter.cpp index 20301d2c76ec..1c6d886f18b7 100644 --- a/libs/hwui/jni/ColorFilter.cpp +++ b/libs/hwui/jni/ColorFilter.cpp @@ -163,6 +163,20 @@ public: filter->updateChild(env, name.c_str(), child); } } + + static void RuntimeColorFilter_updateInputColorFilter(JNIEnv* env, jobject, + jlong colorFilterPtr, jstring childName, + jlong childFilterPtr) { + auto* filter = reinterpret_cast<RuntimeColorFilter*>(colorFilterPtr); + ScopedUtfChars name(env, childName); + auto* child = reinterpret_cast<ColorFilter*>(childFilterPtr); + if (filter && child) { + auto childInput = child->getInstance(); + if (childInput) { + filter->updateChild(env, name.c_str(), childInput.release()); + } + } + } }; static const JNINativeMethod colorfilter_methods[] = { @@ -193,7 +207,9 @@ static const JNINativeMethod runtime_color_filter_methods[] = { {"nativeUpdateUniforms", "(JLjava/lang/String;IIIII)V", (void*)ColorFilterGlue::RuntimeColorFilter_updateUniformsInts}, {"nativeUpdateChild", "(JLjava/lang/String;J)V", - (void*)ColorFilterGlue::RuntimeColorFilter_updateChild}}; + (void*)ColorFilterGlue::RuntimeColorFilter_updateChild}, + {"nativeUpdateInputColorFilter", "(JLjava/lang/String;J)V", + (void*)ColorFilterGlue::RuntimeColorFilter_updateInputColorFilter}}; int register_android_graphics_ColorFilter(JNIEnv* env) { android::RegisterMethodsOrDie(env, "android/graphics/ColorFilter", colorfilter_methods, diff --git a/libs/hwui/jni/RuntimeXfermode.cpp b/libs/hwui/jni/RuntimeXfermode.cpp index c1c8964bf5eb..17bee8fb8b15 100644 --- a/libs/hwui/jni/RuntimeXfermode.cpp +++ b/libs/hwui/jni/RuntimeXfermode.cpp @@ -14,6 +14,7 @@ * limitations under the License. */ +#include "ColorFilter.h" #include "GraphicsJNI.h" #include "RuntimeEffectUtils.h" #include "SkBlender.h" @@ -93,6 +94,19 @@ static void RuntimeXfermode_updateChild(JNIEnv* env, jobject, jlong builderPtr, } } +static void RuntimeXfermode_updateColorFilter(JNIEnv* env, jobject, jlong builderPtr, + jstring childName, jlong colorFilterPtr) { + auto* builder = reinterpret_cast<SkRuntimeEffectBuilder*>(builderPtr); + ScopedUtfChars name(env, childName); + auto* child = reinterpret_cast<ColorFilter*>(colorFilterPtr); + if (child) { + auto childInput = child->getInstance(); + if (childInput) { + UpdateChild(env, builder, name.c_str(), childInput.release()); + } + } +} + static const JNINativeMethod gRuntimeXfermodeMethods[] = { {"nativeGetFinalizer", "()J", (void*)RuntimeXfermode_getNativeFinalizer}, {"nativeCreateBlenderBuilder", "(Ljava/lang/String;)J", @@ -107,6 +121,8 @@ static const JNINativeMethod gRuntimeXfermodeMethods[] = { {"nativeUpdateUniforms", "(JLjava/lang/String;IIIII)V", (void*)RuntimeXfermode_updateIntUniforms}, {"nativeUpdateChild", "(JLjava/lang/String;J)V", (void*)RuntimeXfermode_updateChild}, + {"nativeUpdateColorFilter", "(JLjava/lang/String;J)V", + (void*)RuntimeXfermode_updateColorFilter}, }; int register_android_graphics_RuntimeXfermode(JNIEnv* env) { diff --git a/libs/hwui/jni/Shader.cpp b/libs/hwui/jni/Shader.cpp index 018c2b1374d0..eadb9dea566f 100644 --- a/libs/hwui/jni/Shader.cpp +++ b/libs/hwui/jni/Shader.cpp @@ -1,5 +1,6 @@ #include <vector> +#include "ColorFilter.h" #include "Gainmap.h" #include "GraphicsJNI.h" #include "RuntimeEffectUtils.h" @@ -331,6 +332,15 @@ static void RuntimeShader_updateShader(JNIEnv* env, jobject, jlong shaderBuilder builder->child(name.c_str()) = sk_ref_sp(shader); } +static void RuntimeShader_updateColorFilter(JNIEnv* env, jobject, jlong shaderBuilder, + jstring jUniformName, jlong colorFilterHandle) { + SkRuntimeShaderBuilder* builder = reinterpret_cast<SkRuntimeShaderBuilder*>(shaderBuilder); + ScopedUtfChars name(env, jUniformName); + auto* childEffect = reinterpret_cast<ColorFilter*>(colorFilterHandle); + + UpdateChild(env, builder, name.c_str(), childEffect->getInstance().release()); +} + static void RuntimeShader_updateChild(JNIEnv* env, jobject, jlong shaderBuilder, jstring jUniformName, jlong childHandle) { SkRuntimeShaderBuilder* builder = reinterpret_cast<SkRuntimeShaderBuilder*>(shaderBuilder); @@ -380,6 +390,8 @@ static const JNINativeMethod gRuntimeShaderMethods[] = { {"nativeUpdateUniforms", "(JLjava/lang/String;IIIII)V", (void*)RuntimeShader_updateIntUniforms}, {"nativeUpdateShader", "(JLjava/lang/String;J)V", (void*)RuntimeShader_updateShader}, + {"nativeUpdateColorFilter", "(JLjava/lang/String;J)V", + (void*)RuntimeShader_updateColorFilter}, {"nativeUpdateChild", "(JLjava/lang/String;J)V", (void*)RuntimeShader_updateChild}, }; diff --git a/media/java/android/media/AudioPlaybackConfiguration.java b/media/java/android/media/AudioPlaybackConfiguration.java index c085b8985783..62fb0120a97d 100644 --- a/media/java/android/media/AudioPlaybackConfiguration.java +++ b/media/java/android/media/AudioPlaybackConfiguration.java @@ -311,12 +311,18 @@ public final class AudioPlaybackConfiguration implements Parcelable { @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public static final int MUTED_BY_PORT_VOLUME = (1 << 6); + /** + * @hide + * Flag used when playback is muted by AppOpsManager#OP_CONTROL_AUDIO. + */ + public static final int MUTED_BY_OP_CONTROL_AUDIO = (1 << 7); + /** @hide */ @IntDef( flag = true, value = {MUTED_BY_MASTER, MUTED_BY_STREAM_VOLUME, MUTED_BY_STREAM_MUTED, MUTED_BY_APP_OPS, MUTED_BY_CLIENT_VOLUME, MUTED_BY_VOLUME_SHAPER, - MUTED_BY_PORT_VOLUME}) + MUTED_BY_PORT_VOLUME, MUTED_BY_OP_CONTROL_AUDIO}) @Retention(RetentionPolicy.SOURCE) public @interface PlayerMuteEvent { } @@ -914,6 +920,9 @@ public final class AudioPlaybackConfiguration implements Parcelable { if ((mMutedState & MUTED_BY_PORT_VOLUME) != 0) { apcToString.append("portVolume "); } + if ((mMutedState & MUTED_BY_OP_CONTROL_AUDIO) != 0) { + apcToString.append("opControlAudio "); + } } apcToString.append(" ").append(mFormatInfo); } diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl index 08b0dd3fb11c..54a87ad7fd39 100644 --- a/media/java/android/media/IAudioService.aidl +++ b/media/java/android/media/IAudioService.aidl @@ -640,6 +640,9 @@ interface IAudioService { boolean canBeSpatialized(in AudioAttributes aa, in AudioFormat af); + /* Returns a List<Integer> */ + List getSpatializedChannelMasks(); + void registerSpatializerCallback(in ISpatializerCallback cb); void unregisterSpatializerCallback(in ISpatializerCallback cb); diff --git a/media/java/android/media/MediaFormat.java b/media/java/android/media/MediaFormat.java index 4f94c3e984db..50387548b4ab 100644 --- a/media/java/android/media/MediaFormat.java +++ b/media/java/android/media/MediaFormat.java @@ -16,12 +16,12 @@ package android.media; - import static android.media.audio.Flags.FLAG_IAMF_DEFINITIONS_API; +import static android.media.codec.Flags.FLAG_APV_SUPPORT; import static android.media.codec.Flags.FLAG_IN_PROCESS_SW_AUDIO_CODEC; import static android.media.codec.Flags.FLAG_NUM_INPUT_SLOTS; import static android.media.codec.Flags.FLAG_REGION_OF_INTEREST; -import static android.media.codec.Flags.FLAG_APV_SUPPORT; +import static android.media.tv.flags.Flags.FLAG_APPLY_PICTURE_PROFILES; import static com.android.media.codec.flags.Flags.FLAG_CODEC_IMPORTANCE; import static com.android.media.codec.flags.Flags.FLAG_LARGE_AUDIO_FRAME; @@ -1796,6 +1796,27 @@ public final class MediaFormat { public static final String KEY_NUM_SLOTS = "num-slots"; /** + * A key describing the picture profile ID to be applied to {@link MediaCodec}. + * <p> + * The associated value is a string. + * <p> + * @see {@link android.media.quality.PictureProfile} + * @see {@link android.media.quality.PictureProfile#getProfileId} + */ + @FlaggedApi(FLAG_APPLY_PICTURE_PROFILES) + public static final String KEY_PICTURE_PROFILE_ID = "picture-profile-id"; + + /** + * A key describing the picture profile instance to be applied to {@link MediaCodec}. + * <p> + * The associated value is an instance of {@link android.media.quality.PictureProfile}. + * <p> + * @see {@link android.media.quality.PictureProfile} + */ + @FlaggedApi(FLAG_APPLY_PICTURE_PROFILES) + public static final String KEY_PICTURE_PROFILE_INSTANCE = "picture-profile-instance"; + + /** * QpOffsetRect constitutes the metadata required for encoding a region of interest in an * image or a video frame. The region of interest is represented by a rectangle. The four * integer coordinates of the rectangle are stored in fields left, top, right, bottom. diff --git a/media/java/android/media/Spatializer.java b/media/java/android/media/Spatializer.java index 99fcaf29688c..95c4ad3c3a7f 100644 --- a/media/java/android/media/Spatializer.java +++ b/media/java/android/media/Spatializer.java @@ -16,7 +16,10 @@ package android.media; +import static android.media.audio.Flags.FLAG_SPATIALIZER_CAPABILITIES; + import android.annotation.CallbackExecutor; +import android.annotation.FlaggedApi; import android.annotation.IntDef; import android.annotation.IntRange; import android.annotation.NonNull; @@ -35,6 +38,7 @@ import com.android.internal.annotations.GuardedBy; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.Objects; import java.util.concurrent.Executor; @@ -527,6 +531,28 @@ public class Spatializer { } /** + * Returns a list of channel masks that represent the widest channel masks the spatializer + * is capable of rendering with individual channel positions. + * For instance a spatializer may only support virtual speaker positions for 5.1, it would + * therefore return {@link AudioFormat#CHANNEL_OUT_5POINT1}. But it would still return + * <code>true</code> when querying {@link #canBeSpatialized(AudioAttributes, AudioFormat)} it + * with a channel mask of {@link AudioFormat#CHANNEL_OUT_7POINT1POINT2}: the sound present + * in each channel would still be heard, but the sounds from the rear, side and top pairs would + * be mixed together, and be spatialized at the same location. + * @return a list of channel masks following the <code>CHANNEL_OUT_*</code> output channel + * definitions found in {@link AudioFormat}. + */ + @FlaggedApi(FLAG_SPATIALIZER_CAPABILITIES) + public @NonNull List<Integer> getSpatializedChannelMasks() { + try { + return mAm.getService().getSpatializedChannelMasks(); + } catch (RemoteException e) { + Log.e(TAG, "Error querying getSpatializedChannelMasks", e); + return Collections.emptyList(); + } + } + + /** * Adds a listener to be notified of changes to the enabled state of the * {@code Spatializer}. * @param executor the {@code Executor} handling the callback diff --git a/media/java/android/media/flags/media_better_together.aconfig b/media/java/android/media/flags/media_better_together.aconfig index d8a8c8b0ee2a..bbe8e4ed7b34 100644 --- a/media/java/android/media/flags/media_better_together.aconfig +++ b/media/java/android/media/flags/media_better_together.aconfig @@ -141,6 +141,14 @@ flag { } flag { + name: "enable_route_visibility_control_api" + namespace: "media_better_together" + description: "API changes to allow more control over route visibility by route providers" + bug: "367799834" + is_exported: true +} + +flag { name: "enable_screen_off_scanning" is_exported: true namespace: "media_solutions" diff --git a/media/java/android/media/projection/IMediaProjection.aidl b/media/java/android/media/projection/IMediaProjection.aidl index 8ee966ddc377..dacd1bd06cc0 100644 --- a/media/java/android/media/projection/IMediaProjection.aidl +++ b/media/java/android/media/projection/IMediaProjection.aidl @@ -17,13 +17,14 @@ package android.media.projection; import android.media.projection.IMediaProjectionCallback; +import android.media.projection.StopReason; import android.os.IBinder; import android.app.ActivityOptions.LaunchCookie; /** {@hide} */ interface IMediaProjection { void start(IMediaProjectionCallback callback); - void stop(); + void stop(StopReason stopReason); boolean canProjectAudio(); boolean canProjectVideo(); diff --git a/media/java/android/media/projection/IMediaProjectionManager.aidl b/media/java/android/media/projection/IMediaProjectionManager.aidl index b104972572b9..1d92eabb726d 100644 --- a/media/java/android/media/projection/IMediaProjectionManager.aidl +++ b/media/java/android/media/projection/IMediaProjectionManager.aidl @@ -16,11 +16,13 @@ package android.media.projection; +import android.graphics.Rect; import android.media.projection.IMediaProjection; import android.media.projection.IMediaProjectionCallback; import android.media.projection.IMediaProjectionWatcherCallback; import android.media.projection.MediaProjectionInfo; import android.media.projection.ReviewGrantedConsentResult; +import android.media.projection.StopReason; import android.os.IBinder; import android.view.ContentRecordingSession; @@ -107,12 +109,7 @@ interface IMediaProjectionManager { @EnforcePermission("MANAGE_MEDIA_PROJECTION") @JavaPassthrough(annotation = "@android.annotation.RequiresPermission(android.Manifest" + ".permission.MANAGE_MEDIA_PROJECTION)") - void stopActiveProjection(); - - @EnforcePermission("MANAGE_MEDIA_PROJECTION") - @JavaPassthrough(annotation = "@android.annotation.RequiresPermission(android.Manifest" - + ".permission.MANAGE_MEDIA_PROJECTION)") - void notifyActiveProjectionCapturedContentResized(int width, int height); + void stopActiveProjection(in StopReason stopReason); @EnforcePermission("MANAGE_MEDIA_PROJECTION") @JavaPassthrough(annotation = "@android.annotation.RequiresPermission(android.Manifest" @@ -227,5 +224,11 @@ interface IMediaProjectionManager { @EnforcePermission("MANAGE_MEDIA_PROJECTION") @JavaPassthrough(annotation = "@android.annotation.RequiresPermission(android.Manifest" + ".permission.MANAGE_MEDIA_PROJECTION)") - void notifyWindowingModeChanged(int contentToRecord, int targetProcessUid, int windowingMode); + oneway void notifyWindowingModeChanged(int contentToRecord, int targetProcessUid, int windowingMode); + + @EnforcePermission("MANAGE_MEDIA_PROJECTION") + @JavaPassthrough(annotation = "@android.annotation.RequiresPermission(android.Manifest" + + ".permission.MANAGE_MEDIA_PROJECTION)") + oneway void notifyCaptureBoundsChanged(int contentToRecord, int targetProcessUid, + in Rect captureBounds); } diff --git a/media/java/android/media/projection/MediaProjection.java b/media/java/android/media/projection/MediaProjection.java index 4114f5359ace..f7f10df5786a 100644 --- a/media/java/android/media/projection/MediaProjection.java +++ b/media/java/android/media/projection/MediaProjection.java @@ -317,7 +317,7 @@ public final class MediaProjection { public void stop() { try { Log.d(TAG, "Content Recording: stopping projection"); - mImpl.stop(); + mImpl.stop(StopReason.STOP_HOST_APP); } catch (RemoteException e) { Log.e(TAG, "Unable to stop projection", e); } diff --git a/media/java/android/media/projection/MediaProjectionManager.java b/media/java/android/media/projection/MediaProjectionManager.java index dc55e41fb74c..9cc2cca441a4 100644 --- a/media/java/android/media/projection/MediaProjectionManager.java +++ b/media/java/android/media/projection/MediaProjectionManager.java @@ -297,10 +297,10 @@ public final class MediaProjectionManager { * Stop the current projection if there is one. * @hide */ - public void stopActiveProjection() { + public void stopActiveProjection(@StopReason int stopReason) { try { Log.d(TAG, "Content Recording: stopping active projection"); - mService.stopActiveProjection(); + mService.stopActiveProjection(stopReason); } catch (RemoteException e) { Log.e(TAG, "Unable to stop the currently active media projection", e); } diff --git a/media/java/android/media/projection/StopReason.aidl b/media/java/android/media/projection/StopReason.aidl new file mode 100644 index 000000000000..8611def3d2b9 --- /dev/null +++ b/media/java/android/media/projection/StopReason.aidl @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.media.projection; + +/** + * Identifies the reason for a MediaProjection being stopped (for metric logging purposes) + * @hide + */ +@Backing(type="int") +enum StopReason { + STOP_UNKNOWN = 0, + STOP_HOST_APP = 1, + STOP_TARGET_REMOVED = 2, + STOP_DEVICE_LOCKED = 3, + STOP_PRIVACY_CHIP = 4, + STOP_QS_TILE = 5, + STOP_USER_SWITCH = 6, + STOP_FOREGROUND_SERVICE_CHANGE = 7, + STOP_NEW_PROJECTION = 8, + STOP_NEW_MEDIA_ROUTE = 9, + STOP_ERROR = 10, +} diff --git a/media/java/android/media/tv/extension/analog/IAnalogAttributeInterface.aidl b/media/java/android/media/tv/extension/analog/IAnalogAttributeInterface.aidl new file mode 100644 index 000000000000..550acba8ed65 --- /dev/null +++ b/media/java/android/media/tv/extension/analog/IAnalogAttributeInterface.aidl @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.media.tv.extension.analog; + +/** + * @hide + */ +interface IAnalogAttributeInterface { + int getVersion(); + void setColorSystemCapability(in String[] list); + String[] getColorSystemCapability(); +} diff --git a/media/java/android/media/tv/extension/cam/ICamAppInfoListener.aidl b/media/java/android/media/tv/extension/cam/ICamAppInfoListener.aidl new file mode 100644 index 000000000000..73ae209062d6 --- /dev/null +++ b/media/java/android/media/tv/extension/cam/ICamAppInfoListener.aidl @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.media.tv.extension.cam; + +import android.os.Bundle; + +/** + * @hide + */ +oneway interface ICamAppInfoListener { + void onCamAppInfoChanged(int slotId, in Bundle appInfo); +} diff --git a/media/java/android/media/tv/extension/cam/ICamAppInfoService.aidl b/media/java/android/media/tv/extension/cam/ICamAppInfoService.aidl new file mode 100644 index 000000000000..d3a03bc80056 --- /dev/null +++ b/media/java/android/media/tv/extension/cam/ICamAppInfoService.aidl @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.media.tv.extension.cam; + +import android.media.tv.extension.cam.ICamAppInfoListener; +import android.os.Bundle; + +/** + * @hide + */ +interface ICamAppInfoService { + // Register ICamAppInfoListener to get CICAM Application Information updates. + void addCamAppInfoListener(ICamAppInfoListener listener); + // Unregister ICamAppInfoListener and stop get Application Information notify. + void removeCamAppInfoListener(ICamAppInfoListener listener); + // Get the Application Information of the CICAM. + int getCamAppInfo(int slotId, out Bundle appInfo); +} diff --git a/media/java/android/media/tv/extension/cam/ICamDrmInfoListener.aidl b/media/java/android/media/tv/extension/cam/ICamDrmInfoListener.aidl new file mode 100644 index 000000000000..c727837ed07e --- /dev/null +++ b/media/java/android/media/tv/extension/cam/ICamDrmInfoListener.aidl @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.media.tv.extension.cam; + +import android.os.Bundle; + +/** + * @hide + */ +oneway interface ICamDrmInfoListener { + void onCamDrmInfoChanged(int slotId, in Bundle camDrmInfo); +} diff --git a/media/java/android/media/tv/extension/cam/ICamHostControlAskReleaseReplyCallback.aidl b/media/java/android/media/tv/extension/cam/ICamHostControlAskReleaseReplyCallback.aidl new file mode 100644 index 000000000000..83f2c01e4681 --- /dev/null +++ b/media/java/android/media/tv/extension/cam/ICamHostControlAskReleaseReplyCallback.aidl @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.media.tv.extension.cam; + +/** + * @hide + */ +oneway interface ICamHostControlAskReleaseReplyCallback { + void onAskReleaseReply(String sessionToken, int replyStatus); +} diff --git a/media/java/android/media/tv/extension/cam/ICamHostControlInfoListener.aidl b/media/java/android/media/tv/extension/cam/ICamHostControlInfoListener.aidl new file mode 100644 index 000000000000..f48ca57cccdc --- /dev/null +++ b/media/java/android/media/tv/extension/cam/ICamHostControlInfoListener.aidl @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.media.tv.extension.cam; + +/** + * @hide + */ +oneway interface ICamHostControlInfoListener { + void onCamHostControlInfoChanged(String sessionToken, int sessionStatus); +} diff --git a/media/java/android/media/tv/extension/cam/ICamHostControlService.aidl b/media/java/android/media/tv/extension/cam/ICamHostControlService.aidl new file mode 100644 index 000000000000..6f6c376c1ffa --- /dev/null +++ b/media/java/android/media/tv/extension/cam/ICamHostControlService.aidl @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.media.tv.extension.cam; + +import android.media.tv.extension.cam.ICamHostControlAskReleaseReplyCallback; +import android.media.tv.extension.cam.ICamHostControlInfoListener; + +/** + * @hide + */ +interface ICamHostControlService { + // Register the listener to monitor host control session updates. + void addCamHostcontrolInfoListener(ICamHostControlInfoListener listener); + // Unregister ICamHostControlInfoListener and stop monitoring. + void removeCamHostcontrolInfoListener(ICamHostControlInfoListener listener); + // Request CICAM to release the resource. + int sendCamHostControlAskRelease(String sessionToken, + ICamHostControlAskReleaseReplyCallback callback); + // Enable/disable the host control mode. + void setHostControlMode(String sessionToken, boolean enable); +} diff --git a/media/java/android/media/tv/extension/cam/ICamHostControlTuneQuietlyFlag.aidl b/media/java/android/media/tv/extension/cam/ICamHostControlTuneQuietlyFlag.aidl new file mode 100644 index 000000000000..25a78b99d659 --- /dev/null +++ b/media/java/android/media/tv/extension/cam/ICamHostControlTuneQuietlyFlag.aidl @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.media.tv.extension.cam; + +import android.media.tv.extension.cam.ICamHostControlTuneQuietlyFlagListener; +import android.os.Bundle; + +/** + * @hide + */ +interface ICamHostControlTuneQuietlyFlag { + // Register listener to notify host control tune_quietly_flag. + void addHcTuneQuietlyFlagListener(ICamHostControlTuneQuietlyFlagListener listener); + // Remove listener and stop monitor host control tune_quietly_flag. + void removeHcTuneQuietlyFlagListener(ICamHostControlTuneQuietlyFlagListener listener); + // Returns host control tune_quietly_flag value. + Bundle getHcTuneQuietlyFlag(String sessionToken); +} diff --git a/media/java/android/media/tv/extension/cam/ICamHostControlTuneQuietlyFlagListener.aidl b/media/java/android/media/tv/extension/cam/ICamHostControlTuneQuietlyFlagListener.aidl new file mode 100644 index 000000000000..5967124e5202 --- /dev/null +++ b/media/java/android/media/tv/extension/cam/ICamHostControlTuneQuietlyFlagListener.aidl @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.media.tv.extension.cam; + +/** + * @hide + */ +oneway interface ICamHostControlTuneQuietlyFlagListener { + void onHcTuneQuietlyFlagChanged(String sessionToken, int tuneQuietlyFlag); +} diff --git a/media/java/android/media/tv/extension/cam/ICamInfoListener.aidl b/media/java/android/media/tv/extension/cam/ICamInfoListener.aidl new file mode 100644 index 000000000000..5410bffaa92d --- /dev/null +++ b/media/java/android/media/tv/extension/cam/ICamInfoListener.aidl @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.media.tv.extension.cam; + +import android.os.Bundle; + +/** + * @hide + */ +oneway interface ICamInfoListener { + void onCamInfoChanged(int slotId, in Bundle updatedCamInfo); + void onSlotInfoChanged(int slotId, in Bundle updatedSlotInfo); + void onNewTypeCamInsert(int slotId, in Bundle newCamType); +} diff --git a/media/java/android/media/tv/extension/cam/ICamMonitoringService.aidl b/media/java/android/media/tv/extension/cam/ICamMonitoringService.aidl new file mode 100644 index 000000000000..7b8014c5880f --- /dev/null +++ b/media/java/android/media/tv/extension/cam/ICamMonitoringService.aidl @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.media.tv.extension.cam; + +import android.media.tv.extension.cam.ICamInfoListener; +import android.os.Bundle; + +/** + * @hide + */ +interface ICamMonitoringService { + // Register a listener for slot/CAM info updates. + void addCamInfoListener(in ICamInfoListener listener); + // Unregister a listener for slot/CAM info updates. + void removeCamInfoListener(in ICamInfoListener listener); + // Get CAM information for the specified slot. + Bundle getCamInfo(int slotId); + // Get slot information. + Bundle getSlotInfo(int slotId); + // Returns list of slot Ids. + int[] getSlotIds(); + // Check if the country supports CAM. + boolean isCamSupported(); +} diff --git a/media/java/android/media/tv/extension/cam/ICamPinCapabilityListener.aidl b/media/java/android/media/tv/extension/cam/ICamPinCapabilityListener.aidl new file mode 100644 index 000000000000..f92304af9ade --- /dev/null +++ b/media/java/android/media/tv/extension/cam/ICamPinCapabilityListener.aidl @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.media.tv.extension.cam; + +import android.os.Bundle; + +/** + * @hide + */ +oneway interface ICamPinCapabilityListener { + void onCamPinCapabilityChanged(int slotId, in Bundle bundle); +} diff --git a/media/java/android/media/tv/extension/cam/ICamPinService.aidl b/media/java/android/media/tv/extension/cam/ICamPinService.aidl new file mode 100644 index 000000000000..3f6cb2813c74 --- /dev/null +++ b/media/java/android/media/tv/extension/cam/ICamPinService.aidl @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.media.tv.extension.cam; + +import android.media.tv.extension.cam.ICamPinCapabilityListener; +import android.media.tv.extension.cam.ICamPinStatusListener; +import android.os.Bundle; + +/** + * @hide + */ +interface ICamPinService { + // Register ICamPinCapabilityListener to get CICAM updates. + void addCamPinCapabilityListener(in ICamPinCapabilityListener listener); + // Unregister ICamPinCapabilityListener and stop monitor PIN status and PIN capability. + void removeCamPinCapabilityListener(in ICamPinCapabilityListener listener); + // Send the PinCode that needs to be validated by CICAM. + int requestCamPinValidation(int slotId, in int[] pinCode, in ICamPinStatusListener listener); + // Get the PIN capabilities of the CICAM. + int getCamPinCapability(int slotId, out Bundle camPinCapability); +} diff --git a/media/java/android/media/tv/extension/cam/ICamPinStatusListener.aidl b/media/java/android/media/tv/extension/cam/ICamPinStatusListener.aidl new file mode 100644 index 000000000000..efbc394897d3 --- /dev/null +++ b/media/java/android/media/tv/extension/cam/ICamPinStatusListener.aidl @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.media.tv.extension.cam; + +import android.os.Bundle; + +/** + * @hide + */ +oneway interface ICamPinStatusListener { + void onCamPinValidationReply(int slotId, in Bundle bundle); +} diff --git a/media/java/android/media/tv/extension/cam/ICamProfileInterface.aidl b/media/java/android/media/tv/extension/cam/ICamProfileInterface.aidl new file mode 100644 index 000000000000..3f1d40caa9c9 --- /dev/null +++ b/media/java/android/media/tv/extension/cam/ICamProfileInterface.aidl @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.media.tv.extension.cam; + +import android.os.Bundle; + +/** + * @hide + */ +interface ICamProfileInterface { + // Get CAM service update information for special slot. + Bundle getCamServiceUpdateInfo(int slotNumber); + // Request CAM TIS resend cam info update broadcast message when APK boot up. + void requestResendProfileInfoBroadcastACON(); +} diff --git a/media/java/android/media/tv/extension/cam/IContentControlService.aidl b/media/java/android/media/tv/extension/cam/IContentControlService.aidl new file mode 100644 index 000000000000..6db79abacb76 --- /dev/null +++ b/media/java/android/media/tv/extension/cam/IContentControlService.aidl @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.media.tv.extension.cam; + +import android.media.tv.extension.cam.ICamDrmInfoListener; +import android.os.Bundle; + +/** + * @hide + */ +interface IContentControlService { + // Register the listener to notify the DRM info changed by the CICAM. + void addCamDrmInfoListener(in ICamDrmInfoListener listener); + // Unregister listener to stop monitor DRM Info. + void removeCamDrmInfoListener(in ICamDrmInfoListener listener); + // Get the DRM Info of current watching channel. + int getCamDrmInfo(int slotId, out Bundle camDrmInfo); +} diff --git a/media/java/android/media/tv/extension/cam/IEnterMenuErrorCallback.aidl b/media/java/android/media/tv/extension/cam/IEnterMenuErrorCallback.aidl new file mode 100644 index 000000000000..ff61ddcbcc2f --- /dev/null +++ b/media/java/android/media/tv/extension/cam/IEnterMenuErrorCallback.aidl @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.media.tv.extension.cam; + +/** + * @hide + */ +oneway interface IEnterMenuErrorCallback { + void onAppInfoEnterMenuError(); +} diff --git a/media/java/android/media/tv/extension/cam/IMmiInterface.aidl b/media/java/android/media/tv/extension/cam/IMmiInterface.aidl new file mode 100644 index 000000000000..17a2a9c6771f --- /dev/null +++ b/media/java/android/media/tv/extension/cam/IMmiInterface.aidl @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.media.tv.extension.cam; + +import android.media.tv.extension.cam.IEnterMenuErrorCallback; +import android.media.tv.extension.cam.IMmiSession; +import android.media.tv.extension.cam.IMmiStatusCallback; + + +/** + * @hide + */ +interface IMmiInterface { + // Open a session for MMI. + IMmiSession openSession(int slotId, IMmiStatusCallback callback); + // Request to display CI Module setup screen. + void appInfoEnterMenu(int slotId, IEnterMenuErrorCallback callback); +} diff --git a/media/java/android/media/tv/extension/cam/IMmiSession.aidl b/media/java/android/media/tv/extension/cam/IMmiSession.aidl new file mode 100644 index 000000000000..c4f276219c55 --- /dev/null +++ b/media/java/android/media/tv/extension/cam/IMmiSession.aidl @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.media.tv.extension.cam; + +/** + * @hide + */ +interface IMmiSession { + // Send user answers to CAM on the MMI Menu screen. + void setMenuListAnswer(int response); + // Send user answers to CAM on the MMI Enq screen. + void setEnquiryAnswer(int answerId, String answer); + // Send CloseMmi APDU to Cam. + void closeMmi(); + // Release MMI session. + void close(); +} diff --git a/media/java/android/media/tv/extension/cam/IMmiStatusCallback.aidl b/media/java/android/media/tv/extension/cam/IMmiStatusCallback.aidl new file mode 100644 index 000000000000..3e68ced6a1ce --- /dev/null +++ b/media/java/android/media/tv/extension/cam/IMmiStatusCallback.aidl @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.media.tv.extension.cam; + +import android.os.Bundle; + +/** + * @hide + */ +oneway interface IMmiStatusCallback { + void onMmiEnq(in Bundle request); + void onMmiListMenu(in Bundle request); + void onMmiClose(); +} diff --git a/media/java/android/media/tv/extension/clienttoken/IClientToken.aidl b/media/java/android/media/tv/extension/clienttoken/IClientToken.aidl new file mode 100644 index 000000000000..fa701b3c01ad --- /dev/null +++ b/media/java/android/media/tv/extension/clienttoken/IClientToken.aidl @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.media.tv.extension.clienttoken; + +/** + * @hide + */ +interface IClientToken { + String generateClientToken(); +} diff --git a/media/java/android/media/tv/extension/event/IEventDownload.aidl b/media/java/android/media/tv/extension/event/IEventDownload.aidl new file mode 100644 index 000000000000..29c7553e1014 --- /dev/null +++ b/media/java/android/media/tv/extension/event/IEventDownload.aidl @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.media.tv.extension.event; + +import android.media.tv.extension.event.IEventDownloadListener; +import android.os.Bundle; +import android.os.IBinder; + +/** + * @hide + */ +interface IEventDownload { + // Create an event download session and return it as a Ibinder for DVB/DTMB + IBinder createSession(in Bundle eventDownloadParams, in IEventDownloadListener listener); +} diff --git a/media/java/android/media/tv/extension/event/IEventDownloadListener.aidl b/media/java/android/media/tv/extension/event/IEventDownloadListener.aidl new file mode 100644 index 000000000000..6d7d61f15d27 --- /dev/null +++ b/media/java/android/media/tv/extension/event/IEventDownloadListener.aidl @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.media.tv.extension.event; + +import android.os.Bundle; + +/** + * @hide + */ +oneway interface IEventDownloadListener { + void onCompleted(in Bundle status); +} diff --git a/media/java/android/media/tv/extension/event/IEventDownloadSession.aidl b/media/java/android/media/tv/extension/event/IEventDownloadSession.aidl new file mode 100644 index 000000000000..fe7ee37b324b --- /dev/null +++ b/media/java/android/media/tv/extension/event/IEventDownloadSession.aidl @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.media.tv.extension.event; + +import android.net.Uri; +import android.os.Bundle; + +/** + * @hide + */ +interface IEventDownloadSession { + // Determine to execute barker channel or silent tune flow for related service type + int isBarkerOrSequentialDownloadByServiceType(in Bundle eventDownloadParams); + // Determine whether to start barker channel or silent tune flow. + int isBarkerOrSequentialDownloadByServiceRecord(in Bundle eventDownloadParams); + // Start event download. + void startTuningMultiplex(in Uri channelUri); + // Set active window channels. + void setActiveWindowChannelInfo(in Uri[] activeWinChannelInfos); + // Cancel barker channel or silent tune flow. + void cancel(); + // Release barker channel or silent tune flow. + void release(); +} diff --git a/media/java/android/media/tv/extension/event/IEventMonitor.aidl b/media/java/android/media/tv/extension/event/IEventMonitor.aidl new file mode 100644 index 000000000000..f6e7bd134e78 --- /dev/null +++ b/media/java/android/media/tv/extension/event/IEventMonitor.aidl @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.media.tv.extension.event; + +import android.media.tv.extension.event.IEventMonitorListener; +import android.net.Uri; +import android.os.Bundle; + +/** + * @hide + */ +interface IEventMonitor { + // Get present event information. + Bundle getPresentEventInfo(long channelDbId); + // Add present event information listener. + void addPresentEventInfoListener(in IEventMonitorListener listener); + // Remove present event information listener. + void removePresentEventInfoListener(in IEventMonitorListener listener); + // Get following event information. + Bundle getFollowingEventInfo(long channelDbId); + // Add following event information listener. + void addFollowingEventInfoListener(in IEventMonitorListener listener); + // Remove following event information listener. + void removeFollowingEventInfoListener(in IEventMonitorListener listener); + // Get SDT guidance information. + Bundle getSdtGuidanceInfo(long channelDbId); + // Set Event Background channel list info. + void setBgmTuneChannelInfo(in Uri[] tuneChannelInfos); +} diff --git a/media/java/android/media/tv/extension/event/IEventMonitorListener.aidl b/media/java/android/media/tv/extension/event/IEventMonitorListener.aidl new file mode 100644 index 000000000000..a00e5422a7e0 --- /dev/null +++ b/media/java/android/media/tv/extension/event/IEventMonitorListener.aidl @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.media.tv.extension.event; + +import android.os.Bundle; + +/** + * @hide + */ +oneway interface IEventMonitorListener { + void onInfoChanged(long channelDbId, in Bundle eventinfo); +} diff --git a/media/java/android/media/tv/extension/scan/IFavoriteNetwork.aidl b/media/java/android/media/tv/extension/scan/IFavoriteNetwork.aidl new file mode 100644 index 000000000000..ff78aa4be39c --- /dev/null +++ b/media/java/android/media/tv/extension/scan/IFavoriteNetwork.aidl @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.media.tv.extension.scan; + +import android.media.tv.extension.scan.IFavoriteNetworkListener; +import android.os.Bundle; + +/** + * Country: Norway + * Broadcast Type: BROADCAST_TYPE_DVB_T + * (Operator: RiksTV) + * + * @hide + */ +interface IFavoriteNetwork { + // Get the favorite network information,If there are no conflicts, the array of Bundle is empty. + Bundle[] getFavoriteNetworks(); + // Select and set one of two or more favorite networks detected by the service scan. + int setFavoriteNetwork(in Bundle favoriteNetworkSettings); + // Set the listener to be invoked when two or more favorite networks are detected. + int setListener(in IFavoriteNetworkListener listener); +} diff --git a/media/java/android/media/tv/extension/scan/IFavoriteNetworkListener.aidl b/media/java/android/media/tv/extension/scan/IFavoriteNetworkListener.aidl new file mode 100644 index 000000000000..699422493dd6 --- /dev/null +++ b/media/java/android/media/tv/extension/scan/IFavoriteNetworkListener.aidl @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.media.tv.extension.scan; + +import android.os.Bundle; + +/** + * @hide + */ +oneway interface IFavoriteNetworkListener { + void onDetectFavoriteNetwork(in Bundle detectFavoriteNetworks); +} diff --git a/media/java/android/media/tv/extension/scan/IHDPlusInfo.aidl b/media/java/android/media/tv/extension/scan/IHDPlusInfo.aidl new file mode 100644 index 000000000000..cdf6e23f4b47 --- /dev/null +++ b/media/java/android/media/tv/extension/scan/IHDPlusInfo.aidl @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.media.tv.extension.scan; + +/** + * @hide + */ +interface IHDPlusInfo { + // Specifying a HDPlusInfo and start a network scan. + int setHDPlusInfo(String isBlindScanContinue, String isHDMode); +} diff --git a/media/java/android/media/tv/extension/scan/ILcnConflict.aidl b/media/java/android/media/tv/extension/scan/ILcnConflict.aidl new file mode 100644 index 000000000000..5dff39eb5920 --- /dev/null +++ b/media/java/android/media/tv/extension/scan/ILcnConflict.aidl @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.media.tv.extension.scan; + +import android.media.tv.extension.scan.ILcnConflictListener; +import android.os.Bundle; + +/** + * Country: Italy, France + * Broadcast Type: BROADCAST_TYPE_DVB_T + * + * @hide + */ +interface ILcnConflict { + // Get the LCN conflict groups information, If there are no conflicts, the array of Bundle is empty. + Bundle[] getLcnConflictGroups(); + // Resolve LCN conflicts caused by service scans. + int resolveLcnConflict(in Bundle[] lcnConflictSettings); + // Set the listener to be invoked the LCN conflict event. + int setListener(in ILcnConflictListener listener); +} diff --git a/media/java/android/media/tv/extension/scan/ILcnConflictListener.aidl b/media/java/android/media/tv/extension/scan/ILcnConflictListener.aidl new file mode 100644 index 000000000000..6bbbeb8e1e06 --- /dev/null +++ b/media/java/android/media/tv/extension/scan/ILcnConflictListener.aidl @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.media.tv.extension.scan; + +import android.os.Bundle; + +/** + * @hide + */ +oneway interface ILcnConflictListener { + void onDetectLcnConflict(in Bundle detectLcnConflicts); +} diff --git a/media/java/android/media/tv/extension/scan/ILcnV2ChannelList.aidl b/media/java/android/media/tv/extension/scan/ILcnV2ChannelList.aidl new file mode 100644 index 000000000000..f9a9d345a575 --- /dev/null +++ b/media/java/android/media/tv/extension/scan/ILcnV2ChannelList.aidl @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.media.tv.extension.scan; + +import android.media.tv.extension.scan.ILcnV2ChannelListListener; +import android.os.Bundle; + +/** + * Country: (NorDig etc.) + * Broadcast Type: BROADCAST_TYPE_DVB_T, BROADCAST_TYPE_DVB_C + * + * @hide + */ +interface ILcnV2ChannelList { + // Get the LCN V2 channel list information. If there are no conflicts, the array of Bundle is empty. + Bundle[] getLcnV2ChannelLists(); + // Select and set one of two or more LCN V2 channel list detected by the service scan. + int setLcnV2ChannelList(in Bundle lcnV2ChannelListSettings); + // Set the listener to be invoked when two or more LCN V2 channel list are detected. + int setListener(in ILcnV2ChannelListListener listener); +} diff --git a/media/java/android/media/tv/extension/scan/ILcnV2ChannelListListener.aidl b/media/java/android/media/tv/extension/scan/ILcnV2ChannelListListener.aidl new file mode 100644 index 000000000000..cbdb83c656f4 --- /dev/null +++ b/media/java/android/media/tv/extension/scan/ILcnV2ChannelListListener.aidl @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.media.tv.extension.scan; + +import android.os.Bundle; + +/** + * @hide + */ +oneway interface ILcnV2ChannelListListener { + void onDetectLcnV2ChannelList(in Bundle detectLcnV2ChannelList); +} diff --git a/media/java/android/media/tv/extension/scan/IOperatorDetection.aidl b/media/java/android/media/tv/extension/scan/IOperatorDetection.aidl new file mode 100644 index 000000000000..770f8668983e --- /dev/null +++ b/media/java/android/media/tv/extension/scan/IOperatorDetection.aidl @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.media.tv.extension.scan; + +import android.media.tv.extension.scan.IOperatorDetectionListener; +import android.os.Bundle; + +/** + * Country: Any + * Broadcast Type: BROADCAST_TYPE_DVB_S + * (Operator: M7) + * + * @hide + */ +interface IOperatorDetection { + // Set the operator selected info for scanning. + int setOperatorDetection(in Bundle operatorSelected); + // Set the listener to be invoked when one or more operator detection has been detected by + // operator detection searches. + int setListener(in IOperatorDetectionListener listener); +} diff --git a/media/java/android/media/tv/extension/scan/IOperatorDetectionListener.aidl b/media/java/android/media/tv/extension/scan/IOperatorDetectionListener.aidl new file mode 100644 index 000000000000..7dcd46177c43 --- /dev/null +++ b/media/java/android/media/tv/extension/scan/IOperatorDetectionListener.aidl @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.media.tv.extension.scan; + +import android.os.Bundle; + + +/** + * @hide + */ +oneway interface IOperatorDetectionListener { + void onDetectOperatorDetectionList(in Bundle[] detectOperatorDetectionList); +} diff --git a/media/java/android/media/tv/extension/scan/IRegionChannelList.aidl b/media/java/android/media/tv/extension/scan/IRegionChannelList.aidl new file mode 100644 index 000000000000..fe755f873110 --- /dev/null +++ b/media/java/android/media/tv/extension/scan/IRegionChannelList.aidl @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.media.tv.extension.scan; + +import android.media.tv.extension.scan.IRegionChannelListListener; + +/** + * @hide + */ +interface IRegionChannelList { + // Set the region channel list for scanning. + int setRegionChannelList(String regionChannelList); + // Set the listener to be invoked when one or more region channel list has been detected by + // region channel list searches. + int setListener(in IRegionChannelListListener listener); +} diff --git a/media/java/android/media/tv/extension/scan/IRegionChannelListListener.aidl b/media/java/android/media/tv/extension/scan/IRegionChannelListListener.aidl new file mode 100644 index 000000000000..06b0eb5537a2 --- /dev/null +++ b/media/java/android/media/tv/extension/scan/IRegionChannelListListener.aidl @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.media.tv.extension.scan; + +/** + * @hide + */ +oneway interface IRegionChannelListListener { + void onDetectRegionChannelList(in String[] detectRegionChannelList); +} diff --git a/media/java/android/media/tv/extension/scan/IScanInterface.aidl b/media/java/android/media/tv/extension/scan/IScanInterface.aidl new file mode 100644 index 000000000000..b44d1d243150 --- /dev/null +++ b/media/java/android/media/tv/extension/scan/IScanInterface.aidl @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.media.tv.extension.scan; + +import android.media.tv.extension.scan.IScanListener; +import android.os.Bundle; + +/** + * @hide + */ +interface IScanInterface { + IBinder createSession(int broadcastType, String countryCode, String operator, + in IScanListener listener); + Bundle getParameters(int broadcastType, String countryCode, String operator, + in Bundle params); +} diff --git a/media/java/android/media/tv/extension/scan/IScanListener.aidl b/media/java/android/media/tv/extension/scan/IScanListener.aidl new file mode 100644 index 000000000000..2c4807f97c58 --- /dev/null +++ b/media/java/android/media/tv/extension/scan/IScanListener.aidl @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.media.tv.extension.scan; + +import android.os.Bundle; + +/** + * @hide + */ +oneway interface IScanListener { + // notify events during scan. + void onEvent(in Bundle eventArgs); + // notify the scan progress. + void onScanProgress(String scanProgress, in Bundle scanProgressInfo); + // notify the scan completion. + void onScanCompleted(int scanResult); + // notify that the temporaily held channel list is stored. + void onStoreCompleted(int storeResult); +} diff --git a/media/java/android/media/tv/extension/scan/IScanSatSearch.aidl b/media/java/android/media/tv/extension/scan/IScanSatSearch.aidl new file mode 100644 index 000000000000..b8074fc4a9bd --- /dev/null +++ b/media/java/android/media/tv/extension/scan/IScanSatSearch.aidl @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.media.tv.extension.scan; + +/** + * For satellite search function. + * @hide + */ +interface IScanSatSearch { + // Set currecnt LNB as customized LNB, default LNB is universal LNB + int setCustomizedLnb(String customizedLnb); +} diff --git a/media/java/android/media/tv/extension/scan/IScanSession.aidl b/media/java/android/media/tv/extension/scan/IScanSession.aidl new file mode 100644 index 000000000000..d42eca1342b5 --- /dev/null +++ b/media/java/android/media/tv/extension/scan/IScanSession.aidl @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.media.tv.extension.scan; + +import android.os.Bundle; + +/** + * @hide + */ +interface IScanSession { + // Start a service scan. + int startScan(int broadcastType, String countryCode, String operator, in int[] frequency, + String scanType, String languageCode); + // Reset the scan information held in TIS. + int resetScan(); + // Cancel scan. + int cancelScan(); + + // Get available interface for created ScanExtension interface. + String[] getAvailableExtensionInterfaceNames(); + // Get extension interface for Scan. + IBinder getExtensionInterface(String name); + + // Clear the results of the service scan from the service database. + int clearServiceList(in Bundle optionalClearParams); + // Store the results of the service scan from the service database. + int storeServiceList(); + // Get a service information specified by the service information ID. + Bundle getServiceInfo(String serviceInfoId, in String[] keys); + // Get a service information ID list. + String[] getServiceInfoIdList(); + // Get a list of service info by the filter. + Bundle getServiceInfoList(in Bundle filterInfo, in String[] keys); + // Update the service information. + int updateServiceInfo(in Bundle serviceInfo); + // Updates the service information for the specified service information ID in array list. + int updateServiceInfoByList(in Bundle[] serviceInfo); + + /* DVBI specific functions */ + // Get all of the serviceLists, parsed from Local TV storage, Broadcast, USB file discovery. + Bundle getServiceLists(); + // Users choose one serviceList from the serviceLists, and install the services. + int setServiceList(int serviceListRecId); + // Get all of the packageData, parsed from the selected serviceList XML. + Bundle getPackageData(); + // Choose the package using package id and install the corresponding services. + int setPackage(String packageId); + // Get all of the countryRegionData, parsed from the selected serviceList XML. + Bundle getCountryRegionData(); + // Choose the countryRegion using countryRegion id, and install the corresponding services. + int setCountryRegion(String regionId); + // Get all of the regionData, parsed from the selected serviceList XML. + Bundle getRegionData(); + // Choose the region using the regionData id, and install the corresponding services. + int setRegion(String regionId); + + // Get unique session token for the scan. + String getSessionToken(); + // Release scan resource, the register listener will be released. + int release(); +} diff --git a/media/java/android/media/tv/extension/scan/ITargetRegion.aidl b/media/java/android/media/tv/extension/scan/ITargetRegion.aidl new file mode 100644 index 000000000000..417e12243b82 --- /dev/null +++ b/media/java/android/media/tv/extension/scan/ITargetRegion.aidl @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.media.tv.extension.scan; + +import android.media.tv.extension.scan.ITargetRegionListener; + +import android.os.Bundle; + +/** + * Country: U.K. + * Broadcast Type: BROADCAST_TYPE_DVB_T + * + * @hide + */ +interface ITargetRegion { + // Get the target regions information. If there are no conflicts, the array of Bundle is empty. + Bundle[] getTargetRegions(); + // Select and set one of two or more target region detected by the service scan. + int setTargetRegion(in Bundle targetRegionSettings); + // Set the listener to be invoked when two or more regions are detected. + int setListener(in ITargetRegionListener listener); +} diff --git a/media/java/android/media/tv/extension/scan/ITargetRegionListener.aidl b/media/java/android/media/tv/extension/scan/ITargetRegionListener.aidl new file mode 100644 index 000000000000..9d6aa8e8ea31 --- /dev/null +++ b/media/java/android/media/tv/extension/scan/ITargetRegionListener.aidl @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.media.tv.extension.scan; + +import android.os.Bundle; + +/** + * @hide + */ +oneway interface ITargetRegionListener { + void onDetectTargetRegion(in Bundle detectTargetRegions); +} diff --git a/media/java/android/media/tv/extension/scan/ITkgsInfo.aidl b/media/java/android/media/tv/extension/scan/ITkgsInfo.aidl new file mode 100644 index 000000000000..f25952c1cbdc --- /dev/null +++ b/media/java/android/media/tv/extension/scan/ITkgsInfo.aidl @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.media.tv.extension.scan; + +import android.media.tv.extension.scan.ITkgsInfoListener; +import android.os.Bundle; + +/** + * @hide + */ +interface ITkgsInfo { + int setPrefServiceList(String prefServiceList); + int setTkgsInfoListener(in ITkgsInfoListener listener); +} diff --git a/media/java/android/media/tv/extension/scan/ITkgsInfoListener.aidl b/media/java/android/media/tv/extension/scan/ITkgsInfoListener.aidl new file mode 100644 index 000000000000..e3dcf2d4c5ad --- /dev/null +++ b/media/java/android/media/tv/extension/scan/ITkgsInfoListener.aidl @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.media.tv.extension.scan; + +/** + * @hide + */ +oneway interface ITkgsInfoListener { + void onServiceList(in String[] serviceList); + void onTableVersionUpdate(int tableVersion); + void onUserMessage(String strMessage); +} diff --git a/media/java/android/media/tv/extension/scanbsu/IScanBackgroundServiceUpdate.aidl b/media/java/android/media/tv/extension/scanbsu/IScanBackgroundServiceUpdate.aidl new file mode 100644 index 000000000000..bda60edc48c1 --- /dev/null +++ b/media/java/android/media/tv/extension/scanbsu/IScanBackgroundServiceUpdate.aidl @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.media.tv.extension.scanbsu; + +import android.media.tv.extension.scanbsu.IScanBackgroundServiceUpdateListener; + +/** + * @hide + */ +interface IScanBackgroundServiceUpdate { + // Set the listener for background service update + // receives notifications for svl/tsl/nwl update during background service update. + void addBackgroundServiceUpdateListener(String clientToken, + in IScanBackgroundServiceUpdateListener listener); + // Remove the listener for background service update to stop receiving notifications + // for svl/tsl/nwl update during background service update. + void removeBackgroundServiceUpdateListener(in IScanBackgroundServiceUpdateListener listener); +} diff --git a/media/java/android/media/tv/extension/scanbsu/IScanBackgroundServiceUpdateListener.aidl b/media/java/android/media/tv/extension/scanbsu/IScanBackgroundServiceUpdateListener.aidl new file mode 100644 index 000000000000..d9bcbedb234a --- /dev/null +++ b/media/java/android/media/tv/extension/scanbsu/IScanBackgroundServiceUpdateListener.aidl @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.media.tv.extension.scanbsu; + +import android.os.Bundle; + +/** + * @hide + */ +interface IScanBackgroundServiceUpdateListener { + // On background service update add/delete/update svl records. + void onChannelListUpdate(String sessionToken, out Bundle[] updateInfos); + // On background service update add/delete/update nwl records. + void onNetworkListUpdate(String sessionToken, out Bundle[] updateInfos); + // On background service update add/delete/update tsl records. + void onTransportStreamingListUpdate(String sessionToken, out Bundle[] updateInfos); +} diff --git a/media/java/android/media/tv/extension/screenmode/IScreenModeSettings.aidl b/media/java/android/media/tv/extension/screenmode/IScreenModeSettings.aidl new file mode 100644 index 000000000000..57f3b4ab5017 --- /dev/null +++ b/media/java/android/media/tv/extension/screenmode/IScreenModeSettings.aidl @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.media.tv.extension.screenmode; + +/** + * @hide + */ +interface IScreenModeSettings { + // Set screen mode information using a JSON string. + void setScreenModeSettings(String sessionToken, String setting); + // Get the overscan index which TIS session is applied. + int getOverScanIndex(String sessionToken); + // Get status that TIS session is support overscan or not. + boolean getSupportApplyOverScan(String sessionToken); +} diff --git a/media/java/android/media/tv/extension/servicedb/IChannelListTransfer.aidl b/media/java/android/media/tv/extension/servicedb/IChannelListTransfer.aidl new file mode 100644 index 000000000000..cb6aeccb5b57 --- /dev/null +++ b/media/java/android/media/tv/extension/servicedb/IChannelListTransfer.aidl @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.media.tv.extension.servicedb; + +import android.os.ParcelFileDescriptor; + +/** + * @hide + */ +interface IChannelListTransfer { + // Parse XML file and import Channels information. + void importChannelList(in ParcelFileDescriptor pfd); + // Get Channels information for export and create XML file. + void exportChannelList(in ParcelFileDescriptor pfd); +} diff --git a/media/java/android/media/tv/extension/servicedb/IServiceList.aidl b/media/java/android/media/tv/extension/servicedb/IServiceList.aidl new file mode 100644 index 000000000000..51daa80ccbd6 --- /dev/null +++ b/media/java/android/media/tv/extension/servicedb/IServiceList.aidl @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.media.tv.extension.servicedb; + +import android.os.Bundle; + +/** + * @hide + */ +interface IServiceList { + // Get a list of the Service list IDs quivalent to COLUMN_CHANNEL_LIST_ID + // in the Channels table of TvProvider. + String[] getServiceListIds(); + // Get the information associated with the Service list. + Bundle getServiceListInfo(String serviceListId, in String[] keys); +} diff --git a/media/java/android/media/tv/extension/servicedb/IServiceListEdit.aidl b/media/java/android/media/tv/extension/servicedb/IServiceListEdit.aidl new file mode 100644 index 000000000000..1b1577ffc015 --- /dev/null +++ b/media/java/android/media/tv/extension/servicedb/IServiceListEdit.aidl @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.media.tv.extension.servicedb; + +import android.media.tv.extension.servicedb.IServiceListEditListener; +import android.os.Bundle; + +/** + * @hide + */ +interface IServiceListEdit { + // Open in edit mode. Must call close() after edit is done. + int open(IServiceListEditListener listener); + // Method to close in edit mode. + int close(); + // Method to commit changes made to service database. + int commit(); + // Method to commit and close the changes. + int userEditCommit(); + + // Get a service/transportStream/Network/Satellite record information specified by + // serviceInfoId and keys from tvdb. + Bundle getServiceInfoFromDatabase(String serviceInfoId, in String[] keys); + // Get a list of all service records' information specified by serviceListId and keys from tvdb. + Bundle getServiceInfoListFromDatabase(String serviceListId, in String[] keys); + // Get a list of all service info IDs in the service list of serviceListId from tvdb. + String[] getServiceInfoIdsFromDatabase(String inServiceListId); + // Update a service information by the contents of serviceInfo; + int updateServiceInfoFromDatabase(in Bundle updateServiceInfo); + // Update all service information by the contents of serviceInfoList. + int updateServiceInfoByListFromDatabase(in Bundle[] updateServiceInfoList); + // Remove a service information of the serviceInfoId from the service list. + int removeServiceInfoFromDatabase(String serviceInfoId); + // Remove all service information of the serviceInfoId from the service list. + int removeServiceInfoByListFromDatabase(in String[] serviceInfoIdList); + // Get a list of the Service list IDs which is equivalent to COLUMN_CHANNEL_LIST_ID + // in Channels table from tv db. + String[] getServiceListChannelIds(); + // Get the information associated with the Service list Channel id. + Bundle getServiceListInfoByChannelId(String serviceListChannelId, in String[] keys); + + // Get a list of transportStream records' information specified by serviceListId and keys. + Bundle getTransportStreamInfoList(String serviceListId, in String[] keys); + // Get a list of transportStream records' information specified by serviceListId and keys + // from work db. + Bundle getTransportStreamInfoListForce(String serviceListId, in String[] keys); + + // Get a list of network records' information specified by serviceListId and keys. + Bundle getNetworkInfoList(String serviceListId, in String[] keys); + // Get a list of satellite records' information specified by serviceListId and keys. + Bundle getSatelliteInfoList(String serviceListId, in String[] keys); + + // Decompress whole bundle value of single service/transportStream/Network/Satellite record. + // RecordInfoBundle:a single record got from database by getServiceInfoFromDatabase() + String toRecordInfoByType(in Bundle recordInfoBundle, String recordType); + // Set channels(tv.db) modified result to middleware database(SVL/TSL/NWL/SATL). + int putRecordIdList(String serviceListId, in Bundle recordIdListBundle, int optType); + + // Add predefined ServiceListInfo of Hotbird 13E in scan two satellite scene EU region + // following by commit(). + String addPredefinedServiceListInfo(int broadcastType, String serviceListType, + String serviceListPrefix, String countryCode, int operatorId); + // Add predefined channels of Hotbird 13E in scan two satellite scene EU region. + int addPredefinedChannelList(String serviceListId, in Bundle[] predefinedListBundle); + // Add predefined satellite info of Hotbird 13E in scan two satellite scene EU region. + int addPredefinedSatInfo(String serviceListId, in Bundle predefinedSatInfoBundle); +} diff --git a/media/java/android/media/tv/extension/servicedb/IServiceListEditListener.aidl b/media/java/android/media/tv/extension/servicedb/IServiceListEditListener.aidl new file mode 100644 index 000000000000..e227eda47d4f --- /dev/null +++ b/media/java/android/media/tv/extension/servicedb/IServiceListEditListener.aidl @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.media.tv.extension.servicedb; + +/** + * @hide + */ +oneway interface IServiceListEditListener { + void onCompleted(int requestId, int result); +} diff --git a/media/java/android/media/tv/extension/servicedb/IServiceListExportListener.aidl b/media/java/android/media/tv/extension/servicedb/IServiceListExportListener.aidl new file mode 100644 index 000000000000..c57e8f97ed4c --- /dev/null +++ b/media/java/android/media/tv/extension/servicedb/IServiceListExportListener.aidl @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.media.tv.extension.servicedb; + +/** + * @hide + */ +oneway interface IServiceListExportListener { + void onExported(int exportResult); +} diff --git a/media/java/android/media/tv/extension/servicedb/IServiceListExportSession.aidl b/media/java/android/media/tv/extension/servicedb/IServiceListExportSession.aidl new file mode 100644 index 000000000000..fcde581548f6 --- /dev/null +++ b/media/java/android/media/tv/extension/servicedb/IServiceListExportSession.aidl @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.media.tv.extension.servicedb; + +import android.os.Bundle; +import android.os.ParcelFileDescriptor; + +/** + * @hide + */ +interface IServiceListExportSession { + // Start export service list with reserved parameters. + int exportServiceList(in ParcelFileDescriptor pfd, in Bundle exportParams); + // Release export resources. + int release(); +} diff --git a/media/java/android/media/tv/extension/servicedb/IServiceListImportListener.aidl b/media/java/android/media/tv/extension/servicedb/IServiceListImportListener.aidl new file mode 100644 index 000000000000..abd8320df11d --- /dev/null +++ b/media/java/android/media/tv/extension/servicedb/IServiceListImportListener.aidl @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.media.tv.extension.servicedb; + +/** + * @hide + */ +interface IServiceListImportListener { + void onImported(int importResult); + void onPreloaded(int preloadResult); +}
\ No newline at end of file diff --git a/media/java/android/media/tv/extension/servicedb/IServiceListImportSession.aidl b/media/java/android/media/tv/extension/servicedb/IServiceListImportSession.aidl new file mode 100644 index 000000000000..1f1ae010a444 --- /dev/null +++ b/media/java/android/media/tv/extension/servicedb/IServiceListImportSession.aidl @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.media.tv.extension.servicedb; + +import android.os.Bundle; +import android.os.ParcelFileDescriptor; + +/** + * @hide + */ +interface IServiceListImportSession { + // Start import service list. Should call after preload and before release. + int importServiceList(in ParcelFileDescriptor pfd, in Bundle importParams); + // Preparing for import. + int preload(in ParcelFileDescriptor pfd); + // Release import resources. + int release(); +} diff --git a/media/java/android/media/tv/extension/servicedb/IServiceListSetChannelListListener.aidl b/media/java/android/media/tv/extension/servicedb/IServiceListSetChannelListListener.aidl new file mode 100644 index 000000000000..7c9c5c8a8048 --- /dev/null +++ b/media/java/android/media/tv/extension/servicedb/IServiceListSetChannelListListener.aidl @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.media.tv.extension.servicedb; + +/** + * @hide + */ +oneway interface IServiceListSetChannelListListener { + void onCompleted(int setChannelListResult); +} diff --git a/media/java/android/media/tv/extension/servicedb/IServiceListSetChannelListSession.aidl b/media/java/android/media/tv/extension/servicedb/IServiceListSetChannelListSession.aidl new file mode 100644 index 000000000000..b0527b3709b7 --- /dev/null +++ b/media/java/android/media/tv/extension/servicedb/IServiceListSetChannelListSession.aidl @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.media.tv.extension.servicedb; + +import android.os.Bundle; + +/** + * @hide + */ +interface IServiceListSetChannelListSession { + // Set channelList with channelinfo bundles, serviceListInfo, and operation type. + int setChannelList(in Bundle[] channelsInfo, in Bundle ServiceListInfoBundle, int optType); + // Release set channellist resources. + int release(); +} diff --git a/media/java/android/media/tv/extension/servicedb/IServiceListTransferInterface.aidl b/media/java/android/media/tv/extension/servicedb/IServiceListTransferInterface.aidl new file mode 100644 index 000000000000..91fb15728b06 --- /dev/null +++ b/media/java/android/media/tv/extension/servicedb/IServiceListTransferInterface.aidl @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.media.tv.extension.servicedb; + +import android.media.tv.extension.servicedb.IServiceListExportListener; +import android.media.tv.extension.servicedb.IServiceListImportListener; +import android.media.tv.extension.servicedb.IServiceListSetChannelListListener; +import android.os.IBinder; + +/** + * @hide + */ +interface IServiceListTransferInterface { + IBinder createExportSession(in IServiceListExportListener listener); + IBinder createImportSession(in IServiceListImportListener listener); + IBinder createSetChannelListSession(in IServiceListSetChannelListListener listener); +} diff --git a/media/java/android/media/tv/extension/teletext/IDataServiceSignalInfo.aidl b/media/java/android/media/tv/extension/teletext/IDataServiceSignalInfo.aidl new file mode 100644 index 000000000000..a3725e4e25db --- /dev/null +++ b/media/java/android/media/tv/extension/teletext/IDataServiceSignalInfo.aidl @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.media.tv.extension.teletext; + +import android.media.tv.extension.teletext.IDataServiceSignalInfoListener; +import android.os.Bundle; + + +/** + * @hide + */ +interface IDataServiceSignalInfo { + // Get Teletext data service signal information. + Bundle getDataServiceSignalInfo(String sessionToken); + // Add a listener that receives notifications of teletext running information. + void addDataServiceSignalInfoListener(String clientToken, + IDataServiceSignalInfoListener listener); + // Remove a listener that receives notifications of Teletext running information. + void removeDataServiceSignalInfoListener(String clientToken, + IDataServiceSignalInfoListener listener); +} diff --git a/media/java/android/media/tv/extension/teletext/IDataServiceSignalInfoListener.aidl b/media/java/android/media/tv/extension/teletext/IDataServiceSignalInfoListener.aidl new file mode 100644 index 000000000000..0e99bf5cc955 --- /dev/null +++ b/media/java/android/media/tv/extension/teletext/IDataServiceSignalInfoListener.aidl @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.media.tv.extension.teletext; + +import android.os.Bundle; + +/** + * @hide + */ +oneway interface IDataServiceSignalInfoListener { + void onDataServiceSignalInfoChanged (String sessionToken, in Bundle changedSignalInfo); +} diff --git a/media/java/android/media/tv/extension/teletext/ITeletextPageSubCode.aidl b/media/java/android/media/tv/extension/teletext/ITeletextPageSubCode.aidl new file mode 100644 index 000000000000..c96ffc02f438 --- /dev/null +++ b/media/java/android/media/tv/extension/teletext/ITeletextPageSubCode.aidl @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.media.tv.extension.teletext; + +import android.os.Bundle; + +/** + * @hide + */ +interface ITeletextPageSubCode { + // Get Teletext page number + Bundle getTeletextPageNumber(String sessionToken); + // Set Teletext page number. + void setTeleltextPageNumber(String sessionToken, int pageNumber); + // Get Teletext sub page number. + Bundle getTeletextPageSubCode(String sessionToken); + // Set Teletext sub page number. + void setTeletextPageSubCode(String sessionToken, int pageSubCode); + // Get Teletext TopInfo. + Bundle getTeletextHasTopInfo(String sessionToken); + // Get Teletext TopBlockList. + Bundle getTeletextTopBlockList(String sessionToken); + // Get Teletext TopGroupList. + Bundle getTeletextTopGroupList(String sessionToken, int indexGroup); + // Get Teletext TopPageList. + Bundle getTeletextTopPageList(String sessionToken, int indexPage); +} diff --git a/media/java/android/media/tv/extension/tune/IChannelTunedInterface.aidl b/media/java/android/media/tv/extension/tune/IChannelTunedInterface.aidl new file mode 100644 index 000000000000..88e50844f998 --- /dev/null +++ b/media/java/android/media/tv/extension/tune/IChannelTunedInterface.aidl @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.media.tv.extension.tune; + +import android.media.tv.extension.tune.IChannelTunedListener; + +/* +* @hide +*/ +interface IChannelTunedInterface { + void addChannelTunedListener(in IChannelTunedListener listener); + void removeChannelTunedListener(in IChannelTunedListener listener); +} diff --git a/media/java/android/media/tv/extension/tune/IChannelTunedListener.aidl b/media/java/android/media/tv/extension/tune/IChannelTunedListener.aidl new file mode 100644 index 000000000000..46875463402d --- /dev/null +++ b/media/java/android/media/tv/extension/tune/IChannelTunedListener.aidl @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.media.tv.extension.tune; + +import android.os.Bundle; + +/* +* @hide +*/ +oneway interface IChannelTunedListener { + void onChannelTuned(String sessionToken, in Bundle channelTunedInfo); +} diff --git a/media/java/android/media/tv/extension/tune/IMuxTune.aidl b/media/java/android/media/tv/extension/tune/IMuxTune.aidl new file mode 100644 index 000000000000..4e9dbdae6643 --- /dev/null +++ b/media/java/android/media/tv/extension/tune/IMuxTune.aidl @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.media.tv.extension.tune; + +import android.media.tv.extension.tune.IMuxTuneSession; + +/** +* @hide +*/ +interface IMuxTune { + IMuxTuneSession createSession(int broadcastType, String clientToken); +} diff --git a/media/java/android/media/tv/extension/tune/IMuxTuneSession.aidl b/media/java/android/media/tv/extension/tune/IMuxTuneSession.aidl new file mode 100644 index 000000000000..5ad72b48b50b --- /dev/null +++ b/media/java/android/media/tv/extension/tune/IMuxTuneSession.aidl @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.media.tv.extension.tune; + +import android.os.Bundle; + +/** +* @hide +*/ +interface IMuxTuneSession { + // Start mux tune with tune params. + void start(int broadcastType, int frequency, int brandwith, in Bundle muxTuneParams); + // Stop mux tune. + void stop(); + // Release muxtune resources. + void release(); + // Get the session token created by TIS to identify different sessions. + String getSessionToken(); +} diff --git a/media/tests/projection/src/android/media/projection/FakeIMediaProjection.java b/media/tests/projection/src/android/media/projection/FakeIMediaProjection.java index c9807e626429..58aa56babb64 100644 --- a/media/tests/projection/src/android/media/projection/FakeIMediaProjection.java +++ b/media/tests/projection/src/android/media/projection/FakeIMediaProjection.java @@ -46,7 +46,7 @@ public final class FakeIMediaProjection extends IMediaProjection.Stub { } @Override - public void stop() throws RemoteException { + public void stop(@StopReason int stopReason) throws RemoteException { // Pass along to the client's callback wrapper. mIMediaProjectionCallback.onStop(); } diff --git a/nfc/api/current.txt b/nfc/api/current.txt index 7ae2eafaf461..0ee81cbb7a73 100644 --- a/nfc/api/current.txt +++ b/nfc/api/current.txt @@ -202,6 +202,7 @@ package android.nfc.cardemulation { method public boolean categoryAllowsForegroundPreference(String); method @Nullable @RequiresPermission(android.Manifest.permission.NFC_PREFERRED_PAYMENT_INFO) public java.util.List<java.lang.String> getAidsForPreferredPaymentService(); method public java.util.List<java.lang.String> getAidsForService(android.content.ComponentName, String); + method @FlaggedApi("android.nfc.enable_card_emulation_euicc") public int getDefaultNfcSubscriptionId(); method @Nullable @RequiresPermission(android.Manifest.permission.NFC_PREFERRED_PAYMENT_INFO) public CharSequence getDescriptionForPreferredPaymentService(); method public static android.nfc.cardemulation.CardEmulation getInstance(android.nfc.NfcAdapter); method @Nullable @RequiresPermission(android.Manifest.permission.NFC_PREFERRED_PAYMENT_INFO) public String getRouteDestinationForPreferredPaymentService(); @@ -232,6 +233,7 @@ package android.nfc.cardemulation { field @FlaggedApi("android.nfc.nfc_event_listener") public static final int NFC_INTERNAL_ERROR_NFC_CRASH_RESTART = 1; // 0x1 field @FlaggedApi("android.nfc.nfc_event_listener") public static final int NFC_INTERNAL_ERROR_NFC_HARDWARE_ERROR = 2; // 0x2 field @FlaggedApi("android.nfc.nfc_event_listener") public static final int NFC_INTERNAL_ERROR_UNKNOWN = 0; // 0x0 + field @FlaggedApi("android.nfc.nfc_associated_role_services") public static final String PROPERTY_ALLOW_SHARED_ROLE_PRIORITY = "android.nfc.cardemulation.PROPERTY_ALLOW_SHARED_ROLE_PRIORITY"; field @FlaggedApi("android.nfc.nfc_override_recover_routing_table") public static final int PROTOCOL_AND_TECHNOLOGY_ROUTE_DEFAULT = 3; // 0x3 field @FlaggedApi("android.nfc.nfc_override_recover_routing_table") public static final int PROTOCOL_AND_TECHNOLOGY_ROUTE_DH = 0; // 0x0 field @FlaggedApi("android.nfc.nfc_override_recover_routing_table") public static final int PROTOCOL_AND_TECHNOLOGY_ROUTE_ESE = 1; // 0x1 diff --git a/nfc/api/system-current.txt b/nfc/api/system-current.txt index 15814edcd86a..3ed9b7667be7 100644 --- a/nfc/api/system-current.txt +++ b/nfc/api/system-current.txt @@ -57,17 +57,19 @@ package android.nfc { @FlaggedApi("android.nfc.nfc_oem_extension") public final class NfcOemExtension { method @FlaggedApi("android.nfc.nfc_oem_extension") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void clearPreference(); method @FlaggedApi("android.nfc.nfc_oem_extension") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public int forceRoutingTableCommit(); - method @FlaggedApi("android.nfc.nfc_oem_extension") @NonNull public java.util.List<java.lang.String> getActiveNfceeList(); + method @FlaggedApi("android.nfc.nfc_oem_extension") @NonNull public java.util.Map<java.lang.String,java.lang.Integer> getActiveNfceeList(); + method @FlaggedApi("android.nfc.nfc_oem_extension") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public long getMaxPausePollingTimeoutMills(); method @FlaggedApi("android.nfc.nfc_oem_extension") @NonNull @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public android.nfc.RoutingStatus getRoutingStatus(); method @FlaggedApi("android.nfc.nfc_oem_extension") @NonNull @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public java.util.List<android.nfc.NfcRoutingTableEntry> getRoutingTable(); + method @FlaggedApi("android.nfc.nfc_oem_extension") @NonNull public android.nfc.T4tNdefNfcee getT4tNdefNfcee(); method @FlaggedApi("android.nfc.nfc_oem_extension") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean hasUserEnabledNfc(); method @FlaggedApi("android.nfc.nfc_oem_extension") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean isAutoChangeEnabled(); method @FlaggedApi("android.nfc.nfc_oem_extension") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean isTagPresent(); method @FlaggedApi("android.nfc.nfc_oem_extension") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void maybeTriggerFirmwareUpdate(); method @FlaggedApi("android.nfc.nfc_oem_extension") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void overwriteRoutingTable(int, int, int, int); - method @FlaggedApi("android.nfc.nfc_oem_extension") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void pausePolling(int); + method @FlaggedApi("android.nfc.nfc_oem_extension") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public int pausePolling(long); method @FlaggedApi("android.nfc.nfc_oem_extension") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void registerCallback(@NonNull java.util.concurrent.Executor, @NonNull android.nfc.NfcOemExtension.Callback); - method @FlaggedApi("android.nfc.nfc_oem_extension") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void resumePolling(); + method @FlaggedApi("android.nfc.nfc_oem_extension") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public int resumePolling(); method @FlaggedApi("android.nfc.nfc_oem_extension") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void setAutoChangeEnabled(boolean); method @FlaggedApi("android.nfc.nfc_oem_extension") @RequiresPermission(android.Manifest.permission.NFC_SET_CONTROLLER_ALWAYS_ON) public void setControllerAlwaysOnMode(int); method @FlaggedApi("android.nfc.nfc_oem_extension") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void synchronizeScreenState(); @@ -83,6 +85,8 @@ package android.nfc { field public static final int HCE_ACTIVATE = 1; // 0x1 field public static final int HCE_DATA_TRANSFERRED = 2; // 0x2 field public static final int HCE_DEACTIVATE = 3; // 0x3 + field public static final int POLLING_STATE_CHANGE_ALREADY_IN_REQUESTED_STATE = 2; // 0x2 + field public static final int POLLING_STATE_CHANGE_SUCCEEDED = 1; // 0x1 field public static final int STATUS_OK = 0; // 0x0 field public static final int STATUS_UNKNOWN_ERROR = 1; // 0x1 } @@ -120,6 +124,11 @@ package android.nfc { @FlaggedApi("android.nfc.nfc_oem_extension") public abstract class NfcRoutingTableEntry { method public int getNfceeId(); + method public int getType(); + field public static final int TYPE_AID = 0; // 0x0 + field public static final int TYPE_PROTOCOL = 1; // 0x1 + field public static final int TYPE_SYSTEM_CODE = 3; // 0x3 + field public static final int TYPE_TECHNOLOGY = 2; // 0x2 } @FlaggedApi("android.nfc.nfc_oem_extension") public final class OemLogItems implements android.os.Parcelable { @@ -179,6 +188,47 @@ package android.nfc { field @FlaggedApi("android.nfc.nfc_oem_extension") public static final int TECHNOLOGY_V = 3; // 0x3 } + @FlaggedApi("android.nfc.nfc_oem_extension") public final class T4tNdefNfcee { + method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) @WorkerThread public int clearData(); + method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean isOperationOngoing(); + method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean isSupported(); + method @Nullable @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) @WorkerThread public android.nfc.T4tNdefNfceeCcFileInfo readCcfile(); + method @NonNull @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) @WorkerThread public byte[] readData(@IntRange(from=0, to=65535) int); + method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) @WorkerThread public int writeData(@IntRange(from=0, to=65535) int, @NonNull byte[]); + field public static final int CLEAR_DATA_FAILED_INTERNAL = 0; // 0x0 + field public static final int CLEAR_DATA_SUCCESS = 1; // 0x1 + field public static final int WRITE_DATA_ERROR_CONNECTION_FAILED = -6; // 0xfffffffa + field public static final int WRITE_DATA_ERROR_EMPTY_PAYLOAD = -7; // 0xfffffff9 + field public static final int WRITE_DATA_ERROR_INTERNAL = -1; // 0xffffffff + field public static final int WRITE_DATA_ERROR_INVALID_FILE_ID = -4; // 0xfffffffc + field public static final int WRITE_DATA_ERROR_INVALID_LENGTH = -5; // 0xfffffffb + field public static final int WRITE_DATA_ERROR_NDEF_VALIDATION_FAILED = -8; // 0xfffffff8 + field public static final int WRITE_DATA_ERROR_NFC_NOT_ON = -3; // 0xfffffffd + field public static final int WRITE_DATA_ERROR_RF_ACTIVATED = -2; // 0xfffffffe + field public static final int WRITE_DATA_SUCCESS = 0; // 0x0 + } + + @FlaggedApi("android.nfc.nfc_oem_extension") public final class T4tNdefNfceeCcFileInfo implements android.os.Parcelable { + method public int describeContents(); + method @IntRange(from=15, to=32767) public int getCcFileLength(); + method @IntRange(from=0xffffffff, to=65535) public int getFileId(); + method @IntRange(from=15, to=65535) public int getMaxReadLength(); + method @IntRange(from=5, to=32767) public int getMaxSize(); + method @IntRange(from=13, to=65535) public int getMaxWriteLength(); + method public int getReadAccess(); + method public int getVersion(); + method public int getWriteAccess(); + method public void writeToParcel(@NonNull android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator<android.nfc.T4tNdefNfceeCcFileInfo> CREATOR; + field public static final int READ_ACCESS_GRANTED_RESTRICTED = 128; // 0x80 + field public static final int READ_ACCESS_GRANTED_UNRESTRICTED = 0; // 0x0 + field public static final int VERSION_2_0 = 32; // 0x20 + field public static final int VERSION_3_0 = 48; // 0x30 + field public static final int WRITE_ACCESS_GRANTED_RESTRICTED = 128; // 0x80 + field public static final int WRITE_ACCESS_GRANTED_UNRESTRICTED = 0; // 0x0 + field public static final int WRITE_ACCESS_NOT_GRANTED = 255; // 0xff + } + } package android.nfc.cardemulation { @@ -186,14 +236,19 @@ package android.nfc.cardemulation { public final class CardEmulation { method @FlaggedApi("android.permission.flags.wallet_role_enabled") @Nullable @RequiresPermission(android.Manifest.permission.NFC_PREFERRED_PAYMENT_INFO) public static android.content.ComponentName getPreferredPaymentService(@NonNull android.content.Context); method @FlaggedApi("android.nfc.enable_nfc_mainline") @NonNull public java.util.List<android.nfc.cardemulation.ApduServiceInfo> getServices(@NonNull String, int); - method @FlaggedApi("android.nfc.nfc_override_recover_routing_table") public void overrideRoutingTable(@NonNull android.app.Activity, int, int); - method @FlaggedApi("android.nfc.nfc_override_recover_routing_table") public void recoverRoutingTable(@NonNull android.app.Activity); + method @FlaggedApi("android.nfc.nfc_override_recover_routing_table") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void overrideRoutingTable(@NonNull android.app.Activity, int, int); + method @FlaggedApi("android.nfc.nfc_override_recover_routing_table") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void recoverRoutingTable(@NonNull android.app.Activity); + method @FlaggedApi("android.nfc.enable_card_emulation_euicc") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public int setDefaultNfcSubscriptionId(int); method @FlaggedApi("android.nfc.nfc_set_service_enabled_for_category_other") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public int setServiceEnabledForCategoryOther(@NonNull android.content.ComponentName, boolean); field @FlaggedApi("android.nfc.nfc_set_service_enabled_for_category_other") public static final int SET_SERVICE_ENABLED_STATUS_FAILURE_ALREADY_SET = 3; // 0x3 field @FlaggedApi("android.nfc.nfc_set_service_enabled_for_category_other") public static final int SET_SERVICE_ENABLED_STATUS_FAILURE_FEATURE_UNSUPPORTED = 1; // 0x1 field @FlaggedApi("android.nfc.nfc_set_service_enabled_for_category_other") public static final int SET_SERVICE_ENABLED_STATUS_FAILURE_INVALID_SERVICE = 2; // 0x2 field @FlaggedApi("android.nfc.nfc_set_service_enabled_for_category_other") public static final int SET_SERVICE_ENABLED_STATUS_FAILURE_UNKNOWN_ERROR = 4; // 0x4 field @FlaggedApi("android.nfc.nfc_set_service_enabled_for_category_other") public static final int SET_SERVICE_ENABLED_STATUS_OK = 0; // 0x0 + field @FlaggedApi("android.nfc.enable_card_emulation_euicc") public static final int SET_SUBSCRIPTION_ID_STATUS_FAILED_INTERNAL_ERROR = 2; // 0x2 + field @FlaggedApi("android.nfc.enable_card_emulation_euicc") public static final int SET_SUBSCRIPTION_ID_STATUS_FAILED_INVALID_SUBSCRIPTION_ID = 1; // 0x1 + field @FlaggedApi("android.nfc.enable_card_emulation_euicc") public static final int SET_SUBSCRIPTION_ID_STATUS_FAILED_NOT_SUPPORTED = 3; // 0x3 + field @FlaggedApi("android.nfc.enable_card_emulation_euicc") public static final int SET_SUBSCRIPTION_ID_STATUS_SUCCESS = 0; // 0x0 } } diff --git a/nfc/java/android/nfc/INfcAdapter.aidl b/nfc/java/android/nfc/INfcAdapter.aidl index a08b55fe86b8..ac0a5aaaa195 100644 --- a/nfc/java/android/nfc/INfcAdapter.aidl +++ b/nfc/java/android/nfc/INfcAdapter.aidl @@ -31,6 +31,7 @@ import android.nfc.INfcCardEmulation; import android.nfc.INfcFCardEmulation; import android.nfc.INfcOemExtensionCallback; import android.nfc.INfcUnlockHandler; +import android.nfc.IT4tNdefNfcee; import android.nfc.ITagRemovedCallback; import android.nfc.INfcDta; import android.nfc.INfcWlcStateListener; @@ -52,8 +53,8 @@ interface INfcAdapter int getState(); boolean disable(boolean saveState, in String pkg); boolean enable(in String pkg); - void pausePolling(int timeoutInMs); - void resumePolling(); + int pausePolling(long timeoutInMs); + int resumePolling(); void setForegroundDispatch(in PendingIntent intent, in IntentFilter[] filters, in TechListParcel techLists); @@ -114,7 +115,7 @@ interface INfcAdapter void clearPreference(); void setScreenState(); void checkFirmware(); - List<String> fetchActiveNfceeList(); + Map fetchActiveNfceeList(); void triggerInitialization(); boolean getSettingStatus(); boolean isTagPresent(); @@ -122,4 +123,6 @@ interface INfcAdapter void indicateDataMigration(boolean inProgress, String pkg); int commitRouting(); boolean isTagIntentAllowed(in String pkg, in int Userid); + IT4tNdefNfcee getT4tNdefNfceeInterface(); + long getMaxPausePollingTimeoutMs(); } diff --git a/nfc/java/android/nfc/INfcCardEmulation.aidl b/nfc/java/android/nfc/INfcCardEmulation.aidl index 633d8bfbbb67..bb9fe959dc06 100644 --- a/nfc/java/android/nfc/INfcCardEmulation.aidl +++ b/nfc/java/android/nfc/INfcCardEmulation.aidl @@ -53,6 +53,8 @@ interface INfcCardEmulation void overrideRoutingTable(int userHandle, String protocol, String technology, in String pkg); void recoverRoutingTable(int userHandle); boolean isEuiccSupported(); + int getDefaultNfcSubscriptionId(in String pkg); + int setDefaultNfcSubscriptionId(int subscriptionId, in String pkg); void setAutoChangeStatus(boolean state); boolean isAutoChangeEnabled(); List<String> getRoutingStatus(); diff --git a/nfc/java/android/nfc/IT4tNdefNfcee.aidl b/nfc/java/android/nfc/IT4tNdefNfcee.aidl new file mode 100644 index 000000000000..b4cda5b022fb --- /dev/null +++ b/nfc/java/android/nfc/IT4tNdefNfcee.aidl @@ -0,0 +1,33 @@ +/****************************************************************************** + * + * Copyright (C) 2024 The Android Open Source Project. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************************/ + +package android.nfc; + +import android.nfc.T4tNdefNfceeCcFileInfo; + +/** + * @hide + */ +interface IT4tNdefNfcee { + int writeData(in int fileId, in byte[] data); + byte[] readData(in int fileId); + int clearNdefData(); + boolean isNdefOperationOngoing(); + boolean isNdefNfceeEmulationSupported(); + T4tNdefNfceeCcFileInfo readCcfile(); +} diff --git a/nfc/java/android/nfc/NfcAdapter.java b/nfc/java/android/nfc/NfcAdapter.java index 056844f38f3c..89ce4239cd4d 100644 --- a/nfc/java/android/nfc/NfcAdapter.java +++ b/nfc/java/android/nfc/NfcAdapter.java @@ -589,6 +589,7 @@ public final class NfcAdapter { static INfcTag sTagService; static INfcCardEmulation sCardEmulationService; static INfcFCardEmulation sNfcFCardEmulationService; + static IT4tNdefNfcee sNdefNfceeService; /** * The NfcAdapter object for each application context. @@ -827,7 +828,13 @@ public final class NfcAdapter { throw new UnsupportedOperationException(); } } - + try { + sNdefNfceeService = sService.getT4tNdefNfceeInterface(); + } catch (RemoteException e) { + sNdefNfceeService = null; + Log.e(TAG, "could not retrieve NDEF NFCEE service"); + throw new UnsupportedOperationException(); + } sIsInitialized = true; } NfcAdapter adapter = sNfcAdapters.get(context); diff --git a/nfc/java/android/nfc/NfcOemExtension.java b/nfc/java/android/nfc/NfcOemExtension.java index 9ed678fe6014..f78161e7cad0 100644 --- a/nfc/java/android/nfc/NfcOemExtension.java +++ b/nfc/java/android/nfc/NfcOemExtension.java @@ -39,6 +39,7 @@ import android.os.Binder; import android.os.Bundle; import android.os.RemoteException; import android.os.ResultReceiver; +import android.se.omapi.Reader; import android.util.Log; import java.lang.annotation.Retention; @@ -148,6 +149,48 @@ public final class NfcOemExtension { public @interface ControllerMode{} /** + * Technology Type for {@link #getActiveNfceeList()}. + * @hide + */ + @FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION) + public static final int NFCEE_TECH_NONE = 0; + + /** + * Technology Type for {@link #getActiveNfceeList()}. + * @hide + */ + @FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION) + public static final int NFCEE_TECH_A = 1; + + /** + * Technology Type for {@link #getActiveNfceeList()}. + * @hide + */ + @FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION) + public static final int NFCEE_TECH_B = 1 << 1; + + /** + * Technology Type for {@link #getActiveNfceeList()}. + * @hide + */ + @FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION) + public static final int NFCEE_TECH_F = 1 << 2; + + /** + * Nfc technology flags for {@link #getActiveNfceeList()}. + * + * @hide + */ + @IntDef(flag = true, value = { + NFCEE_TECH_NONE, + NFCEE_TECH_A, + NFCEE_TECH_B, + NFCEE_TECH_F, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface NfceeTechnology {} + + /** * Event that Host Card Emulation is activated. */ public static final int HCE_ACTIVATE = 1; @@ -173,6 +216,31 @@ public final class NfcOemExtension { public @interface HostCardEmulationAction {} /** + * Status code returned when the polling state change request succeeded. + * @see #pausePolling() + * @see #resumePolling() + */ + public static final int POLLING_STATE_CHANGE_SUCCEEDED = 1; + /** + * Status code returned when the polling state change request is already in + * required state. + * @see #pausePolling() + * @see #resumePolling() + */ + public static final int POLLING_STATE_CHANGE_ALREADY_IN_REQUESTED_STATE = 2; + /** + * Possible status codes for {@link #pausePolling()} and + * {@link #resumePolling()}. + * @hide + */ + @IntDef(value = { + POLLING_STATE_CHANGE_SUCCEEDED, + POLLING_STATE_CHANGE_ALREADY_IN_REQUESTED_STATE, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface PollingStateChangeStatusCode {} + + /** * Status OK */ public static final int STATUS_OK = 0; @@ -467,6 +535,28 @@ public final class NfcOemExtension { } /** + * Get an instance of {@link T4tNdefNfcee} object for performing T4T (Type-4 Tag) + * NDEF (NFC Data Exchange Format) NFCEE (NFC Execution Environment) operations. + * This can be used to write NDEF data to emulate a T4T tag in an NFCEE + * (NFC Execution Environment - eSE, SIM, etc). Refer to the NFC forum specification + * "NFCForum-TS-NCI-2.3 section 10.4" and "NFCForum-TS-T4T-1.1 section 4.2" for more details. + * + * This is a singleton object which shall be used by OEM extension module to do NDEF-NFCEE + * read/write operations. + * + * <p>Returns {@link T4tNdefNfcee} + * <p>Does not cause any RF activity and does not block. + * @return NFC Data Exchange Format (NDEF) NFC Execution Environment (NFCEE) object + * @hide + */ + @SystemApi + @NonNull + @FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION) + public T4tNdefNfcee getT4tNdefNfcee() { + return T4tNdefNfcee.getInstance(); + } + + /** * Register an {@link Callback} to listen for NFC oem extension callbacks * Multiple clients can register and callbacks will be invoked asynchronously. * @@ -580,14 +670,18 @@ public final class NfcOemExtension { /** * Get the Active NFCEE (NFC Execution Environment) List * - * @return List of activated secure elements on success - * which can contain "eSE" and "UICC", otherwise empty list. + * @see Reader#getName() for the list of possible NFCEE names. + * + * @return Map< String, @NfceeTechnology Integer > + * A HashMap where keys are activated secure elements and + * the values are bitmap of technologies supported by each secure element + * on success keys can contain "eSE" and "UICC", otherwise empty map. */ @NonNull @FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION) - public List<String> getActiveNfceeList() { + public Map<String, Integer> getActiveNfceeList() { return NfcAdapter.callServiceReturn(() -> - NfcAdapter.sService.fetchActiveNfceeList(), new ArrayList<String>()); + NfcAdapter.sService.fetchActiveNfceeList(), new HashMap<String, Integer>()); } /** @@ -653,24 +747,45 @@ public final class NfcOemExtension { /** * Pauses NFC tag reader mode polling for a {@code timeoutInMs} millisecond. - * In case of {@code timeoutInMs} is zero or invalid polling will be stopped indefinitely - * use {@link #resumePolling()} to resume the polling. - * @param timeoutInMs the pause polling duration in millisecond, ranging from 0 to 40000. + * In case of {@code timeoutInMs} is zero or invalid polling will be stopped indefinitely. + * Use {@link #resumePolling()} to resume the polling. + * Use {@link #getMaxPausePollingTimeoutMs()} to check the max timeout value. + * @param timeoutInMs the pause polling duration in millisecond. + * @return status of the operation + * @throws IllegalArgumentException if timeoutInMs value is invalid + * (0 < timeoutInMs < max). */ @FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION) @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) - public void pausePolling(@DurationMillisLong int timeoutInMs) { - NfcAdapter.callService(() -> NfcAdapter.sService.pausePolling(timeoutInMs)); + public @PollingStateChangeStatusCode int pausePolling(@DurationMillisLong long timeoutInMs) { + return NfcAdapter.callServiceReturn(() -> + NfcAdapter.sService.pausePolling(timeoutInMs), + POLLING_STATE_CHANGE_ALREADY_IN_REQUESTED_STATE); } /** * Resumes default NFC tag reader mode polling for the current device state if polling is * paused. Calling this while already in polling is a no-op. + * @return status of the operation + */ + @FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION) + @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) + public @PollingStateChangeStatusCode int resumePolling() { + return NfcAdapter.callServiceReturn(() -> + NfcAdapter.sService.resumePolling(), + POLLING_STATE_CHANGE_ALREADY_IN_REQUESTED_STATE); + } + + /** + * Gets the max pause polling timeout value in millisecond. + * @return long integer representing the max timeout */ @FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION) @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) - public void resumePolling() { - NfcAdapter.callService(() -> NfcAdapter.sService.resumePolling()); + @DurationMillisLong + public long getMaxPausePollingTimeoutMills() { + return NfcAdapter.callServiceReturn(() -> + NfcAdapter.sService.getMaxPausePollingTimeoutMs(), 0L); } /** diff --git a/nfc/java/android/nfc/NfcRoutingTableEntry.java b/nfc/java/android/nfc/NfcRoutingTableEntry.java index 4e913776a030..c2cbbede9b75 100644 --- a/nfc/java/android/nfc/NfcRoutingTableEntry.java +++ b/nfc/java/android/nfc/NfcRoutingTableEntry.java @@ -17,8 +17,12 @@ package android.nfc; import android.annotation.FlaggedApi; +import android.annotation.IntDef; import android.annotation.SystemApi; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + /** * Class to represent an entry of routing table. This class is abstract and extended by * {@link RoutingTableTechnologyEntry}, {@link RoutingTableProtocolEntry}, @@ -30,10 +34,42 @@ import android.annotation.SystemApi; @SystemApi public abstract class NfcRoutingTableEntry { private final int mNfceeId; + private final int mType; + + /** + * AID routing table type. + */ + public static final int TYPE_AID = 0; + /** + * Protocol routing table type. + */ + public static final int TYPE_PROTOCOL = 1; + /** + * Technology routing table type. + */ + public static final int TYPE_TECHNOLOGY = 2; + /** + * System Code routing table type. + */ + public static final int TYPE_SYSTEM_CODE = 3; + + /** + * Possible type of this routing table entry. + * @hide + */ + @IntDef(prefix = "TYPE_", value = { + TYPE_AID, + TYPE_PROTOCOL, + TYPE_TECHNOLOGY, + TYPE_SYSTEM_CODE + }) + @Retention(RetentionPolicy.SOURCE) + public @interface RoutingTableType {} /** @hide */ - protected NfcRoutingTableEntry(int nfceeId) { + protected NfcRoutingTableEntry(int nfceeId, @RoutingTableType int type) { mNfceeId = nfceeId; + mType = type; } /** @@ -43,4 +79,13 @@ public abstract class NfcRoutingTableEntry { public int getNfceeId() { return mNfceeId; } + + /** + * Get the type of this entry. + * @return an integer defined in {@link RoutingTableType} + */ + @RoutingTableType + public int getType() { + return mType; + } } diff --git a/nfc/java/android/nfc/RoutingTableAidEntry.java b/nfc/java/android/nfc/RoutingTableAidEntry.java index 7634fe342ab9..bf697d662bd6 100644 --- a/nfc/java/android/nfc/RoutingTableAidEntry.java +++ b/nfc/java/android/nfc/RoutingTableAidEntry.java @@ -20,7 +20,7 @@ import android.annotation.NonNull; import android.annotation.SystemApi; /** - * Represents an AID entry in current routing table. + * Represents an Application ID (AID) entry in current routing table. * @hide */ @FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION) @@ -30,7 +30,7 @@ public class RoutingTableAidEntry extends NfcRoutingTableEntry { /** @hide */ public RoutingTableAidEntry(int nfceeId, String value) { - super(nfceeId); + super(nfceeId, TYPE_AID); this.mValue = value; } diff --git a/nfc/java/android/nfc/RoutingTableProtocolEntry.java b/nfc/java/android/nfc/RoutingTableProtocolEntry.java index 0c5be7dd9d97..536de4d7430e 100644 --- a/nfc/java/android/nfc/RoutingTableProtocolEntry.java +++ b/nfc/java/android/nfc/RoutingTableProtocolEntry.java @@ -97,7 +97,7 @@ public class RoutingTableProtocolEntry extends NfcRoutingTableEntry { /** @hide */ public RoutingTableProtocolEntry(int nfceeId, @ProtocolValue int value) { - super(nfceeId); + super(nfceeId, TYPE_PROTOCOL); this.mValue = value; } diff --git a/nfc/java/android/nfc/RoutingTableSystemCodeEntry.java b/nfc/java/android/nfc/RoutingTableSystemCodeEntry.java index f87ad5f95195..f61892d31668 100644 --- a/nfc/java/android/nfc/RoutingTableSystemCodeEntry.java +++ b/nfc/java/android/nfc/RoutingTableSystemCodeEntry.java @@ -20,7 +20,9 @@ import android.annotation.NonNull; import android.annotation.SystemApi; /** - * Represents a system code entry in current routing table. + * Represents a system code entry in current routing table, where system codes are two-byte values + * used in NFC-F technology (a type of NFC communication) to identify specific + * device configurations. * @hide */ @FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION) @@ -30,7 +32,7 @@ public class RoutingTableSystemCodeEntry extends NfcRoutingTableEntry { /** @hide */ public RoutingTableSystemCodeEntry(int nfceeId, byte[] value) { - super(nfceeId); + super(nfceeId, TYPE_SYSTEM_CODE); this.mValue = value; } diff --git a/nfc/java/android/nfc/RoutingTableTechnologyEntry.java b/nfc/java/android/nfc/RoutingTableTechnologyEntry.java index f51a5299be11..2dbc94232b0b 100644 --- a/nfc/java/android/nfc/RoutingTableTechnologyEntry.java +++ b/nfc/java/android/nfc/RoutingTableTechnologyEntry.java @@ -30,22 +30,27 @@ import java.lang.annotation.RetentionPolicy; @SystemApi public class RoutingTableTechnologyEntry extends NfcRoutingTableEntry { /** - * Technology-A + * Technology-A. + * <p>Tech-A is mostly used for payment and ticketing applications. It supports various + * Tag platforms including Type 1, Type 2 and Type 4A tags. </p> */ @FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION) public static final int TECHNOLOGY_A = 0; /** - * Technology-B + * Technology-B which is based on ISO/IEC 14443-3 standard. */ @FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION) public static final int TECHNOLOGY_B = 1; /** - * Technology-F + * Technology-F. + * <p>Tech-F is a standard which supports Type 3 Tags and NFC-DEP protocol etc.</p> */ @FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION) public static final int TECHNOLOGY_F = 2; /** - * Technology-V + * Technology-V. + * <p>Tech-V is an NFC technology used for communication with passive tags that operate + * at a longer range than other NFC technologies. </p> */ @FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION) public static final int TECHNOLOGY_V = 3; @@ -73,7 +78,7 @@ public class RoutingTableTechnologyEntry extends NfcRoutingTableEntry { /** @hide */ public RoutingTableTechnologyEntry(int nfceeId, @TechnologyValue int value) { - super(nfceeId); + super(nfceeId, TYPE_TECHNOLOGY); this.mValue = value; } diff --git a/nfc/java/android/nfc/T4tNdefNfcee.java b/nfc/java/android/nfc/T4tNdefNfcee.java new file mode 100644 index 000000000000..06d02c54eb2e --- /dev/null +++ b/nfc/java/android/nfc/T4tNdefNfcee.java @@ -0,0 +1,258 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package android.nfc; + +import android.annotation.FlaggedApi; +import android.annotation.IntDef; +import android.annotation.IntRange; +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.annotation.RequiresPermission; +import android.annotation.SystemApi; +import android.annotation.WorkerThread; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** + * This class is used for performing T4T (Type-4 Tag) NDEF (NFC Data Exchange Format) + * NFCEE (NFC Execution Environment) operations. + * This can be used to write NDEF data to emulate a T4T tag in an NFCEE + * (NFC Execution Environment - eSE, SIM, etc). Refer to the NFC forum specification + * "NFCForum-TS-NCI-2.3 section 10.4" and "NFCForum-TS-T4T-1.1 section 4.2" for more details. + * @hide + */ +@FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION) +@SystemApi +public final class T4tNdefNfcee { + private static final String TAG = "NdefNfcee"; + static T4tNdefNfcee sNdefNfcee; + + private T4tNdefNfcee() { + } + + /** + * Helper to get an instance of this class. + * + * @return + * @hide + */ + @NonNull + public static T4tNdefNfcee getInstance() { + if (sNdefNfcee == null) { + sNdefNfcee = new T4tNdefNfcee(); + } + return sNdefNfcee; + } + + /** + * Return flag for {@link #writeData(int, byte[])}. + * It indicates write data is successful. + */ + public static final int WRITE_DATA_SUCCESS = 0; + /** + * Return flag for {@link #writeData(int, byte[])}. + * It indicates write data fail due to unknown reasons. + */ + public static final int WRITE_DATA_ERROR_INTERNAL = -1; + /** + * Return flag for {@link #writeData(int, byte[])}. + * It indicates write data fail due to ongoing rf activity. + */ + public static final int WRITE_DATA_ERROR_RF_ACTIVATED = -2; + /** + * Return flag for {@link #writeData(int, byte[])}. + * It indicates write data fail due to Nfc off. + */ + public static final int WRITE_DATA_ERROR_NFC_NOT_ON = -3; + /** + * Return flag for {@link #writeData(int, byte[])}. + * It indicates write data fail due to invalid file id. + */ + public static final int WRITE_DATA_ERROR_INVALID_FILE_ID = -4; + /** + * Return flag for {@link #writeData(int, byte[])}. + * It indicates write data fail due to invalid length. + */ + public static final int WRITE_DATA_ERROR_INVALID_LENGTH = -5; + /** + * Return flag for {@link #writeData(int, byte[])}. + * It indicates write data fail due to core connection create failure. + */ + public static final int WRITE_DATA_ERROR_CONNECTION_FAILED = -6; + /** + * Return flag for {@link #writeData(int, byte[])}. + * It indicates write data fail due to empty payload. + */ + public static final int WRITE_DATA_ERROR_EMPTY_PAYLOAD = -7; + /** + * Returns flag for {@link #writeData(int, byte[])}. + * It idicates write data fail due to invalid ndef format. + */ + public static final int WRITE_DATA_ERROR_NDEF_VALIDATION_FAILED = -8; + + /** + * Possible return values for {@link #writeData(int, byte[])}. + * + * @hide + */ + @IntDef(prefix = { "WRITE_DATA_" }, value = { + WRITE_DATA_SUCCESS, + WRITE_DATA_ERROR_INTERNAL, + WRITE_DATA_ERROR_RF_ACTIVATED, + WRITE_DATA_ERROR_NFC_NOT_ON, + WRITE_DATA_ERROR_INVALID_FILE_ID, + WRITE_DATA_ERROR_INVALID_LENGTH, + WRITE_DATA_ERROR_CONNECTION_FAILED, + WRITE_DATA_ERROR_EMPTY_PAYLOAD, + WRITE_DATA_ERROR_NDEF_VALIDATION_FAILED, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface WriteDataStatus{} + + /** + * This API performs writes of T4T data to NFCEE. + * + * <p>This is an I/O operation and will block until complete. It must + * not be called from the main application thread.</p> + * + * @param fileId File id (Refer NFC Forum Type 4 Tag Specification + * Section 4.2 File Identifiers and Access Conditions + * for more information) to which to write. + * @param data This should be valid Ndef Message format. + * Refer to Nfc forum NDEF specification NDEF Message section + * @return status of the operation. + * @hide + */ + @SystemApi + @WorkerThread + @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) + public @WriteDataStatus int writeData(@IntRange(from = 0, to = 65535) int fileId, + @NonNull byte[] data) { + return NfcAdapter.callServiceReturn(() -> + NfcAdapter.sNdefNfceeService.writeData(fileId, data), WRITE_DATA_ERROR_INTERNAL); + } + + /** + * This API performs reading of T4T content of Nfcee. + * + * <p>This is an I/O operation and will block until complete. It must + * not be called from the main application thread.</p> + * + * @param fileId File Id (Refer + * Section 4.2 File Identifiers and Access Conditions + * for more information) from which to read. + * @return - Returns Ndef message if success + * Refer to Nfc forum NDEF specification NDEF Message section + * @throws IllegalStateException if read fails because the fileId is invalid. + * @hide + */ + @SystemApi + @WorkerThread + @NonNull + @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) + public byte[] readData(@IntRange(from = 0, to = 65535) int fileId) { + return NfcAdapter.callServiceReturn(() -> + NfcAdapter.sNdefNfceeService.readData(fileId), null); + } + + /** + * Return flag for {@link #clearNdefData()}. + * It indicates clear data is successful. + */ + public static final int CLEAR_DATA_SUCCESS = 1; + /** + * Return flag for {@link #clearNdefData()}. + * It indicates clear data failed due to internal error while processing the clear. + */ + public static final int CLEAR_DATA_FAILED_INTERNAL = 0; + + /** + * Possible return values for {@link #clearNdefData()}. + * + * @hide + */ + @IntDef(prefix = { "CLEAR_DATA_" }, value = { + CLEAR_DATA_SUCCESS, + CLEAR_DATA_FAILED_INTERNAL, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface ClearDataStatus{} + + /** + * This API will set all the T4T NDEF NFCEE data to zero. + * + * <p>This is an I/O operation and will block until complete. It must + * not be called from the main application thread. + * + * <p>This API can be called regardless of NDEF file lock state. + * </p> + * @return status of the operation + * + * @hide + */ + @SystemApi + @WorkerThread + @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) + public @ClearDataStatus int clearData() { + return NfcAdapter.callServiceReturn(() -> + NfcAdapter.sNdefNfceeService.clearNdefData(), CLEAR_DATA_FAILED_INTERNAL); + } + + /** + * Returns whether NDEF NFCEE operation is ongoing or not. + * + * @return true if NDEF NFCEE operation is ongoing, else false. + * @hide + */ + @SystemApi + @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) + public boolean isOperationOngoing() { + return NfcAdapter.callServiceReturn(() -> + NfcAdapter.sNdefNfceeService.isNdefOperationOngoing(), false); + } + + /** + * This Api is to check the status of NDEF NFCEE emulation feature is + * supported or not. + * + * @return true if NDEF NFCEE emulation feature is supported, else false. + * @hide + */ + @SystemApi + @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) + public boolean isSupported() { + return NfcAdapter.callServiceReturn(() -> + NfcAdapter.sNdefNfceeService.isNdefNfceeEmulationSupported(), false); + } + + /** + * This API performs reading of T4T NDEF NFCEE CC file content. + * + * Refer to the NFC forum specification "NFCForum-TS-T4T-1.1 section 4.4" for more details. + * + * @return Returns CC file content if success or null if failed to read. + * @hide + */ + @SystemApi + @WorkerThread + @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) + @Nullable + public T4tNdefNfceeCcFileInfo readCcfile() { + return NfcAdapter.callServiceReturn(() -> + NfcAdapter.sNdefNfceeService.readCcfile(), null); + } +} diff --git a/nfc/java/android/nfc/T4tNdefNfceeCcFileInfo.aidl b/nfc/java/android/nfc/T4tNdefNfceeCcFileInfo.aidl new file mode 100644 index 000000000000..f72f74e8b3b9 --- /dev/null +++ b/nfc/java/android/nfc/T4tNdefNfceeCcFileInfo.aidl @@ -0,0 +1,20 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.nfc; + +parcelable T4tNdefNfceeCcFileInfo; + diff --git a/nfc/java/android/nfc/T4tNdefNfceeCcFileInfo.java b/nfc/java/android/nfc/T4tNdefNfceeCcFileInfo.java new file mode 100644 index 000000000000..5fca0529124e --- /dev/null +++ b/nfc/java/android/nfc/T4tNdefNfceeCcFileInfo.java @@ -0,0 +1,293 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.nfc; + +import android.annotation.FlaggedApi; +import android.annotation.IntDef; +import android.annotation.IntRange; +import android.annotation.NonNull; +import android.annotation.SystemApi; +import android.os.Parcel; +import android.os.Parcelable; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** + * This class is used to represence T4T (Type-4 Tag) NDEF (NFC Data Exchange Format) + * NFCEE (NFC Execution Environment) CC (Capability Container) File data. + * The CC file stores metadata about the T4T tag being emulated. + * + * Refer to the NFC forum specification "NFCForum-TS-T4T-1.1 section 4.4" for more details. + * @hide + */ +@FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION) +@SystemApi +public final class T4tNdefNfceeCcFileInfo implements Parcelable { + /** + * Indicates the size of this capability container (called “CC File”)<p> + */ + private int mCcLength; + /** + * Indicates the mapping specification version<p> + */ + private int mVersion; + /** + * Indicates the max data size by a single ReadBinary<p> + */ + private int mMaxReadLength; + /** + * Indicates the max data size by a single UpdateBinary<p> + */ + private int mMaxWriteLength; + /** + * Indicates the NDEF File Identifier<p> + */ + private int mFileId; + /** + * Indicates the maximum Max NDEF file size<p> + */ + private int mMaxSize; + /** + * Indicates the read access condition<p> + */ + private int mReadAccess; + /** + * Indicates the write access condition<p> + */ + private int mWriteAccess; + + /** + * Constructor to be used by NFC service and internal classes. + * @hide + */ + public T4tNdefNfceeCcFileInfo(int cclen, int version, int maxLe, int maxLc, + int ndefFileId, int ndefMaxSize, + int ndefReadAccess, int ndefWriteAccess) { + mCcLength = cclen; + mVersion = version; + mMaxWriteLength = maxLc; + mMaxReadLength = maxLe; + mFileId = ndefFileId; + mMaxSize = ndefMaxSize; + mReadAccess = ndefReadAccess; + mWriteAccess = ndefWriteAccess; + } + + @Override + public void writeToParcel(@NonNull Parcel dest, int flags) { + + dest.writeInt(mCcLength); + dest.writeInt(mVersion); + dest.writeInt(mMaxWriteLength); + dest.writeInt(mMaxReadLength); + dest.writeInt(mFileId); + dest.writeInt(mMaxSize); + dest.writeInt(mReadAccess); + dest.writeInt(mWriteAccess); + } + + /** + * Indicates the size of this capability container (called “CC File”). + * + * @return length of the CC file. + */ + @IntRange(from = 0xf, to = 0x7fff) + public int getCcFileLength() { + return mCcLength; + } + + /** + * T4T tag mapping version 2.0. + * Refer to the NFC forum specification "NFCForum-TS-T4T-1.1 section 4.4" for more details. + */ + public static final int VERSION_2_0 = 0x20; + /** + * T4T tag mapping version 2.0. + * Refer to the NFC forum specification "NFCForum-TS-T4T-1.1 section 4.4" for more details. + */ + public static final int VERSION_3_0 = 0x30; + + /** + * Possible return values for {@link #getVersion()}. + * @hide + */ + @IntDef(prefix = { "VERSION_" }, value = { + VERSION_2_0, + VERSION_3_0, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface Version{} + + /** + * Indicates the mapping version of the T4T tag supported. + * + * Refer to the NFC forum specification "NFCForum-TS-T4T-1.1 section 4.5" for more details. + * + * @return version of the specification + */ + @Version + public int getVersion() { + return mVersion; + } + + /** + * Indicates the max data size that can be read by a single invocation of + * {@link T4tNdefNfcee#readData(int)}. + * + * Refer to the NFC forum specification "NFCForum-TS-T4T-1.1 section 4.4" MLe. + * @return max size of read (in bytes). + */ + @IntRange(from = 0xf, to = 0xffff) + public int getMaxReadLength() { + return mMaxReadLength; + } + + /** + * Indicates the max data size that can be written by a single invocation of + * {@link T4tNdefNfcee#writeData(int, byte[])} + * + * Refer to the NFC forum specification "NFCForum-TS-T4T-1.1 section 4.4" MLc. + * @return max size of write (in bytes). + */ + @IntRange(from = 0xd, to = 0xffff) + public int getMaxWriteLength() { + return mMaxWriteLength; + } + + /** + * Indicates the NDEF File Identifier. This is the identifier used in the last invocation of + * {@link T4tNdefNfcee#writeData(int, byte[])} + * + * @return FileId of the data stored or -1 if no data is present. + */ + @IntRange(from = -1, to = 65535) + public int getFileId() { + return mFileId; + } + + /** + * Indicates the maximum size of T4T NDEF data that can be written to the NFCEE. + * + * @return max size of the contents. + */ + @IntRange(from = 0x5, to = 0x7fff) + public int getMaxSize() { + return mMaxSize; + } + + /** + * T4T tag read access granted without any security. + * Refer to the NFC forum specification "NFCForum-TS-T4T-1.1 section 4.2" for more details. + */ + public static final int READ_ACCESS_GRANTED_UNRESTRICTED = 0x0; + /** + * T4T tag read access granted with limited proprietary access only. + * Refer to the NFC forum specification "NFCForum-TS-T4T-1.1 section 4.2" for more details. + */ + public static final int READ_ACCESS_GRANTED_RESTRICTED = 0x80; + + /** + * Possible return values for {@link #getVersion()}. + * @hide + */ + @IntDef(prefix = { "READ_ACCESS_GRANTED_" }, value = { + READ_ACCESS_GRANTED_RESTRICTED, + READ_ACCESS_GRANTED_UNRESTRICTED, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface ReadAccess {} + + /** + * Indicates the read access condition. + * Refer to the NFC forum specification "NFCForum-TS-T4T-1.1 section 4.2" for more details. + * @return read access restriction + */ + @ReadAccess + public int getReadAccess() { + return mReadAccess; + } + + /** + * T4T tag write access granted without any security. + * Refer to the NFC forum specification "NFCForum-TS-T4T-1.1 section 4.2" for more details. + */ + public static final int WRITE_ACCESS_GRANTED_UNRESTRICTED = 0x0; + /** + * T4T tag write access granted with limited proprietary access only. + * Refer to the NFC forum specification "NFCForum-TS-T4T-1.1 section 4.2" for more details. + */ + public static final int WRITE_ACCESS_GRANTED_RESTRICTED = 0x80; + /** + * T4T tag write access not granted. + * Refer to the NFC forum specification "NFCForum-TS-T4T-1.1 section 4.2" for more details. + */ + public static final int WRITE_ACCESS_NOT_GRANTED = 0xFF; + + /** + * Possible return values for {@link #getVersion()}. + * @hide + */ + @IntDef(prefix = { "READ_ACCESS_GRANTED_" }, value = { + WRITE_ACCESS_GRANTED_RESTRICTED, + WRITE_ACCESS_GRANTED_UNRESTRICTED, + WRITE_ACCESS_NOT_GRANTED, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface WriteAccess {} + + /** + * Indicates the write access condition. + * Refer to the NFC forum specification "NFCForum-TS-T4T-1.1 section 4.2" for more details. + * @return write access restriction + */ + @WriteAccess + public int getWriteAccess() { + return mWriteAccess; + } + + @Override + public int describeContents() { + return 0; + } + + public static final @NonNull Parcelable.Creator<T4tNdefNfceeCcFileInfo> CREATOR = + new Parcelable.Creator<>() { + @Override + public T4tNdefNfceeCcFileInfo createFromParcel(Parcel in) { + + // NdefNfceeCcFileInfo fields + int cclen = in.readInt(); + int version = in.readInt(); + int maxLe = in.readInt(); + int maxLc = in.readInt(); + int ndefFileId = in.readInt(); + int ndefMaxSize = in.readInt(); + int ndefReadAccess = in.readInt(); + int ndefWriteAccess = in.readInt(); + + return new T4tNdefNfceeCcFileInfo(cclen, version, maxLe, maxLc, + ndefFileId, ndefMaxSize, + ndefReadAccess, ndefWriteAccess); + } + + @Override + public T4tNdefNfceeCcFileInfo[] newArray(int size) { + return new T4tNdefNfceeCcFileInfo[size]; + } + }; +} diff --git a/nfc/java/android/nfc/cardemulation/ApduServiceInfo.java b/nfc/java/android/nfc/cardemulation/ApduServiceInfo.java index 9ff83fe77c9b..308b5d1831a6 100644 --- a/nfc/java/android/nfc/cardemulation/ApduServiceInfo.java +++ b/nfc/java/android/nfc/cardemulation/ApduServiceInfo.java @@ -171,6 +171,12 @@ public final class ApduServiceInfo implements Parcelable { private boolean mShouldDefaultToObserveMode; /** + * Whether or not this service wants to share the same routing priority as the + * Wallet role owner. + */ + private boolean mShareRolePriority; + + /** * @hide */ @UnsupportedAppUsage @@ -307,6 +313,12 @@ public final class ApduServiceInfo implements Parcelable { mShouldDefaultToObserveMode = sa.getBoolean( R.styleable.HostApduService_shouldDefaultToObserveMode, false); + if (Flags.nfcAssociatedRoleServices()) { + mShareRolePriority = sa.getBoolean( + R.styleable.HostApduService_shareRolePriority, + false + ); + } sa.recycle(); } else { TypedArray sa = res.obtainAttributes(attrs, @@ -337,6 +349,12 @@ public final class ApduServiceInfo implements Parcelable { } } mStaticOffHostName = mOffHostName; + if (Flags.nfcAssociatedRoleServices()) { + mShareRolePriority = sa.getBoolean( + R.styleable.OffHostApduService_shareRolePriority, + false + ); + } sa.recycle(); } @@ -728,6 +746,17 @@ public final class ApduServiceInfo implements Parcelable { } /** + * Returns whether or not this service wants to share the Wallet role holder priority + * with other packages/services with the same signature. + * + * @return whether or not this service wants to share priority + */ + @FlaggedApi(Flags.FLAG_NFC_ASSOCIATED_ROLE_SERVICES) + public boolean shareRolePriority() { + return mShareRolePriority; + } + + /** * Returns description of service. * @return user readable description of service */ diff --git a/nfc/java/android/nfc/cardemulation/CardEmulation.java b/nfc/java/android/nfc/cardemulation/CardEmulation.java index 24ff7ab9c2b6..803770218299 100644 --- a/nfc/java/android/nfc/cardemulation/CardEmulation.java +++ b/nfc/java/android/nfc/cardemulation/CardEmulation.java @@ -22,6 +22,7 @@ import android.annotation.FlaggedApi; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.RequiresFeature; import android.annotation.RequiresPermission; import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; @@ -45,6 +46,7 @@ import android.os.RemoteException; import android.os.UserHandle; import android.provider.Settings; import android.provider.Settings.SettingNotFoundException; +import android.telephony.SubscriptionManager; import android.util.ArrayMap; import android.util.Log; @@ -244,6 +246,25 @@ public final class CardEmulation { @Retention(RetentionPolicy.SOURCE) public @interface SetServiceEnabledStatusCode {} + /** + * Property name used to indicate that an application wants to allow associated services + * to share the same AID routing priority when this application is the role holder. + * <p> + * Example: + * <pre> + * {@code + * <application> + * ... + * <property android:name="android.nfc.cardemulation.PROPERTY_ALLOW_SHARED_ROLE_PRIORITY" + * android:value="true"/> + * </application> + * } + * </pre> + */ + @FlaggedApi(Flags.FLAG_NFC_ASSOCIATED_ROLE_SERVICES) + public static final String PROPERTY_ALLOW_SHARED_ROLE_PRIORITY = + "android.nfc.cardemulation.PROPERTY_ALLOW_SHARED_ROLE_PRIORITY"; + static boolean sIsInitialized = false; static HashMap<Context, CardEmulation> sCardEmus = new HashMap<Context, CardEmulation>(); static INfcCardEmulation sService; @@ -1010,6 +1031,7 @@ public final class CardEmulation { * @hide */ @SystemApi + @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) @FlaggedApi(Flags.FLAG_NFC_OVERRIDE_RECOVER_ROUTING_TABLE) public void overrideRoutingTable( @NonNull Activity activity, @ProtocolAndTechnologyRoute int protocol, @@ -1037,6 +1059,7 @@ public final class CardEmulation { * @hide */ @SystemApi + @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) @FlaggedApi(Flags.FLAG_NFC_OVERRIDE_RECOVER_ROUTING_TABLE) public void recoverRoutingTable(@NonNull Activity activity) { if (!activity.isResumed()) { @@ -1058,6 +1081,97 @@ public final class CardEmulation { } /** + * Setting the default subscription ID succeeded. + * @hide + */ + @SystemApi + @FlaggedApi(android.nfc.Flags.FLAG_ENABLE_CARD_EMULATION_EUICC) + public static final int SET_SUBSCRIPTION_ID_STATUS_SUCCESS = 0; + + /** + * Setting the default subscription ID failed because the subscription ID is invalid. + * @hide + */ + @SystemApi + @FlaggedApi(android.nfc.Flags.FLAG_ENABLE_CARD_EMULATION_EUICC) + public static final int SET_SUBSCRIPTION_ID_STATUS_FAILED_INVALID_SUBSCRIPTION_ID = 1; + + /** + * Setting the default subscription ID failed because there was an internal error processing + * the request. For ex: NFC service died in the middle of handling the API. + * @hide + */ + @SystemApi + @FlaggedApi(android.nfc.Flags.FLAG_ENABLE_CARD_EMULATION_EUICC) + public static final int SET_SUBSCRIPTION_ID_STATUS_FAILED_INTERNAL_ERROR = 2; + + /** + * Setting the default subscription ID failed because this feature is not supported on the + * device. + * @hide + */ + @SystemApi + @FlaggedApi(android.nfc.Flags.FLAG_ENABLE_CARD_EMULATION_EUICC) + public static final int SET_SUBSCRIPTION_ID_STATUS_FAILED_NOT_SUPPORTED = 3; + + /** @hide */ + @IntDef(prefix = "SET_SUBSCRIPTION_ID_STATUS_", + value = { + SET_SUBSCRIPTION_ID_STATUS_SUCCESS, + SET_SUBSCRIPTION_ID_STATUS_FAILED_INVALID_SUBSCRIPTION_ID, + SET_SUBSCRIPTION_ID_STATUS_FAILED_INTERNAL_ERROR, + SET_SUBSCRIPTION_ID_STATUS_FAILED_NOT_SUPPORTED, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface SetSubscriptionIdStatus {} + + /** + * Sets the system's default NFC subscription id. + * + * <p> For devices with multiple UICC/EUICC that is configured to be NFCEE, this sets the + * default UICC NFCEE that will handle NFC offhost CE transactoions </p> + * + * @param subscriptionId the default NFC subscription Id to set. + * @return status of the operation. + * + * @throws UnsupportedOperationException If the device does not have + * {@link PackageManager#FEATURE_TELEPHONY_SUBSCRIPTION}. + * @hide + */ + @SystemApi + @RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION) + @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) + @FlaggedApi(android.nfc.Flags.FLAG_ENABLE_CARD_EMULATION_EUICC) + public @SetSubscriptionIdStatus int setDefaultNfcSubscriptionId(int subscriptionId) { + return callServiceReturn(() -> + sService.setDefaultNfcSubscriptionId( + subscriptionId, mContext.getPackageName()), + SET_SUBSCRIPTION_ID_STATUS_FAILED_INTERNAL_ERROR); + } + + /** + * Returns the system's default NFC subscription id. + * + * <p> For devices with multiple UICC/EUICC that is configured to be NFCEE, this returns the + * default UICC NFCEE that will handle NFC offhost CE transactoions </p> + * <p> If the device has no UICC that can serve as NFCEE, this will return + * {@link SubscriptionManager#INVALID_SUBSCRIPTION_ID}.</p> + * + * @return the default NFC subscription Id if set, + * {@link SubscriptionManager#INVALID_SUBSCRIPTION_ID} otherwise. + * + * @throws UnsupportedOperationException If the device does not have + * {@link PackageManager#FEATURE_TELEPHONY_SUBSCRIPTION}. + */ + @RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION) + @FlaggedApi(android.nfc.Flags.FLAG_ENABLE_CARD_EMULATION_EUICC) + public int getDefaultNfcSubscriptionId() { + return callServiceReturn(() -> + sService.getDefaultNfcSubscriptionId(mContext.getPackageName()), + SubscriptionManager.INVALID_SUBSCRIPTION_ID); + } + + /** * Returns the value of {@link Settings.Secure#NFC_PAYMENT_DEFAULT_COMPONENT}. * * @param context A context diff --git a/packages/CrashRecovery/services/module/java/com/android/server/PackageWatchdog.java b/packages/CrashRecovery/services/module/java/com/android/server/PackageWatchdog.java index fc482174414a..2ba93f15f7fc 100644 --- a/packages/CrashRecovery/services/module/java/com/android/server/PackageWatchdog.java +++ b/packages/CrashRecovery/services/module/java/com/android/server/PackageWatchdog.java @@ -456,7 +456,7 @@ public class PackageWatchdog { * * <p>This method could be called frequently if there is a severe problem on the device. */ - public void onPackageFailure(@NonNull List<VersionedPackage> packages, + public void notifyPackageFailure(@NonNull List<VersionedPackage> packages, @FailureReasons int failureReason) { if (packages == null) { Slog.w(TAG, "Could not resolve a list of failing packages"); @@ -467,7 +467,7 @@ public class PackageWatchdog { if (Flags.recoverabilityDetection()) { if (now >= mLastMitigation && (now - mLastMitigation) < getMitigationWindowMs()) { - Slog.i(TAG, "Skipping onPackageFailure mitigation"); + Slog.i(TAG, "Skipping notifyPackageFailure mitigation"); return; } } @@ -494,7 +494,7 @@ public class PackageWatchdog { ObserverInternal observer = mAllObservers.valueAt(oIndex); PackageHealthObserver registeredObserver = observer.registeredObserver; if (registeredObserver != null - && observer.onPackageFailureLocked( + && observer.notifyPackageFailureLocked( versionedPackage.getPackageName())) { MonitoredPackage p = observer.getMonitoredPackage( versionedPackage.getPackageName()); @@ -693,7 +693,7 @@ public class PackageWatchdog { // Check if native watchdog reported a crash if ("1".equals(SystemProperties.get("sys.init.updatable_crashing"))) { // We rollback all available low impact rollbacks when crash is unattributable - onPackageFailure(Collections.EMPTY_LIST, FAILURE_REASON_NATIVE_CRASH); + notifyPackageFailure(Collections.EMPTY_LIST, FAILURE_REASON_NATIVE_CRASH); // we stop polling after an attempt to execute rollback, regardless of whether the // attempt succeeds or not } else { @@ -731,6 +731,25 @@ public class PackageWatchdog { } /** + * The minimum value that can be returned by any observer. + * It represents that no mitigations were available. + */ + public static final int LEAST_PACKAGE_HEALTH_OBSERVER_IMPACT = + PackageHealthObserverImpact.USER_IMPACT_LEVEL_0; + + /** + * The mitigation impact beyond which the user will start noticing the mitigations. + */ + public static final int MEDIUM_USER_IMPACT_THRESHOLD = + PackageHealthObserverImpact.USER_IMPACT_LEVEL_20; + + /** + * The mitigation impact beyond which the user impact is severely high. + */ + public static final int HIGH_USER_IMPACT_THRESHOLD = + PackageHealthObserverImpact.USER_IMPACT_LEVEL_71; + + /** * Possible severity values of the user impact of a * {@link PackageHealthObserver#onExecuteHealthCheckMitigation}. * @hide @@ -773,6 +792,11 @@ public class PackageWatchdog { /** * Called when health check fails for the {@code versionedPackage}. * + * Note: if the returned user impact is higher than + * {@link #DEFAULT_HIGH_USER_IMPACT_THRESHOLD}, then + * {@link #onExecuteHealthCheckMitigation} would be called only in severe device conditions + * like boot-loop or network failure. + * * @param versionedPackage the package that is failing. This may be null if a native * service is crashing. * @param failureReason the type of failure that is occurring. @@ -780,8 +804,8 @@ public class PackageWatchdog { * (including this time). * * - * @return any one of {@link PackageHealthObserverImpact} to express the impact - * to the user on {@link #onExecuteHealthCheckMitigation} + * @return any value greater than {@link #LEAST_PACKAGE_HEALTH_OBSERVER_IMPACT} to express + * the impact of mitigation on the user in {@link #onExecuteHealthCheckMitigation} */ @PackageHealthObserverImpact int onHealthCheckFailed( @Nullable VersionedPackage versionedPackage, @@ -790,9 +814,8 @@ public class PackageWatchdog { /** * This would be called after {@link #onHealthCheckFailed}. - * This is called only if current observer returned least - * {@link PackageHealthObserverImpact} mitigation for failed health - * check. + * This is called only if current observer returned least impact mitigation for failed + * health check. * * @param versionedPackage the package that is failing. This may be null if a native * service is crashing. @@ -811,6 +834,9 @@ public class PackageWatchdog { * * @param mitigationCount the number of times mitigation has been attempted for this * boot loop (including this time). + * + * @return any value greater than {@link #LEAST_PACKAGE_HEALTH_OBSERVER_IMPACT} to express + * the impact of mitigation on the user in {@link #onExecuteBootLoopMitigation} */ default @PackageHealthObserverImpact int onBootLoop(int mitigationCount) { return PackageHealthObserverImpact.USER_IMPACT_LEVEL_0; @@ -818,11 +844,13 @@ public class PackageWatchdog { /** * This would be called after {@link #onBootLoop}. - * This is called only if current observer returned least - * {@link PackageHealthObserverImpact} mitigation for fixing boot loop + * This is called only if current observer returned least impact mitigation for fixing + * boot loop. * * @param mitigationCount the number of times mitigation has been attempted for this * boot loop (including this time). + * + * @return {@code true} if action was executed successfully, {@code false} otherwise */ default boolean onExecuteBootLoopMitigation(int mitigationCount) { return false; @@ -916,7 +944,7 @@ public class PackageWatchdog { * effectively behave as if the explicit health check hasn't passed for {@code packageName}. * * <p> {@code packageName} can still be considered failed if reported by - * {@link #onPackageFailureLocked} before the package expires. + * {@link #notifyPackageFailureLocked} before the package expires. * * <p> Triggered by components outside the system server when they are fully functional after an * update. @@ -1460,7 +1488,7 @@ public class PackageWatchdog { * @hide */ @GuardedBy("sLock") - public boolean onPackageFailureLocked(String packageName) { + public boolean notifyPackageFailureLocked(String packageName) { if (getMonitoredPackage(packageName) == null && registeredObserver.isPersistent() && registeredObserver.mayObservePackage(packageName)) { putMonitoredPackage(sPackageWatchdog.newMonitoredPackage( diff --git a/packages/CrashRecovery/services/platform/java/com/android/server/PackageWatchdog.java b/packages/CrashRecovery/services/platform/java/com/android/server/PackageWatchdog.java index 129e47f22f38..88fe36cda395 100644 --- a/packages/CrashRecovery/services/platform/java/com/android/server/PackageWatchdog.java +++ b/packages/CrashRecovery/services/platform/java/com/android/server/PackageWatchdog.java @@ -477,7 +477,7 @@ public class PackageWatchdog { * * <p>This method could be called frequently if there is a severe problem on the device. */ - public void onPackageFailure(@NonNull List<VersionedPackage> packages, + public void notifyPackageFailure(@NonNull List<VersionedPackage> packages, @FailureReasons int failureReason) { if (packages == null) { Slog.w(TAG, "Could not resolve a list of failing packages"); @@ -488,7 +488,7 @@ public class PackageWatchdog { if (Flags.recoverabilityDetection()) { if (now >= mLastMitigation && (now - mLastMitigation) < getMitigationWindowMs()) { - Slog.i(TAG, "Skipping onPackageFailure mitigation"); + Slog.i(TAG, "Skipping notifyPackageFailure mitigation"); return; } } @@ -515,7 +515,7 @@ public class PackageWatchdog { ObserverInternal observer = mAllObservers.valueAt(oIndex); PackageHealthObserver registeredObserver = observer.registeredObserver; if (registeredObserver != null - && observer.onPackageFailureLocked( + && observer.notifyPackageFailureLocked( versionedPackage.getPackageName())) { MonitoredPackage p = observer.getMonitoredPackage( versionedPackage.getPackageName()); @@ -714,7 +714,7 @@ public class PackageWatchdog { // Check if native watchdog reported a crash if ("1".equals(SystemProperties.get("sys.init.updatable_crashing"))) { // We rollback all available low impact rollbacks when crash is unattributable - onPackageFailure(Collections.EMPTY_LIST, FAILURE_REASON_NATIVE_CRASH); + notifyPackageFailure(Collections.EMPTY_LIST, FAILURE_REASON_NATIVE_CRASH); // we stop polling after an attempt to execute rollback, regardless of whether the // attempt succeeds or not } else { @@ -926,7 +926,7 @@ public class PackageWatchdog { * effectively behave as if the explicit health check hasn't passed for {@code packageName}. * * <p> {@code packageName} can still be considered failed if reported by - * {@link #onPackageFailureLocked} before the package expires. + * {@link #notifyPackageFailureLocked} before the package expires. * * <p> Triggered by components outside the system server when they are fully functional after an * update. @@ -1253,7 +1253,7 @@ public class PackageWatchdog { return; } final List<VersionedPackage> pkgList = Collections.singletonList(pkg); - onPackageFailure(pkgList, FAILURE_REASON_EXPLICIT_HEALTH_CHECK); + notifyPackageFailure(pkgList, FAILURE_REASON_EXPLICIT_HEALTH_CHECK); }); } @@ -1467,7 +1467,7 @@ public class PackageWatchdog { * @hide */ @GuardedBy("mLock") - public boolean onPackageFailureLocked(String packageName) { + public boolean notifyPackageFailureLocked(String packageName) { if (getMonitoredPackage(packageName) == null && registeredObserver.isPersistent() && registeredObserver.mayObservePackage(packageName)) { putMonitoredPackage(sPackageWatchdog.newMonitoredPackage( diff --git a/packages/NeuralNetworks/OWNERS b/packages/NeuralNetworks/OWNERS new file mode 100644 index 000000000000..6b391503b5c4 --- /dev/null +++ b/packages/NeuralNetworks/OWNERS @@ -0,0 +1,5 @@ +# Bug component: 195575 + +sandeepbandaru@google.com +shivanker@google.com +shiqing@google.com
\ No newline at end of file diff --git a/packages/SettingsLib/IntroPreference/src/com/android/settingslib/widget/IntroPreference.kt b/packages/SettingsLib/IntroPreference/src/com/android/settingslib/widget/IntroPreference.kt index 0cdfc6610bbd..81337612e59a 100644 --- a/packages/SettingsLib/IntroPreference/src/com/android/settingslib/widget/IntroPreference.kt +++ b/packages/SettingsLib/IntroPreference/src/com/android/settingslib/widget/IntroPreference.kt @@ -31,7 +31,7 @@ class IntroPreference @JvmOverloads constructor( attrs: AttributeSet? = null, defStyleAttr: Int = 0, defStyleRes: Int = 0 -) : Preference(context, attrs, defStyleAttr, defStyleRes) { +) : Preference(context, attrs, defStyleAttr, defStyleRes), GroupSectionDividerMixin { private var isCollapsable: Boolean = false private var minLines: Int = 2 diff --git a/packages/SettingsLib/UsageProgressBarPreference/res/layout/preference_usage_progress_bar.xml b/packages/SettingsLib/UsageProgressBarPreference/res/layout/preference_usage_progress_bar.xml index ea033a39f766..7d366f3091bc 100644 --- a/packages/SettingsLib/UsageProgressBarPreference/res/layout/preference_usage_progress_bar.xml +++ b/packages/SettingsLib/UsageProgressBarPreference/res/layout/preference_usage_progress_bar.xml @@ -22,9 +22,9 @@ android:layout_height="wrap_content" android:gravity="center_vertical" android:orientation="vertical" - android:layout_marginStart="?android:attr/listPreferredItemPaddingStart" - android:layout_marginEnd="?android:attr/listPreferredItemPaddingEnd" - android:paddingBottom="16dp"> + android:paddingStart="?android:attr/listPreferredItemPaddingStart" + android:paddingEnd="?android:attr/listPreferredItemPaddingEnd" + android:paddingBottom="@dimen/settingslib_expressive_space_small1"> <androidx.constraintlayout.widget.ConstraintLayout android:layout_width="match_parent" diff --git a/packages/SettingsLib/res/drawable/ic_tv_box_internal_speaker.xml b/packages/SettingsLib/res/drawable/ic_tv_box_internal_speaker.xml new file mode 100644 index 000000000000..2a90e051b83b --- /dev/null +++ b/packages/SettingsLib/res/drawable/ic_tv_box_internal_speaker.xml @@ -0,0 +1,25 @@ +<!-- + ~ Copyright (C) 2022 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. + --> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24" + android:tint="?android:attr/textColorPrimary" + android:autoMirrored="true"> + <path android:fillColor="#FFFFFFFF" + android:pathData="M14,20.725V18.675Q16.25,18.025 17.625,16.175Q19,14.325 19,11.975Q19,9.625 17.625,7.775Q16.25,5.925 14,5.275V3.225Q17.1,3.925 19.05,6.362Q21,8.8 21,11.975Q21,15.15 19.05,17.587Q17.1,20.025 14,20.725ZM3,15V9H7L12,4V20L7,15ZM14,16V7.95Q15.175,8.5 15.838,9.6Q16.5,10.7 16.5,12Q16.5,13.275 15.838,14.362Q15.175,15.45 14,16ZM10,8.85 L7.85,11H5V13H7.85L10,15.15ZM7.5,12Z"/> +</vector>
\ No newline at end of file diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml index f03014ca95e2..eaf155df4785 100644 --- a/packages/SettingsLib/res/values/strings.xml +++ b/packages/SettingsLib/res/values/strings.xml @@ -1419,7 +1419,7 @@ <!-- Name of the internal speaker and mic. [CHAR LIMIT=30] --> <string name="media_transfer_this_device_name_desktop">This computer (internal)</string> <!-- Name of the default media output of the TV. [CHAR LIMIT=30] --> - <string name="media_transfer_this_device_name_tv">@string/tv_media_transfer_default</string> + <string name="media_transfer_this_device_name_tv">This TV</string> <!-- Name of the dock device. [CHAR LIMIT=30] --> <string name="media_transfer_dock_speaker_device_name">Dock speaker</string> <!-- Default name of the external device. [CHAR LIMIT=30] --> @@ -1462,12 +1462,11 @@ <!-- Media output switcher. Subtitle for devices connected through HDMI EARC if a device name is available. [CHAR LIMIT=NONE] --> <string name="tv_media_transfer_earc_subtitle">Connected via eARC</string> - <!-- TV media output switcher. Title for the default audio output of the device [CHAR LIMIT=NONE] --> - <string name="tv_media_transfer_default">TV default</string> - <!-- TV media output switcher. Subtitle for default audio output which is HDMI, e.g. TV dongle [CHAR LIMIT=NONE] --> - <string name="tv_media_transfer_hdmi">HDMI output</string> - <!-- TV media output switcher. Subtitle for default audio output which is internal speaker, i.e. panel VTs [CHAR LIMIT=NONE] --> - <string name="tv_media_transfer_internal_speakers">Internal speakers</string> + <!-- TV media output switcher. Subtitle for default audio output which is internal speaker [CHAR LIMIT=NONE] --> + <string name="tv_media_transfer_internal_speakers">Built-in speaker</string> + + <!-- TV media output switcher. Title for default audio output which is HDMI, e.g. TV dongle [CHAR LIMIT=NONE] --> + <string name="tv_media_transfer_hdmi_title">TV Audio</string> <!-- Warning message to tell user is have problem during profile connect, it need to turn off device and back on. [CHAR_LIMIT=NONE] --> <string name="profile_connect_timeout_subtext">Problem connecting. Turn device off & back on</string> diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidDeviceManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidDeviceManager.java index b3e48b26782e..fa28cf6c8a76 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidDeviceManager.java +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidDeviceManager.java @@ -94,6 +94,14 @@ public class HearingAidDeviceManager { boolean setSubDeviceIfNeeded(CachedBluetoothDevice newDevice) { final long hiSyncId = newDevice.getHiSyncId(); if (isValidHiSyncId(hiSyncId)) { + // The remote device supports CSIP, the other ear should be processed as a member + // device. Ignore hiSyncId grouping from ASHA here. + if (newDevice.getProfiles().stream().anyMatch( + profile -> profile instanceof CsipSetCoordinatorProfile)) { + Log.w(TAG, "Skip ASHA grouping since this device supports CSIP"); + return false; + } + final CachedBluetoothDevice hearingAidDevice = getCachedDevice(hiSyncId); // Just add one of the hearing aids from a pair in the list that is shown in the UI. // Once there is another device with the same hiSyncId, to add new device as sub @@ -161,6 +169,7 @@ public class HearingAidDeviceManager { // device. Ignore hiSyncId grouping from ASHA here. if (cachedDevice.getProfiles().stream().anyMatch( profile -> profile instanceof CsipSetCoordinatorProfile)) { + Log.w(TAG, "Skip ASHA grouping since this device supports CSIP"); continue; } diff --git a/packages/SettingsLib/src/com/android/settingslib/media/DeviceIconUtil.java b/packages/SettingsLib/src/com/android/settingslib/media/DeviceIconUtil.java index 717a8ee32082..aa2ede311e23 100644 --- a/packages/SettingsLib/src/com/android/settingslib/media/DeviceIconUtil.java +++ b/packages/SettingsLib/src/com/android/settingslib/media/DeviceIconUtil.java @@ -33,6 +33,8 @@ import android.annotation.SuppressLint; import android.content.Context; import android.content.pm.PackageManager; import android.graphics.drawable.Drawable; +import android.media.AudioDeviceInfo; +import android.media.AudioManager; import android.media.MediaRoute2Info; import android.os.SystemProperties; import android.util.SparseIntArray; @@ -116,14 +118,15 @@ public class DeviceIconUtil { @SuppressLint("SwitchIntDef") @DrawableRes - private static int getIconResourceIdForTv(@MediaRoute2Info.Type int type) { + private int getIconResourceIdForTv(@MediaRoute2Info.Type int type) { return switch (type) { case MediaRoute2Info.TYPE_USB_DEVICE, MediaRoute2Info.TYPE_USB_HEADSET -> R.drawable.ic_headphone; case MediaRoute2Info.TYPE_USB_ACCESSORY -> R.drawable.ic_usb; case MediaRoute2Info.TYPE_DOCK -> R.drawable.ic_dock_device; - case MediaRoute2Info.TYPE_HDMI, MediaRoute2Info.TYPE_BUILTIN_SPEAKER -> - R.drawable.ic_tv; + case MediaRoute2Info.TYPE_BUILTIN_SPEAKER -> + isPanelTv() ? R.drawable.ic_tv : R.drawable.ic_tv_box_internal_speaker; + case MediaRoute2Info.TYPE_HDMI -> R.drawable.ic_tv; case MediaRoute2Info.TYPE_HDMI_ARC, MediaRoute2Info.TYPE_HDMI_EARC -> R.drawable.ic_hdmi; case MediaRoute2Info.TYPE_WIRED_HEADSET, MediaRoute2Info.TYPE_WIRED_HEADPHONES -> @@ -132,6 +135,23 @@ public class DeviceIconUtil { }; } + private boolean isPanelTv() { + if (mContext == null) { + // This should only happen during testing. + return true; + } + AudioManager audioManager = mContext.getSystemService(AudioManager.class); + AudioDeviceInfo[] devices = audioManager.getDevices( + AudioManager.GET_DEVICES_OUTPUTS); + // If we have an HDMI output (not ARC/eARC) we can assume it's a dongle / set top box. + for (AudioDeviceInfo device : devices) { + if (device.getType() == TYPE_HDMI) { + return false; + } + } + return true; + } + static { AUDIO_DEVICE_TO_MEDIA_ROUTE_TYPE.put(TYPE_USB_DEVICE, MediaRoute2Info.TYPE_USB_DEVICE); AUDIO_DEVICE_TO_MEDIA_ROUTE_TYPE.put(TYPE_USB_HEADSET, MediaRoute2Info.TYPE_USB_HEADSET); diff --git a/packages/SettingsLib/src/com/android/settingslib/media/MediaDevice.java b/packages/SettingsLib/src/com/android/settingslib/media/MediaDevice.java index 2321097d42d7..b01b7c9048ba 100644 --- a/packages/SettingsLib/src/com/android/settingslib/media/MediaDevice.java +++ b/packages/SettingsLib/src/com/android/settingslib/media/MediaDevice.java @@ -390,6 +390,16 @@ public abstract class MediaDevice implements Comparable<MediaDevice> { } /** + * Get the {@link MediaRoute2Info.Type} of the device. + */ + public int getRouteType() { + if (mRouteInfo == null) { + return TYPE_UNKNOWN; + } + return mRouteInfo.getType(); + } + + /** * Checks if route's volume is fixed, if true, we should disable volume control for the device. * * @return route for this device is fixed. diff --git a/packages/SettingsLib/src/com/android/settingslib/media/PhoneMediaDevice.java b/packages/SettingsLib/src/com/android/settingslib/media/PhoneMediaDevice.java index 4766a869e406..6ff1a99156ac 100644 --- a/packages/SettingsLib/src/com/android/settingslib/media/PhoneMediaDevice.java +++ b/packages/SettingsLib/src/com/android/settingslib/media/PhoneMediaDevice.java @@ -29,6 +29,7 @@ import static android.media.MediaRoute2Info.TYPE_WIRED_HEADSET; import static android.media.MediaRoute2Info.TYPE_LINE_DIGITAL; import static android.media.MediaRoute2Info.TYPE_LINE_ANALOG; import static android.media.MediaRoute2Info.TYPE_AUX_LINE; + import static com.android.settingslib.media.MediaDevice.SelectionBehavior.SELECTION_BEHAVIOR_TRANSFER; import android.Manifest; @@ -40,6 +41,7 @@ import android.hardware.hdmi.HdmiDeviceInfo; import android.hardware.hdmi.HdmiPortInfo; import android.media.MediaRoute2Info; import android.media.RouteListingPreference; +import android.os.Build; import android.os.SystemProperties; import android.util.Log; @@ -72,7 +74,7 @@ public class PhoneMediaDevice extends MediaDevice { /** Returns this device name for media transfer. */ public static @NonNull String getMediaTransferThisDeviceName(@NonNull Context context) { if (isTv(context)) { - return context.getString(R.string.media_transfer_this_device_name_tv); + return Build.MODEL; } else if (isTablet()) { return context.getString(R.string.media_transfer_this_device_name_tablet); } else if (inputRoutingEnabledAndIsDesktop(context)) { @@ -110,7 +112,7 @@ public class PhoneMediaDevice extends MediaDevice { name = getMediaTransferThisDeviceName(context); break; case TYPE_HDMI: - name = context.getString(isTv ? R.string.tv_media_transfer_default : + name = context.getString(isTv ? R.string.tv_media_transfer_hdmi_title : R.string.media_transfer_external_device_name); break; case TYPE_HDMI_ARC: @@ -223,8 +225,6 @@ public class PhoneMediaDevice extends MediaDevice { switch (mRouteInfo.getType()) { case TYPE_BUILTIN_SPEAKER: return mContext.getString(R.string.tv_media_transfer_internal_speakers); - case TYPE_HDMI: - return mContext.getString(R.string.tv_media_transfer_hdmi); case TYPE_HDMI_ARC: if (getHdmiOutDeviceName(mContext) == null) { // Connection type is already part of the title. diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/applications/AppIconCacheManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/applications/AppIconCacheManagerTest.java index 1b0e1f1236c8..013ff923e130 100644 --- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/applications/AppIconCacheManagerTest.java +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/applications/AppIconCacheManagerTest.java @@ -16,11 +16,14 @@ package com.android.settingslib.applications; +import static android.content.ComponentCallbacks2.TRIM_MEMORY_BACKGROUND; + import static com.google.common.truth.Truth.assertThat; import static org.mockito.Mockito.doReturn; import android.graphics.drawable.Drawable; +import android.util.Log; import org.junit.After; import org.junit.Before; @@ -30,9 +33,12 @@ import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.robolectric.RobolectricTestRunner; +import java.util.concurrent.atomic.AtomicInteger; + @RunWith(RobolectricTestRunner.class) public class AppIconCacheManagerTest { + private static final String TAG = "AppIconCacheManagerTest"; private static final String APP_PACKAGE_NAME = "com.test.app"; private static final String APP_PACKAGE_NAME1 = "com.test.app1"; private static final String APP_PACKAGE_NAME2 = "com.test.app2"; @@ -176,4 +182,28 @@ public class AppIconCacheManagerTest { assertThat(mAppIconCacheManager.get(APP_PACKAGE_NAME2, APP_UID)).isNull(); assertThat(mAppIconCacheManager.get(APP_PACKAGE_NAME3, APP_UID)).isNull(); } + + @Test + public void trimMemory_multiThread_shouldNotCrash() { + int numberOfTasks = 10; + AtomicInteger completedTasks = new AtomicInteger(0); + + Runnable task = + () -> { + String threadName = Thread.currentThread().getName(); + Log.i(TAG, "Starting thread: " + threadName); + AppIconCacheManager.getInstance().trimMemory(TRIM_MEMORY_BACKGROUND); + completedTasks.incrementAndGet(); + Log.i(TAG, "Ending thread: " + threadName); + }; + + for (Integer i = 0; i < numberOfTasks; i++) { + Thread thread = new Thread(task); + thread.start(); + } + + while (completedTasks.get() < numberOfTasks) { + // Wait until all threads are finished. + } + } } diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/DeviceIconUtilTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/DeviceIconUtilTest.java index 883640db5e27..5ac22a732f3c 100644 --- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/DeviceIconUtilTest.java +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/DeviceIconUtilTest.java @@ -173,7 +173,7 @@ public class DeviceIconUtilTest { public void getIconResIdFromMediaRouteType_tv_builtinSpeaker_isTv() { assertThat(new DeviceIconUtil(/* isTv */ true) .getIconResIdFromMediaRouteType(MediaRoute2Info.TYPE_BUILTIN_SPEAKER)) - .isEqualTo(R.drawable.ic_tv); + .isAnyOf(R.drawable.ic_tv, R.drawable.ic_tv_box_internal_speaker); } @Test @@ -331,7 +331,7 @@ public class DeviceIconUtilTest { public void getIconResIdFromAudioDeviceType_tv_builtinSpeaker_isTv() { assertThat(new DeviceIconUtil(/* isTv */ true) .getIconResIdFromAudioDeviceType(AudioDeviceInfo.TYPE_BUILTIN_SPEAKER)) - .isEqualTo(R.drawable.ic_tv); + .isAnyOf(R.drawable.ic_tv, R.drawable.ic_tv_box_internal_speaker); } @Test diff --git a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java index 927a1c59cc76..1f291cdefb03 100644 --- a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java +++ b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java @@ -107,6 +107,8 @@ public class SecureSettings { Settings.Secure.DISPLAY_WHITE_BALANCE_ENABLED, Settings.Secure.SYNC_PARENT_SOUNDS, Settings.Secure.CAMERA_DOUBLE_TWIST_TO_FLIP_ENABLED, + Settings.Secure.DOUBLE_TAP_POWER_BUTTON_GESTURE_ENABLED, + Settings.Secure.DOUBLE_TAP_POWER_BUTTON_GESTURE, Settings.Secure.CAMERA_DOUBLE_TAP_POWER_GESTURE_DISABLED, Settings.Secure.SYSTEM_NAVIGATION_KEYS_ENABLED, // ACCESSIBILITY_QS_TARGETS needs to be restored after ENABLED_ACCESSIBILITY_SERVICES diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java index 6d73ee27f076..abd5b9a4a4bb 100644 --- a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java +++ b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java @@ -160,6 +160,9 @@ public class SecureSettingsValidators { VALIDATORS.put(Secure.DISPLAY_WHITE_BALANCE_ENABLED, BOOLEAN_VALIDATOR); VALIDATORS.put(Secure.SYNC_PARENT_SOUNDS, BOOLEAN_VALIDATOR); VALIDATORS.put(Secure.CAMERA_DOUBLE_TWIST_TO_FLIP_ENABLED, BOOLEAN_VALIDATOR); + VALIDATORS.put(Secure.DOUBLE_TAP_POWER_BUTTON_GESTURE_ENABLED, BOOLEAN_VALIDATOR); + VALIDATORS.put(Secure.DOUBLE_TAP_POWER_BUTTON_GESTURE, + new InclusiveIntegerRangeValidator(0, 1)); VALIDATORS.put(Secure.CAMERA_DOUBLE_TAP_POWER_GESTURE_DISABLED, BOOLEAN_VALIDATOR); VALIDATORS.put(Secure.SYSTEM_NAVIGATION_KEYS_ENABLED, BOOLEAN_VALIDATOR); VALIDATORS.put(Secure.QS_TILES, TILE_LIST_VALIDATOR); diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java index 600c36e5dfc9..5ae11bacb445 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java @@ -2124,6 +2124,15 @@ class SettingsProtoDumpUtil { SecureSettingsProto.Display.SCREEN_RESOLUTION_MODE); p.end(displayToken); + final long doubleTapPowerButtonToken = p.start(SecureSettingsProto.DOUBLE_TAP_POWER_BUTTON); + dumpSetting(s, p, + Settings.Secure.DOUBLE_TAP_POWER_BUTTON_GESTURE_ENABLED, + SecureSettingsProto.DoubleTapPowerButton.GESTURE_ENABLED); + dumpSetting(s, p, + Settings.Secure.DOUBLE_TAP_POWER_BUTTON_GESTURE, + SecureSettingsProto.DoubleTapPowerButton.GESTURE); + p.end(doubleTapPowerButtonToken); + final long dozeToken = p.start(SecureSettingsProto.DOZE); dumpSetting(s, p, Settings.Secure.DOZE_ENABLED, diff --git a/packages/SettingsProvider/src/com/android/providers/settings/WritableNamespaces.java b/packages/SettingsProvider/src/com/android/providers/settings/WritableNamespaces.java index d835c5f5c179..b0409c037107 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/WritableNamespaces.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/WritableNamespaces.java @@ -33,6 +33,15 @@ import java.util.Set; final class WritableNamespaces { public static final Set<String> ALLOWLIST = new ArraySet<String>(Arrays.asList( - "exo" + "captive_portal_login", + "connectivity", + "exo", + "nearby", + "netd_native", + "network_security", + "on_device_personalization", + "tethering", + "tethering_u_or_later_native", + "thread_network" )); } diff --git a/packages/Shell/Android.bp b/packages/Shell/Android.bp index 3350efc33ad8..5f810858b7cd 100644 --- a/packages/Shell/Android.bp +++ b/packages/Shell/Android.bp @@ -27,6 +27,7 @@ android_app { ], flags_packages: [ "android.security.flags-aconfig", + "android.permission.flags-aconfig", ], platform_apis: true, certificate: "platform", @@ -51,5 +52,6 @@ android_library { manifest: "AndroidManifest.xml", flags_packages: [ "android.security.flags-aconfig", + "android.permission.flags-aconfig", ], } diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml index ac02af81420c..27e6bab1642d 100644 --- a/packages/Shell/AndroidManifest.xml +++ b/packages/Shell/AndroidManifest.xml @@ -981,6 +981,14 @@ <uses-permission android:name="android.permission.READ_SYSTEM_PREFERENCES" /> <uses-permission android:name="android.permission.WRITE_SYSTEM_PREFERENCES" /> + <!-- Permissions required for CTS test - ActivityManagerForegroundServiceTypeTest --> + <uses-permission android:name="android.permission.health.READ_HEART_RATE" + android:featureFlag="android.permission.flags.replace_body_sensor_permission_enabled"/> + <uses-permission android:name="android.permission.health.READ_OXYGEN_SATURATION" + android:featureFlag="android.permission.flags.replace_body_sensor_permission_enabled"/> + <uses-permission android:name="android.permission.health.READ_SKIN_TEMPERATURE" + android:featureFlag="android.permission.flags.replace_body_sensor_permission_enabled"/> + <application android:label="@string/app_label" android:theme="@android:style/Theme.DeviceDefault.DayNight" diff --git a/packages/StatementService/Android.bp b/packages/StatementService/Android.bp index 90e1808b7d44..39b0302beff8 100644 --- a/packages/StatementService/Android.bp +++ b/packages/StatementService/Android.bp @@ -38,8 +38,10 @@ android_app { "StatementServiceParser", "androidx.appcompat_appcompat", "androidx.collection_collection-ktx", + "androidx.room_room-runtime", "androidx.work_work-runtime", "androidx.work_work-runtime-ktx", "kotlinx-coroutines-android", ], + plugins: ["androidx.room_room-compiler-plugin"], } diff --git a/packages/StatementService/src/com/android/statementservice/database/Converters.kt b/packages/StatementService/src/com/android/statementservice/database/Converters.kt new file mode 100644 index 000000000000..21ecc8b4a651 --- /dev/null +++ b/packages/StatementService/src/com/android/statementservice/database/Converters.kt @@ -0,0 +1,130 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.statementservice.database + +import android.content.UriRelativeFilter +import android.content.UriRelativeFilterGroup +import android.util.JsonReader +import androidx.room.TypeConverter +import org.json.JSONArray +import org.json.JSONObject +import java.io.StringReader +import java.util.ArrayList + +class Converters { + companion object { + private const val ACTION_NAME = "action" + private const val FILTERS_NAME = "filters" + private const val URI_PART_NAME = "uriPart" + private const val PATTERN_TYPE_NAME = "patternType" + private const val FILTER_NAME = "filter" + } + + @TypeConverter + fun groupsToJson(groups: List<UriRelativeFilterGroup>): String { + val json = JSONArray() + for (group in groups) { + json.put(groupToJson(group)) + } + return json.toString() + } + + @TypeConverter + fun stringToGroups(json: String): List<UriRelativeFilterGroup> { + val groups = ArrayList<UriRelativeFilterGroup>() + StringReader(json).use { stringReader -> + JsonReader(stringReader).use { reader -> + reader.beginArray() + while (reader.hasNext()) { + groups.add(parseGroup(reader)) + } + reader.endArray() + } + } + return groups + } + + private fun groupToJson(group: UriRelativeFilterGroup): JSONObject { + val jsonObject = JSONObject() + jsonObject.put(ACTION_NAME, group.action) + val filters = JSONArray() + for (filter in group.uriRelativeFilters) { + filters.put(filterToJson(filter)) + } + jsonObject.put(FILTERS_NAME, filters) + return jsonObject + } + + private fun filterToJson(filter: UriRelativeFilter): JSONObject { + val jsonObject = JSONObject() + jsonObject.put(URI_PART_NAME, filter.uriPart) + jsonObject.put(PATTERN_TYPE_NAME, filter.patternType) + jsonObject.put(FILTER_NAME, filter.filter) + return jsonObject + } + + private fun parseGroup(reader: JsonReader): UriRelativeFilterGroup { + val jsonObject = JSONObject() + reader.beginObject() + while (reader.hasNext()) { + val name = reader.nextName() + when (name) { + ACTION_NAME -> jsonObject.put(ACTION_NAME, reader.nextInt()) + FILTERS_NAME -> jsonObject.put(FILTERS_NAME, parseFilters(reader)) + else -> reader.skipValue() + } + } + reader.endObject() + + val group = UriRelativeFilterGroup(jsonObject.getInt(ACTION_NAME)) + val filters = jsonObject.getJSONArray(FILTERS_NAME) + for (i in 0 until filters.length()) { + val filter = filters.getJSONObject(i) + group.addUriRelativeFilter(UriRelativeFilter( + filter.getInt(URI_PART_NAME), + filter.getInt(PATTERN_TYPE_NAME), + filter.getString(FILTER_NAME) + )) + } + return group + } + + private fun parseFilters(reader: JsonReader): JSONArray { + val filters = JSONArray() + reader.beginArray() + while (reader.hasNext()) { + filters.put(parseFilter(reader)) + } + reader.endArray() + return filters + } + + private fun parseFilter(reader: JsonReader): JSONObject { + reader.beginObject() + val jsonObject = JSONObject() + while (reader.hasNext()) { + val name = reader.nextName() + when (name) { + URI_PART_NAME, PATTERN_TYPE_NAME -> jsonObject.put(name, reader.nextInt()) + FILTER_NAME -> jsonObject.put(name, reader.nextString()) + else -> reader.skipValue() + } + } + reader.endObject() + return jsonObject + } +}
\ No newline at end of file diff --git a/packages/StatementService/src/com/android/statementservice/database/DomainGroups.kt b/packages/StatementService/src/com/android/statementservice/database/DomainGroups.kt new file mode 100644 index 000000000000..c61666910cb4 --- /dev/null +++ b/packages/StatementService/src/com/android/statementservice/database/DomainGroups.kt @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.statementservice.database + +import android.content.UriRelativeFilterGroup +import androidx.room.Entity + +@Entity(primaryKeys = ["packageName", "domain"]) +data class DomainGroups( + val packageName: String, + val domain: String, + val groups: List<UriRelativeFilterGroup> +)
\ No newline at end of file diff --git a/packages/StatementService/src/com/android/statementservice/database/DomainGroupsDao.kt b/packages/StatementService/src/com/android/statementservice/database/DomainGroupsDao.kt new file mode 100644 index 000000000000..3b4dcea48180 --- /dev/null +++ b/packages/StatementService/src/com/android/statementservice/database/DomainGroupsDao.kt @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.statementservice.database + +import androidx.room.Dao +import androidx.room.Insert +import androidx.room.Query + +@Dao +interface DomainGroupsDao { + @Query("SELECT * FROM DomainGroups WHERE packageName = :packageName") + fun getDomainGroups(packageName: String): List<DomainGroups> + + @Insert + fun insertDomainGroups(vararg domainGroups: DomainGroups) + + @Query("DELETE FROM DomainGroups WHERE packageName = :packageName AND domain = :domain") + fun clear(packageName: String, domain: String) + + @Query("DELETE FROM DomainGroups WHERE packageName = :packageName") + fun clear(packageName: String) +}
\ No newline at end of file diff --git a/packages/StatementService/src/com/android/statementservice/database/DomainGroupsDatabase.kt b/packages/StatementService/src/com/android/statementservice/database/DomainGroupsDatabase.kt new file mode 100644 index 000000000000..39833f6bc80b --- /dev/null +++ b/packages/StatementService/src/com/android/statementservice/database/DomainGroupsDatabase.kt @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.statementservice.database + +import android.content.Context +import androidx.room.Database +import androidx.room.Room +import androidx.room.RoomDatabase +import androidx.room.TypeConverters + +@Database(entities = [DomainGroups::class], version = 1) +@TypeConverters(Converters::class) +abstract class DomainGroupsDatabase : RoomDatabase() { + companion object { + private const val DATABASE_NAME = "domain-groups" + @Volatile + private var instance: DomainGroupsDatabase? = null + + fun getInstance(context: Context) = instance ?: synchronized(this) { + instance ?: Room.databaseBuilder( + context, + DomainGroupsDatabase::class.java, DATABASE_NAME + ).build().also { instance = it } + } + } + abstract fun domainGroupsDao(): DomainGroupsDao +}
\ No newline at end of file diff --git a/packages/StatementService/src/com/android/statementservice/domain/DomainVerificationReceiverV1.kt b/packages/StatementService/src/com/android/statementservice/domain/DomainVerificationReceiverV1.kt index acb54f6093de..0d7a1fdbcfb8 100644 --- a/packages/StatementService/src/com/android/statementservice/domain/DomainVerificationReceiverV1.kt +++ b/packages/StatementService/src/com/android/statementservice/domain/DomainVerificationReceiverV1.kt @@ -22,6 +22,7 @@ import android.content.pm.PackageManager import androidx.work.ExistingWorkPolicy import androidx.work.WorkManager import com.android.statementservice.domain.worker.CollectV1Worker +import com.android.statementservice.domain.worker.GroupUpdateV1Worker import com.android.statementservice.domain.worker.SingleV1RequestWorker /** @@ -67,7 +68,7 @@ class DomainVerificationReceiverV1 : BaseDomainVerificationReceiver() { } } - //clear sp before enqueue unique work since policy is REPLACE + // clear sp before enqueue unique work since policy is REPLACE val deContext = context.createDeviceProtectedStorageContext() val editor = deContext?.getSharedPreferences(packageName, Context.MODE_PRIVATE)?.edit() editor?.clear()?.apply() @@ -78,6 +79,7 @@ class DomainVerificationReceiverV1 : BaseDomainVerificationReceiver() { workRequests ) .then(CollectV1Worker.buildRequest(verificationId, packageName)) + .then(GroupUpdateV1Worker.buildRequest(packageName)) .enqueue() } } diff --git a/packages/StatementService/src/com/android/statementservice/domain/DomainVerifier.kt b/packages/StatementService/src/com/android/statementservice/domain/DomainVerifier.kt index 29f844fb1a5d..6914347544de 100644 --- a/packages/StatementService/src/com/android/statementservice/domain/DomainVerifier.kt +++ b/packages/StatementService/src/com/android/statementservice/domain/DomainVerifier.kt @@ -24,6 +24,7 @@ import androidx.collection.LruCache import com.android.statementservice.network.retriever.StatementRetriever import com.android.statementservice.retriever.AbstractAsset import com.android.statementservice.retriever.AbstractAssetMatcher +import com.android.statementservice.retriever.Statement import com.android.statementservice.utils.Result import com.android.statementservice.utils.StatementUtils import com.android.statementservice.utils.component1 @@ -87,10 +88,10 @@ class DomainVerifier private constructor( host: String, packageName: String, network: Network? = null - ): Pair<WorkResult, VerifyStatus> { + ): Triple<WorkResult, VerifyStatus, Statement?> { val assetMatcher = synchronized(targetAssetCache) { targetAssetCache[packageName] } .takeIf { it!!.isPresent } - ?: return WorkResult.failure() to VerifyStatus.FAILURE_PACKAGE_MANAGER + ?: return Triple(WorkResult.failure(), VerifyStatus.FAILURE_PACKAGE_MANAGER, null) return verifyHost(host, assetMatcher.get(), network) } @@ -98,34 +99,34 @@ class DomainVerifier private constructor( host: String, assetMatcher: AbstractAssetMatcher, network: Network? = null - ): Pair<WorkResult, VerifyStatus> { + ): Triple<WorkResult, VerifyStatus, Statement?> { var exception: Exception? = null val resultAndStatus = try { val sourceAsset = StatementUtils.createWebAssetString(host) .let(AbstractAsset::create) val result = retriever.retrieve(sourceAsset, network) - ?: return WorkResult.success() to VerifyStatus.FAILURE_UNKNOWN + ?: return Triple(WorkResult.success(), VerifyStatus.FAILURE_UNKNOWN, null) when (result.responseCode) { HttpURLConnection.HTTP_MOVED_PERM, HttpURLConnection.HTTP_MOVED_TEMP -> { - WorkResult.failure() to VerifyStatus.FAILURE_REDIRECT + Triple(WorkResult.failure(), VerifyStatus.FAILURE_REDIRECT, null) } else -> { - val isVerified = result.statements.any { statement -> + val statement = result.statements.firstOrNull { statement -> (StatementUtils.RELATION.matches(statement.relation) && assetMatcher.matches(statement.target)) } - if (isVerified) { - WorkResult.success() to VerifyStatus.SUCCESS + if (statement != null) { + Triple(WorkResult.success(), VerifyStatus.SUCCESS, statement) } else { - WorkResult.failure() to VerifyStatus.FAILURE_REJECTED_BY_SERVER + Triple(WorkResult.failure(), VerifyStatus.FAILURE_REJECTED_BY_SERVER, statement) } } } } catch (e: Exception) { exception = e - WorkResult.retry() to VerifyStatus.FAILURE_UNKNOWN + Triple(WorkResult.retry(), VerifyStatus.FAILURE_UNKNOWN, null) } if (DEBUG) { diff --git a/packages/StatementService/src/com/android/statementservice/domain/worker/BaseRequestWorker.kt b/packages/StatementService/src/com/android/statementservice/domain/worker/BaseRequestWorker.kt index a17f9c9186ff..64d2d98b931b 100644 --- a/packages/StatementService/src/com/android/statementservice/domain/worker/BaseRequestWorker.kt +++ b/packages/StatementService/src/com/android/statementservice/domain/worker/BaseRequestWorker.kt @@ -17,9 +17,12 @@ package com.android.statementservice.domain.worker import android.content.Context +import android.content.UriRelativeFilterGroup +import android.content.pm.verify.domain.DomainVerificationInfo import android.content.pm.verify.domain.DomainVerificationManager import androidx.work.CoroutineWorker import androidx.work.WorkerParameters +import com.android.statementservice.database.DomainGroupsDatabase import com.android.statementservice.domain.DomainVerifier abstract class BaseRequestWorker( @@ -27,8 +30,19 @@ abstract class BaseRequestWorker( protected val params: WorkerParameters ) : CoroutineWorker(appContext, params) { + protected val database = DomainGroupsDatabase.getInstance(appContext).domainGroupsDao() + protected val verificationManager = appContext.getSystemService(DomainVerificationManager::class.java)!! protected val verifier = DomainVerifier.getInstance(appContext) + + protected fun updateUriRelativeFilterGroups(packageName: String, domainGroupUpdates: Map<String, List<UriRelativeFilterGroup>>) { + val verifiedDomains = verificationManager.getDomainVerificationInfo(packageName)?.hostToStateMap?.filterValues { + it == DomainVerificationInfo.STATE_SUCCESS || it == DomainVerificationInfo.STATE_MODIFIABLE_VERIFIED + }?.keys?.toList() ?: emptyList() + val domainGroups = verificationManager.getUriRelativeFilterGroups(packageName, verifiedDomains) + domainGroupUpdates.forEach { (domain, groups) -> domainGroups[domain] = groups } + verificationManager.setUriRelativeFilterGroups(packageName, domainGroups) + } } diff --git a/packages/StatementService/src/com/android/statementservice/domain/worker/GroupUpdateV1Worker.kt b/packages/StatementService/src/com/android/statementservice/domain/worker/GroupUpdateV1Worker.kt new file mode 100644 index 000000000000..f53dfc47acaa --- /dev/null +++ b/packages/StatementService/src/com/android/statementservice/domain/worker/GroupUpdateV1Worker.kt @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.statementservice.domain.worker + +import android.content.Context +import androidx.work.Data +import androidx.work.OneTimeWorkRequestBuilder +import androidx.work.WorkerParameters +import kotlinx.coroutines.coroutineScope + +class GroupUpdateV1Worker(appContext: Context, params: WorkerParameters) : + BaseRequestWorker(appContext, params) { + + companion object { + + private const val PACKAGE_NAME_KEY = "packageName" + + fun buildRequest(packageName: String) = OneTimeWorkRequestBuilder<GroupUpdateV1Worker>() + .setInputData( + Data.Builder() + .putString(PACKAGE_NAME_KEY, packageName) + .build() + ) + .build() + } + + override suspend fun doWork() = coroutineScope { + val packageName = params.inputData.getString(PACKAGE_NAME_KEY)!! + updateUriRelativeFilterGroups(packageName) + Result.success() + } + + private fun updateUriRelativeFilterGroups(packageName: String) { + val groupUpdates = database.getDomainGroups(packageName) + updateUriRelativeFilterGroups( + packageName, + groupUpdates.associateBy({it.domain}, {it.groups}) + ) + database.clear(packageName) + } +}
\ No newline at end of file diff --git a/packages/StatementService/src/com/android/statementservice/domain/worker/RetryRequestWorker.kt b/packages/StatementService/src/com/android/statementservice/domain/worker/RetryRequestWorker.kt index 61ab2c264e6a..f83601a7807b 100644 --- a/packages/StatementService/src/com/android/statementservice/domain/worker/RetryRequestWorker.kt +++ b/packages/StatementService/src/com/android/statementservice/domain/worker/RetryRequestWorker.kt @@ -17,10 +17,13 @@ package com.android.statementservice.domain.worker import android.content.Context +import android.content.UriRelativeFilterGroup +import android.content.pm.verify.domain.DomainVerificationManager import androidx.work.NetworkType import androidx.work.WorkerParameters import com.android.statementservice.domain.VerifyStatus import com.android.statementservice.utils.AndroidUtils +import com.android.statementservice.utils.StatementUtils import kotlinx.coroutines.async import kotlinx.coroutines.awaitAll import kotlinx.coroutines.coroutineScope @@ -36,7 +39,13 @@ class RetryRequestWorker( params: WorkerParameters ) : BaseRequestWorker(appContext, params) { - data class VerifyResult(val domainSetId: UUID, val host: String, val status: VerifyStatus) + data class VerifyResult( + val domainSetId: UUID, + val host: String, + val status: VerifyStatus, + val packageName: String, + val groups: List<UriRelativeFilterGroup> + ) override suspend fun doWork() = coroutineScope { if (!AndroidUtils.isReceiverV2Enabled(appContext)) { @@ -49,8 +58,11 @@ class RetryRequestWorker( .map { (domainSetId, packageName, host) -> async { if (isActive && !isStopped) { - val (_, status) = verifier.verifyHost(host, packageName, params.network) - VerifyResult(domainSetId, host, status) + val (_, status, statement) = verifier.verifyHost(host, packageName, params.network) + val groups = statement?.dynamicAppLinkComponents.orEmpty().map { + StatementUtils.createUriRelativeFilterGroup(it) + } + VerifyResult(domainSetId, host, status, packageName, groups) } else { // If the job gets cancelled, stop the remaining hosts, but continue the // job to commit the results for hosts that were already requested. @@ -60,17 +72,25 @@ class RetryRequestWorker( } .awaitAll() .filterNotNull() // TODO(b/159952358): Fast fail packages which can't be retrieved. - .groupBy { it.domainSetId } - .forEach { (domainSetId, resultsById) -> - resultsById.groupBy { it.status } - .mapValues { it.value.map(VerifyResult::host).toSet() } - .forEach { (status, hosts) -> - verificationManager.setDomainVerificationStatus( - domainSetId, - hosts, - status.value - ) + .groupBy { it.packageName } + .forEach { (packageName, resultsByName) -> + val groupUpdates = mutableMapOf<String, List<UriRelativeFilterGroup>>() + resultsByName.groupBy { it.domainSetId } + .forEach { (domainSetId, resultsById) -> + resultsById.groupBy { it.status } + .forEach { (status, verifyResults) -> + val error = verificationManager.setDomainVerificationStatus( + domainSetId, + verifyResults.map(VerifyResult::host).toSet(), + status.value + ) + if (error == DomainVerificationManager.STATUS_OK + && status == VerifyStatus.SUCCESS) { + verifyResults.forEach { groupUpdates[it.host] = it.groups } + } + } } + updateUriRelativeFilterGroups(packageName, groupUpdates) } // Succeed regardless of results since this retry is best effort and not required diff --git a/packages/StatementService/src/com/android/statementservice/domain/worker/SingleV1RequestWorker.kt b/packages/StatementService/src/com/android/statementservice/domain/worker/SingleV1RequestWorker.kt index 7a198cb59ca4..253a162a73a2 100644 --- a/packages/StatementService/src/com/android/statementservice/domain/worker/SingleV1RequestWorker.kt +++ b/packages/StatementService/src/com/android/statementservice/domain/worker/SingleV1RequestWorker.kt @@ -22,7 +22,9 @@ import androidx.work.Data import androidx.work.OneTimeWorkRequest import androidx.work.OneTimeWorkRequestBuilder import androidx.work.WorkerParameters +import com.android.statementservice.database.DomainGroups import com.android.statementservice.utils.AndroidUtils +import com.android.statementservice.utils.StatementUtils import kotlinx.coroutines.coroutineScope class SingleV1RequestWorker(appContext: Context, params: WorkerParameters) : @@ -60,7 +62,9 @@ class SingleV1RequestWorker(appContext: Context, params: WorkerParameters) : val packageName = params.inputData.getString(PACKAGE_NAME_KEY)!! val host = params.inputData.getString(HOST_KEY)!! - val (result, status) = verifier.verifyHost(host, packageName, params.network) + database.clear(packageName, host) + + val (result, status, statement) = verifier.verifyHost(host, packageName, params.network) if (DEBUG) { Log.d( @@ -75,6 +79,10 @@ class SingleV1RequestWorker(appContext: Context, params: WorkerParameters) : val deContext = appContext.createDeviceProtectedStorageContext() val sp = deContext?.getSharedPreferences(packageName, Context.MODE_PRIVATE) sp?.edit()?.putInt("$HOST_SUCCESS_PREFIX$host", status.value)?.apply() + val groups = statement?.dynamicAppLinkComponents.orEmpty().map { + StatementUtils.createUriRelativeFilterGroup(it) + } + database.insertDomainGroups(DomainGroups(packageName, host, groups)) Result.success() } is Result.Failure -> { diff --git a/packages/StatementService/src/com/android/statementservice/domain/worker/SingleV2RequestWorker.kt b/packages/StatementService/src/com/android/statementservice/domain/worker/SingleV2RequestWorker.kt index 562b132d36d6..8b1347a69932 100644 --- a/packages/StatementService/src/com/android/statementservice/domain/worker/SingleV2RequestWorker.kt +++ b/packages/StatementService/src/com/android/statementservice/domain/worker/SingleV2RequestWorker.kt @@ -22,6 +22,7 @@ import androidx.work.OneTimeWorkRequest import androidx.work.OneTimeWorkRequestBuilder import androidx.work.WorkerParameters import com.android.statementservice.utils.AndroidUtils +import com.android.statementservice.utils.StatementUtils import kotlinx.coroutines.coroutineScope import java.util.UUID @@ -59,9 +60,13 @@ class SingleV2RequestWorker(appContext: Context, params: WorkerParameters) : val packageName = params.inputData.getString(PACKAGE_NAME_KEY)!! val host = params.inputData.getString(HOST_KEY)!! - val (result, status) = verifier.verifyHost(host, packageName, params.network) + val (result, status, statement) = verifier.verifyHost(host, packageName, params.network) verificationManager.setDomainVerificationStatus(domainSetId, setOf(host), status.value) + val groups = statement?.dynamicAppLinkComponents.orEmpty().map { + StatementUtils.createUriRelativeFilterGroup(it) + } + updateUriRelativeFilterGroups(packageName, mapOf(host to groups)) result } diff --git a/packages/StatementService/src/com/android/statementservice/network/retriever/StatementParser.kt b/packages/StatementService/src/com/android/statementservice/network/retriever/StatementParser.kt index ad137400fa86..d10cb0f91c11 100644 --- a/packages/StatementService/src/com/android/statementservice/network/retriever/StatementParser.kt +++ b/packages/StatementService/src/com/android/statementservice/network/retriever/StatementParser.kt @@ -39,6 +39,11 @@ object StatementParser { private const val FIELD_NOT_STRING_FORMAT_STRING = "Expected %s to be string." private const val FIELD_NOT_ARRAY_FORMAT_STRING = "Expected %s to be array." + private const val COMMENTS_NAME = "comments" + private const val EXCLUDE_NAME = "exclude" + private const val FRAGMENT_NAME = "#" + private const val QUERY_NAME = "?" + private const val PATH_NAME = "/" /** * Parses a JSON array of statements. @@ -99,9 +104,7 @@ object StatementParser { FIELD_NOT_ARRAY_FORMAT_STRING.format(StatementUtils.ASSET_DESCRIPTOR_FIELD_RELATION) ) val target = AssetFactory.create(targetObject) - val dynamicAppLinkComponents = parseDynamicAppLinkComponents( - statement.optJSONObject(StatementUtils.ASSET_DESCRIPTOR_FIELD_RELATION_EXTENSIONS) - ) + val dynamicAppLinkComponents = parseDynamicAppLinkComponents(statement) val statements = (0 until relations.length()) .map { relations.getString(it) } @@ -129,13 +132,13 @@ object StatementParser { } private fun parseComponent(component: JSONObject): DynamicAppLinkComponent { - val query = component.optJSONObject("?") + val query = component.optJSONObject(QUERY_NAME) return DynamicAppLinkComponent.create( - component.optBoolean("exclude", false), - component.optString("#"), - component.optString("/"), + component.optBoolean(EXCLUDE_NAME, false), + if (component.has(FRAGMENT_NAME)) component.getString(FRAGMENT_NAME) else null, + if (component.has(PATH_NAME)) component.getString(PATH_NAME) else null, query?.keys()?.asSequence()?.associateWith { query.getString(it) }, - component.optString("comments") + component.optString(COMMENTS_NAME) ) } diff --git a/packages/StatementService/src/com/android/statementservice/retriever/DynamicAppLinkComponent.java b/packages/StatementService/src/com/android/statementservice/retriever/DynamicAppLinkComponent.java index dc27e125e204..c32f1949fed4 100644 --- a/packages/StatementService/src/com/android/statementservice/retriever/DynamicAppLinkComponent.java +++ b/packages/StatementService/src/com/android/statementservice/retriever/DynamicAppLinkComponent.java @@ -130,7 +130,7 @@ public final class DynamicAppLinkComponent { @Override public String toString() { StringBuilder statement = new StringBuilder(); - statement.append("HandleAllUriRule: "); + statement.append("DynamicAppLinkComponent: "); statement.append(mExclude); statement.append(", "); statement.append(mFragment); diff --git a/packages/StatementService/src/com/android/statementservice/retriever/JsonParser.java b/packages/StatementService/src/com/android/statementservice/retriever/JsonParser.java index 7635e8234dc0..ab1853c1d3ae 100644 --- a/packages/StatementService/src/com/android/statementservice/retriever/JsonParser.java +++ b/packages/StatementService/src/com/android/statementservice/retriever/JsonParser.java @@ -24,8 +24,6 @@ import org.json.JSONException; import org.json.JSONObject; import java.io.IOException; -import java.util.ArrayList; -import java.util.List; /** * A helper class that creates a {@link JSONObject} from a {@link JsonReader}. @@ -48,7 +46,7 @@ public final class JsonParser { JsonToken token = reader.peek(); if (token.equals(JsonToken.BEGIN_ARRAY)) { - output.put(fieldName, new JSONArray(parseArray(reader))); + output.put(fieldName, parseArray(reader)); } else if (token.equals(JsonToken.STRING)) { output.put(fieldName, reader.nextString()); } else if (token.equals(JsonToken.BEGIN_OBJECT)) { @@ -57,9 +55,11 @@ public final class JsonParser { } catch (JSONException e) { errorMsg = e.getMessage(); } + } else if (token.equals(JsonToken.BOOLEAN)) { + output.put(fieldName, reader.nextBoolean()); } else { reader.skipValue(); - errorMsg = "Unsupported value type."; + errorMsg = "Unsupported value type: " + token; } } reader.endObject(); @@ -72,17 +72,36 @@ public final class JsonParser { } /** - * Parses one string array from the {@link JsonReader}. + * Parses one JSON array from the {@link JsonReader}. */ - public static List<String> parseArray(JsonReader reader) throws IOException { - ArrayList<String> output = new ArrayList<>(); + public static JSONArray parseArray(JsonReader reader) throws IOException, JSONException { + JSONArray output = new JSONArray(); + String errorMsg = null; reader.beginArray(); while (reader.hasNext()) { - output.add(reader.nextString()); + JsonToken token = reader.peek(); + if (token.equals(JsonToken.BEGIN_ARRAY)) { + output.put(parseArray(reader)); + } else if (token.equals(JsonToken.STRING)) { + output.put(reader.nextString()); + } else if (token.equals(JsonToken.BEGIN_OBJECT)) { + try { + output.put(parse(reader)); + } catch (JSONException e) { + errorMsg = e.getMessage(); + } + } else { + reader.skipValue(); + errorMsg = "Unsupported value type: " + token; + } } reader.endArray(); + if (errorMsg != null) { + throw new JSONException(errorMsg); + } + return output; } } diff --git a/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/activity/A11yMenuSettingsActivity.java b/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/activity/A11yMenuSettingsActivity.java index c71ef8360008..129dd9b3c14d 100644 --- a/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/activity/A11yMenuSettingsActivity.java +++ b/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/activity/A11yMenuSettingsActivity.java @@ -36,7 +36,6 @@ import androidx.preference.Preference; import androidx.preference.PreferenceFragmentCompat; import androidx.preference.PreferenceManager; -import com.android.systemui.accessibility.accessibilitymenu.Flags; import com.android.systemui.accessibility.accessibilitymenu.R; /** @@ -62,10 +61,8 @@ public class A11yMenuSettingsActivity extends FragmentActivity { ((TextView) findViewById(R.id.action_bar_title)).setText( getResources().getString(R.string.accessibility_menu_settings_name) ); - if (Flags.actionBarWrapContent()) { - setHeightWrapContent(findViewById(com.android.internal.R.id.action_bar)); - setHeightWrapContent(findViewById(com.android.internal.R.id.action_bar_container)); - } + setHeightWrapContent(findViewById(com.android.internal.R.id.action_bar)); + setHeightWrapContent(findViewById(com.android.internal.R.id.action_bar_container)); } private void setHeightWrapContent(View view) { diff --git a/packages/SystemUI/aconfig/systemui.aconfig b/packages/SystemUI/aconfig/systemui.aconfig index 3541742e2bb7..e59fe47194da 100644 --- a/packages/SystemUI/aconfig/systemui.aconfig +++ b/packages/SystemUI/aconfig/systemui.aconfig @@ -1215,6 +1215,13 @@ flag { } flag { + name: "glanceable_hub_v2" + namespace: "systemui" + description: "Gates the refreshed glanceable hub experience that also brings the glanceable hub to mobile phones" + bug: "375689917" +} + +flag { name: "dream_overlay_updated_font" namespace: "systemui" description: "Flag to enable updated font settings for dream overlay" diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityTransitionAnimator.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityTransitionAnimator.kt index eee0cafd34fe..f1cbba7272b0 100644 --- a/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityTransitionAnimator.kt +++ b/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityTransitionAnimator.kt @@ -17,6 +17,7 @@ package com.android.systemui.animation import android.app.ActivityManager +import android.app.ActivityOptions import android.app.ActivityTaskManager import android.app.PendingIntent import android.app.TaskInfo @@ -434,8 +435,7 @@ constructor( private fun cleanUp() { cleanUpRunnable?.run() } - }, - initializeLazily = longLivedReturnAnimationsEnabled(), + } ) // mTypeSet and mModes match back signals only, and not home. This is on purpose, because @@ -478,8 +478,8 @@ constructor( /** Create a new animation [Runner] controlled by [controller]. */ @VisibleForTesting @JvmOverloads - fun createRunner(controller: Controller, initializeLazily: Boolean = false): Runner { - if (initializeLazily) assertLongLivedReturnAnimations() + fun createRunner(controller: Controller, longLived: Boolean = false): Runner { + if (longLived) assertLongLivedReturnAnimations() // Make sure we use the modified timings when animating a dialog into an app. val transitionAnimator = @@ -489,13 +489,7 @@ constructor( transitionAnimator } - return Runner( - controller, - callback!!, - transitionAnimator, - lifecycleListener, - initializeLazily, - ) + return Runner(controller, callback!!, transitionAnimator, lifecycleListener, longLived) } interface PendingIntentStarter { @@ -699,7 +693,7 @@ constructor( } val launchRemoteTransition = RemoteTransition( - OriginTransition(createRunner(controller, initializeLazily = true)), + OriginTransition(createRunner(controller, longLived = true)), "${cookie}_launchTransition", ) transitionRegister.register(launchFilter, launchRemoteTransition, includeTakeover = true) @@ -721,7 +715,7 @@ constructor( } val returnRemoteTransition = RemoteTransition( - OriginTransition(createRunner(returnController, initializeLazily = true)), + OriginTransition(createRunner(returnController, longLived = true)), "${cookie}_returnTransition", ) transitionRegister.register(returnFilter, returnRemoteTransition, includeTakeover = true) @@ -910,14 +904,22 @@ constructor( @VisibleForTesting inner class Runner( - private val controller: Controller, + /** + * This can hold a reference to a view, so it needs to be cleaned up and can't be held on to + * forever when ![longLived]. + */ + private var controller: Controller?, private val callback: Callback, /** The animator to use to animate the window transition. */ private val transitionAnimator: TransitionAnimator, /** Listener for animation lifecycle events. */ private val listener: Listener? = null, - /** Whether the internal [delegate] should be initialized lazily. */ - private val initializeLazily: Boolean = false, + /** + * Whether the internal should be kept around after execution for later usage. IMPORTANT: + * should always be false if this [Runner] is to be used directly with [ActivityOptions] + * (i.e. for ephemeral launches), or the controller will leak its view. + */ + private val longLived: Boolean = false, ) : IRemoteAnimationRunner.Stub() { // This is being passed across IPC boundaries and cycles (through PendingIntentRecords, // etc.) are possible. So we need to make sure we drop any references that might @@ -926,7 +928,7 @@ constructor( init { delegate = null - if (!initializeLazily) { + if (!longLived) { // Ephemeral launches bundle the runner with the launch request (instead of being // registered ahead of time for later use). This means that there could be a timeout // between creation and invocation, so the delegate needs to exist from the @@ -1004,16 +1006,17 @@ constructor( @AnyThread private fun maybeSetUp() { - if (!initializeLazily || delegate != null) return + if (!longLived || delegate != null) return createDelegate() } @AnyThread private fun createDelegate() { + if (controller == null) return delegate = AnimationDelegate( mainExecutor, - controller, + controller!!, callback, DelegatingAnimationCompletionListener(listener, this::dispose), transitionAnimator, @@ -1025,7 +1028,12 @@ constructor( fun dispose() { // Drop references to animation controller once we're done with the animation // to avoid leaking. - mainExecutor.execute { delegate = null } + mainExecutor.execute { + delegate = null + // When long lived, the same Runner can be used more than once. In this case we need + // to keep the controller around so we can rebuild the delegate on demand. + if (!longLived) controller = null + } } } diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalContainer.kt b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalContainer.kt index 87e9c427d695..4705d8dd86c4 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalContainer.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalContainer.kt @@ -44,6 +44,7 @@ import com.android.compose.animation.scene.SceneTransitionLayout import com.android.compose.animation.scene.Swipe import com.android.compose.animation.scene.observableTransitionState import com.android.compose.animation.scene.transitions +import com.android.systemui.Flags.communalHubOnMobile import com.android.systemui.communal.shared.model.CommunalBackgroundType import com.android.systemui.communal.shared.model.CommunalScenes import com.android.systemui.communal.shared.model.CommunalTransitionKeys @@ -186,15 +187,19 @@ fun CommunalContainer( ) { scene( CommunalScenes.Blank, - userActions = mapOf(Swipe.Start(fromSource = Edge.End) to CommunalScenes.Communal), + userActions = + if (communalHubOnMobile()) emptyMap() + else mapOf(Swipe.Start(fromSource = Edge.End) to CommunalScenes.Communal), ) { // This scene shows nothing only allowing for transitions to the communal scene. Box(modifier = Modifier.fillMaxSize()) } - val userActions = mapOf(Swipe.End to CommunalScenes.Blank) - - scene(CommunalScenes.Communal, userActions = userActions) { + scene( + CommunalScenes.Communal, + userActions = + if (communalHubOnMobile()) emptyMap() else mapOf(Swipe.End to CommunalScenes.Blank), + ) { CommunalScene( backgroundType = backgroundType, colors = colors, diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/blueprint/DefaultBlueprint.kt b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/blueprint/DefaultBlueprint.kt index 2a2c2fc4934e..105e8dadfafb 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/blueprint/DefaultBlueprint.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/blueprint/DefaultBlueprint.kt @@ -21,7 +21,6 @@ import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue @@ -70,10 +69,7 @@ constructor( override val id: String = "default" @Composable - override fun SceneScope.Content( - viewModel: LockscreenContentViewModel, - modifier: Modifier, - ) { + override fun SceneScope.Content(viewModel: LockscreenContentViewModel, modifier: Modifier) { val isUdfpsVisible = viewModel.isUdfpsVisible val isShadeLayoutWide by viewModel.isShadeLayoutWide.collectAsStateWithLifecycle() val unfoldTranslations by viewModel.unfoldTranslations.collectAsStateWithLifecycle() @@ -85,22 +81,18 @@ constructor( with(notificationSection) { HeadsUpNotifications() } } - LockscreenLongPress( - viewModel = viewModel.touchHandling, - modifier = modifier, - ) { onSettingsMenuPlaced -> + LockscreenLongPress(viewModel = viewModel.touchHandling, modifier = modifier) { + onSettingsMenuPlaced -> Layout( content = { // Constrained to above the lock icon. - Column( - modifier = Modifier.fillMaxSize(), - ) { + Column(modifier = Modifier.fillMaxSize()) { with(statusBarSection) { StatusBar( modifier = Modifier.fillMaxWidth() .padding( - horizontal = { unfoldTranslations.start.roundToInt() }, + horizontal = { unfoldTranslations.start.roundToInt() } ) ) } @@ -109,13 +101,14 @@ constructor( with(topAreaSection) { DefaultClockLayout( smartSpacePaddingTop = viewModel::getSmartSpacePaddingTop, + isShadeLayoutWide = isShadeLayoutWide, modifier = Modifier.thenIf(isShadeLayoutWide) { Modifier.fillMaxWidth(0.5f) } .graphicsLayer { translationX = unfoldTranslations.start - } + }, ) } if (isShadeLayoutWide && !isBypassEnabled) { @@ -127,7 +120,7 @@ constructor( modifier = Modifier.fillMaxWidth(0.5f) .fillMaxHeight() - .align(alignment = Alignment.TopEnd) + .align(alignment = Alignment.TopEnd), ) } } @@ -142,7 +135,7 @@ constructor( AodNotificationIcons( modifier = Modifier.align(alignment = Alignment.TopStart) - .padding(start = aodIconPadding), + .padding(start = aodIconPadding) ) Notifications( areNotificationsVisible = areNotificationsVisible, @@ -152,7 +145,7 @@ constructor( } } else { AodNotificationIcons( - modifier = Modifier.padding(start = aodIconPadding), + modifier = Modifier.padding(start = aodIconPadding) ) } } @@ -205,11 +198,7 @@ constructor( val endShortcutMeasurable = measurables[4] val settingsMenuMeasurable = measurables[5] - val noMinConstraints = - constraints.copy( - minWidth = 0, - minHeight = 0, - ) + val noMinConstraints = constraints.copy(minWidth = 0, minHeight = 0) val lockIconPlaceable = lockIconMeasurable.measure(noMinConstraints) val lockIconBounds = IntRect( @@ -235,14 +224,8 @@ constructor( val settingsMenuPlaceable = settingsMenuMeasurable.measure(noMinConstraints) layout(constraints.maxWidth, constraints.maxHeight) { - aboveLockIconPlaceable.place( - x = 0, - y = 0, - ) - lockIconPlaceable.place( - x = lockIconBounds.left, - y = lockIconBounds.top, - ) + aboveLockIconPlaceable.place(x = 0, y = 0) + lockIconPlaceable.place(x = lockIconBounds.left, y = lockIconBounds.top) belowLockIconPlaceable.place( x = 0, y = constraints.maxHeight - belowLockIconPlaceable.height, diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/MediaCarouselSection.kt b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/MediaCarouselSection.kt index 3ca2b9c1d86c..4a9f44b74099 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/MediaCarouselSection.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/MediaCarouselSection.kt @@ -17,9 +17,11 @@ package com.android.systemui.keyguard.ui.composable.section import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.ui.Modifier +import androidx.compose.ui.res.dimensionResource import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.android.compose.animation.scene.SceneScope import com.android.systemui.keyguard.ui.viewmodel.KeyguardMediaViewModel @@ -27,6 +29,7 @@ import com.android.systemui.media.controls.ui.composable.MediaCarousel import com.android.systemui.media.controls.ui.controller.MediaCarouselController import com.android.systemui.media.controls.ui.view.MediaHost import com.android.systemui.media.dagger.MediaModule +import com.android.systemui.res.R import javax.inject.Inject import javax.inject.Named @@ -39,13 +42,22 @@ constructor( ) { @Composable - fun SceneScope.KeyguardMediaCarousel() { + fun SceneScope.KeyguardMediaCarousel( + isShadeLayoutWide: Boolean, + modifier: Modifier = Modifier, + ) { val isMediaVisible by keyguardMediaViewModel.isMediaVisible.collectAsStateWithLifecycle() - + val horizontalPadding = + if (isShadeLayoutWide) { + dimensionResource(id = R.dimen.notification_side_paddings) + } else { + dimensionResource(id = R.dimen.notification_side_paddings) + + dimensionResource(id = R.dimen.notification_panel_margin_horizontal) + } MediaCarousel( isVisible = isMediaVisible, mediaHost = mediaHost, - modifier = Modifier.fillMaxWidth(), + modifier = modifier.fillMaxWidth().padding(horizontal = horizontalPadding), carouselController = mediaCarouselController, ) } diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/TopAreaSection.kt b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/TopAreaSection.kt index afa92f2533ce..db33e7c628d7 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/TopAreaSection.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/TopAreaSection.kt @@ -63,6 +63,7 @@ constructor( @Composable fun SceneScope.DefaultClockLayout( smartSpacePaddingTop: (Resources) -> Int, + isShadeLayoutWide: Boolean, modifier: Modifier = Modifier, ) { val currentClockLayout by clockViewModel.currentClockLayout.collectAsStateWithLifecycle() @@ -128,7 +129,7 @@ constructor( ) } } - with(mediaCarouselSection) { KeyguardMediaCarousel() } + with(mediaCarouselSection) { KeyguardMediaCarousel(isShadeLayoutWide) } } } diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettings.kt b/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettings.kt index e725ce589f3e..58336c2e9d41 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettings.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettings.kt @@ -79,8 +79,8 @@ object QuickSettings { val MediaLandscapeTopOffset = ValueKey("MediaLandscapeTopOffset") object MediaOffset { - // Brightness + padding - val InQS = 92.dp + // Brightness + val InQS = 60.dp val Default = 0.dp @Composable diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsScene.kt b/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsScene.kt index 0e7165c7f3ec..52adaf2a5b5d 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsScene.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsScene.kt @@ -74,6 +74,7 @@ import com.android.compose.animation.scene.UserActionResult import com.android.compose.animation.scene.animateSceneDpAsState import com.android.compose.animation.scene.animateSceneFloatAsState import com.android.compose.animation.scene.content.state.TransitionState +import com.android.compose.modifiers.padding import com.android.compose.modifiers.thenIf import com.android.compose.windowsizeclass.LocalWindowSizeClass import com.android.systemui.battery.BatteryMeterViewController @@ -379,7 +380,11 @@ private fun SceneScope.QuickSettingsScene( mediaHost = mediaHost, modifier = Modifier.fillMaxWidth() - .layoutId(QSMediaMeasurePolicy.LayoutId.Media), + .layoutId(QSMediaMeasurePolicy.LayoutId.Media) + .padding( + horizontal = + dimensionResource(id = R.dimen.qs_horizontal_margin) + ), carouselController = mediaCarouselController, ) } diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsShadeOverlay.kt b/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsShadeOverlay.kt index 26c827a5417c..f84865ffc6af 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsShadeOverlay.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsShadeOverlay.kt @@ -168,7 +168,6 @@ fun SceneScope.QuickSettingsLayout( modifier = Modifier.fillMaxWidth() .heightIn(max = QuickSettingsShade.Dimensions.GridMaxHeight), - viewModel.editModeViewModel::startEditing, ) } } diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/GoneScene.kt b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/GoneScene.kt index ae5dd8abb82e..5fb9416cf35b 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/GoneScene.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/GoneScene.kt @@ -19,12 +19,17 @@ package com.android.systemui.scene.ui.composable import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.derivedStateOf +import androidx.compose.runtime.getValue +import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import com.android.compose.animation.scene.SceneScope import com.android.compose.animation.scene.UserAction import com.android.compose.animation.scene.UserActionResult import com.android.compose.animation.scene.animateContentDpAsState import com.android.compose.animation.scene.animateContentFloatAsState +import com.android.compose.animation.scene.content.state.TransitionState import com.android.systemui.dagger.SysUISingleton import com.android.systemui.lifecycle.ExclusiveActivatable import com.android.systemui.lifecycle.rememberViewModel @@ -63,9 +68,25 @@ constructor( } @Composable - override fun SceneScope.Content( - modifier: Modifier, - ) { + override fun SceneScope.Content(modifier: Modifier) { + + val isIdle by remember { + derivedStateOf { layoutState.transitionState is TransitionState.Idle } + } + + LaunchedEffect(isIdle) { + // Wait for being Idle on this Scene, otherwise LaunchedEffect would fire too soon, + // and another transition could override the NSSL stack bounds. + if (isIdle) { + // Reset the stack bounds to avoid caching these values from the previous Scenes, + // and not to confuse the StackScrollAlgorithm when it displays a HUN over GONE. + notificationStackScrolLView.get().apply { + setStackTop(0f) + setStackCutoff(0f) + } + } + } + animateContentFloatAsState( value = QuickSettings.SharedValues.SquishinessValues.GoneSceneStarting, key = QuickSettings.SharedValues.TilesSquishiness, @@ -75,9 +96,7 @@ constructor( SnoozeableHeadsUpNotificationSpace( stackScrollView = notificationStackScrolLView.get(), viewModel = - rememberViewModel("GoneScene") { - notificationsPlaceholderViewModelFactory.create() - }, + rememberViewModel("GoneScene") { notificationsPlaceholderViewModelFactory.create() }, ) } } diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainer.kt b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainer.kt index 2d58c8cad2b1..a266e7eb44a1 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainer.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainer.kt @@ -49,7 +49,6 @@ import com.android.systemui.scene.shared.model.SceneDataSourceDelegator import com.android.systemui.scene.shared.model.Scenes import com.android.systemui.scene.ui.viewmodel.SceneContainerViewModel import javax.inject.Provider -import kotlinx.coroutines.flow.collectLatest /** * Renders a container of a collection of "scenes" that the user can switch between using certain @@ -117,7 +116,7 @@ fun SceneContainer( ) { "invalid ContentKey: $actionableContentKey" } - actionableContent.userActions.collectLatest { userActions -> + viewModel.filteredUserActions(actionableContent.userActions).collect { userActions -> userActionsByContentKey[actionableContentKey] = viewModel.resolveSceneFamilies(userActions) } diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeHeader.kt b/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeHeader.kt index 05a0119d68e4..bfcde7dab6d2 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeHeader.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeHeader.kt @@ -130,10 +130,6 @@ fun SceneScope.CollapsedShadeHeader( modifier: Modifier = Modifier, ) { val viewModel = rememberViewModel("CollapsedShadeHeader") { viewModelFactory.create() } - val isDisabled by viewModel.isDisabled.collectAsStateWithLifecycle() - if (isDisabled) { - return - } val cutoutWidth = LocalDisplayCutout.current.width() val cutoutHeight = LocalDisplayCutout.current.height() @@ -196,7 +192,7 @@ fun SceneScope.CollapsedShadeHeader( horizontalArrangement = Arrangement.End, modifier = Modifier.element(ShadeHeader.Elements.CollapsedContentEnd) - .padding(horizontal = horizontalPadding) + .padding(horizontal = horizontalPadding), ) { if (isLargeScreenLayout) { ShadeCarrierGroup( @@ -207,7 +203,7 @@ fun SceneScope.CollapsedShadeHeader( SystemIconContainer( viewModel = viewModel, isClickable = isLargeScreenLayout, - modifier = Modifier.align(Alignment.CenterVertically) + modifier = Modifier.align(Alignment.CenterVertically), ) { StatusIcons( viewModel = viewModel, @@ -217,7 +213,7 @@ fun SceneScope.CollapsedShadeHeader( modifier = Modifier.align(Alignment.CenterVertically) .padding(end = 6.dp) - .weight(1f, fill = false) + .weight(1f, fill = false), ) BatteryIcon( createBatteryMeterViewController = @@ -252,27 +248,15 @@ fun SceneScope.CollapsedShadeHeader( CutoutLocation.NONE, CutoutLocation.RIGHT -> { startPlaceable.placeRelative(x = 0, y = 0) - endPlaceable.placeRelative( - x = startPlaceable.width, - y = 0, - ) + endPlaceable.placeRelative(x = startPlaceable.width, y = 0) } CutoutLocation.CENTER -> { startPlaceable.placeRelative(x = 0, y = 0) - endPlaceable.placeRelative( - x = startPlaceable.width + cutoutWidthPx, - y = 0, - ) + endPlaceable.placeRelative(x = startPlaceable.width + cutoutWidthPx, y = 0) } CutoutLocation.LEFT -> { - startPlaceable.placeRelative( - x = cutoutWidthPx, - y = 0, - ) - endPlaceable.placeRelative( - x = startPlaceable.width + cutoutWidthPx, - y = 0, - ) + startPlaceable.placeRelative(x = cutoutWidthPx, y = 0) + endPlaceable.placeRelative(x = startPlaceable.width + cutoutWidthPx, y = 0) } } } @@ -288,10 +272,6 @@ fun SceneScope.ExpandedShadeHeader( modifier: Modifier = Modifier, ) { val viewModel = rememberViewModel("ExpandedShadeHeader") { viewModelFactory.create() } - val isDisabled by viewModel.isDisabled.collectAsStateWithLifecycle() - if (isDisabled) { - return - } val useExpandedFormat by remember { derivedStateOf { shouldUseExpandedFormat(layoutState.transitionState) } @@ -302,17 +282,14 @@ fun SceneScope.ExpandedShadeHeader( Box(modifier = modifier.sysuiResTag(ShadeHeader.TestTags.Root)) { if (isPrivacyChipVisible) { Box(modifier = Modifier.height(CollapsedHeight).fillMaxWidth()) { - PrivacyChip( - viewModel = viewModel, - modifier = Modifier.align(Alignment.CenterEnd), - ) + PrivacyChip(viewModel = viewModel, modifier = Modifier.align(Alignment.CenterEnd)) } } Column( verticalArrangement = Arrangement.Bottom, modifier = Modifier.fillMaxWidth() - .defaultMinSize(minHeight = ShadeHeader.Dimensions.ExpandedHeight) + .defaultMinSize(minHeight = ShadeHeader.Dimensions.ExpandedHeight), ) { Box(modifier = Modifier.fillMaxWidth()) { Box { @@ -362,11 +339,7 @@ fun SceneScope.ExpandedShadeHeader( } @Composable -private fun SceneScope.Clock( - scale: Float, - viewModel: ShadeHeaderViewModel, - modifier: Modifier, -) { +private fun SceneScope.Clock(scale: Float, viewModel: ShadeHeaderViewModel, modifier: Modifier) { val layoutDirection = LocalLayoutDirection.current Element(key = ShadeHeader.Elements.Clock, modifier = modifier) { @@ -391,10 +364,10 @@ private fun SceneScope.Clock( LayoutDirection.Ltr -> 0f LayoutDirection.Rtl -> 1f }, - 0.5f + 0.5f, ) } - .clickable { viewModel.onClockClicked() } + .clickable { viewModel.onClockClicked() }, ) } } @@ -447,10 +420,7 @@ private fun BatteryIcon( } @Composable -private fun ShadeCarrierGroup( - viewModel: ShadeHeaderViewModel, - modifier: Modifier = Modifier, -) { +private fun ShadeCarrierGroup(viewModel: ShadeHeaderViewModel, modifier: Modifier = Modifier) { Row(modifier = modifier) { val subIds by viewModel.mobileSubIds.collectAsStateWithLifecycle() @@ -465,11 +435,11 @@ private fun ShadeCarrierGroup( viewModel = (viewModel.mobileIconsViewModel.viewModelForSub( subId, - StatusBarLocation.SHADE_CARRIER_GROUP + StatusBarLocation.SHADE_CARRIER_GROUP, ) as ShadeCarrierGroupMobileIconViewModel), ) .also { it.setOnClickListener { viewModel.onShadeCarrierGroupClicked() } } - }, + } ) } } @@ -506,7 +476,7 @@ private fun SceneScope.StatusIcons( Utils.getColorAttrDefaultColor(themedContext, android.R.attr.textColorPrimary), Utils.getColorAttrDefaultColor( themedContext, - android.R.attr.textColorPrimaryInverse + android.R.attr.textColorPrimaryInverse, ), ) statusBarIconController.addIconGroup(iconManager) @@ -551,7 +521,7 @@ private fun SystemIconContainer( viewModel: ShadeHeaderViewModel, isClickable: Boolean, modifier: Modifier = Modifier, - content: @Composable RowScope.() -> Unit + content: @Composable RowScope.() -> Unit, ) { val interactionSource = remember { MutableInteractionSource() } val isHovered by interactionSource.collectIsHoveredAsState() @@ -578,10 +548,7 @@ private fun SystemIconContainer( } @Composable -private fun SceneScope.PrivacyChip( - viewModel: ShadeHeaderViewModel, - modifier: Modifier = Modifier, -) { +private fun SceneScope.PrivacyChip(viewModel: ShadeHeaderViewModel, modifier: Modifier = Modifier) { val privacyList by viewModel.privacyItems.collectAsStateWithLifecycle() AndroidView( diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeScene.kt b/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeScene.kt index bba3d69ea77f..fd1632ed4cb4 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeScene.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeScene.kt @@ -353,13 +353,24 @@ private fun SceneScope.SingleShade( ) } + val qqsLayoutPaddingBottom = + dimensionResource(id = R.dimen.qqs_layout_padding_bottom) ShadeMediaCarousel( isVisible = isMediaVisible, isInRow = mediaInRow, mediaHost = mediaHost, mediaOffsetProvider = mediaOffsetProvider, carouselController = mediaCarouselController, - modifier = Modifier.layoutId(SingleShadeMeasurePolicy.LayoutId.Media), + modifier = + Modifier.layoutId(SingleShadeMeasurePolicy.LayoutId.Media) + .padding( + horizontal = + shadeHorizontalPadding + + dimensionResource(id = R.dimen.qs_horizontal_margin) + ) + .thenIf(!mediaInRow) { + Modifier.padding(bottom = qqsLayoutPaddingBottom) + }, usingCollapsedLandscapeMedia = usingCollapsedLandscapeMedia, isInSplitShade = false, ) @@ -562,10 +573,14 @@ private fun SceneScope.SplitShade( mediaOffsetProvider = mediaOffsetProvider, modifier = Modifier.thenIf( - MediaContentPicker.shouldElevateMedia(layoutState) - ) { - Modifier.zIndex(1f) - }, + MediaContentPicker.shouldElevateMedia(layoutState) + ) { + Modifier.zIndex(1f) + } + .padding( + horizontal = + dimensionResource(id = R.dimen.qs_horizontal_margin) + ), carouselController = mediaCarouselController, isInSplitShade = true, ) diff --git a/packages/SystemUI/customization/res/values/dimens.xml b/packages/SystemUI/customization/res/values/dimens.xml index 21b4c7165226..2bb5541f4b0a 100644 --- a/packages/SystemUI/customization/res/values/dimens.xml +++ b/packages/SystemUI/customization/res/values/dimens.xml @@ -33,6 +33,7 @@ <dimen name="small_clock_height">114dp</dimen> <dimen name="small_clock_padding_top">28dp</dimen> <dimen name="clock_padding_start">28dp</dimen> + <dimen name="weather_date_icon_padding">28dp</dimen> <!-- When large clock is showing, offset the smartspace by this amount --> <dimen name="keyguard_smartspace_top_offset">12dp</dimen> diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/brightness/ui/viewmodel/BrightnessSliderViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/brightness/ui/viewmodel/BrightnessSliderViewModelTest.kt index 0f148f89e3c5..2d093bf1630b 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/brightness/ui/viewmodel/BrightnessSliderViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/brightness/ui/viewmodel/BrightnessSliderViewModelTest.kt @@ -25,6 +25,7 @@ import com.android.systemui.brightness.domain.interactor.brightnessPolicyEnforce import com.android.systemui.brightness.domain.interactor.screenBrightnessInteractor import com.android.systemui.brightness.shared.model.GammaBrightness import com.android.systemui.brightness.shared.model.LinearBrightness +import com.android.systemui.classifier.domain.interactor.falsingInteractor import com.android.systemui.common.shared.model.ContentDescription import com.android.systemui.common.shared.model.Icon import com.android.systemui.common.shared.model.Text @@ -61,6 +62,7 @@ class BrightnessSliderViewModelTest : SysuiTestCase() { brightnessPolicyEnforcementInteractor, sliderHapticsViewModelFactory, brightnessMirrorShowingInteractor, + falsingInteractor, supportsMirroring = true, brightnessWarningToast, ) diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryInteractorTest.kt index d90d58b8d25c..1bb5c9afdc33 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryInteractorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryInteractorTest.kt @@ -43,7 +43,6 @@ import com.android.systemui.keyguard.data.repository.fakeTrustRepository import com.android.systemui.keyguard.shared.model.KeyguardState import com.android.systemui.keyguard.shared.model.SuccessFingerprintAuthenticationStatus import com.android.systemui.kosmos.testScope -import com.android.systemui.scene.domain.interactor.sceneBackInteractor import com.android.systemui.scene.domain.interactor.sceneInteractor import com.android.systemui.scene.domain.startable.sceneContainerStartable import com.android.systemui.scene.shared.model.Scenes @@ -72,7 +71,6 @@ class DeviceEntryInteractorTest : SysuiTestCase() { private val trustRepository by lazy { kosmos.fakeTrustRepository } private val sceneInteractor by lazy { kosmos.sceneInteractor } private val authenticationInteractor by lazy { kosmos.authenticationInteractor } - private val sceneBackInteractor by lazy { kosmos.sceneBackInteractor } private val sceneContainerStartable by lazy { kosmos.sceneContainerStartable } private val sysuiStatusBarStateController by lazy { kosmos.sysuiStatusBarStateController } private lateinit var underTest: DeviceEntryInteractor @@ -437,7 +435,9 @@ class DeviceEntryInteractorTest : SysuiTestCase() { fun isDeviceEntered_unlockedWhileOnShade_emitsTrue() = testScope.runTest { val isDeviceEntered by collectLastValue(underTest.isDeviceEntered) + val isDeviceEnteredDirectly by collectLastValue(underTest.isDeviceEnteredDirectly) assertThat(isDeviceEntered).isFalse() + assertThat(isDeviceEnteredDirectly).isFalse() val currentScene by collectLastValue(sceneInteractor.currentScene) assertThat(currentScene).isEqualTo(Scenes.Lockscreen) @@ -445,19 +445,20 @@ class DeviceEntryInteractorTest : SysuiTestCase() { switchToScene(Scenes.Shade) assertThat(currentScene).isEqualTo(Scenes.Shade) // Simulating a "leave it open when the keyguard is hidden" which means the bouncer will - // be - // shown and successful authentication should take the user back to where they are, the - // shade scene. + // be shown and successful authentication should take the user back to where they are, + // the shade scene. sysuiStatusBarStateController.setLeaveOpenOnKeyguardHide(true) switchToScene(Scenes.Bouncer) assertThat(currentScene).isEqualTo(Scenes.Bouncer) assertThat(isDeviceEntered).isFalse() + assertThat(isDeviceEnteredDirectly).isFalse() // Authenticate with PIN to unlock and dismiss the lockscreen: authenticationInteractor.authenticate(FakeAuthenticationRepository.DEFAULT_PIN) runCurrent() assertThat(isDeviceEntered).isTrue() + assertThat(isDeviceEnteredDirectly).isFalse() } private fun TestScope.switchToScene(sceneKey: SceneKey) { diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayServiceTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayServiceTest.kt index bbfc9607fed9..a8048793be06 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayServiceTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayServiceTest.kt @@ -36,7 +36,6 @@ import androidx.lifecycle.Lifecycle import androidx.lifecycle.LifecycleOwner import androidx.lifecycle.LifecycleRegistry import androidx.test.filters.SmallTest -import com.android.app.viewcapture.ViewCapture import com.android.app.viewcapture.ViewCaptureAwareWindowManager import com.android.app.viewcapture.ViewCaptureFactory import com.android.compose.animation.scene.ObservableTransitionState @@ -44,15 +43,15 @@ import com.android.internal.logging.UiEventLogger import com.android.keyguard.KeyguardUpdateMonitor import com.android.keyguard.KeyguardUpdateMonitorCallback import com.android.systemui.Flags.FLAG_COMMUNAL_HUB +import com.android.systemui.Flags.FLAG_COMMUNAL_HUB_ON_MOBILE import com.android.systemui.Flags.FLAG_SCENE_CONTAINER import com.android.systemui.SysuiTestCase +import com.android.systemui.ambient.touch.TouchHandler import com.android.systemui.ambient.touch.TouchMonitor import com.android.systemui.ambient.touch.dagger.AmbientTouchComponent import com.android.systemui.ambient.touch.scrim.ScrimController import com.android.systemui.ambient.touch.scrim.ScrimManager -import com.android.systemui.bouncer.data.repository.FakeKeyguardBouncerRepository import com.android.systemui.bouncer.data.repository.fakeKeyguardBouncerRepository -import com.android.systemui.communal.data.repository.FakeCommunalSceneRepository import com.android.systemui.communal.data.repository.fakeCommunalSceneRepository import com.android.systemui.communal.domain.interactor.CommunalInteractor import com.android.systemui.communal.domain.interactor.communalInteractor @@ -64,6 +63,7 @@ import com.android.systemui.complication.ComplicationLayoutEngine import com.android.systemui.complication.dagger.ComplicationComponent import com.android.systemui.dreams.complication.HideComplicationTouchHandler import com.android.systemui.dreams.dagger.DreamOverlayComponent +import com.android.systemui.dreams.touch.CommunalTouchHandler import com.android.systemui.flags.andSceneContainer import com.android.systemui.keyguard.domain.interactor.keyguardInteractor import com.android.systemui.keyguard.gesture.domain.gestureInteractor @@ -87,21 +87,17 @@ import org.junit.Before import org.junit.Test import org.junit.runner.RunWith import org.mockito.ArgumentCaptor -import org.mockito.Captor -import org.mockito.Mock import org.mockito.Mockito import org.mockito.Mockito.clearInvocations import org.mockito.Mockito.isNull import org.mockito.Mockito.never import org.mockito.Mockito.verify -import org.mockito.MockitoAnnotations import org.mockito.kotlin.any import org.mockito.kotlin.argumentCaptor import org.mockito.kotlin.eq import org.mockito.kotlin.firstValue import org.mockito.kotlin.mock import org.mockito.kotlin.spy -import org.mockito.kotlin.times import org.mockito.kotlin.verifyNoMoreInteractions import org.mockito.kotlin.whenever import platform.test.runner.parameterized.ParameterizedAndroidJunit4 @@ -117,68 +113,50 @@ class DreamOverlayServiceTest(flags: FlagsParameterization?) : SysuiTestCase() { private val kosmos = testKosmos() private val testScope = kosmos.testScope - @Mock lateinit var mLifecycleOwner: DreamOverlayLifecycleOwner - - private lateinit var lifecycleRegistry: FakeLifecycleRegistry - - lateinit var mCommunalInteractor: CommunalInteractor - - private lateinit var mWindowParams: WindowManager.LayoutParams - - @Mock lateinit var mDreamOverlayCallback: IDreamOverlayCallback - - @Mock lateinit var mWindowManager: WindowManagerImpl - - @Mock lateinit var mComplicationComponentFactory: ComplicationComponent.Factory - - @Mock lateinit var mComplicationHostViewController: ComplicationHostViewController - - @Mock lateinit var mComplicationVisibilityController: ComplicationLayoutEngine - - @Mock - lateinit var mDreamComplicationComponentFactory: - com.android.systemui.dreams.complication.dagger.ComplicationComponent.Factory - - @Mock lateinit var mHideComplicationTouchHandler: HideComplicationTouchHandler - - @Mock lateinit var mDreamOverlayComponentFactory: DreamOverlayComponent.Factory - - @Mock lateinit var mAmbientTouchComponentFactory: AmbientTouchComponent.Factory - - @Mock lateinit var mDreamOverlayContainerView: DreamOverlayContainerView - - @Mock lateinit var mDreamOverlayContainerViewController: DreamOverlayContainerViewController - - @Mock lateinit var mKeyguardUpdateMonitor: KeyguardUpdateMonitor - - @Mock lateinit var mTouchMonitor: TouchMonitor - - @Mock lateinit var mStateController: DreamOverlayStateController - - @Mock lateinit var mDreamOverlayContainerViewParent: ViewGroup - - @Mock lateinit var mTouchInsetManager: TouchInsetManager - - @Mock lateinit var mUiEventLogger: UiEventLogger - - @Mock lateinit var mScrimManager: ScrimManager - - @Mock lateinit var mScrimController: ScrimController - - @Mock lateinit var mSystemDialogsCloser: SystemDialogsCloser - - @Mock lateinit var mDreamOverlayCallbackController: DreamOverlayCallbackController - - @Mock lateinit var mLazyViewCapture: Lazy<ViewCapture> + private val mLifecycleOwner = mock<DreamOverlayLifecycleOwner>() + private val mDreamOverlayCallback = mock<IDreamOverlayCallback>() + private val mWindowManager = mock<WindowManagerImpl>() + private val mComplicationComponentFactory = mock<ComplicationComponent.Factory>() + private val mComplicationHostViewController = mock<ComplicationHostViewController>() + private val mComplicationVisibilityController = mock<ComplicationLayoutEngine>() + private val mDreamComplicationComponentFactory = + mock<com.android.systemui.dreams.complication.dagger.ComplicationComponent.Factory>() + private val mHideComplicationTouchHandler = mock<HideComplicationTouchHandler>() + private val mDreamOverlayComponentFactory = mock<DreamOverlayComponent.Factory>() + private val mCommunalTouchHandler = mock<CommunalTouchHandler>() + private val mAmbientTouchComponentFactory = mock<AmbientTouchComponent.Factory>() + private val mDreamOverlayContainerView = mock<DreamOverlayContainerView>() + private val mDreamOverlayContainerViewController = + mock<DreamOverlayContainerViewController> { + on { containerView }.thenReturn(mDreamOverlayContainerView) + } + private val mKeyguardUpdateMonitor = mock<KeyguardUpdateMonitor>() + private val mTouchMonitor = mock<TouchMonitor>() + private val mStateController = mock<DreamOverlayStateController>() + private val mDreamOverlayContainerViewParent = mock<ViewGroup>() + private val mTouchInsetManager = mock<TouchInsetManager>() + private val mUiEventLogger = mock<UiEventLogger>() + private val mScrimController = mock<ScrimController>() + private val mScrimManager = + mock<ScrimManager> { on { currentController }.thenReturn(mScrimController) } + private val mSystemDialogsCloser = mock<SystemDialogsCloser>() + private val mDreamOverlayCallbackController = mock<DreamOverlayCallbackController>() + private val mLazyViewCapture = lazy { viewCaptureSpy } + + private val mViewCaptor = argumentCaptor<View>() + private val mTouchHandlersCaptor = argumentCaptor<Set<TouchHandler>>() + + private val mWindowParams = WindowManager.LayoutParams() + private val lifecycleRegistry = FakeLifecycleRegistry(mLifecycleOwner) + private val bouncerRepository = kosmos.fakeKeyguardBouncerRepository + private val communalRepository = kosmos.fakeCommunalSceneRepository + private var viewCaptureSpy = spy(ViewCaptureFactory.getInstance(context)) + private val gestureInteractor = spy(kosmos.gestureInteractor) + private lateinit var mCommunalInteractor: CommunalInteractor private lateinit var mViewCaptureAwareWindowManager: ViewCaptureAwareWindowManager - private lateinit var bouncerRepository: FakeKeyguardBouncerRepository - private lateinit var communalRepository: FakeCommunalSceneRepository - private var viewCaptureSpy = spy(ViewCaptureFactory.getInstance(context)) - private lateinit var gestureInteractor: GestureInteractor private lateinit var environmentComponents: EnvironmentComponents - @Captor var mViewCaptor: ArgumentCaptor<View>? = null private lateinit var mService: DreamOverlayService private class EnvironmentComponents( @@ -234,6 +212,7 @@ class DreamOverlayServiceTest(flags: FlagsParameterization?) : SysuiTestCase() { mock<com.android.systemui.dreams.complication.dagger.ComplicationComponent>() whenever(dreamComplicationComponent.getHideComplicationTouchHandler()) .thenReturn(mHideComplicationTouchHandler) + whenever(dreamOverlayComponent.communalTouchHandler).thenReturn(mCommunalTouchHandler) whenever(dreamComplicationComponentFactory.create(any(), any())) .thenReturn(dreamComplicationComponent) @@ -259,13 +238,6 @@ class DreamOverlayServiceTest(flags: FlagsParameterization?) : SysuiTestCase() { @Before fun setup() { - MockitoAnnotations.initMocks(this) - - lifecycleRegistry = FakeLifecycleRegistry(mLifecycleOwner) - bouncerRepository = kosmos.fakeKeyguardBouncerRepository - communalRepository = kosmos.fakeCommunalSceneRepository - gestureInteractor = spy(kosmos.gestureInteractor) - environmentComponents = setupComponentFactories( mDreamComplicationComponentFactory, @@ -273,12 +245,6 @@ class DreamOverlayServiceTest(flags: FlagsParameterization?) : SysuiTestCase() { mComplicationComponentFactory, mAmbientTouchComponentFactory, ) - - whenever(mDreamOverlayContainerViewController.containerView) - .thenReturn(mDreamOverlayContainerView) - whenever(mScrimManager.getCurrentController()).thenReturn(mScrimController) - whenever(mLazyViewCapture.value).thenReturn(viewCaptureSpy) - mWindowParams = WindowManager.LayoutParams() mViewCaptureAwareWindowManager = ViewCaptureAwareWindowManager( mWindowManager, @@ -381,10 +347,10 @@ class DreamOverlayServiceTest(flags: FlagsParameterization?) : SysuiTestCase() { verify(mStateController).setOverlayActive(false) verify(mStateController).setLowLightActive(false) verify(mStateController).setEntryAnimationsFinished(false) - verify(mStateController, Mockito.never()).setOverlayActive(true) - verify(mUiEventLogger, Mockito.never()) + verify(mStateController, never()).setOverlayActive(true) + verify(mUiEventLogger, never()) .log(DreamOverlayService.DreamOverlayEvent.DREAM_OVERLAY_COMPLETE_START) - verify(mDreamOverlayCallbackController, Mockito.never()).onStartDream() + verify(mDreamOverlayCallbackController, never()).onStartDream() } @Test @@ -528,14 +494,14 @@ class DreamOverlayServiceTest(flags: FlagsParameterization?) : SysuiTestCase() { mMainExecutor.runAllReady() // Verify view added. - verify(mWindowManager).addView(mViewCaptor!!.capture(), any()) + verify(mWindowManager).addView(mViewCaptor.capture(), any()) // Service destroyed. mService.onEndDream() mMainExecutor.runAllReady() // Verify view removed. - verify(mWindowManager).removeView(mViewCaptor!!.value) + verify(mWindowManager).removeView(mViewCaptor.firstValue) // Verify state correctly set. verify(mStateController).setOverlayActive(false) @@ -567,8 +533,8 @@ class DreamOverlayServiceTest(flags: FlagsParameterization?) : SysuiTestCase() { // The overlay starts then finishes. val inOrder = Mockito.inOrder(mWindowManager) - inOrder.verify(mWindowManager).addView(mViewCaptor!!.capture(), any()) - inOrder.verify(mWindowManager).removeView(mViewCaptor!!.value) + inOrder.verify(mWindowManager).addView(mViewCaptor.capture(), any()) + inOrder.verify(mWindowManager).removeView(mViewCaptor.firstValue) } @Test @@ -596,8 +562,8 @@ class DreamOverlayServiceTest(flags: FlagsParameterization?) : SysuiTestCase() { // The overlay starts then finishes. val inOrder = Mockito.inOrder(mWindowManager) - inOrder.verify(mWindowManager).addView(mViewCaptor!!.capture(), any()) - inOrder.verify(mWindowManager).removeView(mViewCaptor!!.value) + inOrder.verify(mWindowManager).addView(mViewCaptor.capture(), any()) + inOrder.verify(mWindowManager).removeView(mViewCaptor.firstValue) } @Test @@ -615,14 +581,14 @@ class DreamOverlayServiceTest(flags: FlagsParameterization?) : SysuiTestCase() { mMainExecutor.runAllReady() // Verify view added. - verify(mWindowManager).addView(mViewCaptor!!.capture(), any()) + verify(mWindowManager).addView(mViewCaptor.capture(), any()) // Service destroyed. mService.onDestroy() mMainExecutor.runAllReady() // Verify view removed. - verify(mWindowManager).removeView(mViewCaptor!!.value) + verify(mWindowManager).removeView(mViewCaptor.firstValue) // Verify state correctly set. verify(mKeyguardUpdateMonitor).removeCallback(any()) @@ -639,7 +605,7 @@ class DreamOverlayServiceTest(flags: FlagsParameterization?) : SysuiTestCase() { mMainExecutor.runAllReady() // Verify no view is removed. - verify(mWindowManager, Mockito.never()).removeView(any()) + verify(mWindowManager, never()).removeView(any()) // Verify state still correctly set. verify(mKeyguardUpdateMonitor).removeCallback(any()) @@ -665,7 +631,7 @@ class DreamOverlayServiceTest(flags: FlagsParameterization?) : SysuiTestCase() { false, /*shouldShowComplication*/ ) mMainExecutor.runAllReady() - verify(mWindowManager, Mockito.never()).addView(any(), any()) + verify(mWindowManager, never()).addView(any(), any()) } @Test @@ -673,7 +639,7 @@ class DreamOverlayServiceTest(flags: FlagsParameterization?) : SysuiTestCase() { // Service destroyed before dream started. mService.onDestroy() mMainExecutor.runAllReady() - verify(mWindowManager, Mockito.never()).removeView(any()) + verify(mWindowManager, never()).removeView(any()) } @Test @@ -691,8 +657,8 @@ class DreamOverlayServiceTest(flags: FlagsParameterization?) : SysuiTestCase() { mMainExecutor.runAllReady() // Verify that a new window is added. - verify(mWindowManager).addView(mViewCaptor!!.capture(), any()) - val windowDecorView = mViewCaptor!!.value + verify(mWindowManager).addView(mViewCaptor.capture(), any()) + val windowDecorView = mViewCaptor.firstValue // Assert that the overlay is not showing complications. assertThat(mService.shouldShowComplications()).isFalse() @@ -751,7 +717,7 @@ class DreamOverlayServiceTest(flags: FlagsParameterization?) : SysuiTestCase() { @Test fun testWakeUpBeforeStartDoesNothing() { mService.onWakeUp() - verify(mDreamOverlayContainerViewController, Mockito.never()).onWakeUp() + verify(mDreamOverlayContainerViewController, never()).onWakeUp() } @Test @@ -879,8 +845,8 @@ class DreamOverlayServiceTest(flags: FlagsParameterization?) : SysuiTestCase() { ) mMainExecutor.runAllReady() - whenever(mDreamOverlayContainerViewController.isBouncerShowing()).thenReturn(true) - mService!!.onComeToFront() + whenever(mDreamOverlayContainerViewController.isBouncerShowing).thenReturn(true) + mService.onComeToFront() verify(mScrimController).expand(any()) } @@ -900,7 +866,7 @@ class DreamOverlayServiceTest(flags: FlagsParameterization?) : SysuiTestCase() { ) mMainExecutor.runAllReady() - mService!!.onComeToFront() + mService.onComeToFront() assertThat(communalRepository.currentScene.value).isEqualTo(CommunalScenes.Blank) } @@ -920,7 +886,7 @@ class DreamOverlayServiceTest(flags: FlagsParameterization?) : SysuiTestCase() { ) mMainExecutor.runAllReady() - mService!!.onComeToFront() + mService.onComeToFront() verify(mSystemDialogsCloser).closeSystemDialogs() } @@ -1320,6 +1286,45 @@ class DreamOverlayServiceTest(flags: FlagsParameterization?) : SysuiTestCase() { environmentComponents.verifyNoMoreInteractions() } + @DisableFlags(FLAG_COMMUNAL_HUB_ON_MOBILE) + @Test + fun testAmbientTouchHandlersRegistration_registerHideComplicationAndCommunal() { + val client = client + + // Inform the overlay service of dream starting. + client.startDream( + mWindowParams, + mDreamOverlayCallback, + DREAM_COMPONENT, + false /*isPreview*/, + false, /*shouldShowComplication*/ + ) + mMainExecutor.runAllReady() + + verify(mAmbientTouchComponentFactory).create(any(), mTouchHandlersCaptor.capture(), any()) + assertThat(mTouchHandlersCaptor.firstValue) + .containsExactly(mHideComplicationTouchHandler, mCommunalTouchHandler) + } + + @EnableFlags(FLAG_COMMUNAL_HUB_ON_MOBILE) + @Test + fun testAmbientTouchHandlersRegistration_v2_registerOnlyHideComplication() { + val client = client + + // Inform the overlay service of dream starting. + client.startDream( + mWindowParams, + mDreamOverlayCallback, + DREAM_COMPONENT, + false /*isPreview*/, + false, /*shouldShowComplication*/ + ) + mMainExecutor.runAllReady() + + verify(mAmbientTouchComponentFactory).create(any(), mTouchHandlersCaptor.capture(), any()) + assertThat(mTouchHandlersCaptor.firstValue).containsExactly(mHideComplicationTouchHandler) + } + internal class FakeLifecycleRegistry(provider: LifecycleOwner) : LifecycleRegistry(provider) { val mLifecycles: MutableList<State> = ArrayList() diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/ui/viewmodel/DreamUserActionsViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/ui/viewmodel/DreamUserActionsViewModelTest.kt index 82bcecef1f70..55b87db232e8 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/ui/viewmodel/DreamUserActionsViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/ui/viewmodel/DreamUserActionsViewModelTest.kt @@ -27,6 +27,7 @@ import com.android.compose.animation.scene.UserActionResult import com.android.systemui.SysuiTestCase import com.android.systemui.authentication.data.repository.fakeAuthenticationRepository import com.android.systemui.authentication.shared.model.AuthenticationMethodModel +import com.android.systemui.communal.domain.interactor.setCommunalAvailable import com.android.systemui.coroutines.collectLastValue import com.android.systemui.deviceentry.domain.interactor.deviceUnlockedInteractor import com.android.systemui.flags.EnableSceneContainer @@ -72,8 +73,10 @@ class DreamUserActionsViewModelTest : SysuiTestCase() { @Test @DisableFlags(DualShade.FLAG_NAME) - fun actions_singleShade() = + fun actions_communalNotAvailable_singleShade() = testScope.runTest { + kosmos.setCommunalAvailable(false) + val actions by collectLastValue(underTest.actions) setUpState( @@ -85,6 +88,8 @@ class DreamUserActionsViewModelTest : SysuiTestCase() { assertThat(actions?.get(Swipe.Up)).isEqualTo(UserActionResult(Scenes.Bouncer)) assertThat(actions?.get(Swipe.Down)) .isEqualTo(UserActionResult(Scenes.Shade, isIrreversible = true)) + assertThat(actions?.get(Swipe.Start)).isNull() + assertThat(actions?.get(Swipe.End)).isNull() setUpState( isShadeTouchable = false, @@ -102,12 +107,16 @@ class DreamUserActionsViewModelTest : SysuiTestCase() { assertThat(actions?.get(Swipe.Up)).isEqualTo(UserActionResult(Scenes.Gone)) assertThat(actions?.get(Swipe.Down)) .isEqualTo(UserActionResult(Scenes.Shade, isIrreversible = true)) + assertThat(actions?.get(Swipe.Start)).isNull() + assertThat(actions?.get(Swipe.End)).isNull() } @Test @DisableFlags(DualShade.FLAG_NAME) - fun actions_splitShade() = + fun actions_communalNotAvailable_splitShade() = testScope.runTest { + kosmos.setCommunalAvailable(false) + val actions by collectLastValue(underTest.actions) setUpState( @@ -119,6 +128,8 @@ class DreamUserActionsViewModelTest : SysuiTestCase() { assertThat(actions?.get(Swipe.Up)).isEqualTo(UserActionResult(Scenes.Bouncer)) assertThat(actions?.get(Swipe.Down)) .isEqualTo(UserActionResult(Scenes.Shade, ToSplitShade, isIrreversible = true)) + assertThat(actions?.get(Swipe.Start)).isNull() + assertThat(actions?.get(Swipe.End)).isNull() setUpState( isShadeTouchable = false, @@ -136,12 +147,136 @@ class DreamUserActionsViewModelTest : SysuiTestCase() { assertThat(actions?.get(Swipe.Up)).isEqualTo(UserActionResult(Scenes.Gone)) assertThat(actions?.get(Swipe.Down)) .isEqualTo(UserActionResult(Scenes.Shade, ToSplitShade, isIrreversible = true)) + assertThat(actions?.get(Swipe.Start)).isNull() + assertThat(actions?.get(Swipe.End)).isNull() } @Test @EnableFlags(DualShade.FLAG_NAME) - fun actions_dualShade() = + fun actions_communalNotAvailable_dualShade() = testScope.runTest { + kosmos.setCommunalAvailable(false) + + val actions by collectLastValue(underTest.actions) + + setUpState( + isShadeTouchable = true, + isDeviceUnlocked = false, + shadeMode = ShadeMode.Dual, + ) + assertThat(actions).isNotEmpty() + assertThat(actions?.get(Swipe.Up)).isEqualTo(UserActionResult(Scenes.Bouncer)) + assertThat(actions?.get(Swipe.Down)) + .isEqualTo( + UserActionResult.ShowOverlay(Overlays.NotificationsShade, isIrreversible = true) + ) + assertThat(actions?.get(Swipe.Start)).isNull() + assertThat(actions?.get(Swipe.End)).isNull() + + setUpState( + isShadeTouchable = false, + isDeviceUnlocked = false, + shadeMode = ShadeMode.Dual, + ) + assertThat(actions).isEmpty() + + setUpState(isShadeTouchable = true, isDeviceUnlocked = true, shadeMode = ShadeMode.Dual) + assertThat(actions).isNotEmpty() + assertThat(actions?.get(Swipe.Up)).isEqualTo(UserActionResult(Scenes.Gone)) + assertThat(actions?.get(Swipe.Down)) + .isEqualTo( + UserActionResult.ShowOverlay(Overlays.NotificationsShade, isIrreversible = true) + ) + assertThat(actions?.get(Swipe.Start)).isNull() + assertThat(actions?.get(Swipe.End)).isNull() + } + + @Test + @DisableFlags(DualShade.FLAG_NAME) + fun actions_communalAvailable_singleShade() = + testScope.runTest { + kosmos.setCommunalAvailable(true) + + val actions by collectLastValue(underTest.actions) + + setUpState( + isShadeTouchable = true, + isDeviceUnlocked = false, + shadeMode = ShadeMode.Single, + ) + assertThat(actions).isNotEmpty() + assertThat(actions?.get(Swipe.Up)).isEqualTo(UserActionResult(Scenes.Bouncer)) + assertThat(actions?.get(Swipe.Down)) + .isEqualTo(UserActionResult(Scenes.Shade, isIrreversible = true)) + assertThat(actions?.get(Swipe.Start)).isEqualTo(UserActionResult(Scenes.Communal)) + assertThat(actions?.get(Swipe.End)).isNull() + + setUpState( + isShadeTouchable = false, + isDeviceUnlocked = false, + shadeMode = ShadeMode.Single, + ) + assertThat(actions).isEmpty() + + setUpState( + isShadeTouchable = true, + isDeviceUnlocked = true, + shadeMode = ShadeMode.Single, + ) + assertThat(actions).isNotEmpty() + assertThat(actions?.get(Swipe.Up)).isEqualTo(UserActionResult(Scenes.Gone)) + assertThat(actions?.get(Swipe.Down)) + .isEqualTo(UserActionResult(Scenes.Shade, isIrreversible = true)) + assertThat(actions?.get(Swipe.Start)).isEqualTo(UserActionResult(Scenes.Communal)) + assertThat(actions?.get(Swipe.End)).isNull() + } + + @Test + @DisableFlags(DualShade.FLAG_NAME) + fun actions_communalAvailable_splitShade() = + testScope.runTest { + kosmos.setCommunalAvailable(true) + + val actions by collectLastValue(underTest.actions) + + setUpState( + isShadeTouchable = true, + isDeviceUnlocked = false, + shadeMode = ShadeMode.Split, + ) + assertThat(actions).isNotEmpty() + assertThat(actions?.get(Swipe.Up)).isEqualTo(UserActionResult(Scenes.Bouncer)) + assertThat(actions?.get(Swipe.Down)) + .isEqualTo(UserActionResult(Scenes.Shade, ToSplitShade, isIrreversible = true)) + assertThat(actions?.get(Swipe.Start)).isEqualTo(UserActionResult(Scenes.Communal)) + assertThat(actions?.get(Swipe.End)).isNull() + + setUpState( + isShadeTouchable = false, + isDeviceUnlocked = false, + shadeMode = ShadeMode.Split, + ) + assertThat(actions).isEmpty() + + setUpState( + isShadeTouchable = true, + isDeviceUnlocked = true, + shadeMode = ShadeMode.Split, + ) + assertThat(actions).isNotEmpty() + assertThat(actions?.get(Swipe.Up)).isEqualTo(UserActionResult(Scenes.Gone)) + assertThat(actions?.get(Swipe.Down)) + .isEqualTo(UserActionResult(Scenes.Shade, ToSplitShade, isIrreversible = true)) + assertThat(actions?.get(Swipe.Start)).isEqualTo(UserActionResult(Scenes.Communal)) + assertThat(actions?.get(Swipe.End)).isNull() + } + + @Test + @EnableFlags(DualShade.FLAG_NAME) + fun actions_communalAvailable_dualShade() = + testScope.runTest { + kosmos.setCommunalAvailable(true) + val actions by collectLastValue(underTest.actions) setUpState( @@ -155,6 +290,8 @@ class DreamUserActionsViewModelTest : SysuiTestCase() { .isEqualTo( UserActionResult.ShowOverlay(Overlays.NotificationsShade, isIrreversible = true) ) + assertThat(actions?.get(Swipe.Start)).isEqualTo(UserActionResult(Scenes.Communal)) + assertThat(actions?.get(Swipe.End)).isNull() setUpState( isShadeTouchable = false, @@ -170,6 +307,8 @@ class DreamUserActionsViewModelTest : SysuiTestCase() { .isEqualTo( UserActionResult.ShowOverlay(Overlays.NotificationsShade, isIrreversible = true) ) + assertThat(actions?.get(Swipe.Start)).isEqualTo(UserActionResult(Scenes.Communal)) + assertThat(actions?.get(Swipe.End)).isNull() } private fun TestScope.setUpState( diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/inputdevice/tutorial/ui/viewmodel/KeyboardTouchpadTutorialViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/inputdevice/tutorial/ui/viewmodel/KeyboardTouchpadTutorialViewModelTest.kt index 639737b37efd..76434ee54627 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/inputdevice/tutorial/ui/viewmodel/KeyboardTouchpadTutorialViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/inputdevice/tutorial/ui/viewmodel/KeyboardTouchpadTutorialViewModelTest.kt @@ -27,9 +27,11 @@ import com.android.systemui.coroutines.collectLastValue import com.android.systemui.coroutines.collectValues import com.android.systemui.inputdevice.tutorial.InputDeviceTutorialLogger import com.android.systemui.inputdevice.tutorial.domain.interactor.KeyboardTouchpadConnectionInteractor -import com.android.systemui.inputdevice.tutorial.ui.view.KeyboardTouchpadTutorialActivity.Companion.INTENT_TUTORIAL_TYPE_KEY -import com.android.systemui.inputdevice.tutorial.ui.view.KeyboardTouchpadTutorialActivity.Companion.INTENT_TUTORIAL_TYPE_KEYBOARD -import com.android.systemui.inputdevice.tutorial.ui.view.KeyboardTouchpadTutorialActivity.Companion.INTENT_TUTORIAL_TYPE_TOUCHPAD +import com.android.systemui.inputdevice.tutorial.ui.view.KeyboardTouchpadTutorialActivity.Companion.INTENT_TUTORIAL_SCOPE_KEY +import com.android.systemui.inputdevice.tutorial.ui.view.KeyboardTouchpadTutorialActivity.Companion.INTENT_TUTORIAL_SCOPE_KEYBOARD +import com.android.systemui.inputdevice.tutorial.ui.view.KeyboardTouchpadTutorialActivity.Companion.INTENT_TUTORIAL_SCOPE_TOUCHPAD +import com.android.systemui.inputdevice.tutorial.ui.view.KeyboardTouchpadTutorialActivity.Companion.INTENT_TUTORIAL_SCOPE_TOUCHPAD_BACK +import com.android.systemui.inputdevice.tutorial.ui.view.KeyboardTouchpadTutorialActivity.Companion.INTENT_TUTORIAL_SCOPE_TOUCHPAD_HOME import com.android.systemui.inputdevice.tutorial.ui.viewmodel.Screen.ACTION_KEY import com.android.systemui.inputdevice.tutorial.ui.viewmodel.Screen.BACK_GESTURE import com.android.systemui.inputdevice.tutorial.ui.viewmodel.Screen.HOME_GESTURE @@ -66,8 +68,8 @@ class KeyboardTouchpadTutorialViewModelTest : SysuiTestCase() { private val sysUiState = kosmos.sysUiState private val touchpadRepo = PrettyFakeTouchpadRepository() private val keyboardRepo = kosmos.keyboardRepository - private var startingPeripheral = INTENT_TUTORIAL_TYPE_TOUCHPAD - private val viewModel by lazy { createViewModel(startingPeripheral) } + private var tutorialScope = INTENT_TUTORIAL_SCOPE_TOUCHPAD + private val viewModel by lazy { createViewModel(tutorialScope) } // createUnsafe so its methods don't have to be called on Main thread private val lifecycle = LifecycleRegistry.createUnsafe(mock(LifecycleOwner::class.java)) @@ -75,7 +77,7 @@ class KeyboardTouchpadTutorialViewModelTest : SysuiTestCase() { @get:Rule val mainDispatcherRule = MainDispatcherRule(kosmos.testDispatcher) private fun createViewModel( - startingPeripheral: String = INTENT_TUTORIAL_TYPE_TOUCHPAD, + scope: String = INTENT_TUTORIAL_SCOPE_TOUCHPAD, hasTouchpadTutorialScreens: Boolean = true, ): KeyboardTouchpadTutorialViewModel { val viewModel = @@ -84,7 +86,7 @@ class KeyboardTouchpadTutorialViewModelTest : SysuiTestCase() { KeyboardTouchpadConnectionInteractor(keyboardRepo, touchpadRepo), hasTouchpadTutorialScreens, mock<InputDeviceTutorialLogger>(), - SavedStateHandle(mapOf(INTENT_TUTORIAL_TYPE_KEY to startingPeripheral)) + SavedStateHandle(mapOf(INTENT_TUTORIAL_SCOPE_KEY to scope)), ) lifecycle.addObserver(viewModel) return viewModel @@ -169,7 +171,7 @@ class KeyboardTouchpadTutorialViewModelTest : SysuiTestCase() { @Test fun screensOrder_whenGoingBackAndOnlyKeyboardConnected() = testScope.runTest { - startingPeripheral = INTENT_TUTORIAL_TYPE_KEYBOARD + tutorialScope = INTENT_TUTORIAL_SCOPE_KEYBOARD val screens by collectValues(viewModel.screen) val closeActivity by collectLastValue(viewModel.closeActivity) peripheralsState(keyboardConnected = true, touchpadConnected = false) @@ -185,7 +187,7 @@ class KeyboardTouchpadTutorialViewModelTest : SysuiTestCase() { @Test fun screensOrder_whenTouchpadConnected() = testScope.runTest { - startingPeripheral = INTENT_TUTORIAL_TYPE_TOUCHPAD + tutorialScope = INTENT_TUTORIAL_SCOPE_TOUCHPAD val screens by collectValues(viewModel.screen) val closeActivity by collectLastValue(viewModel.closeActivity) @@ -193,22 +195,47 @@ class KeyboardTouchpadTutorialViewModelTest : SysuiTestCase() { goToNextScreen() goToNextScreen() - goToNextScreen() assertThat(screens).containsExactly(BACK_GESTURE, HOME_GESTURE).inOrder() assertThat(closeActivity).isTrue() } @Test - fun screensOrder_whenKeyboardConnected() = + fun screensOrder_withBackGestureScope() = testScope.runTest { - startingPeripheral = INTENT_TUTORIAL_TYPE_KEYBOARD + tutorialScope = INTENT_TUTORIAL_SCOPE_TOUCHPAD_BACK val screens by collectValues(viewModel.screen) val closeActivity by collectLastValue(viewModel.closeActivity) + peripheralsState(touchpadConnected = true) - peripheralsState(keyboardConnected = true) + goToNextScreen() + + assertThat(screens).containsExactly(BACK_GESTURE).inOrder() + assertThat(closeActivity).isTrue() + } + + @Test + fun screensOrder_withHomeGestureScope() = + testScope.runTest { + tutorialScope = INTENT_TUTORIAL_SCOPE_TOUCHPAD_HOME + val screens by collectValues(viewModel.screen) + val closeActivity by collectLastValue(viewModel.closeActivity) + peripheralsState(touchpadConnected = true) goToNextScreen() + + assertThat(screens).containsExactly(HOME_GESTURE).inOrder() + assertThat(closeActivity).isTrue() + } + + @Test + fun screensOrder_withKeyboardScope() = + testScope.runTest { + tutorialScope = INTENT_TUTORIAL_SCOPE_KEYBOARD + val screens by collectValues(viewModel.screen) + val closeActivity by collectLastValue(viewModel.closeActivity) + peripheralsState(keyboardConnected = true) + goToNextScreen() assertThat(screens).containsExactly(ACTION_KEY).inOrder() @@ -218,7 +245,7 @@ class KeyboardTouchpadTutorialViewModelTest : SysuiTestCase() { @Test fun touchpadGesturesDisabled_onlyDuringTouchpadTutorial() = testScope.runTest { - startingPeripheral = INTENT_TUTORIAL_TYPE_TOUCHPAD + tutorialScope = INTENT_TUTORIAL_SCOPE_TOUCHPAD collectValues(viewModel.screen) // just to initialize viewModel peripheralsState(keyboardConnected = true, touchpadConnected = true) @@ -234,8 +261,8 @@ class KeyboardTouchpadTutorialViewModelTest : SysuiTestCase() { testScope.runTest { val viewModel = createViewModel( - startingPeripheral = INTENT_TUTORIAL_TYPE_TOUCHPAD, - hasTouchpadTutorialScreens = false + scope = INTENT_TUTORIAL_SCOPE_TOUCHPAD, + hasTouchpadTutorialScreens = false, ) val screens by collectValues(viewModel.screen) val closeActivity by collectLastValue(viewModel.closeActivity) @@ -248,7 +275,7 @@ class KeyboardTouchpadTutorialViewModelTest : SysuiTestCase() { @Test fun touchpadGesturesDisabled_whenTutorialGoesToForeground() = testScope.runTest { - startingPeripheral = INTENT_TUTORIAL_TYPE_TOUCHPAD + tutorialScope = INTENT_TUTORIAL_SCOPE_TOUCHPAD collectValues(viewModel.screen) // just to initialize viewModel peripheralsState(touchpadConnected = true) @@ -260,7 +287,7 @@ class KeyboardTouchpadTutorialViewModelTest : SysuiTestCase() { @Test fun touchpadGesturesNotDisabled_whenTutorialGoesToBackground() = testScope.runTest { - startingPeripheral = INTENT_TUTORIAL_TYPE_TOUCHPAD + tutorialScope = INTENT_TUTORIAL_SCOPE_TOUCHPAD collectValues(viewModel.screen) peripheralsState(touchpadConnected = true) @@ -288,7 +315,7 @@ class KeyboardTouchpadTutorialViewModelTest : SysuiTestCase() { private fun TestScope.peripheralsState( keyboardConnected: Boolean = false, - touchpadConnected: Boolean = false + touchpadConnected: Boolean = false, ) { keyboardRepo.setIsAnyKeyboardConnected(keyboardConnected) touchpadRepo.setIsAnyTouchpadConnected(touchpadConnected) diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyboard/shortcut/data/repository/CustomShortcutCategoriesRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyboard/shortcut/data/repository/CustomShortcutCategoriesRepositoryTest.kt index f04540426fc1..0d32b7fb1b3e 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyboard/shortcut/data/repository/CustomShortcutCategoriesRepositoryTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyboard/shortcut/data/repository/CustomShortcutCategoriesRepositoryTest.kt @@ -18,36 +18,31 @@ package com.android.systemui.keyboard.shortcut.data.repository import android.content.Context import android.content.Context.INPUT_SERVICE -import android.hardware.input.InputGestureData -import android.hardware.input.InputGestureData.createKeyTrigger -import android.hardware.input.KeyGestureEvent.KEY_GESTURE_TYPE_ALL_APPS +import android.hardware.input.InputManager.CUSTOM_INPUT_GESTURE_RESULT_SUCCESS import android.hardware.input.fakeInputManager import android.platform.test.annotations.DisableFlags import android.platform.test.annotations.EnableFlags -import android.view.KeyEvent.KEYCODE_A import android.view.KeyEvent.KEYCODE_SLASH -import android.view.KeyEvent.META_ALT_ON import android.view.KeyEvent.META_CAPS_LOCK_ON -import android.view.KeyEvent.META_CTRL_ON -import android.view.KeyEvent.META_FUNCTION_ON -import android.view.KeyEvent.META_META_LEFT_ON import android.view.KeyEvent.META_META_ON -import android.view.KeyEvent.META_SHIFT_ON -import android.view.KeyEvent.META_SHIFT_RIGHT_ON -import android.view.KeyEvent.META_SYM_ON import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.hardware.input.Flags.FLAG_ENABLE_CUSTOMIZABLE_INPUT_GESTURES import com.android.hardware.input.Flags.FLAG_USE_KEY_GESTURE_EVENT_HANDLER import com.android.systemui.SysuiTestCase import com.android.systemui.coroutines.collectLastValue +import com.android.systemui.keyboard.shared.model.ShortcutCustomizationRequestResult import com.android.systemui.keyboard.shortcut.customShortcutCategoriesRepository +import com.android.systemui.keyboard.shortcut.data.source.TestShortcuts.ALL_SUPPORTED_MODIFIERS +import com.android.systemui.keyboard.shortcut.data.source.TestShortcuts.allAppsInputGestureData import com.android.systemui.keyboard.shortcut.data.source.TestShortcuts.allCustomizableInputGesturesWithSimpleShortcutCombinations import com.android.systemui.keyboard.shortcut.data.source.TestShortcuts.customizableInputGestureWithUnknownKeyGestureType import com.android.systemui.keyboard.shortcut.data.source.TestShortcuts.expectedShortcutCategoriesWithSimpleShortcutCombination +import com.android.systemui.keyboard.shortcut.data.source.TestShortcuts.goHomeInputGestureData +import com.android.systemui.keyboard.shortcut.data.source.TestShortcuts.standardAddCustomShortcutRequestInfo +import com.android.systemui.keyboard.shortcut.data.source.TestShortcuts.standardDeleteCustomShortcutRequestInfo +import com.android.systemui.keyboard.shortcut.data.source.TestShortcuts.standardKeyCombination import com.android.systemui.keyboard.shortcut.shared.model.KeyCombination -import com.android.systemui.keyboard.shortcut.shared.model.ShortcutCategoryType -import com.android.systemui.keyboard.shortcut.shared.model.ShortcutCustomizationRequestInfo import com.android.systemui.keyboard.shortcut.shared.model.ShortcutKey import com.android.systemui.keyboard.shortcut.shortcutHelperTestHelper import com.android.systemui.kosmos.testScope @@ -74,24 +69,21 @@ class CustomShortcutCategoriesRepositoryTest : SysuiTestCase() { it.userTracker = FakeUserTracker(onCreateCurrentUserContext = { mockUserContext }) } - private val fakeInputManager = kosmos.fakeInputManager + private val inputManager = kosmos.fakeInputManager.inputManager private val testScope = kosmos.testScope private val helper = kosmos.shortcutHelperTestHelper private val repo = kosmos.customShortcutCategoriesRepository @Before fun setup() { - whenever(mockUserContext.getSystemService(INPUT_SERVICE)) - .thenReturn(fakeInputManager.inputManager) + whenever(mockUserContext.getSystemService(INPUT_SERVICE)).thenReturn(inputManager) } @Test @EnableFlags(FLAG_ENABLE_CUSTOMIZABLE_INPUT_GESTURES, FLAG_USE_KEY_GESTURE_EVENT_HANDLER) fun categories_emitsCorrectlyConvertedShortcutCategories() { testScope.runTest { - whenever( - fakeInputManager.inputManager.getCustomInputGestures(/* filter= */ anyOrNull()) - ) + whenever(inputManager.getCustomInputGestures(/* filter= */ anyOrNull())) .thenReturn(allCustomizableInputGesturesWithSimpleShortcutCombinations) helper.toggle(deviceId = 123) @@ -106,9 +98,7 @@ class CustomShortcutCategoriesRepositoryTest : SysuiTestCase() { @DisableFlags(FLAG_ENABLE_CUSTOMIZABLE_INPUT_GESTURES, FLAG_USE_KEY_GESTURE_EVENT_HANDLER) fun categories_emitsEmptyListWhenFlagIsDisabled() { testScope.runTest { - whenever( - fakeInputManager.inputManager.getCustomInputGestures(/* filter= */ anyOrNull()) - ) + whenever(inputManager.getCustomInputGestures(/* filter= */ anyOrNull())) .thenReturn(allCustomizableInputGesturesWithSimpleShortcutCombinations) helper.toggle(deviceId = 123) @@ -122,9 +112,7 @@ class CustomShortcutCategoriesRepositoryTest : SysuiTestCase() { @EnableFlags(FLAG_ENABLE_CUSTOMIZABLE_INPUT_GESTURES, FLAG_USE_KEY_GESTURE_EVENT_HANDLER) fun categories_ignoresUnknownKeyGestureTypes() { testScope.runTest { - whenever( - fakeInputManager.inputManager.getCustomInputGestures(/* filter= */ anyOrNull()) - ) + whenever(inputManager.getCustomInputGestures(/* filter= */ anyOrNull())) .thenReturn(customizableInputGestureWithUnknownKeyGestureType) helper.toggle(deviceId = 123) @@ -151,7 +139,7 @@ class CustomShortcutCategoriesRepositoryTest : SysuiTestCase() { helper.toggle(deviceId = 123) val pressedKeys by collectLastValue(repo.pressedKeys) repo.updateUserKeyCombination( - KeyCombination(modifiers = allSupportedModifiers, keyCode = null) + KeyCombination(modifiers = ALL_SUPPORTED_MODIFIERS, keyCode = null) ) assertThat(pressedKeys) @@ -199,11 +187,11 @@ class CustomShortcutCategoriesRepositoryTest : SysuiTestCase() { @Test fun shortcutBeingCustomized_updatedOnCustomizationRequested() { testScope.runTest { - repo.onCustomizationRequested(standardCustomizationRequestInfo) + repo.onCustomizationRequested(standardAddCustomShortcutRequestInfo) val shortcutBeingCustomized = repo.getShortcutBeingCustomized() - assertThat(shortcutBeingCustomized).isEqualTo(standardCustomizationRequestInfo) + assertThat(shortcutBeingCustomized).isEqualTo(standardAddCustomShortcutRequestInfo) } } @@ -223,7 +211,7 @@ class CustomShortcutCategoriesRepositoryTest : SysuiTestCase() { fun buildInputGestureDataForShortcutBeingCustomized_noKeyCombinationSelected_returnsNull() { testScope.runTest { helper.toggle(deviceId = 123) - repo.onCustomizationRequested(standardCustomizationRequestInfo) + repo.onCustomizationRequested(standardAddCustomShortcutRequestInfo) val inputGestureData = repo.buildInputGestureDataForShortcutBeingCustomized() @@ -235,46 +223,32 @@ class CustomShortcutCategoriesRepositoryTest : SysuiTestCase() { fun buildInputGestureDataForShortcutBeingCustomized_successfullyBuildInputGestureData() { testScope.runTest { helper.toggle(deviceId = 123) - repo.onCustomizationRequested(standardCustomizationRequestInfo) + repo.onCustomizationRequested(standardAddCustomShortcutRequestInfo) repo.updateUserKeyCombination(standardKeyCombination) val inputGestureData = repo.buildInputGestureDataForShortcutBeingCustomized() // using toString as we're testing for only structural equality not referential. // inputGestureData is a java class and isEqual Tests for referential equality // as well which would cause this assert to fail - assertThat(inputGestureData.toString()).isEqualTo(standardInputGestureData.toString()) + assertThat(inputGestureData.toString()).isEqualTo(allAppsInputGestureData.toString()) } } - private val standardCustomizationRequestInfo = - ShortcutCustomizationRequestInfo.Add( - label = "Open apps list", - categoryType = ShortcutCategoryType.System, - subCategoryLabel = "System controls", - ) - - private val standardKeyCombination = - KeyCombination( - modifiers = META_META_ON or META_SHIFT_ON or META_META_LEFT_ON or META_SHIFT_RIGHT_ON, - keyCode = KEYCODE_A, - ) - - private val allSupportedModifiers = - META_META_ON or - META_CTRL_ON or - META_FUNCTION_ON or - META_SHIFT_ON or - META_ALT_ON or - META_SYM_ON - - private val standardInputGestureData = - InputGestureData.Builder() - .setKeyGestureType(KEY_GESTURE_TYPE_ALL_APPS) - .setTrigger( - createKeyTrigger( - /* keycode = */ standardKeyCombination.keyCode!!, - /* modifierState = */ standardKeyCombination.modifiers and allSupportedModifiers, - ) - ) - .build() + @Test + @EnableFlags(FLAG_ENABLE_CUSTOMIZABLE_INPUT_GESTURES, FLAG_USE_KEY_GESTURE_EVENT_HANDLER) + fun deleteShortcut_successfullyRetrievesGestureDataAndDeletesShortcut() { + testScope.runTest { + whenever(inputManager.getCustomInputGestures(anyOrNull())) + .thenReturn(listOf(allAppsInputGestureData, goHomeInputGestureData)) + whenever(inputManager.removeCustomInputGesture(allAppsInputGestureData)) + .thenReturn(CUSTOM_INPUT_GESTURE_RESULT_SUCCESS) + + helper.toggle(deviceId = 123) + repo.onCustomizationRequested(standardDeleteCustomShortcutRequestInfo) + + val result = repo.deleteShortcutCurrentlyBeingCustomized() + + assertThat(result).isEqualTo(ShortcutCustomizationRequestResult.SUCCESS) + } + } } diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyboard/shortcut/data/source/TestShortcuts.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyboard/shortcut/data/source/TestShortcuts.kt index a1e7ef4ac5a3..8466eab2aca6 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyboard/shortcut/data/source/TestShortcuts.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyboard/shortcut/data/source/TestShortcuts.kt @@ -19,9 +19,23 @@ package com.android.systemui.keyboard.shortcut.data.source import android.hardware.input.InputGestureData import android.hardware.input.InputGestureData.createKeyTrigger import android.hardware.input.KeyGestureEvent +import android.hardware.input.KeyGestureEvent.KEY_GESTURE_TYPE_ALL_APPS +import android.hardware.input.KeyGestureEvent.KEY_GESTURE_TYPE_HOME +import android.os.SystemClock import android.view.KeyEvent +import android.view.KeyEvent.ACTION_DOWN +import android.view.KeyEvent.KEYCODE_A +import android.view.KeyEvent.META_ALT_ON +import android.view.KeyEvent.META_CTRL_ON +import android.view.KeyEvent.META_FUNCTION_ON +import android.view.KeyEvent.META_META_LEFT_ON +import android.view.KeyEvent.META_META_ON +import android.view.KeyEvent.META_SHIFT_ON +import android.view.KeyEvent.META_SHIFT_RIGHT_ON +import android.view.KeyEvent.META_SYM_ON import android.view.KeyboardShortcutGroup import android.view.KeyboardShortcutInfo +import com.android.systemui.keyboard.shortcut.shared.model.KeyCombination import com.android.systemui.keyboard.shortcut.shared.model.Shortcut import com.android.systemui.keyboard.shortcut.shared.model.ShortcutCategory import com.android.systemui.keyboard.shortcut.shared.model.ShortcutCategoryType @@ -29,9 +43,11 @@ import com.android.systemui.keyboard.shortcut.shared.model.ShortcutCategoryType. import com.android.systemui.keyboard.shortcut.shared.model.ShortcutCategoryType.MultiTasking import com.android.systemui.keyboard.shortcut.shared.model.ShortcutCategoryType.System import com.android.systemui.keyboard.shortcut.shared.model.ShortcutCommand +import com.android.systemui.keyboard.shortcut.shared.model.ShortcutCustomizationRequestInfo import com.android.systemui.keyboard.shortcut.shared.model.ShortcutKey import com.android.systemui.keyboard.shortcut.shared.model.ShortcutSubCategory import com.android.systemui.keyboard.shortcut.shared.model.shortcut +import com.android.systemui.keyboard.shortcut.ui.model.ShortcutCustomizationUiState import com.android.systemui.res.R object TestShortcuts { @@ -525,4 +541,110 @@ object TestShortcuts { keyGestureType = KeyGestureEvent.KEY_GESTURE_TYPE_RECENT_APPS_SWITCHER ), ) + + val standardAddCustomShortcutRequestInfo = + ShortcutCustomizationRequestInfo.Add( + label = "Open apps list", + categoryType = System, + subCategoryLabel = "System controls", + ) + + val standardDeleteCustomShortcutRequestInfo = + ShortcutCustomizationRequestInfo.Delete( + label = "Open apps list", + categoryType = System, + subCategoryLabel = "System controls", + ) + + val standardKeyCombination = + KeyCombination( + modifiers = META_META_ON or META_SHIFT_ON or META_META_LEFT_ON or META_SHIFT_RIGHT_ON, + keyCode = KEYCODE_A, + ) + + const val ALL_SUPPORTED_MODIFIERS = + META_META_ON or + META_CTRL_ON or + META_FUNCTION_ON or + META_SHIFT_ON or + META_ALT_ON or + META_SYM_ON + + val allAppsInputGestureData: InputGestureData = + InputGestureData.Builder() + .setKeyGestureType(KEY_GESTURE_TYPE_ALL_APPS) + .setTrigger( + createKeyTrigger( + /* keycode = */ standardKeyCombination.keyCode!!, + /* modifierState = */ standardKeyCombination.modifiers and + ALL_SUPPORTED_MODIFIERS, + ) + ) + .build() + + val goHomeInputGestureData: InputGestureData = + InputGestureData.Builder() + .setKeyGestureType(KEY_GESTURE_TYPE_HOME) + .setTrigger( + createKeyTrigger( + /* keycode = */ standardKeyCombination.keyCode!!, + /* modifierState = */ standardKeyCombination.modifiers and + ALL_SUPPORTED_MODIFIERS, + ) + ) + .build() + + val expectedStandardDeleteShortcutUiState = + ShortcutCustomizationUiState.DeleteShortcutDialog(isDialogShowing = false) + + val keyDownEventWithoutActionKeyPressed = + androidx.compose.ui.input.key.KeyEvent( + android.view.KeyEvent( + /* downTime = */ SystemClock.uptimeMillis(), + /* eventTime = */ SystemClock.uptimeMillis(), + /* action = */ ACTION_DOWN, + /* code = */ KEYCODE_A, + /* repeat = */ 0, + /* metaState = */ META_CTRL_ON, + ) + ) + + val keyDownEventWithActionKeyPressed = + androidx.compose.ui.input.key.KeyEvent( + android.view.KeyEvent( + /* downTime = */ SystemClock.uptimeMillis(), + /* eventTime = */ SystemClock.uptimeMillis(), + /* action = */ ACTION_DOWN, + /* code = */ KEYCODE_A, + /* repeat = */ 0, + /* metaState = */ META_CTRL_ON or META_META_ON, + ) + ) + + val keyUpEventWithActionKeyPressed = + androidx.compose.ui.input.key.KeyEvent( + android.view.KeyEvent( + /* downTime = */ SystemClock.uptimeMillis(), + /* eventTime = */ SystemClock.uptimeMillis(), + /* action = */ ACTION_DOWN, + /* code = */ KEYCODE_A, + /* repeat = */ 0, + /* metaState = */ 0, + ) + ) + + val standardAddShortcutRequest = + ShortcutCustomizationRequestInfo.Add( + label = "Standard shortcut", + categoryType = ShortcutCategoryType.System, + subCategoryLabel = "Standard subcategory", + ) + + val expectedStandardAddShortcutUiState = + ShortcutCustomizationUiState.AddShortcutDialog( + shortcutLabel = "Standard shortcut", + defaultCustomShortcutModifierKey = + ShortcutKey.Icon.ResIdIcon(R.drawable.ic_ksh_key_meta), + isDialogShowing = false, + ) } diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/quickaffordance/HomeControlsKeyguardQuickAffordanceConfigParameterizedStateTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/quickaffordance/HomeControlsKeyguardQuickAffordanceConfigParameterizedStateTest.kt index 032979447861..0a4198a99bba 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/quickaffordance/HomeControlsKeyguardQuickAffordanceConfigParameterizedStateTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/quickaffordance/HomeControlsKeyguardQuickAffordanceConfigParameterizedStateTest.kt @@ -32,7 +32,8 @@ import java.util.Optional import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach -import kotlinx.coroutines.test.runBlockingTest +import kotlinx.coroutines.test.UnconfinedTestDispatcher +import kotlinx.coroutines.test.runTest import org.junit.Before import org.junit.Test import org.junit.runner.RunWith @@ -125,14 +126,11 @@ class HomeControlsKeyguardQuickAffordanceConfigParameterizedStateTest : SysuiTes ) underTest = - HomeControlsKeyguardQuickAffordanceConfig( - context = context, - component = component, - ) + HomeControlsKeyguardQuickAffordanceConfig(context = context, component = component) } @Test - fun state() = runBlockingTest { + fun state() = runTest(UnconfinedTestDispatcher()) { whenever(component.isEnabled()).thenReturn(isFeatureEnabled) whenever(controlsController.getFavorites()) .thenReturn( diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/quickaffordance/HomeControlsKeyguardQuickAffordanceConfigTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/quickaffordance/HomeControlsKeyguardQuickAffordanceConfigTest.kt index 7d68cc0a3560..0003d07d1e2f 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/quickaffordance/HomeControlsKeyguardQuickAffordanceConfigTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/quickaffordance/HomeControlsKeyguardQuickAffordanceConfigTest.kt @@ -19,19 +19,20 @@ package com.android.systemui.keyguard.data.quickaffordance import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest -import com.android.systemui.res.R import com.android.systemui.SysuiTestCase import com.android.systemui.animation.Expandable import com.android.systemui.controls.controller.ControlsController import com.android.systemui.controls.dagger.ControlsComponent import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceConfig.OnTriggeredResult +import com.android.systemui.res.R import com.android.systemui.util.mockito.mock import com.google.common.truth.Truth.assertThat import java.util.Optional import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach -import kotlinx.coroutines.test.runBlockingTest +import kotlinx.coroutines.test.UnconfinedTestDispatcher +import kotlinx.coroutines.test.runTest import org.junit.Before import org.junit.Test import org.junit.runner.RunWith @@ -54,14 +55,11 @@ class HomeControlsKeyguardQuickAffordanceConfigTest : SysuiTestCase() { whenever(component.canShowWhileLockedSetting).thenReturn(MutableStateFlow(true)) underTest = - HomeControlsKeyguardQuickAffordanceConfig( - context = context, - component = component, - ) + HomeControlsKeyguardQuickAffordanceConfig(context = context, component = component) } @Test - fun state_whenCannotShowWhileLocked_returnsHidden() = runBlockingTest { + fun state_whenCannotShowWhileLocked_returnsHidden() = runTest(UnconfinedTestDispatcher()) { whenever(component.canShowWhileLockedSetting).thenReturn(MutableStateFlow(false)) whenever(component.isEnabled()).thenReturn(true) whenever(component.getTileImageId()).thenReturn(R.drawable.controls_icon) @@ -81,7 +79,7 @@ class HomeControlsKeyguardQuickAffordanceConfigTest : SysuiTestCase() { } @Test - fun state_whenListingControllerIsMissing_returnsHidden() = runBlockingTest { + fun state_whenListingControllerIsMissing_returnsHidden() = runTest(UnconfinedTestDispatcher()) { whenever(component.isEnabled()).thenReturn(true) whenever(component.getTileImageId()).thenReturn(R.drawable.controls_icon) whenever(component.getTileTitleId()).thenReturn(R.string.quick_controls_title) @@ -100,23 +98,26 @@ class HomeControlsKeyguardQuickAffordanceConfigTest : SysuiTestCase() { } @Test - fun onQuickAffordanceTriggered_canShowWhileLockedSettingIsTrue() = runBlockingTest { - whenever(component.canShowWhileLockedSetting).thenReturn(MutableStateFlow(true)) + fun onQuickAffordanceTriggered_canShowWhileLockedSettingIsTrue() = + runTest(UnconfinedTestDispatcher()) { + whenever(component.canShowWhileLockedSetting).thenReturn(MutableStateFlow(true)) - val onClickedResult = underTest.onTriggered(expandable) + val onClickedResult = underTest.onTriggered(expandable) - assertThat(onClickedResult).isInstanceOf(OnTriggeredResult.StartActivity::class.java) - assertThat((onClickedResult as OnTriggeredResult.StartActivity).canShowWhileLocked).isTrue() - } + assertThat(onClickedResult).isInstanceOf(OnTriggeredResult.StartActivity::class.java) + assertThat((onClickedResult as OnTriggeredResult.StartActivity).canShowWhileLocked) + .isTrue() + } @Test - fun onQuickAffordanceTriggered_canShowWhileLockedSettingIsFalse() = runBlockingTest { - whenever(component.canShowWhileLockedSetting).thenReturn(MutableStateFlow(false)) + fun onQuickAffordanceTriggered_canShowWhileLockedSettingIsFalse() = + runTest(UnconfinedTestDispatcher()) { + whenever(component.canShowWhileLockedSetting).thenReturn(MutableStateFlow(false)) - val onClickedResult = underTest.onTriggered(expandable) + val onClickedResult = underTest.onTriggered(expandable) - assertThat(onClickedResult).isInstanceOf(OnTriggeredResult.StartActivity::class.java) - assertThat((onClickedResult as OnTriggeredResult.StartActivity).canShowWhileLocked) - .isFalse() - } + assertThat(onClickedResult).isInstanceOf(OnTriggeredResult.StartActivity::class.java) + assertThat((onClickedResult as OnTriggeredResult.StartActivity).canShowWhileLocked) + .isFalse() + } } diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/quickaffordance/QrCodeScannerKeyguardQuickAffordanceConfigTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/quickaffordance/QrCodeScannerKeyguardQuickAffordanceConfigTest.kt index ca64cec98b2e..05a74c038cc1 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/quickaffordance/QrCodeScannerKeyguardQuickAffordanceConfigTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/quickaffordance/QrCodeScannerKeyguardQuickAffordanceConfigTest.kt @@ -29,7 +29,7 @@ import com.android.systemui.util.mockito.whenever import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach -import kotlinx.coroutines.test.runBlockingTest +import kotlinx.coroutines.test.UnconfinedTestDispatcher import kotlinx.coroutines.test.runTest import org.junit.Before import org.junit.Test @@ -56,60 +56,63 @@ class QrCodeScannerKeyguardQuickAffordanceConfigTest : SysuiTestCase() { } @Test - fun affordance_setsUpRegistrationAndDeliversInitialModel() = runBlockingTest { - whenever(controller.isEnabledForLockScreenButton).thenReturn(true) - var latest: KeyguardQuickAffordanceConfig.LockScreenState? = null - - val job = underTest.lockScreenState.onEach { latest = it }.launchIn(this) + fun affordance_setsUpRegistrationAndDeliversInitialModel() = + runTest(UnconfinedTestDispatcher()) { + whenever(controller.isEnabledForLockScreenButton).thenReturn(true) + var latest: KeyguardQuickAffordanceConfig.LockScreenState? = null + + val job = underTest.lockScreenState.onEach { latest = it }.launchIn(this) + + val callbackCaptor = argumentCaptor<QRCodeScannerController.Callback>() + verify(controller).addCallback(callbackCaptor.capture()) + verify(controller) + .registerQRCodeScannerChangeObservers( + QRCodeScannerController.DEFAULT_QR_CODE_SCANNER_CHANGE, + QRCodeScannerController.QR_CODE_SCANNER_PREFERENCE_CHANGE, + ) + assertVisibleState(latest) - val callbackCaptor = argumentCaptor<QRCodeScannerController.Callback>() - verify(controller).addCallback(callbackCaptor.capture()) - verify(controller) - .registerQRCodeScannerChangeObservers( - QRCodeScannerController.DEFAULT_QR_CODE_SCANNER_CHANGE, - QRCodeScannerController.QR_CODE_SCANNER_PREFERENCE_CHANGE - ) - assertVisibleState(latest) - - job.cancel() - verify(controller).removeCallback(callbackCaptor.value) - } + job.cancel() + verify(controller).removeCallback(callbackCaptor.value) + } @Test - fun affordance_scannerActivityChanged_deliversModelWithUpdatedIntent() = runBlockingTest { - whenever(controller.isEnabledForLockScreenButton).thenReturn(true) - var latest: KeyguardQuickAffordanceConfig.LockScreenState? = null - val job = underTest.lockScreenState.onEach { latest = it }.launchIn(this) - val callbackCaptor = argumentCaptor<QRCodeScannerController.Callback>() - verify(controller).addCallback(callbackCaptor.capture()) + fun affordance_scannerActivityChanged_deliversModelWithUpdatedIntent() = + runTest(UnconfinedTestDispatcher()) { + whenever(controller.isEnabledForLockScreenButton).thenReturn(true) + var latest: KeyguardQuickAffordanceConfig.LockScreenState? = null + val job = underTest.lockScreenState.onEach { latest = it }.launchIn(this) + val callbackCaptor = argumentCaptor<QRCodeScannerController.Callback>() + verify(controller).addCallback(callbackCaptor.capture()) - whenever(controller.intent).thenReturn(INTENT_2) - callbackCaptor.value.onQRCodeScannerActivityChanged() + whenever(controller.intent).thenReturn(INTENT_2) + callbackCaptor.value.onQRCodeScannerActivityChanged() - assertVisibleState(latest) + assertVisibleState(latest) - job.cancel() - verify(controller).removeCallback(callbackCaptor.value) - } + job.cancel() + verify(controller).removeCallback(callbackCaptor.value) + } @Test - fun affordance_scannerPreferenceChanged_deliversVisibleModel() = runBlockingTest { - var latest: KeyguardQuickAffordanceConfig.LockScreenState? = null - val job = underTest.lockScreenState.onEach { latest = it }.launchIn(this) - val callbackCaptor = argumentCaptor<QRCodeScannerController.Callback>() - verify(controller).addCallback(callbackCaptor.capture()) + fun affordance_scannerPreferenceChanged_deliversVisibleModel() = + runTest(UnconfinedTestDispatcher()) { + var latest: KeyguardQuickAffordanceConfig.LockScreenState? = null + val job = underTest.lockScreenState.onEach { latest = it }.launchIn(this) + val callbackCaptor = argumentCaptor<QRCodeScannerController.Callback>() + verify(controller).addCallback(callbackCaptor.capture()) - whenever(controller.isEnabledForLockScreenButton).thenReturn(true) - callbackCaptor.value.onQRCodeScannerPreferenceChanged() + whenever(controller.isEnabledForLockScreenButton).thenReturn(true) + callbackCaptor.value.onQRCodeScannerPreferenceChanged() - assertVisibleState(latest) + assertVisibleState(latest) - job.cancel() - verify(controller).removeCallback(callbackCaptor.value) - } + job.cancel() + verify(controller).removeCallback(callbackCaptor.value) + } @Test - fun affordance_scannerPreferenceChanged_deliversNone() = runBlockingTest { + fun affordance_scannerPreferenceChanged_deliversNone() = runTest(UnconfinedTestDispatcher()) { var latest: KeyguardQuickAffordanceConfig.LockScreenState? = null val job = underTest.lockScreenState.onEach { latest = it }.launchIn(this) val callbackCaptor = argumentCaptor<QRCodeScannerController.Callback>() @@ -128,30 +131,29 @@ class QrCodeScannerKeyguardQuickAffordanceConfigTest : SysuiTestCase() { fun onQuickAffordanceTriggered() { assertThat(underTest.onTriggered(mock())) .isEqualTo( - OnTriggeredResult.StartActivity( - intent = INTENT_1, - canShowWhileLocked = true, - ) + OnTriggeredResult.StartActivity(intent = INTENT_1, canShowWhileLocked = true) ) } @Test - fun getPickerScreenState_enabledIfConfiguredOnDevice_isEnabledForPickerState() = runTest { - whenever(controller.isAllowedOnLockScreen).thenReturn(true) - whenever(controller.isAbleToLaunchScannerActivity).thenReturn(true) + fun getPickerScreenState_enabledIfConfiguredOnDevice_isEnabledForPickerState() = + runTest(UnconfinedTestDispatcher()) { + whenever(controller.isAllowedOnLockScreen).thenReturn(true) + whenever(controller.isAbleToLaunchScannerActivity).thenReturn(true) - assertThat(underTest.getPickerScreenState()) - .isEqualTo(KeyguardQuickAffordanceConfig.PickerScreenState.Default()) - } + assertThat(underTest.getPickerScreenState()) + .isEqualTo(KeyguardQuickAffordanceConfig.PickerScreenState.Default()) + } @Test - fun getPickerScreenState_disabledIfConfiguredOnDevice_isDisabledForPickerState() = runTest { - whenever(controller.isAllowedOnLockScreen).thenReturn(true) - whenever(controller.isAbleToLaunchScannerActivity).thenReturn(false) - - assertThat(underTest.getPickerScreenState()) - .isEqualTo(KeyguardQuickAffordanceConfig.PickerScreenState.UnavailableOnDevice) - } + fun getPickerScreenState_disabledIfConfiguredOnDevice_isDisabledForPickerState() = + runTest(UnconfinedTestDispatcher()) { + whenever(controller.isAllowedOnLockScreen).thenReturn(true) + whenever(controller.isAbleToLaunchScannerActivity).thenReturn(false) + + assertThat(underTest.getPickerScreenState()) + .isEqualTo(KeyguardQuickAffordanceConfig.PickerScreenState.UnavailableOnDevice) + } private fun assertVisibleState(latest: KeyguardQuickAffordanceConfig.LockScreenState?) { assertThat(latest) diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/WindowManagerLockscreenVisibilityInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/WindowManagerLockscreenVisibilityInteractorTest.kt index 2c12f8782ddc..e60a52c12c0b 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/WindowManagerLockscreenVisibilityInteractorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/WindowManagerLockscreenVisibilityInteractorTest.kt @@ -24,6 +24,7 @@ import com.android.systemui.authentication.data.repository.FakeAuthenticationRep import com.android.systemui.authentication.domain.interactor.authenticationInteractor import com.android.systemui.coroutines.collectLastValue import com.android.systemui.coroutines.collectValues +import com.android.systemui.deviceentry.domain.interactor.deviceEntryInteractor import com.android.systemui.deviceentry.domain.interactor.deviceUnlockedInteractor import com.android.systemui.flags.DisableSceneContainer import com.android.systemui.flags.EnableSceneContainer @@ -34,10 +35,12 @@ import com.android.systemui.keyguard.shared.model.SuccessFingerprintAuthenticati import com.android.systemui.keyguard.shared.model.TransitionState import com.android.systemui.keyguard.shared.model.TransitionStep import com.android.systemui.kosmos.testScope +import com.android.systemui.scene.data.model.asIterable +import com.android.systemui.scene.data.model.sceneStackOf import com.android.systemui.scene.data.repository.Idle import com.android.systemui.scene.data.repository.Transition -import com.android.systemui.scene.data.repository.sceneContainerRepository import com.android.systemui.scene.data.repository.setSceneTransition +import com.android.systemui.scene.domain.interactor.sceneBackInteractor import com.android.systemui.scene.domain.interactor.sceneInteractor import com.android.systemui.scene.shared.model.Scenes import com.android.systemui.testKosmos @@ -85,7 +88,7 @@ class WindowManagerLockscreenVisibilityInteractorTest : SysuiTestCase() { fun setUp() { // lazy value needs to be called here otherwise flow collection misbehaves underTest.value - kosmos.sceneContainerRepository.setTransitionState(sceneTransitions) + kosmos.setSceneTransition(ObservableTransitionState.Idle(Scenes.Lockscreen)) } @Test @@ -967,15 +970,56 @@ class WindowManagerLockscreenVisibilityInteractorTest : SysuiTestCase() { @Test @EnableSceneContainer + fun lockscreenVisibilityWithScenes_staysTrue_despiteEnteringIndirectly() = + testScope.runTest { + val isDeviceUnlocked by + collectLastValue( + kosmos.deviceUnlockedInteractor.deviceUnlockStatus.map { it.isUnlocked } + ) + assertThat(isDeviceUnlocked).isFalse() + + val currentScene by collectLastValue(kosmos.sceneInteractor.currentScene) + assertThat(currentScene).isEqualTo(Scenes.Lockscreen) + + val lockscreenVisibility by collectLastValue(underTest.value.lockscreenVisibility) + assertThat(lockscreenVisibility).isTrue() + + kosmos.setSceneTransition(Idle(Scenes.Shade)) + kosmos.sceneInteractor.changeScene(Scenes.Shade, "") + kosmos.sceneBackInteractor.onSceneChange(from = Scenes.Lockscreen, to = Scenes.Shade) + assertThat(currentScene).isEqualTo(Scenes.Shade) + assertThat(lockscreenVisibility).isTrue() + val sceneBackStack by collectLastValue(kosmos.sceneBackInteractor.backStack) + assertThat(sceneBackStack?.asIterable()?.toList()).isEqualTo(listOf(Scenes.Lockscreen)) + + val isDeviceEntered by collectLastValue(kosmos.deviceEntryInteractor.isDeviceEntered) + val isDeviceEnteredDirectly by + collectLastValue(kosmos.deviceEntryInteractor.isDeviceEnteredDirectly) + runCurrent() + assertThat(isDeviceEntered).isFalse() + assertThat(isDeviceEnteredDirectly).isFalse() + + kosmos.authenticationInteractor.authenticate(FakeAuthenticationRepository.DEFAULT_PIN) + kosmos.sceneBackInteractor.updateBackStack { sceneStackOf(Scenes.Gone) } + assertThat(sceneBackStack?.asIterable()?.toList()).isEqualTo(listOf(Scenes.Gone)) + + assertThat(isDeviceEntered).isTrue() + assertThat(isDeviceEnteredDirectly).isFalse() + assertThat(isDeviceUnlocked).isTrue() + assertThat(lockscreenVisibility).isTrue() + } + + @Test + @EnableSceneContainer fun sceneContainer_usingGoingAwayAnimation_duringTransitionToGone() = testScope.runTest { val usingKeyguardGoingAwayAnimation by collectLastValue(underTest.value.usingKeyguardGoingAwayAnimation) - sceneTransitions.value = lsToGone + kosmos.setSceneTransition(lsToGone) assertThat(usingKeyguardGoingAwayAnimation).isTrue() - sceneTransitions.value = ObservableTransitionState.Idle(Scenes.Gone) + kosmos.setSceneTransition(ObservableTransitionState.Idle(Scenes.Gone)) assertThat(usingKeyguardGoingAwayAnimation).isFalse() } @@ -986,14 +1030,14 @@ class WindowManagerLockscreenVisibilityInteractorTest : SysuiTestCase() { val usingKeyguardGoingAwayAnimation by collectLastValue(underTest.value.usingKeyguardGoingAwayAnimation) - sceneTransitions.value = lsToGone + kosmos.setSceneTransition(lsToGone) surfaceBehindIsAnimatingFlow.emit(true) assertThat(usingKeyguardGoingAwayAnimation).isTrue() - sceneTransitions.value = ObservableTransitionState.Idle(Scenes.Gone) + kosmos.setSceneTransition(ObservableTransitionState.Idle(Scenes.Gone)) assertThat(usingKeyguardGoingAwayAnimation).isTrue() - sceneTransitions.value = goneToLs + kosmos.setSceneTransition(goneToLs) assertThat(usingKeyguardGoingAwayAnimation).isTrue() surfaceBehindIsAnimatingFlow.emit(false) @@ -1003,11 +1047,6 @@ class WindowManagerLockscreenVisibilityInteractorTest : SysuiTestCase() { companion object { private val progress = MutableStateFlow(0f) - private val sceneTransitions = - MutableStateFlow<ObservableTransitionState>( - ObservableTransitionState.Idle(Scenes.Lockscreen) - ) - private val lsToGone = ObservableTransitionState.Transition( Scenes.Lockscreen, diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenUserActionsViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenUserActionsViewModelTest.kt index 5c4b7432e18d..62cc76345c87 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenUserActionsViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenUserActionsViewModelTest.kt @@ -32,12 +32,11 @@ import com.android.systemui.Flags import com.android.systemui.SysuiTestCase import com.android.systemui.authentication.data.repository.fakeAuthenticationRepository import com.android.systemui.authentication.shared.model.AuthenticationMethodModel -import com.android.systemui.communal.domain.interactor.communalInteractor import com.android.systemui.communal.domain.interactor.setCommunalAvailable import com.android.systemui.coroutines.collectLastValue import com.android.systemui.deviceentry.data.repository.fakeDeviceEntryRepository -import com.android.systemui.deviceentry.domain.interactor.deviceEntryInteractor import com.android.systemui.flags.EnableSceneContainer +import com.android.systemui.keyguard.data.repository.keyguardOcclusionRepository import com.android.systemui.kosmos.testScope import com.android.systemui.lifecycle.activateIn import com.android.systemui.power.data.repository.fakePowerRepository @@ -48,7 +47,6 @@ import com.android.systemui.scene.shared.model.Scenes import com.android.systemui.scene.shared.model.TransitionKeys import com.android.systemui.scene.ui.viewmodel.SceneContainerEdge import com.android.systemui.shade.data.repository.shadeRepository -import com.android.systemui.shade.domain.interactor.shadeInteractor import com.android.systemui.testKosmos import com.google.common.truth.Truth.assertThat import kotlin.math.pow @@ -69,12 +67,13 @@ import platform.test.runner.parameterized.Parameters class LockscreenUserActionsViewModelTest : SysuiTestCase() { companion object { - private const val parameterCount = 6 + private const val parameterCount = 7 @Parameters( name = "canSwipeToEnter={0}, downWithTwoPointers={1}, downFromEdge={2}," + - " isSingleShade={3}, isCommunalAvailable={4}, isShadeTouchable={5}" + " isSingleShade={3}, isCommunalAvailable={4}, isShadeTouchable={5}," + + " isOccluded={6}" ) @JvmStatic fun combinations() = buildList { @@ -87,6 +86,7 @@ class LockscreenUserActionsViewModelTest : SysuiTestCase() { /* isSingleShade= */ combination and 8 != 0, /* isCommunalAvailable= */ combination and 16 != 0, /* isShadeTouchable= */ combination and 32 != 0, + /* isOccluded= */ combination and 64 != 0, ) .also { check(it.size == parameterCount) } ) @@ -116,10 +116,12 @@ class LockscreenUserActionsViewModelTest : SysuiTestCase() { downFromEdge: Boolean, isNarrowScreen: Boolean, isShadeTouchable: Boolean, + isOccluded: Boolean, ): SceneKey? { return when { !isShadeTouchable -> null - downFromEdge && isNarrowScreen -> Scenes.QuickSettings + downFromEdge && isNarrowScreen && !isOccluded -> Scenes.QuickSettings + downFromEdge && isNarrowScreen && isOccluded -> null else -> Scenes.Shade } } @@ -168,8 +170,9 @@ class LockscreenUserActionsViewModelTest : SysuiTestCase() { @JvmField @Parameter(3) var isNarrowScreen: Boolean = true @JvmField @Parameter(4) var isCommunalAvailable: Boolean = false @JvmField @Parameter(5) var isShadeTouchable: Boolean = false + @JvmField @Parameter(6) var isOccluded: Boolean = false - private val underTest by lazy { createLockscreenSceneViewModel() } + private val underTest by lazy { kosmos.lockscreenUserActionsViewModel } @Test @EnableFlags(Flags.FLAG_COMMUNAL_HUB) @@ -196,6 +199,7 @@ class LockscreenUserActionsViewModelTest : SysuiTestCase() { WakefulnessState.ASLEEP } ) + kosmos.keyguardOcclusionRepository.setShowWhenLockedActivityInfo(onTop = isOccluded) val userActions by collectLastValue(underTest.actions) val downDestination = @@ -217,6 +221,7 @@ class LockscreenUserActionsViewModelTest : SysuiTestCase() { downFromEdge = downFromEdge, isNarrowScreen = isNarrowScreen, isShadeTouchable = isShadeTouchable, + isOccluded = isOccluded, ) ) @@ -285,6 +290,7 @@ class LockscreenUserActionsViewModelTest : SysuiTestCase() { WakefulnessState.ASLEEP } ) + kosmos.keyguardOcclusionRepository.setShowWhenLockedActivityInfo(onTop = isOccluded) val userActions by collectLastValue(underTest.actions) @@ -354,12 +360,4 @@ class LockscreenUserActionsViewModelTest : SysuiTestCase() { ) ) } - - private fun createLockscreenSceneViewModel(): LockscreenUserActionsViewModel { - return LockscreenUserActionsViewModel( - deviceEntryInteractor = kosmos.deviceEntryInteractor, - communalInteractor = kosmos.communalInteractor, - shadeInteractor = kosmos.shadeInteractor, - ) - } } diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/mediaprojection/data/repository/MediaProjectionManagerRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/mediaprojection/data/repository/MediaProjectionManagerRepositoryTest.kt index 02825a55923f..ff00bfb540c6 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/mediaprojection/data/repository/MediaProjectionManagerRepositoryTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/mediaprojection/data/repository/MediaProjectionManagerRepositoryTest.kt @@ -18,6 +18,7 @@ package com.android.systemui.mediaprojection.data.repository import android.hardware.display.displayManager import android.media.projection.MediaProjectionInfo +import android.media.projection.StopReason import android.os.Binder import android.os.Handler import android.os.UserHandle @@ -339,8 +340,9 @@ class MediaProjectionManagerRepositoryTest : SysuiTestCase() { @Test fun stopProjecting_invokesManager() = testScope.runTest { - repo.stopProjecting() + repo.stopProjecting(StopReason.STOP_QS_TILE) - verify(fakeMediaProjectionManager.mediaProjectionManager).stopActiveProjection() + verify(fakeMediaProjectionManager.mediaProjectionManager) + .stopActiveProjection(StopReason.STOP_QS_TILE) } } diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/ui/compose/selection/MutableSelectionStateTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/ui/compose/selection/MutableSelectionStateTest.kt index 4acf3ee7878b..645efae16b8b 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/ui/compose/selection/MutableSelectionStateTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/ui/compose/selection/MutableSelectionStateTest.kt @@ -27,7 +27,7 @@ import org.junit.runner.RunWith @SmallTest @RunWith(AndroidJUnit4::class) class MutableSelectionStateTest : SysuiTestCase() { - private val underTest = MutableSelectionState({}, {}) + private val underTest = MutableSelectionState() @Test fun selectTile_isCorrectlySelected() { @@ -48,120 +48,6 @@ class MutableSelectionStateTest : SysuiTestCase() { assertThat(underTest.selection?.manual).isFalse() } - @Test - fun startResize_createsResizingState() { - assertThat(underTest.resizingState).isNull() - - // Resizing starts but no tile is selected - underTest.onResizingDragStart(TileWidths(0, 0, 1)) - assertThat(underTest.resizingState).isNull() - - // Resizing starts with a selected tile - underTest.select(TEST_SPEC, manual = true) - underTest.onResizingDragStart(TileWidths(0, 0, 1)) - - assertThat(underTest.resizingState).isNotNull() - } - - @Test - fun endResize_clearsResizingState() { - val spec = TileSpec.create("testSpec") - - // Resizing starts with a selected tile - underTest.select(spec, manual = true) - underTest.onResizingDragStart(TileWidths(base = 0, min = 0, max = 10)) - assertThat(underTest.resizingState).isNotNull() - - underTest.onResizingDragEnd() - assertThat(underTest.resizingState).isNull() - } - - @Test - fun unselect_clearsResizingState() { - // Resizing starts with a selected tile - underTest.select(TEST_SPEC, manual = true) - underTest.onResizingDragStart(TileWidths(base = 0, min = 0, max = 10)) - assertThat(underTest.resizingState).isNotNull() - - underTest.unSelect() - assertThat(underTest.resizingState).isNull() - } - - @Test - fun onResizingDrag_updatesResizingState() { - // Resizing starts with a selected tile - underTest.select(TEST_SPEC, manual = true) - underTest.onResizingDragStart(TileWidths(base = 0, min = 0, max = 10)) - assertThat(underTest.resizingState).isNotNull() - - underTest.onResizingDrag(5f) - assertThat(underTest.resizingState?.width).isEqualTo(5) - - underTest.onResizingDrag(2f) - assertThat(underTest.resizingState?.width).isEqualTo(7) - - underTest.onResizingDrag(-6f) - assertThat(underTest.resizingState?.width).isEqualTo(1) - } - - @Test - fun onResizingDrag_receivesResizeCallback() { - var resized = false - val onResize: (TileSpec) -> Unit = { - assertThat(it).isEqualTo(TEST_SPEC) - resized = !resized - } - val underTest = MutableSelectionState(onResize = onResize, {}) - - // Resizing starts with a selected tile - underTest.select(TEST_SPEC, true) - underTest.onResizingDragStart(TileWidths(base = 0, min = 0, max = 10)) - assertThat(underTest.resizingState).isNotNull() - - // Drag under the threshold - underTest.onResizingDrag(1f) - assertThat(resized).isFalse() - - // Drag over the threshold - underTest.onResizingDrag(5f) - assertThat(resized).isTrue() - - // Drag back under the threshold - underTest.onResizingDrag(-5f) - assertThat(resized).isFalse() - } - - @Test - fun onResizingEnded_receivesResizeEndCallback() { - var resizeEnded = false - val onResizeEnd: (TileSpec) -> Unit = { resizeEnded = true } - val underTest = MutableSelectionState({}, onResizeEnd = onResizeEnd) - - // Resizing starts with a selected tile - underTest.select(TEST_SPEC, true) - underTest.onResizingDragStart(TileWidths(base = 0, min = 0, max = 10)) - - underTest.onResizingDragEnd() - assertThat(resizeEnded).isTrue() - } - - @Test - fun onResizingEnded_setsSelectionAutomatically() { - val underTest = MutableSelectionState({}, {}) - - // Resizing starts with a selected tile - underTest.select(TEST_SPEC, manual = true) - underTest.onResizingDragStart(TileWidths(base = 0, min = 0, max = 10)) - - // Assert the selection was manual - assertThat(underTest.selection?.manual).isTrue() - - underTest.onResizingDragEnd() - - // Assert the selection is no longer manual due to the resizing - assertThat(underTest.selection?.manual).isFalse() - } - companion object { private val TEST_SPEC = TileSpec.create("testSpec") } diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/ui/compose/selection/ResizingStateTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/ui/compose/selection/ResizingStateTest.kt index 6e66783da44e..2206f4dcf5a8 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/ui/compose/selection/ResizingStateTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/ui/compose/selection/ResizingStateTest.kt @@ -19,7 +19,9 @@ package com.android.systemui.qs.panels.ui.compose.selection import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase +import com.android.systemui.qs.pipeline.shared.TileSpec import com.google.common.truth.Truth.assertThat +import kotlinx.coroutines.test.runTest import org.junit.Test import org.junit.runner.RunWith @@ -27,36 +29,32 @@ import org.junit.runner.RunWith @RunWith(AndroidJUnit4::class) class ResizingStateTest : SysuiTestCase() { - @Test - fun drag_updatesStateCorrectly() { - var resized = false - val underTest = - ResizingState(TileWidths(base = 0, min = 0, max = 10)) { resized = !resized } - - assertThat(underTest.width).isEqualTo(0) + private val underTest = + ResizingState(TileSpec.create("a"), startsAsIcon = true).apply { updateAnchors(10f, 20f) } - underTest.onDrag(2f) - assertThat(underTest.width).isEqualTo(2) - - underTest.onDrag(1f) - assertThat(underTest.width).isEqualTo(3) - assertThat(resized).isTrue() + @Test + fun newResizingState_setInitialValueCorrectly() { + assertThat(underTest.anchoredDraggableState.currentValue).isEqualTo(QSDragAnchor.Icon) + } - underTest.onDrag(-1f) - assertThat(underTest.width).isEqualTo(2) - assertThat(resized).isFalse() + @Test + fun updateAnchors_setBoundsCorrectly() { + assertThat(underTest.bounds).isEqualTo(10f to 20f) } @Test - fun dragOutOfBounds_isClampedCorrectly() { - val underTest = ResizingState(TileWidths(base = 0, min = 0, max = 10)) {} + fun dragOverThreshold_resizesToLarge() = runTest { + underTest.anchoredDraggableState.anchoredDrag { dragTo(16f) } - assertThat(underTest.width).isEqualTo(0) + assertThat(underTest.temporaryResizeOperation.spec).isEqualTo(TileSpec.create("a")) + assertThat(underTest.temporaryResizeOperation.toIcon).isFalse() + } - underTest.onDrag(100f) - assertThat(underTest.width).isEqualTo(10) + @Test + fun dragUnderThreshold_staysIcon() = runTest { + underTest.anchoredDraggableState.anchoredDrag { dragTo(12f) } - underTest.onDrag(-200f) - assertThat(underTest.width).isEqualTo(0) + assertThat(underTest.temporaryResizeOperation.spec).isEqualTo(TileSpec.create("a")) + assertThat(underTest.temporaryResizeOperation.toIcon).isTrue() } } diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/ui/viewmodel/EditModeButtonViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/ui/viewmodel/EditModeButtonViewModelTest.kt new file mode 100644 index 000000000000..f2bfd729f74a --- /dev/null +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/ui/viewmodel/EditModeButtonViewModelTest.kt @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.qs.panels.ui.viewmodel + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.filters.SmallTest +import com.android.systemui.SysuiTestCase +import com.android.systemui.classifier.fakeFalsingManager +import com.android.systemui.kosmos.collectLastValue +import com.android.systemui.kosmos.runCurrent +import com.android.systemui.kosmos.runTest +import com.android.systemui.testKosmos +import com.google.common.truth.Truth.assertThat +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +@SmallTest +class EditModeButtonViewModelTest : SysuiTestCase() { + val kosmos = testKosmos() + + val underTest = kosmos.editModeButtonViewModelFactory.create() + + @Test + fun falsingFalseTap_editModeDoesntStart() = + kosmos.runTest { + val isEditing by collectLastValue(editModeViewModel.isEditing) + + fakeFalsingManager.setFalseTap(true) + + underTest.onButtonClick() + runCurrent() + + assertThat(isEditing).isFalse() + } + + @Test + fun falsingNotFalseTap_editModeStarted() = + kosmos.runTest { + val isEditing by collectLastValue(editModeViewModel.isEditing) + + fakeFalsingManager.setFalseTap(false) + + underTest.onButtonClick() + runCurrent() + + assertThat(isEditing).isTrue() + } +} diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/interactor/DisabledContentInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/interactor/DisabledContentInteractorTest.kt new file mode 100644 index 000000000000..08225a7770d2 --- /dev/null +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/interactor/DisabledContentInteractorTest.kt @@ -0,0 +1,145 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.scene.domain.interactor + +import android.app.StatusBarManager +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.filters.SmallTest +import com.android.compose.animation.scene.Swipe +import com.android.compose.animation.scene.UserAction +import com.android.compose.animation.scene.UserActionResult +import com.android.systemui.SysuiTestCase +import com.android.systemui.kosmos.applicationCoroutineScope +import com.android.systemui.kosmos.collectLastValue +import com.android.systemui.kosmos.runTest +import com.android.systemui.kosmos.useUnconfinedTestDispatcher +import com.android.systemui.scene.shared.model.Overlays +import com.android.systemui.statusbar.disableflags.data.repository.fakeDisableFlagsRepository +import com.android.systemui.statusbar.disableflags.shared.model.DisableFlagsModel +import com.android.systemui.testKosmos +import com.google.common.truth.Truth.assertThat +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.launch +import org.junit.Test +import org.junit.runner.RunWith + +@SmallTest +@RunWith(AndroidJUnit4::class) +class DisabledContentInteractorTest : SysuiTestCase() { + + private val kosmos = testKosmos().useUnconfinedTestDispatcher() + + private val underTest = kosmos.disabledContentInteractor + + @Test + fun isDisabled_notificationsShade() = + kosmos.runTest { + fakeDisableFlagsRepository.disableFlags.value = + DisableFlagsModel(disable2 = StatusBarManager.DISABLE2_NONE) + assertThat(underTest.isDisabled(Overlays.NotificationsShade)).isFalse() + + fakeDisableFlagsRepository.disableFlags.value = + DisableFlagsModel(disable2 = StatusBarManager.DISABLE2_NOTIFICATION_SHADE) + assertThat(underTest.isDisabled(Overlays.NotificationsShade)).isTrue() + } + + @Test + fun isDisabled_qsShade() = + kosmos.runTest { + fakeDisableFlagsRepository.disableFlags.value = + DisableFlagsModel(disable2 = StatusBarManager.DISABLE2_NONE) + assertThat(underTest.isDisabled(Overlays.QuickSettingsShade)).isFalse() + + fakeDisableFlagsRepository.disableFlags.value = + DisableFlagsModel(disable2 = StatusBarManager.DISABLE2_QUICK_SETTINGS) + assertThat(underTest.isDisabled(Overlays.QuickSettingsShade)).isTrue() + } + + @Test + fun repeatWhenDisabled() = + kosmos.runTest { + var notificationDisabledCount = 0 + applicationCoroutineScope.launch { + underTest.repeatWhenDisabled(Overlays.NotificationsShade) { + notificationDisabledCount++ + } + } + var qsDisabledCount = 0 + applicationCoroutineScope.launch { + underTest.repeatWhenDisabled(Overlays.QuickSettingsShade) { qsDisabledCount++ } + } + + fakeDisableFlagsRepository.disableFlags.value = + DisableFlagsModel(disable2 = StatusBarManager.DISABLE2_QUICK_SETTINGS) + assertThat(notificationDisabledCount).isEqualTo(0) + assertThat(qsDisabledCount).isEqualTo(1) + + fakeDisableFlagsRepository.disableFlags.value = + DisableFlagsModel( + disable2 = + StatusBarManager.DISABLE2_NOTIFICATION_SHADE or + StatusBarManager.DISABLE2_QUICK_SETTINGS + ) + assertThat(notificationDisabledCount).isEqualTo(1) + assertThat(qsDisabledCount).isEqualTo(1) + + fakeDisableFlagsRepository.disableFlags.value = + DisableFlagsModel(disable2 = StatusBarManager.DISABLE2_NOTIFICATION_SHADE) + assertThat(notificationDisabledCount).isEqualTo(1) + assertThat(qsDisabledCount).isEqualTo(1) + + fakeDisableFlagsRepository.disableFlags.value = + DisableFlagsModel(disable2 = StatusBarManager.DISABLE2_QUICK_SETTINGS) + assertThat(notificationDisabledCount).isEqualTo(1) + assertThat(qsDisabledCount).isEqualTo(2) + } + + @Test + fun filteredUserActions() = + kosmos.runTest { + val map = + mapOf<UserAction, UserActionResult>( + Swipe.Up to UserActionResult.ShowOverlay(Overlays.NotificationsShade), + Swipe.Down to UserActionResult.ShowOverlay(Overlays.QuickSettingsShade), + ) + val unfiltered = MutableStateFlow(map) + val filtered by collectLastValue(underTest.filteredUserActions(unfiltered)) + assertThat(filtered).isEqualTo(map) + + fakeDisableFlagsRepository.disableFlags.value = + DisableFlagsModel(disable2 = StatusBarManager.DISABLE2_NOTIFICATION_SHADE) + assertThat(filtered) + .isEqualTo( + mapOf(Swipe.Down to UserActionResult.ShowOverlay(Overlays.QuickSettingsShade)) + ) + + fakeDisableFlagsRepository.disableFlags.value = + DisableFlagsModel(disable2 = StatusBarManager.DISABLE2_QUICK_SETTINGS) + assertThat(filtered) + .isEqualTo( + mapOf(Swipe.Up to UserActionResult.ShowOverlay(Overlays.NotificationsShade)) + ) + + fakeDisableFlagsRepository.disableFlags.value = + DisableFlagsModel( + disable2 = + StatusBarManager.DISABLE2_NOTIFICATION_SHADE or + StatusBarManager.DISABLE2_QUICK_SETTINGS + ) + assertThat(filtered).isEqualTo(emptyMap<UserAction, UserActionResult>()) + } +} diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/interactor/SceneInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/interactor/SceneInteractorTest.kt index 7fe3d8d08afa..48edded5df18 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/interactor/SceneInteractorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/interactor/SceneInteractorTest.kt @@ -18,6 +18,7 @@ package com.android.systemui.scene.domain.interactor +import android.app.StatusBarManager import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.compose.animation.scene.ObservableTransitionState @@ -30,6 +31,8 @@ import com.android.systemui.flags.EnableSceneContainer import com.android.systemui.keyguard.data.repository.fakeDeviceEntryFingerprintAuthRepository import com.android.systemui.keyguard.domain.interactor.keyguardEnabledInteractor import com.android.systemui.keyguard.shared.model.SuccessFingerprintAuthenticationStatus +import com.android.systemui.kosmos.collectLastValue +import com.android.systemui.kosmos.runTest import com.android.systemui.kosmos.testScope import com.android.systemui.scene.data.repository.Idle import com.android.systemui.scene.data.repository.Transition @@ -43,6 +46,8 @@ import com.android.systemui.scene.shared.model.Overlays import com.android.systemui.scene.shared.model.SceneFamilies import com.android.systemui.scene.shared.model.Scenes import com.android.systemui.scene.shared.model.fakeSceneDataSource +import com.android.systemui.statusbar.disableflags.data.repository.fakeDisableFlagsRepository +import com.android.systemui.statusbar.disableflags.shared.model.DisableFlagsModel import com.android.systemui.testKosmos import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.ExperimentalCoroutinesApi @@ -523,4 +528,51 @@ class SceneInteractorTest : SysuiTestCase() { assertThat(currentScene).isEqualTo(Scenes.Gone) } + + @Test + fun showOverlay_overlayDisabled_doesNothing() = + kosmos.runTest { + val currentOverlays by collectLastValue(underTest.currentOverlays) + val disabledOverlay = Overlays.QuickSettingsShade + fakeDisableFlagsRepository.disableFlags.value = + DisableFlagsModel(disable2 = StatusBarManager.DISABLE2_QUICK_SETTINGS) + assertThat(disabledContentInteractor.isDisabled(disabledOverlay)).isTrue() + assertThat(currentOverlays).doesNotContain(disabledOverlay) + + underTest.showOverlay(disabledOverlay, "reason") + + assertThat(currentOverlays).doesNotContain(disabledOverlay) + } + + @Test + fun replaceOverlay_withDisabledOverlay_doesNothing() = + kosmos.runTest { + val currentOverlays by collectLastValue(underTest.currentOverlays) + val showingOverlay = Overlays.NotificationsShade + underTest.showOverlay(showingOverlay, "reason") + assertThat(currentOverlays).isEqualTo(setOf(showingOverlay)) + val disabledOverlay = Overlays.QuickSettingsShade + fakeDisableFlagsRepository.disableFlags.value = + DisableFlagsModel(disable2 = StatusBarManager.DISABLE2_QUICK_SETTINGS) + assertThat(disabledContentInteractor.isDisabled(disabledOverlay)).isTrue() + + underTest.replaceOverlay(showingOverlay, disabledOverlay, "reason") + + assertThat(currentOverlays).isEqualTo(setOf(showingOverlay)) + } + + @Test + fun changeScene_toDisabledScene_doesNothing() = + kosmos.runTest { + val currentScene by collectLastValue(underTest.currentScene) + val disabledScene = Scenes.Shade + fakeDisableFlagsRepository.disableFlags.value = + DisableFlagsModel(disable2 = StatusBarManager.DISABLE2_NOTIFICATION_SHADE) + assertThat(disabledContentInteractor.isDisabled(disabledScene)).isTrue() + assertThat(currentScene).isNotEqualTo(disabledScene) + + underTest.changeScene(disabledScene, "reason") + + assertThat(currentScene).isNotEqualTo(disabledScene) + } } diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt index cca847effe94..5d49c113a539 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt @@ -81,6 +81,9 @@ import com.android.systemui.keyguard.domain.interactor.scenetransition.lockscree import com.android.systemui.keyguard.shared.model.FailFingerprintAuthenticationStatus import com.android.systemui.keyguard.shared.model.KeyguardState import com.android.systemui.keyguard.shared.model.SuccessFingerprintAuthenticationStatus +import com.android.systemui.kosmos.collectLastValue +import com.android.systemui.kosmos.runCurrent +import com.android.systemui.kosmos.runTest import com.android.systemui.kosmos.testScope import com.android.systemui.model.sysUiState import com.android.systemui.power.data.repository.fakePowerRepository @@ -101,6 +104,8 @@ import com.android.systemui.shade.domain.interactor.shadeInteractor import com.android.systemui.shade.shared.flag.DualShade import com.android.systemui.shared.system.QuickStepContract import com.android.systemui.statusbar.VibratorHelper +import com.android.systemui.statusbar.disableflags.data.repository.fakeDisableFlagsRepository +import com.android.systemui.statusbar.disableflags.shared.model.DisableFlagsModel import com.android.systemui.statusbar.domain.interactor.keyguardOcclusionInteractor import com.android.systemui.statusbar.notification.data.repository.FakeHeadsUpRowRepository import com.android.systemui.statusbar.notification.data.repository.HeadsUpRowRepository @@ -2673,6 +2678,25 @@ class SceneContainerStartableTest : SysuiTestCase() { assertThat(isAlternateBouncerVisible).isFalse() } + @Test + fun handleDisableFlags() = + kosmos.runTest { + underTest.start() + val currentScene by collectLastValue(sceneInteractor.currentScene) + val currentOverlays by collectLastValue(sceneInteractor.currentOverlays) + sceneInteractor.changeScene(Scenes.Shade, "reason") + sceneInteractor.showOverlay(Overlays.NotificationsShade, "reason") + assertThat(currentScene).isEqualTo(Scenes.Shade) + assertThat(currentOverlays).contains(Overlays.NotificationsShade) + + fakeDisableFlagsRepository.disableFlags.value = + DisableFlagsModel(disable2 = StatusBarManager.DISABLE2_NOTIFICATION_SHADE) + runCurrent() + + assertThat(currentScene).isNotEqualTo(Scenes.Shade) + assertThat(currentOverlays).isEmpty() + } + private fun TestScope.emulateSceneTransition( transitionStateFlow: MutableStateFlow<ObservableTransitionState>, toScene: SceneKey, diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeDisplaysInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeDisplaysInteractorTest.kt index 8ef1e568cd58..016a24acd461 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeDisplaysInteractorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeDisplaysInteractorTest.kt @@ -17,6 +17,7 @@ package com.android.systemui.shade.domain.interactor import android.content.Context +import android.content.MutableContextWrapper import android.content.res.Configuration import android.content.res.Resources import android.view.Display @@ -30,6 +31,7 @@ import com.android.systemui.display.shared.model.DisplayWindowProperties import com.android.systemui.scene.ui.view.WindowRootView import com.android.systemui.shade.data.repository.FakeShadeDisplayRepository import com.android.systemui.statusbar.phone.ConfigurationForwarder +import java.util.Optional import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.UnconfinedTestDispatcher @@ -64,13 +66,14 @@ class ShadeDisplaysInteractorTest : SysuiTestCase() { private val interactor = ShadeDisplaysInteractor( - shadeRootview, + Optional.of(shadeRootview), positionRepository, - defaultContext, + MutableContextWrapper(defaultContext), + resources, contextStore, - testScope, + testScope.backgroundScope, configurationForwarder, - testScope.coroutineContext, + testScope.backgroundScope.coroutineContext, ) @Before @@ -79,7 +82,6 @@ class ShadeDisplaysInteractorTest : SysuiTestCase() { whenever(display.displayId).thenReturn(0) whenever(resources.configuration).thenReturn(configuration) - whenever(resources.configuration).thenReturn(configuration) whenever(defaultContext.displayId).thenReturn(0) whenever(defaultContext.getSystemService(any())).thenReturn(defaultWm) @@ -124,7 +126,6 @@ class ShadeDisplaysInteractorTest : SysuiTestCase() { whenever(display.displayId).thenReturn(0) positionRepository.setDisplayId(1) interactor.start() - testScope.advanceUntilIdle() verify(defaultWm).removeView(eq(shadeRootview)) verify(secondaryWm).addView(eq(shadeRootview), any()) @@ -135,10 +136,8 @@ class ShadeDisplaysInteractorTest : SysuiTestCase() { whenever(display.displayId).thenReturn(0) positionRepository.setDisplayId(0) interactor.start() - testScope.advanceUntilIdle() positionRepository.setDisplayId(1) - testScope.advanceUntilIdle() verify(defaultWm).removeView(eq(shadeRootview)) verify(secondaryWm).addView(eq(shadeRootview), any()) @@ -149,10 +148,8 @@ class ShadeDisplaysInteractorTest : SysuiTestCase() { whenever(display.displayId).thenReturn(0) positionRepository.setDisplayId(0) interactor.start() - testScope.advanceUntilIdle() positionRepository.setDisplayId(1) - testScope.advanceUntilIdle() verify(configurationForwarder).onConfigurationChanged(eq(configuration)) } diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/coordinator/ColorizedFgsCoordinatorTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/coordinator/ColorizedFgsCoordinatorTest.java index 1f2925528077..544d20145db3 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/coordinator/ColorizedFgsCoordinatorTest.java +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/coordinator/ColorizedFgsCoordinatorTest.java @@ -17,6 +17,7 @@ package com.android.systemui.statusbar.notification.collection.coordinator; import static android.app.Notification.FLAG_FOREGROUND_SERVICE; +import static android.app.Notification.FLAG_PROMOTED_ONGOING; import static android.app.NotificationManager.IMPORTANCE_DEFAULT; import static android.app.NotificationManager.IMPORTANCE_HIGH; import static android.app.NotificationManager.IMPORTANCE_MIN; @@ -24,12 +25,18 @@ import static android.app.NotificationManager.IMPORTANCE_MIN; import static junit.framework.Assert.assertFalse; import static junit.framework.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; + import android.app.Notification; import android.app.PendingIntent; import android.app.Person; import android.content.Intent; import android.graphics.Color; import android.os.UserHandle; +import android.platform.test.annotations.DisableFlags; +import android.platform.test.annotations.EnableFlags; import android.testing.TestableLooper; import androidx.test.ext.junit.runners.AndroidJUnit4; @@ -38,11 +45,14 @@ import androidx.test.filters.SmallTest; import com.android.systemui.SysuiTestCase; import com.android.systemui.statusbar.notification.collection.NotifPipeline; import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder; +import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifPromoter; import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifSectioner; +import com.android.systemui.statusbar.notification.promoted.PromotedNotificationUi; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.MockitoAnnotations; @@ -136,6 +146,60 @@ public class ColorizedFgsCoordinatorTest extends SysuiTestCase { assertFalse(mFgsSection.isInSection(mEntryBuilder.build())); } + @Test + @EnableFlags(PromotedNotificationUi.FLAG_NAME) + public void testIncludePromotedOngoingInSection_flagEnabled() { + // GIVEN the notification has FLAG_PROMOTED_ONGOING + mEntryBuilder.setFlag(mContext, FLAG_PROMOTED_ONGOING, true); + + // THEN the entry is in the fgs section + assertTrue(mFgsSection.isInSection(mEntryBuilder.build())); + } + + @Test + @DisableFlags(PromotedNotificationUi.FLAG_NAME) + public void testDiscludePromotedOngoingInSection_flagDisabled() { + // GIVEN the notification has FLAG_PROMOTED_ONGOING + mEntryBuilder.setFlag(mContext, FLAG_PROMOTED_ONGOING, true); + + // THEN the entry is NOT in the fgs section + assertFalse(mFgsSection.isInSection(mEntryBuilder.build())); + } + + @Test + @EnableFlags(PromotedNotificationUi.FLAG_NAME) + public void promoterSelectsPromotedOngoing_flagEnabled() { + ArgumentCaptor<NotifPromoter> captor = ArgumentCaptor.forClass(NotifPromoter.class); + verify(mNotifPipeline).addPromoter(captor.capture()); + NotifPromoter promoter = captor.getValue(); + + // GIVEN the notification has FLAG_PROMOTED_ONGOING + mEntryBuilder.setFlag(mContext, FLAG_PROMOTED_ONGOING, true); + + // THEN the entry is promoted to top level + assertTrue(promoter.shouldPromoteToTopLevel(mEntryBuilder.build())); + } + + @Test + @EnableFlags(PromotedNotificationUi.FLAG_NAME) + public void promoterIgnoresNonPromotedOngoing_flagEnabled() { + ArgumentCaptor<NotifPromoter> captor = ArgumentCaptor.forClass(NotifPromoter.class); + verify(mNotifPipeline).addPromoter(captor.capture()); + NotifPromoter promoter = captor.getValue(); + + // GIVEN the notification does not have FLAG_PROMOTED_ONGOING + mEntryBuilder.setFlag(mContext, FLAG_PROMOTED_ONGOING, false); + + // THEN the entry is NOT promoted to top level + assertFalse(promoter.shouldPromoteToTopLevel(mEntryBuilder.build())); + } + + @Test + @DisableFlags(PromotedNotificationUi.FLAG_NAME) + public void noPromoterAdded_flagDisabled() { + verify(mNotifPipeline, never()).addPromoter(any()); + } + private Notification.CallStyle makeCallStyle() { final PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0, new Intent("action"), PendingIntent.FLAG_IMMUTABLE); diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelTest.kt index a940ed4d70f9..f48fd3c998b1 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelTest.kt @@ -838,27 +838,26 @@ class SharedNotificationContainerViewModelTest(flags: FlagsParameterization) : S testScope.runTest { var notificationCount = 10 val calculateSpace = { space: Float, useExtraShelfSpace: Boolean -> notificationCount } - val maxNotifications by collectLastValue(underTest.getMaxNotifications(calculateSpace)) + val config by collectLastValue(underTest.getLockscreenDisplayConfig(calculateSpace)) advanceTimeBy(50L) showLockscreen() shadeTestUtil.setSplitShade(false) configurationRepository.onAnyConfigurationChange() - assertThat(maxNotifications).isEqualTo(10) + assertThat(config?.maxNotifications).isEqualTo(10) // Also updates when directly requested (as it would from NotificationStackScrollLayout) notificationCount = 25 sharedNotificationContainerInteractor.notificationStackChanged() advanceTimeBy(50L) - assertThat(maxNotifications).isEqualTo(25) + assertThat(config?.maxNotifications).isEqualTo(25) // Also ensure another collection starts with the same value. As an example, folding // then unfolding will restart the coroutine and it must get the last value immediately. - val newMaxNotifications by - collectLastValue(underTest.getMaxNotifications(calculateSpace)) + val newConfig by collectLastValue(underTest.getLockscreenDisplayConfig(calculateSpace)) advanceTimeBy(50L) - assertThat(newMaxNotifications).isEqualTo(25) + assertThat(newConfig?.maxNotifications).isEqualTo(25) } @Test @@ -866,18 +865,18 @@ class SharedNotificationContainerViewModelTest(flags: FlagsParameterization) : S testScope.runTest { var notificationCount = 10 val calculateSpace = { space: Float, useExtraShelfSpace: Boolean -> notificationCount } - val maxNotifications by collectLastValue(underTest.getMaxNotifications(calculateSpace)) + val config by collectLastValue(underTest.getLockscreenDisplayConfig(calculateSpace)) advanceTimeBy(50L) showLockscreen() shadeTestUtil.setSplitShade(false) configurationRepository.onAnyConfigurationChange() - assertThat(maxNotifications).isEqualTo(10) + assertThat(config?.maxNotifications).isEqualTo(10) // Shade expanding... still 10 shadeTestUtil.setLockscreenShadeExpansion(0.5f) - assertThat(maxNotifications).isEqualTo(10) + assertThat(config?.maxNotifications).isEqualTo(10) notificationCount = 25 @@ -885,20 +884,20 @@ class SharedNotificationContainerViewModelTest(flags: FlagsParameterization) : S shadeTestUtil.setLockscreenShadeTracking(true) // Should still be 10, since the user is interacting - assertThat(maxNotifications).isEqualTo(10) + assertThat(config?.maxNotifications).isEqualTo(10) shadeTestUtil.setLockscreenShadeTracking(false) shadeTestUtil.setLockscreenShadeExpansion(0f) // Stopped tracking, show 25 - assertThat(maxNotifications).isEqualTo(25) + assertThat(config?.maxNotifications).isEqualTo(25) } @Test fun maxNotificationsOnShade() = testScope.runTest { val calculateSpace = { space: Float, useExtraShelfSpace: Boolean -> 10 } - val maxNotifications by collectLastValue(underTest.getMaxNotifications(calculateSpace)) + val config by collectLastValue(underTest.getLockscreenDisplayConfig(calculateSpace)) advanceTimeBy(50L) // Show lockscreen with shade expanded @@ -908,7 +907,7 @@ class SharedNotificationContainerViewModelTest(flags: FlagsParameterization) : S configurationRepository.onAnyConfigurationChange() // -1 means No Limit - assertThat(maxNotifications).isEqualTo(-1) + assertThat(config?.maxNotifications).isEqualTo(-1) } @Test diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/MultiDisplayAutoHideControllerStoreTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/MultiDisplayAutoHideControllerStoreTest.kt new file mode 100644 index 000000000000..0b0b1e45d604 --- /dev/null +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/MultiDisplayAutoHideControllerStoreTest.kt @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.statusbar.phone + +import android.platform.test.annotations.EnableFlags +import android.view.Display.DEFAULT_DISPLAY +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.filters.SmallTest +import com.android.systemui.SysuiTestCase +import com.android.systemui.display.data.repository.displayRepository +import com.android.systemui.kosmos.testScope +import com.android.systemui.kosmos.useUnconfinedTestDispatcher +import com.android.systemui.statusbar.core.StatusBarConnectedDisplays +import com.android.systemui.testKosmos +import kotlinx.coroutines.runBlocking +import kotlinx.coroutines.test.runTest +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.kotlin.never +import org.mockito.kotlin.verify + +@SmallTest +@RunWith(AndroidJUnit4::class) +@EnableFlags(StatusBarConnectedDisplays.FLAG_NAME) +class MultiDisplayAutoHideControllerStoreTest : SysuiTestCase() { + + private val kosmos = testKosmos().useUnconfinedTestDispatcher() + private val testScope = kosmos.testScope + private val fakeDisplayRepository = kosmos.displayRepository + + // Lazy so that @EnableFlags has time to run before underTest is instantiated. + private val underTest by lazy { kosmos.multiDisplayAutoHideControllerStore } + + @Before fun addDisplays() = runBlocking { fakeDisplayRepository.addDisplay(DEFAULT_DISPLAY) } + + @Test + fun beforeDisplayRemoved_doesNotStopInstances() = + testScope.runTest { + val instance = underTest.forDisplay(DEFAULT_DISPLAY) + + verify(instance, never()).stop() + } + + @Test + fun displayRemoved_stopsInstance() = + testScope.runTest { + val instance = underTest.forDisplay(DEFAULT_DISPLAY) + + fakeDisplayRepository.removeDisplay(DEFAULT_DISPLAY) + + verify(instance).stop() + } +} diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/user/domain/interactor/GuestUserInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/user/domain/interactor/GuestUserInteractorTest.kt index 20b273ae7f4e..d5651ec8ce6c 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/user/domain/interactor/GuestUserInteractorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/user/domain/interactor/GuestUserInteractorTest.kt @@ -22,21 +22,25 @@ import android.content.Context import android.content.pm.UserInfo import android.os.UserHandle import android.os.UserManager +import android.testing.TestableLooper import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.internal.logging.UiEventLogger import com.android.systemui.GuestResetOrExitSessionReceiver import com.android.systemui.GuestResumeSessionReceiver import com.android.systemui.SysuiTestCase +import com.android.systemui.kosmos.runTest +import com.android.systemui.kosmos.testDispatcher +import com.android.systemui.kosmos.testScope +import com.android.systemui.kosmos.useUnconfinedTestDispatcher import com.android.systemui.statusbar.policy.DeviceProvisionedController +import com.android.systemui.testKosmos import com.android.systemui.user.data.repository.FakeUserRepository import com.android.systemui.user.domain.model.ShowDialogRequestModel import com.android.systemui.util.mockito.any import com.android.systemui.util.mockito.kotlinArgumentCaptor import com.android.systemui.util.mockito.whenever import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.runBlocking -import kotlinx.coroutines.test.TestCoroutineScope import org.junit.Before import org.junit.Test import org.junit.runner.RunWith @@ -48,6 +52,7 @@ import org.mockito.MockitoAnnotations @SmallTest @RunWith(AndroidJUnit4::class) +@TestableLooper.RunWithLooper class GuestUserInteractorTest : SysuiTestCase() { @Mock private lateinit var manager: UserManager @@ -64,16 +69,15 @@ class GuestUserInteractorTest : SysuiTestCase() { private lateinit var underTest: GuestUserInteractor - private lateinit var scope: TestCoroutineScope - private lateinit var repository: FakeUserRepository + private val kosmos = testKosmos().useUnconfinedTestDispatcher() + private val scope = kosmos.testScope + private val repository = FakeUserRepository() @Before fun setUp() { MockitoAnnotations.initMocks(this) whenever(manager.createGuest(any())).thenReturn(GUEST_USER_INFO) - scope = TestCoroutineScope() - repository = FakeUserRepository() repository.setUserInfos(ALL_USERS) underTest = initGuestUserInteractor(context) @@ -83,8 +87,8 @@ class GuestUserInteractorTest : SysuiTestCase() { GuestUserInteractor( applicationContext = context, applicationScope = scope, - mainDispatcher = IMMEDIATE, - backgroundDispatcher = IMMEDIATE, + mainDispatcher = kosmos.testDispatcher, + backgroundDispatcher = kosmos.testDispatcher, manager = manager, repository = repository, deviceProvisionedController = deviceProvisionedController, @@ -92,7 +96,7 @@ class GuestUserInteractorTest : SysuiTestCase() { refreshUsersScheduler = RefreshUsersScheduler( applicationScope = scope, - mainDispatcher = IMMEDIATE, + mainDispatcher = kosmos.testDispatcher, repository = repository, ), uiEventLogger = uiEventLogger, @@ -118,7 +122,7 @@ class GuestUserInteractorTest : SysuiTestCase() { @Test fun onDeviceBootCompleted_allowedToAdd_createGuest() = - runBlocking(IMMEDIATE) { + kosmos.runTest { setAllowedToAdd() underTest.onDeviceBootCompleted() @@ -129,7 +133,7 @@ class GuestUserInteractorTest : SysuiTestCase() { @Test fun onDeviceBootCompleted_awaitProvisioning_andCreateGuest() = - runBlocking(IMMEDIATE) { + kosmos.runTest { setAllowedToAdd(isAllowed = false) underTest.onDeviceBootCompleted() val captor = @@ -145,7 +149,7 @@ class GuestUserInteractorTest : SysuiTestCase() { @Test fun createAndSwitchTo() = - runBlocking(IMMEDIATE) { + kosmos.runTest { underTest.createAndSwitchTo( showDialog = showDialog, dismissDialog = dismissDialog, @@ -160,7 +164,7 @@ class GuestUserInteractorTest : SysuiTestCase() { @Test fun createAndSwitchTo_failsToCreate_doesNotSwitchTo() = - runBlocking(IMMEDIATE) { + kosmos.runTest { whenever(manager.createGuest(any())).thenReturn(null) underTest.createAndSwitchTo( @@ -177,7 +181,7 @@ class GuestUserInteractorTest : SysuiTestCase() { @Test fun exit_returnsToTargetUser() = - runBlocking(IMMEDIATE) { + kosmos.runTest { repository.setSelectedUserInfo(GUEST_USER_INFO) val targetUserId = NON_GUEST_USER_INFO.id @@ -197,7 +201,7 @@ class GuestUserInteractorTest : SysuiTestCase() { @Test fun exit_returnsToLastNonGuest() = - runBlocking(IMMEDIATE) { + kosmos.runTest { val expectedUserId = NON_GUEST_USER_INFO.id whenever(manager.getUserInfo(expectedUserId)).thenReturn(NON_GUEST_USER_INFO) repository.lastSelectedNonGuestUserId = expectedUserId @@ -219,7 +223,7 @@ class GuestUserInteractorTest : SysuiTestCase() { @Test fun exit_lastNonGuestWasRemoved_returnsToMainUser() = - runBlocking(IMMEDIATE) { + kosmos.runTest { val removedUserId = 310 val mainUserId = 10 repository.lastSelectedNonGuestUserId = removedUserId @@ -242,7 +246,7 @@ class GuestUserInteractorTest : SysuiTestCase() { @Test fun exit_guestWasEphemeral_itIsRemoved() = - runBlocking(IMMEDIATE) { + kosmos.runTest { whenever(manager.markGuestForDeletion(anyInt())).thenReturn(true) repository.setUserInfos(listOf(NON_GUEST_USER_INFO, EPHEMERAL_GUEST_USER_INFO)) repository.setSelectedUserInfo(EPHEMERAL_GUEST_USER_INFO) @@ -265,7 +269,7 @@ class GuestUserInteractorTest : SysuiTestCase() { @Test fun exit_forceRemoveGuest_itIsRemoved() = - runBlocking(IMMEDIATE) { + kosmos.runTest { whenever(manager.markGuestForDeletion(anyInt())).thenReturn(true) repository.setSelectedUserInfo(GUEST_USER_INFO) val targetUserId = NON_GUEST_USER_INFO.id @@ -287,7 +291,7 @@ class GuestUserInteractorTest : SysuiTestCase() { @Test fun exit_selectedDifferentFromGuestUser_doNothing() = - runBlocking(IMMEDIATE) { + kosmos.runTest { repository.setSelectedUserInfo(NON_GUEST_USER_INFO) underTest.exit( @@ -304,7 +308,7 @@ class GuestUserInteractorTest : SysuiTestCase() { @Test fun exit_selectedIsActuallyNotAguestUser_doNothing() = - runBlocking(IMMEDIATE) { + kosmos.runTest { repository.setSelectedUserInfo(NON_GUEST_USER_INFO) underTest.exit( @@ -321,7 +325,7 @@ class GuestUserInteractorTest : SysuiTestCase() { @Test fun remove_returnsToTargetUser() = - runBlocking(IMMEDIATE) { + kosmos.runTest { whenever(manager.markGuestForDeletion(anyInt())).thenReturn(true) repository.setSelectedUserInfo(GUEST_USER_INFO) @@ -342,7 +346,7 @@ class GuestUserInteractorTest : SysuiTestCase() { @Test fun remove_selectedDifferentFromGuestUser_doNothing() = - runBlocking(IMMEDIATE) { + kosmos.runTest { whenever(manager.markGuestForDeletion(anyInt())).thenReturn(true) repository.setSelectedUserInfo(NON_GUEST_USER_INFO) @@ -359,7 +363,7 @@ class GuestUserInteractorTest : SysuiTestCase() { @Test fun remove_selectedIsActuallyNotAguestUser_doNothing() = - runBlocking(IMMEDIATE) { + kosmos.runTest { whenever(manager.markGuestForDeletion(anyInt())).thenReturn(true) repository.setSelectedUserInfo(NON_GUEST_USER_INFO) @@ -395,11 +399,7 @@ class GuestUserInteractorTest : SysuiTestCase() { companion object { private val IMMEDIATE = Dispatchers.Main.immediate private val NON_GUEST_USER_INFO = - UserInfo( - /* id= */ 818, - /* name= */ "non_guest", - /* flags= */ UserInfo.FLAG_FULL, - ) + UserInfo(/* id= */ 818, /* name= */ "non_guest", /* flags= */ UserInfo.FLAG_FULL) private val GUEST_USER_INFO = UserInfo( /* id= */ 669, @@ -416,10 +416,6 @@ class GuestUserInteractorTest : SysuiTestCase() { /* flags= */ UserInfo.FLAG_EPHEMERAL or UserInfo.FLAG_FULL, UserManager.USER_TYPE_FULL_GUEST, ) - private val ALL_USERS = - listOf( - NON_GUEST_USER_INFO, - GUEST_USER_INFO, - ) + private val ALL_USERS = listOf(NON_GUEST_USER_INFO, GUEST_USER_INFO) } } diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/clocks/ClockAnimations.kt b/packages/SystemUI/plugin/src/com/android/systemui/plugins/clocks/ClockAnimations.kt new file mode 100644 index 000000000000..2df14a86e77c --- /dev/null +++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/clocks/ClockAnimations.kt @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the + * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ +package com.android.systemui.plugins.clocks + +import android.view.View +import com.android.systemui.plugins.annotations.ProtectedInterface + +/** Methods which trigger various clock animations */ +@ProtectedInterface +interface ClockAnimations { + /** Runs an enter animation (if any) */ + fun enter() + + /** Sets how far into AOD the device currently is. */ + fun doze(fraction: Float) + + /** Sets how far into the folding animation the device is. */ + fun fold(fraction: Float) + + /** Runs the battery animation (if any). */ + fun charge() + + /** + * Runs when the clock's position changed during the move animation. + * + * @param fromLeft the [View.getLeft] position of the clock, before it started moving. + * @param direction the direction in which it is moving. A positive number means right, and + * negative means left. + * @param fraction fraction of the clock movement. 0 means it is at the beginning, and 1 means + * it finished moving. + * @deprecated use {@link #onPositionUpdated(float, float)} instead. + */ + fun onPositionUpdated(fromLeft: Int, direction: Int, fraction: Float) + + /** + * Runs when the clock's position changed during the move animation. + * + * @param distance is the total distance in pixels to offset the glyphs when animation + * completes. Negative distance means we are animating the position towards the center. + * @param fraction fraction of the clock movement. 0 means it is at the beginning, and 1 means + * it finished moving. + */ + fun onPositionUpdated(distance: Float, fraction: Float) + + /** + * Runs when swiping clock picker, swipingFraction: 1.0 -> clock is scaled up in the preview, + * 0.0 -> clock is scaled down in the shade; previewRatio is previewSize / screenSize + */ + fun onPickerCarouselSwiping(swipingFraction: Float) +} diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/clocks/ClockConfig.kt b/packages/SystemUI/plugin/src/com/android/systemui/plugins/clocks/ClockConfig.kt new file mode 100644 index 000000000000..d84d89087349 --- /dev/null +++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/clocks/ClockConfig.kt @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the + * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ +package com.android.systemui.plugins.clocks + +/** + * Exposes the rendering capabilities of this clock to SystemUI so that it can be hosted and render + * correctly in SystemUI's process. Ideally all clocks could be rendered identically, but in + * practice we different clocks require different behavior from SystemUI. + */ +data class ClockConfig( + val id: ClockId, + + /** Localized name of the clock */ + val name: String, + + /** Localized accessibility description for the clock */ + val description: String, + + /** Transition to AOD should move smartspace like large clock instead of small clock */ + val useAlternateSmartspaceAODTransition: Boolean = false, + + /** Deprecated version of isReactiveToTone; moved to ClockPickerConfig */ + @Deprecated("TODO(b/352049256): Remove in favor of ClockPickerConfig.isReactiveToTone") + val isReactiveToTone: Boolean = true, + + /** True if the clock is large frame clock, which will use weather in compose. */ + val useCustomClockScene: Boolean = false, +) + +/** Render configuration options for a specific clock face. */ +data class ClockFaceConfig( + /** Expected interval between calls to onTimeTick. Can always reduce to PER_MINUTE in AOD. */ + val tickRate: ClockTickRate = ClockTickRate.PER_MINUTE, + + /** Call to check whether the clock consumes weather data */ + val hasCustomWeatherDataDisplay: Boolean = false, + + /** + * Whether this clock has a custom position update animation. If true, the keyguard will call + * `onPositionUpdated` to notify the clock of a position update animation. If false, a default + * animation will be used (e.g. a simple translation). + */ + val hasCustomPositionUpdatedAnimation: Boolean = false, + + /** True if the clock is large frame clock, which will use weatherBlueprint in compose. */ + val useCustomClockScene: Boolean = false, +) + +/** Tick rates for clocks */ +enum class ClockTickRate(val value: Int) { + PER_MINUTE(2), // Update the clock once per minute. + PER_SECOND(1), // Update the clock once per second. + PER_FRAME(0), // Update the clock every second. +} diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/clocks/ClockController.kt b/packages/SystemUI/plugin/src/com/android/systemui/plugins/clocks/ClockController.kt new file mode 100644 index 000000000000..32fec3277f18 --- /dev/null +++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/clocks/ClockController.kt @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the + * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ +package com.android.systemui.plugins.clocks + +import com.android.systemui.plugins.annotations.ProtectedInterface +import com.android.systemui.plugins.annotations.SimpleProperty +import java.io.PrintWriter + +/** Interface for controlling an active clock */ +@ProtectedInterface +interface ClockController { + @get:SimpleProperty + /** A small version of the clock, appropriate for smaller viewports */ + val smallClock: ClockFaceController + + @get:SimpleProperty + /** A large version of the clock, appropriate when a bigger viewport is available */ + val largeClock: ClockFaceController + + @get:SimpleProperty + /** Determines the way the hosting app should behave when rendering either clock face */ + val config: ClockConfig + + @get:SimpleProperty + /** Events that clocks may need to respond to */ + val events: ClockEvents + + /** Initializes various rendering parameters. If never called, provides reasonable defaults. */ + fun initialize(isDarkTheme: Boolean, dozeFraction: Float, foldFraction: Float) + + /** Optional method for dumping debug information */ + fun dump(pw: PrintWriter) +} diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/clocks/ClockEvents.kt b/packages/SystemUI/plugin/src/com/android/systemui/plugins/clocks/ClockEvents.kt new file mode 100644 index 000000000000..235475f6b202 --- /dev/null +++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/clocks/ClockEvents.kt @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the + * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ +package com.android.systemui.plugins.clocks + +import com.android.systemui.plugins.annotations.ProtectedInterface +import com.android.systemui.plugins.annotations.ProtectedReturn +import java.util.Locale +import java.util.TimeZone + +/** Events that should call when various rendering parameters change */ +@ProtectedInterface +interface ClockEvents { + @get:ProtectedReturn("return false;") + /** Set to enable or disable swipe interaction */ + var isReactiveTouchInteractionEnabled: Boolean // TODO(b/364664388): Remove/Rename + + /** Call whenever timezone changes */ + fun onTimeZoneChanged(timeZone: TimeZone) + + /** Call whenever the text time format changes (12hr vs 24hr) */ + fun onTimeFormatChanged(is24Hr: Boolean) + + /** Call whenever the locale changes */ + fun onLocaleChanged(locale: Locale) + + /** Call whenever the weather data should update */ + fun onWeatherDataChanged(data: WeatherData) + + /** Call with alarm information */ + fun onAlarmDataChanged(data: AlarmData) + + /** Call with zen/dnd information */ + fun onZenDataChanged(data: ZenData) + + /** Update reactive axes for this clock */ + fun onFontAxesChanged(axes: List<ClockFontAxisSetting>) +} diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/clocks/ClockFaceController.kt b/packages/SystemUI/plugin/src/com/android/systemui/plugins/clocks/ClockFaceController.kt new file mode 100644 index 000000000000..8a023f1c2388 --- /dev/null +++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/clocks/ClockFaceController.kt @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the + * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ +package com.android.systemui.plugins.clocks + +import android.view.View +import com.android.systemui.plugins.annotations.ProtectedInterface +import com.android.systemui.plugins.annotations.SimpleProperty + +/** Interface for a specific clock face version rendered by the clock */ +@ProtectedInterface +interface ClockFaceController { + @get:SimpleProperty + @Deprecated("Prefer use of layout") + /** View that renders the clock face */ + val view: View + + @get:SimpleProperty + /** Layout specification for this clock */ + val layout: ClockFaceLayout + + @get:SimpleProperty + /** Determines the way the hosting app should behave when rendering this clock face */ + val config: ClockFaceConfig + + @get:SimpleProperty + /** Current theme information the clock is using */ + val theme: ThemeConfig + + @get:SimpleProperty + /** Events specific to this clock face */ + val events: ClockFaceEvents + + @get:SimpleProperty + /** Triggers for various animations */ + val animations: ClockAnimations +} diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/clocks/ClockFaceEvents.kt b/packages/SystemUI/plugin/src/com/android/systemui/plugins/clocks/ClockFaceEvents.kt new file mode 100644 index 000000000000..029e54658f60 --- /dev/null +++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/clocks/ClockFaceEvents.kt @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the + * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ +package com.android.systemui.plugins.clocks + +import android.graphics.Rect +import com.android.systemui.plugins.annotations.ProtectedInterface + +/** Events that have specific data about the related face */ +@ProtectedInterface +interface ClockFaceEvents { + /** Call every tick to update the rendered time */ + fun onTimeTick() + + /** + * Call whenever the theme or seedColor is updated + * + * Theme can be specific to the clock face. + * - isDarkTheme -> clock should be light + * - !isDarkTheme -> clock should be dark + */ + fun onThemeChanged(theme: ThemeConfig) + + /** + * Call whenever font settings change. Pass in a target font size in pixels. The specific clock + * design is allowed to ignore this target size on a case-by-case basis. + */ + fun onFontSettingChanged(fontSizePx: Float) + + /** + * Target region information for the clock face. For small clock, this will match the bounds of + * the parent view mostly, but have a target height based on the height of the default clock. + * For large clocks, the parent view is the entire device size, but most clocks will want to + * render within the centered targetRect to avoid obstructing other elements. The specified + * targetRegion is relative to the parent view. + */ + fun onTargetRegionChanged(targetRegion: Rect?) + + /** Called to notify the clock about its display. */ + fun onSecondaryDisplayChanged(onSecondaryDisplay: Boolean) +} + +/** Contains Theming information for the clock face */ +data class ThemeConfig( + /** True if the clock should use dark theme (light text on dark background) */ + val isDarkTheme: Boolean, + + /** + * A clock specific seed color to use when theming, if any was specified by the user. A null + * value denotes that we should use the seed color for the current system theme. + */ + val seedColor: Int?, +) diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/clocks/ClockFaceLayout.kt b/packages/SystemUI/plugin/src/com/android/systemui/plugins/clocks/ClockFaceLayout.kt new file mode 100644 index 000000000000..fb5ef02aa06a --- /dev/null +++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/clocks/ClockFaceLayout.kt @@ -0,0 +1,174 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the + * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ +package com.android.systemui.plugins.clocks + +import android.content.Context +import android.util.DisplayMetrics +import android.view.View +import androidx.constraintlayout.widget.ConstraintSet +import androidx.constraintlayout.widget.ConstraintSet.BOTTOM +import androidx.constraintlayout.widget.ConstraintSet.END +import androidx.constraintlayout.widget.ConstraintSet.PARENT_ID +import androidx.constraintlayout.widget.ConstraintSet.START +import androidx.constraintlayout.widget.ConstraintSet.TOP +import androidx.constraintlayout.widget.ConstraintSet.WRAP_CONTENT +import com.android.internal.policy.SystemBarUtils +import com.android.systemui.plugins.annotations.GeneratedImport +import com.android.systemui.plugins.annotations.ProtectedInterface +import com.android.systemui.plugins.annotations.ProtectedReturn + +/** Specifies layout information for the clock face */ +@ProtectedInterface +@GeneratedImport("java.util.ArrayList") +@GeneratedImport("android.view.View") +interface ClockFaceLayout { + @get:ProtectedReturn("return new ArrayList<View>();") + /** All clock views to add to the root constraint layout before applying constraints. */ + val views: List<View> + + @ProtectedReturn("return constraints;") + /** Custom constraints to apply to Lockscreen ConstraintLayout. */ + fun applyConstraints(constraints: ConstraintSet): ConstraintSet + + @ProtectedReturn("return constraints;") + /** Custom constraints to apply to preview ConstraintLayout. */ + fun applyPreviewConstraints( + clockPreviewConfig: ClockPreviewConfig, + constraints: ConstraintSet, + ): ConstraintSet + + /** Apply specified AOD BurnIn parameters to this layout */ + fun applyAodBurnIn(aodBurnInModel: AodClockBurnInModel) +} + +/** Data class to contain AOD BurnIn information for correct aod rendering */ +data class AodClockBurnInModel( + /** Scale that the clock should render at to mitigate burnin */ + val scale: Float, + + /** X-Translation for the clock to mitigate burnin */ + val translationX: Float, + + /** Y-Translation for the clock to mitigate burnin */ + val translationY: Float, +) + +/** A ClockFaceLayout that applies the default lockscreen layout to a single view */ +class DefaultClockFaceLayout(val view: View) : ClockFaceLayout { + override val views = listOf(view) + + override fun applyConstraints(constraints: ConstraintSet): ConstraintSet { + if (views.size != 1) { + throw IllegalArgumentException( + "Should have only one container view when using DefaultClockFaceLayout" + ) + } + return constraints + } + + override fun applyPreviewConstraints( + clockPreviewConfig: ClockPreviewConfig, + constraints: ConstraintSet, + ): ConstraintSet { + return applyDefaultPreviewConstraints(clockPreviewConfig, constraints) + } + + override fun applyAodBurnIn(aodBurnInModel: AodClockBurnInModel) { + // Default clock doesn't need detailed control of view + } + + companion object { + fun applyDefaultPreviewConstraints( + clockPreviewConfig: ClockPreviewConfig, + constraints: ConstraintSet, + ): ConstraintSet { + constraints.apply { + val context = clockPreviewConfig.previewContext + val lockscreenClockViewLargeId = getId(context, "lockscreen_clock_view_large") + constrainWidth(lockscreenClockViewLargeId, WRAP_CONTENT) + constrainHeight(lockscreenClockViewLargeId, WRAP_CONTENT) + constrainMaxHeight(lockscreenClockViewLargeId, 0) + + val largeClockTopMargin = + SystemBarUtils.getStatusBarHeight(context) + + getDimen(context, "small_clock_padding_top") + + getDimen(context, "keyguard_smartspace_top_offset") + + getDimen(context, "date_weather_view_height") + + getDimen(context, "enhanced_smartspace_height") + connect(lockscreenClockViewLargeId, TOP, PARENT_ID, TOP, largeClockTopMargin) + connect(lockscreenClockViewLargeId, START, PARENT_ID, START) + connect(lockscreenClockViewLargeId, END, PARENT_ID, END) + + // In preview, we'll show UDFPS icon for UDFPS devices + // and nothing for non-UDFPS devices, + // and we're not planning to add this vide in clockHostView + // so we only need position of device entry icon to constrain clock + // Copied calculation codes from applyConstraints in DefaultDeviceEntrySection + val bottomPaddingPx = getDimen(context, "lock_icon_margin_bottom") + val defaultDensity = + DisplayMetrics.DENSITY_DEVICE_STABLE.toFloat() / + DisplayMetrics.DENSITY_DEFAULT.toFloat() + val lockIconRadiusPx = (defaultDensity * 36).toInt() + val clockBottomMargin = bottomPaddingPx + 2 * lockIconRadiusPx + + connect(lockscreenClockViewLargeId, BOTTOM, PARENT_ID, BOTTOM, clockBottomMargin) + val smallClockViewId = getId(context, "lockscreen_clock_view") + constrainWidth(smallClockViewId, WRAP_CONTENT) + constrainHeight(smallClockViewId, getDimen(context, "small_clock_height")) + connect( + smallClockViewId, + START, + PARENT_ID, + START, + getDimen(context, "clock_padding_start") + + getDimen(context, "status_view_margin_horizontal"), + ) + val smallClockTopMargin = + getSmallClockTopPadding( + clockPreviewConfig = clockPreviewConfig, + SystemBarUtils.getStatusBarHeight(context), + ) + connect(smallClockViewId, TOP, PARENT_ID, TOP, smallClockTopMargin) + } + return constraints + } + + fun getId(context: Context, name: String): Int { + val packageName = context.packageName + val res = context.packageManager.getResourcesForApplication(packageName) + val id = res.getIdentifier(name, "id", packageName) + return id + } + + fun getDimen(context: Context, name: String): Int { + val packageName = context.packageName + val res = context.resources + val id = res.getIdentifier(name, "dimen", packageName) + return if (id == 0) 0 else res.getDimensionPixelSize(id) + } + + fun getSmallClockTopPadding( + clockPreviewConfig: ClockPreviewConfig, + statusBarHeight: Int, + ): Int { + return if (clockPreviewConfig.isShadeLayoutWide) { + getDimen(clockPreviewConfig.previewContext, "keyguard_split_shade_top_margin") - + if (clockPreviewConfig.isSceneContainerFlagEnabled) statusBarHeight else 0 + } else { + getDimen(clockPreviewConfig.previewContext, "keyguard_clock_top_margin") + + if (!clockPreviewConfig.isSceneContainerFlagEnabled) statusBarHeight else 0 + } + } + } +} diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/clocks/ClockMessageBuffers.kt b/packages/SystemUI/plugin/src/com/android/systemui/plugins/clocks/ClockMessageBuffers.kt new file mode 100644 index 000000000000..bec589ae139e --- /dev/null +++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/clocks/ClockMessageBuffers.kt @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the + * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ +package com.android.systemui.plugins.clocks + +import com.android.systemui.log.core.MessageBuffer + +/** MessageBuffers for clocks that want to log information to SystemUI dumps */ +data class ClockMessageBuffers( + /** Message buffer for general infrastructure */ + val infraMessageBuffer: MessageBuffer, + + /** Message buffer for small clock rendering */ + val smallClockMessageBuffer: MessageBuffer, + + /** Message buffer for large clock rendering */ + val largeClockMessageBuffer: MessageBuffer, +) { + constructor(buffer: MessageBuffer) : this(buffer, buffer, buffer) {} +} diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/clocks/ClockPickerConfig.kt b/packages/SystemUI/plugin/src/com/android/systemui/plugins/clocks/ClockPickerConfig.kt new file mode 100644 index 000000000000..1bc9367ce3c5 --- /dev/null +++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/clocks/ClockPickerConfig.kt @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the + * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ +package com.android.systemui.plugins.clocks + +import android.graphics.drawable.Drawable + +data class ClockPickerConfig +@JvmOverloads +constructor( + val id: String, + + /** Localized name of the clock */ + val name: String, + + /** Localized accessibility description for the clock */ + val description: String, + + /* Static & lightweight thumbnail version of the clock */ + val thumbnail: Drawable, + + /** True if the clock will react to tone changes in the seed color */ + val isReactiveToTone: Boolean = true, + + /** Font axes that can be modified on this clock */ + val axes: List<ClockFontAxis> = listOf(), +) + +/** Represents an Axis that can be modified */ +data class ClockFontAxis( + /** Axis key, not user renderable */ + val key: String, + + /** Intended mode of user interaction */ + val type: AxisType, + + /** Maximum value the axis supports */ + val maxValue: Float, + + /** Minimum value the axis supports */ + val minValue: Float, + + /** Current value the axis is set to */ + val currentValue: Float, + + /** User-renderable name of the axis */ + val name: String, + + /** Description of the axis */ + val description: String, +) { + fun toSetting() = ClockFontAxisSetting(key, currentValue) + + companion object { + fun merge( + fontAxes: List<ClockFontAxis>, + axisSettings: List<ClockFontAxisSetting>, + ): List<ClockFontAxis> { + val result = mutableListOf<ClockFontAxis>() + for (axis in fontAxes) { + val setting = axisSettings.firstOrNull { axis.key == it.key } + val output = setting?.let { axis.copy(currentValue = it.value) } ?: axis + result.add(output) + } + return result + } + } +} + +/** Axis user interaction modes */ +enum class AxisType { + /** Continuous range between minValue & maxValue. */ + Float, + + /** Only minValue & maxValue are valid. No intermediate values between them are allowed. */ + Boolean, +} diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/clocks/ClockPreviewConfig.kt b/packages/SystemUI/plugin/src/com/android/systemui/plugins/clocks/ClockPreviewConfig.kt new file mode 100644 index 000000000000..544b705c55c5 --- /dev/null +++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/clocks/ClockPreviewConfig.kt @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.plugins.clocks + +import android.content.Context + +data class ClockPreviewConfig( + val previewContext: Context, + val isShadeLayoutWide: Boolean, + val isSceneContainerFlagEnabled: Boolean = false, +) diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/clocks/ClockProviderPlugin.kt b/packages/SystemUI/plugin/src/com/android/systemui/plugins/clocks/ClockProviderPlugin.kt index fb9e96c820cf..7426f061b84c 100644 --- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/clocks/ClockProviderPlugin.kt +++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/clocks/ClockProviderPlugin.kt @@ -13,35 +13,11 @@ */ package com.android.systemui.plugins.clocks -import android.content.Context -import android.graphics.Rect -import android.graphics.drawable.Drawable -import android.util.DisplayMetrics -import android.view.View -import androidx.constraintlayout.widget.ConstraintSet -import androidx.constraintlayout.widget.ConstraintSet.BOTTOM -import androidx.constraintlayout.widget.ConstraintSet.END -import androidx.constraintlayout.widget.ConstraintSet.PARENT_ID -import androidx.constraintlayout.widget.ConstraintSet.START -import androidx.constraintlayout.widget.ConstraintSet.TOP -import androidx.constraintlayout.widget.ConstraintSet.WRAP_CONTENT -import com.android.internal.annotations.Keep -import com.android.internal.policy.SystemBarUtils -import com.android.systemui.log.core.MessageBuffer import com.android.systemui.plugins.Plugin import com.android.systemui.plugins.annotations.GeneratedImport import com.android.systemui.plugins.annotations.ProtectedInterface import com.android.systemui.plugins.annotations.ProtectedReturn import com.android.systemui.plugins.annotations.ProvidesInterface -import com.android.systemui.plugins.annotations.SimpleProperty -import java.io.PrintWriter -import java.util.Locale -import java.util.TimeZone -import org.json.JSONArray -import org.json.JSONObject - -/** Identifies a clock design */ -typealias ClockId = String /** A Plugin which exposes the ClockProvider interface */ @ProtectedInterface @@ -74,509 +50,8 @@ interface ClockProvider { fun getClockPickerConfig(settings: ClockSettings): ClockPickerConfig } -/** Interface for controlling an active clock */ -@ProtectedInterface -interface ClockController { - @get:SimpleProperty - /** A small version of the clock, appropriate for smaller viewports */ - val smallClock: ClockFaceController - - @get:SimpleProperty - /** A large version of the clock, appropriate when a bigger viewport is available */ - val largeClock: ClockFaceController - - @get:SimpleProperty - /** Determines the way the hosting app should behave when rendering either clock face */ - val config: ClockConfig - - @get:SimpleProperty - /** Events that clocks may need to respond to */ - val events: ClockEvents - - /** Initializes various rendering parameters. If never called, provides reasonable defaults. */ - fun initialize(isDarkTheme: Boolean, dozeFraction: Float, foldFraction: Float) - - /** Optional method for dumping debug information */ - fun dump(pw: PrintWriter) -} - -/** Interface for a specific clock face version rendered by the clock */ -@ProtectedInterface -interface ClockFaceController { - @get:SimpleProperty - @Deprecated("Prefer use of layout") - /** View that renders the clock face */ - val view: View - - @get:SimpleProperty - /** Layout specification for this clock */ - val layout: ClockFaceLayout - - @get:SimpleProperty - /** Determines the way the hosting app should behave when rendering this clock face */ - val config: ClockFaceConfig - - @get:SimpleProperty - /** Current theme information the clock is using */ - val theme: ThemeConfig - - @get:SimpleProperty - /** Events specific to this clock face */ - val events: ClockFaceEvents - - @get:SimpleProperty - /** Triggers for various animations */ - val animations: ClockAnimations -} - -/** For clocks that want to report debug information */ -data class ClockMessageBuffers( - /** Message buffer for general infra */ - val infraMessageBuffer: MessageBuffer, - - /** Message buffer for small clock renering */ - val smallClockMessageBuffer: MessageBuffer, - - /** Message buffer for large clock rendering */ - val largeClockMessageBuffer: MessageBuffer, -) { - constructor(buffer: MessageBuffer) : this(buffer, buffer, buffer) {} -} - -data class AodClockBurnInModel(val scale: Float, val translationX: Float, val translationY: Float) - -/** Specifies layout information for the clock face */ -@ProtectedInterface -@GeneratedImport("java.util.ArrayList") -@GeneratedImport("android.view.View") -interface ClockFaceLayout { - @get:ProtectedReturn("return new ArrayList<View>();") - /** All clock views to add to the root constraint layout before applying constraints. */ - val views: List<View> - - @ProtectedReturn("return constraints;") - /** Custom constraints to apply to Lockscreen ConstraintLayout. */ - fun applyConstraints(constraints: ConstraintSet): ConstraintSet - - @ProtectedReturn("return constraints;") - /** Custom constraints to apply to preview ConstraintLayout. */ - fun applyPreviewConstraints(context: Context, constraints: ConstraintSet): ConstraintSet - - fun applyAodBurnIn(aodBurnInModel: AodClockBurnInModel) -} - -/** A ClockFaceLayout that applies the default lockscreen layout to a single view */ -class DefaultClockFaceLayout(val view: View) : ClockFaceLayout { - // both small and large clock should have a container (RelativeLayout in - // SimpleClockFaceController) - override val views = listOf(view) - - override fun applyConstraints(constraints: ConstraintSet): ConstraintSet { - if (views.size != 1) { - throw IllegalArgumentException( - "Should have only one container view when using DefaultClockFaceLayout" - ) - } - return constraints - } - - override fun applyPreviewConstraints( - context: Context, - constraints: ConstraintSet, - ): ConstraintSet { - return applyDefaultPreviewConstraints(context, constraints) - } - - override fun applyAodBurnIn(aodBurnInModel: AodClockBurnInModel) { - // Default clock doesn't need detailed control of view - } - - companion object { - fun applyDefaultPreviewConstraints( - context: Context, - constraints: ConstraintSet, - ): ConstraintSet { - constraints.apply { - val lockscreenClockViewLargeId = getId(context, "lockscreen_clock_view_large") - constrainWidth(lockscreenClockViewLargeId, WRAP_CONTENT) - constrainHeight(lockscreenClockViewLargeId, WRAP_CONTENT) - constrainMaxHeight(lockscreenClockViewLargeId, 0) - - val largeClockTopMargin = - SystemBarUtils.getStatusBarHeight(context) + - getDimen(context, "small_clock_padding_top") + - getDimen(context, "keyguard_smartspace_top_offset") + - getDimen(context, "date_weather_view_height") + - getDimen(context, "enhanced_smartspace_height") - connect(lockscreenClockViewLargeId, TOP, PARENT_ID, TOP, largeClockTopMargin) - connect(lockscreenClockViewLargeId, START, PARENT_ID, START) - connect(lockscreenClockViewLargeId, END, PARENT_ID, END) - - // In preview, we'll show UDFPS icon for UDFPS devices - // and nothing for non-UDFPS devices, - // and we're not planning to add this vide in clockHostView - // so we only need position of device entry icon to constrain clock - // Copied calculation codes from applyConstraints in DefaultDeviceEntrySection - val bottomPaddingPx = getDimen(context, "lock_icon_margin_bottom") - val defaultDensity = - DisplayMetrics.DENSITY_DEVICE_STABLE.toFloat() / - DisplayMetrics.DENSITY_DEFAULT.toFloat() - val lockIconRadiusPx = (defaultDensity * 36).toInt() - val clockBottomMargin = bottomPaddingPx + 2 * lockIconRadiusPx - - connect(lockscreenClockViewLargeId, BOTTOM, PARENT_ID, BOTTOM, clockBottomMargin) - val smallClockViewId = getId(context, "lockscreen_clock_view") - constrainWidth(smallClockViewId, WRAP_CONTENT) - constrainHeight(smallClockViewId, getDimen(context, "small_clock_height")) - connect( - smallClockViewId, - START, - PARENT_ID, - START, - getDimen(context, "clock_padding_start") + - getDimen(context, "status_view_margin_horizontal"), - ) - val smallClockTopMargin = - getDimen(context, "keyguard_clock_top_margin") + - SystemBarUtils.getStatusBarHeight(context) - connect(smallClockViewId, TOP, PARENT_ID, TOP, smallClockTopMargin) - } - return constraints - } - - fun getId(context: Context, name: String): Int { - val packageName = context.packageName - val res = context.packageManager.getResourcesForApplication(packageName) - val id = res.getIdentifier(name, "id", packageName) - return id - } - - fun getDimen(context: Context, name: String): Int { - val packageName = context.packageName - val res = context.packageManager.getResourcesForApplication(packageName) - val id = res.getIdentifier(name, "dimen", packageName) - return if (id == 0) 0 else res.getDimensionPixelSize(id) - } - } -} - -/** Events that should call when various rendering parameters change */ -@ProtectedInterface -interface ClockEvents { - @get:ProtectedReturn("return false;") - /** Set to enable or disable swipe interaction */ - var isReactiveTouchInteractionEnabled: Boolean // TODO(b/364664388): Remove/Rename - - /** Call whenever timezone changes */ - fun onTimeZoneChanged(timeZone: TimeZone) - - /** Call whenever the text time format changes (12hr vs 24hr) */ - fun onTimeFormatChanged(is24Hr: Boolean) - - /** Call whenever the locale changes */ - fun onLocaleChanged(locale: Locale) - - /** Call whenever the weather data should update */ - fun onWeatherDataChanged(data: WeatherData) - - /** Call with alarm information */ - fun onAlarmDataChanged(data: AlarmData) - - /** Call with zen/dnd information */ - fun onZenDataChanged(data: ZenData) - - /** Update reactive axes for this clock */ - fun onFontAxesChanged(axes: List<ClockFontAxisSetting>) -} - -/** Axis setting value for a clock */ -data class ClockFontAxisSetting( - /** Axis key; matches ClockFontAxis.key */ - val key: String, - - /** Value to set this axis to */ - val value: Float, -) { - companion object { - private val KEY_AXIS_KEY = "key" - private val KEY_AXIS_VALUE = "value" - - fun toJson(setting: ClockFontAxisSetting): JSONObject { - return JSONObject().apply { - put(KEY_AXIS_KEY, setting.key) - put(KEY_AXIS_VALUE, setting.value) - } - } - - fun toJson(settings: List<ClockFontAxisSetting>): JSONArray { - return JSONArray().apply { - for (axis in settings) { - put(toJson(axis)) - } - } - } - - fun fromJson(jsonObj: JSONObject): ClockFontAxisSetting { - return ClockFontAxisSetting( - key = jsonObj.getString(KEY_AXIS_KEY), - value = jsonObj.getDouble(KEY_AXIS_VALUE).toFloat(), - ) - } - - fun fromJson(jsonArray: JSONArray): List<ClockFontAxisSetting> { - val result = mutableListOf<ClockFontAxisSetting>() - for (i in 0..jsonArray.length() - 1) { - val obj = jsonArray.getJSONObject(i) - if (obj == null) continue - result.add(fromJson(obj)) - } - return result - } - - fun toFVar(settings: List<ClockFontAxisSetting>): String { - val sb = StringBuilder() - for (axis in settings) { - if (sb.length > 0) sb.append(", ") - sb.append("'${axis.key}' ${axis.value.toInt()}") - } - return sb.toString() - } - } -} - -/** Methods which trigger various clock animations */ -@ProtectedInterface -interface ClockAnimations { - /** Runs an enter animation (if any) */ - fun enter() - - /** Sets how far into AOD the device currently is. */ - fun doze(fraction: Float) - - /** Sets how far into the folding animation the device is. */ - fun fold(fraction: Float) - - /** Runs the battery animation (if any). */ - fun charge() - - /** - * Runs when the clock's position changed during the move animation. - * - * @param fromLeft the [View.getLeft] position of the clock, before it started moving. - * @param direction the direction in which it is moving. A positive number means right, and - * negative means left. - * @param fraction fraction of the clock movement. 0 means it is at the beginning, and 1 means - * it finished moving. - * @deprecated use {@link #onPositionUpdated(float, float)} instead. - */ - fun onPositionUpdated(fromLeft: Int, direction: Int, fraction: Float) - - /** - * Runs when the clock's position changed during the move animation. - * - * @param distance is the total distance in pixels to offset the glyphs when animation - * completes. Negative distance means we are animating the position towards the center. - * @param fraction fraction of the clock movement. 0 means it is at the beginning, and 1 means - * it finished moving. - */ - fun onPositionUpdated(distance: Float, fraction: Float) - - /** - * Runs when swiping clock picker, swipingFraction: 1.0 -> clock is scaled up in the preview, - * 0.0 -> clock is scaled down in the shade; previewRatio is previewSize / screenSize - */ - fun onPickerCarouselSwiping(swipingFraction: Float) -} - -/** Events that have specific data about the related face */ -@ProtectedInterface -interface ClockFaceEvents { - /** Call every time tick */ - fun onTimeTick() - - /** - * Call whenever the theme or seedColor is updated - * - * Theme can be specific to the clock face. - * - isDarkTheme -> clock should be light - * - !isDarkTheme -> clock should be dark - */ - fun onThemeChanged(theme: ThemeConfig) - - /** - * Call whenever font settings change. Pass in a target font size in pixels. The specific clock - * design is allowed to ignore this target size on a case-by-case basis. - */ - fun onFontSettingChanged(fontSizePx: Float) - - /** - * Target region information for the clock face. For small clock, this will match the bounds of - * the parent view mostly, but have a target height based on the height of the default clock. - * For large clocks, the parent view is the entire device size, but most clocks will want to - * render within the centered targetRect to avoid obstructing other elements. The specified - * targetRegion is relative to the parent view. - */ - fun onTargetRegionChanged(targetRegion: Rect?) - - /** Called to notify the clock about its display. */ - fun onSecondaryDisplayChanged(onSecondaryDisplay: Boolean) -} - -data class ThemeConfig(val isDarkTheme: Boolean, val seedColor: Int?) - -/** Tick rates for clocks */ -enum class ClockTickRate(val value: Int) { - PER_MINUTE(2), // Update the clock once per minute. - PER_SECOND(1), // Update the clock once per second. - PER_FRAME(0), // Update the clock every second. -} +/** Identifies a clock design */ +typealias ClockId = String /** Some data about a clock design */ data class ClockMetadata(val clockId: ClockId) - -data class ClockPickerConfig -@JvmOverloads -constructor( - val id: String, - - /** Localized name of the clock */ - val name: String, - - /** Localized accessibility description for the clock */ - val description: String, - - /* Static & lightweight thumbnail version of the clock */ - val thumbnail: Drawable, - - /** True if the clock will react to tone changes in the seed color */ - val isReactiveToTone: Boolean = true, - - /** Font axes that can be modified on this clock */ - val axes: List<ClockFontAxis> = listOf(), -) - -/** Represents an Axis that can be modified */ -data class ClockFontAxis( - /** Axis key, not user renderable */ - val key: String, - - /** Intended mode of user interaction */ - val type: AxisType, - - /** Maximum value the axis supports */ - val maxValue: Float, - - /** Minimum value the axis supports */ - val minValue: Float, - - /** Current value the axis is set to */ - val currentValue: Float, - - /** User-renderable name of the axis */ - val name: String, - - /** Description of the axis */ - val description: String, -) { - fun toSetting() = ClockFontAxisSetting(key, currentValue) - - companion object { - fun merge( - fontAxes: List<ClockFontAxis>, - axisSettings: List<ClockFontAxisSetting>, - ): List<ClockFontAxis> { - val result = mutableListOf<ClockFontAxis>() - for (axis in fontAxes) { - val setting = axisSettings.firstOrNull { axis.key == it.key } - val output = setting?.let { axis.copy(currentValue = it.value) } ?: axis - result.add(output) - } - return result - } - } -} - -/** Axis user interaction modes */ -enum class AxisType { - /** Continuous range between minValue & maxValue. */ - Float, - - /** Only minValue & maxValue are valid. No intermediate values between them are allowed. */ - Boolean, -} - -/** Render configuration for the full clock. Modifies the way systemUI behaves with this clock. */ -data class ClockConfig( - val id: String, - - /** Localized name of the clock */ - val name: String, - - /** Localized accessibility description for the clock */ - val description: String, - - /** Transition to AOD should move smartspace like large clock instead of small clock */ - val useAlternateSmartspaceAODTransition: Boolean = false, - - /** Deprecated version of isReactiveToTone; moved to ClockPickerConfig */ - @Deprecated("TODO(b/352049256): Remove in favor of ClockPickerConfig.isReactiveToTone") - val isReactiveToTone: Boolean = true, - - /** True if the clock is large frame clock, which will use weather in compose. */ - val useCustomClockScene: Boolean = false, -) - -/** Render configuration options for a clock face. Modifies the way SystemUI behaves. */ -data class ClockFaceConfig( - /** Expected interval between calls to onTimeTick. Can always reduce to PER_MINUTE in AOD. */ - val tickRate: ClockTickRate = ClockTickRate.PER_MINUTE, - - /** Call to check whether the clock consumes weather data */ - val hasCustomWeatherDataDisplay: Boolean = false, - - /** - * Whether this clock has a custom position update animation. If true, the keyguard will call - * `onPositionUpdated` to notify the clock of a position update animation. If false, a default - * animation will be used (e.g. a simple translation). - */ - val hasCustomPositionUpdatedAnimation: Boolean = false, - - /** True if the clock is large frame clock, which will use weatherBlueprint in compose. */ - val useCustomClockScene: Boolean = false, -) - -/** Structure for keeping clock-specific settings */ -@Keep -data class ClockSettings( - val clockId: ClockId? = null, - val seedColor: Int? = null, - val axes: List<ClockFontAxisSetting> = listOf(), -) { - // Exclude metadata from equality checks - var metadata: JSONObject = JSONObject() - - companion object { - private val KEY_CLOCK_ID = "clockId" - private val KEY_SEED_COLOR = "seedColor" - private val KEY_METADATA = "metadata" - private val KEY_AXIS_LIST = "axes" - - fun toJson(setting: ClockSettings): JSONObject { - return JSONObject().apply { - put(KEY_CLOCK_ID, setting.clockId) - put(KEY_SEED_COLOR, setting.seedColor) - put(KEY_METADATA, setting.metadata) - put(KEY_AXIS_LIST, ClockFontAxisSetting.toJson(setting.axes)) - } - } - - fun fromJson(json: JSONObject): ClockSettings { - val clockId = if (!json.isNull(KEY_CLOCK_ID)) json.getString(KEY_CLOCK_ID) else null - val seedColor = if (!json.isNull(KEY_SEED_COLOR)) json.getInt(KEY_SEED_COLOR) else null - val axisList = json.optJSONArray(KEY_AXIS_LIST)?.let(ClockFontAxisSetting::fromJson) - return ClockSettings(clockId, seedColor, axisList ?: listOf()).apply { - metadata = json.optJSONObject(KEY_METADATA) ?: JSONObject() - } - } - } -} diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/clocks/ClockSettings.kt b/packages/SystemUI/plugin/src/com/android/systemui/plugins/clocks/ClockSettings.kt new file mode 100644 index 000000000000..6128c00f3843 --- /dev/null +++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/clocks/ClockSettings.kt @@ -0,0 +1,110 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the + * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ +package com.android.systemui.plugins.clocks + +import com.android.internal.annotations.Keep +import org.json.JSONArray +import org.json.JSONObject + +@Keep +/** Structure for keeping clock-specific settings */ +data class ClockSettings( + val clockId: ClockId? = null, + val seedColor: Int? = null, + val axes: List<ClockFontAxisSetting> = listOf(), +) { + // Exclude metadata from equality checks + var metadata: JSONObject = JSONObject() + + companion object { + private val KEY_CLOCK_ID = "clockId" + private val KEY_SEED_COLOR = "seedColor" + private val KEY_METADATA = "metadata" + private val KEY_AXIS_LIST = "axes" + + fun toJson(setting: ClockSettings): JSONObject { + return JSONObject().apply { + put(KEY_CLOCK_ID, setting.clockId) + put(KEY_SEED_COLOR, setting.seedColor) + put(KEY_METADATA, setting.metadata) + put(KEY_AXIS_LIST, ClockFontAxisSetting.toJson(setting.axes)) + } + } + + fun fromJson(json: JSONObject): ClockSettings { + val clockId = if (!json.isNull(KEY_CLOCK_ID)) json.getString(KEY_CLOCK_ID) else null + val seedColor = if (!json.isNull(KEY_SEED_COLOR)) json.getInt(KEY_SEED_COLOR) else null + val axisList = json.optJSONArray(KEY_AXIS_LIST)?.let(ClockFontAxisSetting::fromJson) + return ClockSettings(clockId, seedColor, axisList ?: listOf()).apply { + metadata = json.optJSONObject(KEY_METADATA) ?: JSONObject() + } + } + } +} + +@Keep +/** Axis setting value for a clock */ +data class ClockFontAxisSetting( + /** Axis key; matches ClockFontAxis.key */ + val key: String, + + /** Value to set this axis to */ + val value: Float, +) { + companion object { + private val KEY_AXIS_KEY = "key" + private val KEY_AXIS_VALUE = "value" + + fun toJson(setting: ClockFontAxisSetting): JSONObject { + return JSONObject().apply { + put(KEY_AXIS_KEY, setting.key) + put(KEY_AXIS_VALUE, setting.value) + } + } + + fun toJson(settings: List<ClockFontAxisSetting>): JSONArray { + return JSONArray().apply { + for (axis in settings) { + put(toJson(axis)) + } + } + } + + fun fromJson(jsonObj: JSONObject): ClockFontAxisSetting { + return ClockFontAxisSetting( + key = jsonObj.getString(KEY_AXIS_KEY), + value = jsonObj.getDouble(KEY_AXIS_VALUE).toFloat(), + ) + } + + fun fromJson(jsonArray: JSONArray): List<ClockFontAxisSetting> { + val result = mutableListOf<ClockFontAxisSetting>() + for (i in 0..jsonArray.length() - 1) { + val obj = jsonArray.getJSONObject(i) + if (obj == null) continue + result.add(fromJson(obj)) + } + return result + } + + fun toFVar(settings: List<ClockFontAxisSetting>): String { + val sb = StringBuilder() + for (axis in settings) { + if (sb.length > 0) sb.append(", ") + sb.append("'${axis.key}' ${axis.value.toInt()}") + } + return sb.toString() + } + } +} diff --git a/packages/SystemUI/res/drawable/volume_background_top_legacy.xml b/packages/SystemUI/res/drawable/volume_background_top_legacy.xml index 3cd87fc32061..58ae150f2539 100644 --- a/packages/SystemUI/res/drawable/volume_background_top_legacy.xml +++ b/packages/SystemUI/res/drawable/volume_background_top_legacy.xml @@ -16,7 +16,7 @@ --> <layer-list xmlns:android="http://schemas.android.com/apk/res/android" xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"> - <item> + <item android:gravity="bottom|end"> <shape> <size android:width="@dimen/volume_dialog_panel_width" /> <solid android:color="?androidprv:attr/colorSurface" /> diff --git a/packages/SystemUI/res/layout/volume_dialog_legacy.xml b/packages/SystemUI/res/layout/volume_dialog_legacy.xml index 9010ab764da0..d44b6a8534f2 100644 --- a/packages/SystemUI/res/layout/volume_dialog_legacy.xml +++ b/packages/SystemUI/res/layout/volume_dialog_legacy.xml @@ -93,9 +93,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@drawable/volume_background_bottom" - android:paddingLeft="@dimen/volume_dialog_ringer_rows_padding" - android:paddingBottom="@dimen/volume_dialog_ringer_rows_padding" - android:paddingRight="@dimen/volume_dialog_ringer_rows_padding"> + android:paddingBottom="@dimen/volume_dialog_ringer_rows_padding"> <com.android.keyguard.AlphaOptimizedImageButton android:id="@+id/settings" android:src="@drawable/horizontal_ellipsis" diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml index e14008a7773b..0381811e29ed 100644 --- a/packages/SystemUI/res/values/styles.xml +++ b/packages/SystemUI/res/values/styles.xml @@ -831,6 +831,11 @@ <item name="android:textColor">?attr/onSurfaceVariant</item> </style> + <style name="TextAppearance.QSEditTitle" > + <item name="android:fontFamily">"gsf-title-medium-emphasized"</item> + <item name="android:textColor">?attr/onSurfaceVariant</item> + </style> + <style name="QSCustomizeToolbar" parent="@*android:style/Widget.DeviceDefault.Toolbar"> <item name="android:textColor">?attr/onSurface</item> <item name="android:elevation">10dp</item> diff --git a/packages/SystemUI/src/com/android/keyguard/EmergencyButton.java b/packages/SystemUI/src/com/android/keyguard/EmergencyButton.java index 8ed675c61edf..6ef7de4a32b5 100644 --- a/packages/SystemUI/src/com/android/keyguard/EmergencyButton.java +++ b/packages/SystemUI/src/com/android/keyguard/EmergencyButton.java @@ -16,7 +16,10 @@ package com.android.keyguard; +import static com.android.systemui.Flags.gsfBouncer; + import android.content.Context; +import android.graphics.Typeface; import android.text.TextUtils; import android.util.AttributeSet; import android.view.MotionEvent; @@ -122,6 +125,9 @@ public class EmergencyButton extends Button { textId = com.android.internal.R.string.lockscreen_emergency_call; } setText(textId); + if (gsfBouncer()) { + setTypeface(Typeface.create("gsf-title-medium", Typeface.NORMAL)); + } } else { setVisibility(View.GONE); } diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java index 6bcacd023c74..fcaccd27a567 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java @@ -32,6 +32,7 @@ import static androidx.constraintlayout.widget.ConstraintSet.START; import static androidx.constraintlayout.widget.ConstraintSet.TOP; import static androidx.constraintlayout.widget.ConstraintSet.WRAP_CONTENT; +import static com.android.systemui.Flags.gsfBouncer; import static com.android.systemui.plugins.FalsingManager.LOW_PENALTY; import static java.lang.Integer.max; @@ -51,6 +52,7 @@ import android.graphics.Bitmap; import android.graphics.BlendMode; import android.graphics.Canvas; import android.graphics.Rect; +import android.graphics.Typeface; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.graphics.drawable.Icon; @@ -1335,6 +1337,9 @@ public class KeyguardSecurityContainer extends ConstraintLayout { true); mUserSwitcherViewGroup = mView.findViewById(R.id.keyguard_bouncer_user_switcher); mUserSwitcher = mView.findViewById(R.id.user_switcher_header); + if (gsfBouncer()) { + mUserSwitcher.setTypeface(Typeface.create("gsf-label-medium", Typeface.NORMAL)); + } } interface UserSwitcherCallback { diff --git a/packages/SystemUI/src/com/android/keyguard/NumPadKey.java b/packages/SystemUI/src/com/android/keyguard/NumPadKey.java index 7fe4ec852045..ebde8a3057ce 100644 --- a/packages/SystemUI/src/com/android/keyguard/NumPadKey.java +++ b/packages/SystemUI/src/com/android/keyguard/NumPadKey.java @@ -15,11 +15,13 @@ */ package com.android.keyguard; +import static com.android.systemui.Flags.gsfBouncer; import static com.android.systemui.bouncer.shared.constants.KeyguardBouncerConstants.ColorId.NUM_PAD_KEY; import android.content.Context; import android.content.res.Configuration; import android.content.res.TypedArray; +import android.graphics.Typeface; import android.graphics.drawable.Drawable; import android.graphics.drawable.GradientDrawable; import android.os.PowerManager; @@ -158,6 +160,9 @@ public class NumPadKey extends ViewGroup implements NumPadAnimationListener { int klondikeColor = Utils.getColorAttr(getContext(), android.R.attr.textColorSecondary) .getDefaultColor(); mDigitText.setTextColor(textColor); + if (gsfBouncer()) { + mDigitText.setTypeface(Typeface.create("gsf-label-large-emphasized", Typeface.NORMAL)); + } mKlondikeText.setTextColor(klondikeColor); if (mAnimator != null) mAnimator.reloadColors(getContext()); diff --git a/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterView.java b/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterView.java index e63472684585..1176cb0523c1 100644 --- a/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterView.java +++ b/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterView.java @@ -19,6 +19,7 @@ import static android.provider.Settings.System.SHOW_BATTERY_PERCENT; import static com.android.settingslib.flags.Flags.newStatusBarIcons; import static com.android.systemui.DejankUtils.whitelistIpcs; +import static com.android.systemui.Flags.gsfQuickSettings; import static java.lang.annotation.RetentionPolicy.SOURCE; @@ -33,6 +34,7 @@ import android.content.res.Configuration; import android.content.res.Resources; import android.content.res.TypedArray; import android.graphics.Rect; +import android.graphics.Typeface; import android.graphics.drawable.Drawable; import android.os.UserHandle; import android.provider.Settings; @@ -384,6 +386,9 @@ public class BatteryMeterView extends LinearLayout implements DarkReceiver { } float fontHeight = mBatteryPercentView.getPaint().getFontMetricsInt(null); mBatteryPercentView.setLineHeight(TypedValue.COMPLEX_UNIT_PX, fontHeight); + if (gsfQuickSettings()) { + mBatteryPercentView.setTypeface(Typeface.create("gsf-label-large", Typeface.NORMAL)); + } if (mTextColor != 0) mBatteryPercentView.setTextColor(mTextColor); addView(mBatteryPercentView, new LayoutParams( LayoutParams.WRAP_CONTENT, diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/ui/BouncerMessageView.kt b/packages/SystemUI/src/com/android/systemui/bouncer/ui/BouncerMessageView.kt index 79a11ee88826..ad49fd03c577 100644 --- a/packages/SystemUI/src/com/android/systemui/bouncer/ui/BouncerMessageView.kt +++ b/packages/SystemUI/src/com/android/systemui/bouncer/ui/BouncerMessageView.kt @@ -17,11 +17,13 @@ package com.android.systemui.bouncer.ui import android.content.Context +import android.graphics.Typeface import android.util.AttributeSet import android.widget.LinearLayout import com.android.keyguard.BouncerKeyguardMessageArea import com.android.keyguard.KeyguardMessageArea import com.android.keyguard.KeyguardMessageAreaController +import com.android.systemui.Flags import com.android.systemui.res.R class BouncerMessageView : LinearLayout { @@ -37,10 +39,20 @@ class BouncerMessageView : LinearLayout { var secondaryMessageView: BouncerKeyguardMessageArea? = null var primaryMessage: KeyguardMessageAreaController<KeyguardMessageArea>? = null var secondaryMessage: KeyguardMessageAreaController<KeyguardMessageArea>? = null + override fun onFinishInflate() { super.onFinishInflate() primaryMessageView = findViewById(R.id.bouncer_primary_message_area) secondaryMessageView = findViewById(R.id.bouncer_secondary_message_area) + + if (Flags.gsfBouncer()) { + primaryMessageView?.apply { + typeface = Typeface.create("gsf-title-large-emphasized", Typeface.NORMAL) + } + secondaryMessageView?.apply { + typeface = Typeface.create("gsf-title-medium-emphasized", Typeface.NORMAL) + } + } } fun init(factory: KeyguardMessageAreaController.Factory) { diff --git a/packages/SystemUI/src/com/android/systemui/brightness/ui/compose/BrightnessSlider.kt b/packages/SystemUI/src/com/android/systemui/brightness/ui/compose/BrightnessSlider.kt index ccd953de7d03..5bad9fc9c5d7 100644 --- a/packages/SystemUI/src/com/android/systemui/brightness/ui/compose/BrightnessSlider.kt +++ b/packages/SystemUI/src/com/android/systemui/brightness/ui/compose/BrightnessSlider.kt @@ -16,6 +16,7 @@ package com.android.systemui.brightness.ui.compose +import android.view.MotionEvent import androidx.compose.animation.core.animateFloatAsState import androidx.compose.foundation.clickable import androidx.compose.foundation.gestures.Orientation @@ -41,6 +42,7 @@ import androidx.compose.ui.geometry.CornerRadius import androidx.compose.ui.geometry.Offset import androidx.compose.ui.geometry.Size import androidx.compose.ui.graphics.Color +import androidx.compose.ui.input.pointer.pointerInteropFilter import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.colorResource import androidx.compose.ui.res.stringResource @@ -221,7 +223,16 @@ fun BrightnessSliderContainer( ) .then(if (viewModel.showMirror) Modifier.drawInOverlay() else Modifier) .sliderBackground(containerColor) - .fillMaxWidth(), + .fillMaxWidth() + .pointerInteropFilter { + if ( + it.actionMasked == MotionEvent.ACTION_UP || + it.actionMasked == MotionEvent.ACTION_CANCEL + ) { + viewModel.emitBrightnessTouchForFalsing() + } + false + }, formatter = viewModel::formatValue, hapticsViewModelFactory = viewModel.hapticsViewModelFactory, ) diff --git a/packages/SystemUI/src/com/android/systemui/brightness/ui/viewmodel/BrightnessSliderViewModel.kt b/packages/SystemUI/src/com/android/systemui/brightness/ui/viewmodel/BrightnessSliderViewModel.kt index 1630ee58449f..7df71550d43d 100644 --- a/packages/SystemUI/src/com/android/systemui/brightness/ui/viewmodel/BrightnessSliderViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/brightness/ui/viewmodel/BrightnessSliderViewModel.kt @@ -16,12 +16,14 @@ package com.android.systemui.brightness.ui.viewmodel -import androidx.compose.runtime.getValue import android.content.Context import androidx.annotation.StringRes +import androidx.compose.runtime.getValue import com.android.systemui.brightness.domain.interactor.BrightnessPolicyEnforcementInteractor import com.android.systemui.brightness.domain.interactor.ScreenBrightnessInteractor import com.android.systemui.brightness.shared.model.GammaBrightness +import com.android.systemui.classifier.Classifier +import com.android.systemui.classifier.domain.interactor.FalsingInteractor import com.android.systemui.common.shared.model.ContentDescription import com.android.systemui.common.shared.model.Icon import com.android.systemui.common.shared.model.Text @@ -52,6 +54,7 @@ constructor( private val brightnessPolicyEnforcementInteractor: BrightnessPolicyEnforcementInteractor, val hapticsViewModelFactory: SliderHapticsViewModel.Factory, private val brightnessMirrorShowingInteractor: BrightnessMirrorShowingInteractor, + private val falsingInteractor: FalsingInteractor, @Assisted private val supportsMirroring: Boolean, private val brightnessWarningToast: BrightnessWarningToast, ) : ExclusiveActivatable() { @@ -87,6 +90,10 @@ constructor( brightnessWarningToast.show(viewContext, resId) } + fun emitBrightnessTouchForFalsing() { + falsingInteractor.isFalseTouch(Classifier.BRIGHTNESS_SLIDER) + } + /** * As a brightness slider is dragged, the corresponding events should be sent using this method. */ diff --git a/packages/SystemUI/src/com/android/systemui/classifier/domain/interactor/FalsingInteractor.kt b/packages/SystemUI/src/com/android/systemui/classifier/domain/interactor/FalsingInteractor.kt index 57e9ade30bb5..074b64e0fab0 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/domain/interactor/FalsingInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/classifier/domain/interactor/FalsingInteractor.kt @@ -23,6 +23,7 @@ import com.android.systemui.classifier.FalsingCollector import com.android.systemui.classifier.FalsingCollectorActual import com.android.systemui.dagger.SysUISingleton import com.android.systemui.plugins.FalsingManager +import com.android.systemui.plugins.FalsingManager.Penalty import javax.inject.Inject /** @@ -63,12 +64,13 @@ constructor( * Inserts the given [result] into the falsing system, affecting future runs of the classifier * as if this was a result that had organically happened before. */ - fun updateFalseConfidence( - result: FalsingClassifier.Result, - ) = collector.updateFalseConfidence(result) + fun updateFalseConfidence(result: FalsingClassifier.Result) = + collector.updateFalseConfidence(result) /** Returns `true` if the gesture should be rejected. */ - fun isFalseTouch( - @Classifier.InteractionType interactionType: Int, - ): Boolean = manager.isFalseTouch(interactionType) + fun isFalseTouch(@Classifier.InteractionType interactionType: Int): Boolean = + manager.isFalseTouch(interactionType) + + /** Returns `true` if the tap gesture should be rejected */ + fun isFalseTap(@Penalty penalty: Int): Boolean = manager.isFalseTap(penalty) } diff --git a/packages/SystemUI/src/com/android/systemui/communal/CommunalSceneStartable.kt b/packages/SystemUI/src/com/android/systemui/communal/CommunalSceneStartable.kt index db9a7f5e81ae..d648b9c6442b 100644 --- a/packages/SystemUI/src/com/android/systemui/communal/CommunalSceneStartable.kt +++ b/packages/SystemUI/src/com/android/systemui/communal/CommunalSceneStartable.kt @@ -23,6 +23,7 @@ import com.android.compose.animation.scene.SceneKey import com.android.compose.animation.scene.TransitionKey import com.android.internal.logging.UiEventLogger import com.android.systemui.CoreStartable +import com.android.systemui.Flags.communalHubOnMobile import com.android.systemui.Flags.communalSceneKtfRefactor import com.android.systemui.communal.domain.interactor.CommunalInteractor import com.android.systemui.communal.domain.interactor.CommunalSceneInteractor @@ -216,6 +217,9 @@ constructor( communalSceneInteractor.changeScene( newScene = CommunalScenes.Blank, loggingReason = "hub timeout", + transitionKey = + if (communalHubOnMobile()) CommunalTransitionKeys.SimpleFade + else null, ) uiEventLogger.log(CommunalUiEvent.COMMUNAL_HUB_TIMEOUT) } diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUICoreStartableModule.kt b/packages/SystemUI/src/com/android/systemui/dagger/SystemUICoreStartableModule.kt index 7b91eaecd33a..38cfb9b333a8 100644 --- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUICoreStartableModule.kt +++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUICoreStartableModule.kt @@ -25,6 +25,8 @@ import com.android.systemui.back.domain.interactor.BackActionInteractor import com.android.systemui.biometrics.BiometricNotificationService import com.android.systemui.bouncer.domain.startable.BouncerStartable import com.android.systemui.clipboardoverlay.ClipboardListener +import com.android.systemui.complication.ComplicationTypesUpdater +import com.android.systemui.complication.DreamClockTimeComplication import com.android.systemui.controls.dagger.StartControlsStartableModule import com.android.systemui.dagger.qualifiers.PerUser import com.android.systemui.dreams.AssistantAttentionMonitor @@ -337,4 +339,18 @@ abstract class SystemUICoreStartableModule { abstract fun bindDreamOverlayRegistrant( dreamOverlayRegistrant: DreamOverlayRegistrant ): CoreStartable + + /** Inject into DreamClockTimeComplication.Registrant */ + @Binds + @IntoMap + @ClassKey(DreamClockTimeComplication.Registrant::class) + abstract fun bindDreamClockTimeComplicationRegistrant( + registrant: DreamClockTimeComplication.Registrant + ): CoreStartable + + /** Inject into ComplicationTypesUpdater. */ + @Binds + @IntoMap + @ClassKey(ComplicationTypesUpdater::class) + abstract fun bindComplicationTypesUpdater(updater: ComplicationTypesUpdater): CoreStartable } diff --git a/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryInteractor.kt b/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryInteractor.kt index 400d09742d13..2e1096fcae36 100644 --- a/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryInteractor.kt @@ -84,30 +84,53 @@ constructor( ) /** + * Emits `true` when the current scene switches to [Scenes.Gone] for the first time after having + * been on [Scenes.Lockscreen]. + * + * Different from [isDeviceEntered] such that the current scene must actually go through + * [Scenes.Gone] to produce a `true`. [isDeviceEntered] also takes into account the navigation + * back stack and will produce a `true` value even when the current scene is still not + * [Scenes.Gone] but the bottommost entry of the navigation back stack switched from + * [Scenes.Lockscreen] to [Scenes.Gone] while the user is staring at another scene. + */ + val isDeviceEnteredDirectly: StateFlow<Boolean> = + sceneInteractor.currentScene + .filter { currentScene -> + currentScene == Scenes.Gone || currentScene == Scenes.Lockscreen + } + .mapLatestConflated { scene -> + if (scene == Scenes.Gone) { + // Make sure device unlock status is definitely unlocked before we + // consider the device "entered". + deviceUnlockedInteractor.deviceUnlockStatus.first { it.isUnlocked } + true + } else { + false + } + } + .stateIn( + scope = applicationScope, + started = SharingStarted.Eagerly, + initialValue = false, + ) + + /** * Whether the device has been entered (i.e. the lockscreen has been dismissed, by any method). * This can be `false` when the device is unlocked, e.g. when the user still needs to swipe away * the non-secure lockscreen, even though they've already authenticated. * * Note: This does not imply that the lockscreen is visible or not. + * + * Different from [isDeviceEnteredDirectly] such that the current scene doesn't actually have to + * go through [Scenes.Gone] to produce a `true`. [isDeviceEnteredDirectly] doesn't take the + * navigation back stack into account and will only produce a `true` value even when the current + * scene is actually [Scenes.Gone]. */ val isDeviceEntered: StateFlow<Boolean> = combine( // This flow emits true when the currentScene switches to Gone for the first time // after having been on Lockscreen. - sceneInteractor.currentScene - .filter { currentScene -> - currentScene == Scenes.Gone || currentScene == Scenes.Lockscreen - } - .mapLatestConflated { scene -> - if (scene == Scenes.Gone) { - // Make sure device unlock status is definitely unlocked before we - // consider the device "entered". - deviceUnlockedInteractor.deviceUnlockStatus.first { it.isUnlocked } - true - } else { - false - } - }, + isDeviceEnteredDirectly, // This flow emits true only if the bottom of the navigation back stack has been // switched from Lockscreen to Gone. In other words, only if the device was unlocked // while visiting at least one scene "above" the Lockscreen scene. diff --git a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java index 408fe831d74c..43b7cedcd767 100644 --- a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java +++ b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java @@ -18,6 +18,7 @@ package com.android.systemui.dreams; import static android.service.dreams.Flags.dreamWakeRedirect; +import static com.android.systemui.Flags.communalHubOnMobile; import static com.android.systemui.Flags.glanceableHubAllowKeyguardWhenDreaming; import static com.android.systemui.dreams.dagger.DreamModule.DREAM_OVERLAY_WINDOW_TITLE; import static com.android.systemui.dreams.dagger.DreamModule.DREAM_TOUCH_INSET_MANAGER; @@ -54,12 +55,14 @@ import com.android.internal.logging.UiEventLogger; import com.android.internal.policy.PhoneWindow; import com.android.keyguard.KeyguardUpdateMonitor; import com.android.keyguard.KeyguardUpdateMonitorCallback; +import com.android.systemui.ambient.touch.TouchHandler; import com.android.systemui.ambient.touch.TouchMonitor; import com.android.systemui.ambient.touch.dagger.AmbientTouchComponent; import com.android.systemui.ambient.touch.scrim.ScrimManager; import com.android.systemui.communal.domain.interactor.CommunalInteractor; import com.android.systemui.communal.shared.log.CommunalUiEvent; import com.android.systemui.communal.shared.model.CommunalScenes; +import com.android.systemui.communal.shared.model.CommunalTransitionKeys; import com.android.systemui.complication.dagger.ComplicationComponent; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.dreams.dagger.DreamOverlayComponent; @@ -76,8 +79,8 @@ import com.android.systemui.util.concurrency.DelayableExecutor; import kotlinx.coroutines.Job; import java.util.ArrayList; -import java.util.Arrays; import java.util.HashSet; +import java.util.List; import java.util.concurrent.CancellationException; import java.util.function.Consumer; @@ -483,11 +486,16 @@ public class DreamOverlayService extends android.service.dreams.DreamOverlayServ final DreamOverlayComponent dreamOverlayComponent = mDreamOverlayComponentFactory.create( mLifecycleOwner, complicationComponent.getComplicationHostViewController(), mTouchInsetManager); + + final ArrayList<TouchHandler> touchHandlers = new ArrayList<>( + List.of(dreamComplicationComponent.getHideComplicationTouchHandler())); + if (!communalHubOnMobile()) { + // Do not add the communal touch handler for glanceable hub v2 since there is no dream + // to hub swipe gesture. + touchHandlers.add(dreamOverlayComponent.getCommunalTouchHandler()); + } final AmbientTouchComponent ambientTouchComponent = mAmbientTouchComponentFactory.create( - mLifecycleOwner, - new HashSet<>(Arrays.asList( - dreamComplicationComponent.getHideComplicationTouchHandler(), - dreamOverlayComponent.getCommunalTouchHandler())), TAG); + mLifecycleOwner, new HashSet<>(touchHandlers), TAG); setLifecycleStateLocked(Lifecycle.State.STARTED); @@ -568,7 +576,7 @@ public class DreamOverlayService extends android.service.dreams.DreamOverlayServ } else { mCommunalInteractor.changeScene(CommunalScenes.Communal, "dream wake requested", - null); + communalHubOnMobile() ? CommunalTransitionKeys.INSTANCE.getSimpleFade() : null); } } diff --git a/packages/SystemUI/src/com/android/systemui/dreams/ui/viewmodel/DreamUserActionsViewModel.kt b/packages/SystemUI/src/com/android/systemui/dreams/ui/viewmodel/DreamUserActionsViewModel.kt index b37206a4fef7..160574fa2244 100644 --- a/packages/SystemUI/src/com/android/systemui/dreams/ui/viewmodel/DreamUserActionsViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/dreams/ui/viewmodel/DreamUserActionsViewModel.kt @@ -19,6 +19,7 @@ package com.android.systemui.dreams.ui.viewmodel import com.android.compose.animation.scene.Swipe import com.android.compose.animation.scene.UserAction import com.android.compose.animation.scene.UserActionResult +import com.android.systemui.communal.domain.interactor.CommunalInteractor import com.android.systemui.deviceentry.domain.interactor.DeviceUnlockedInteractor import com.android.systemui.scene.shared.model.Scenes import com.android.systemui.scene.ui.viewmodel.UserActionsViewModel @@ -38,6 +39,7 @@ import kotlinx.coroutines.flow.map class DreamUserActionsViewModel @AssistedInject constructor( + private val communalInteractor: CommunalInteractor, private val deviceUnlockedInteractor: DeviceUnlockedInteractor, private val shadeInteractor: ShadeInteractor, ) : UserActionsViewModel() { @@ -50,10 +52,13 @@ constructor( } else { combine( deviceUnlockedInteractor.deviceUnlockStatus.map { it.isUnlocked }, + communalInteractor.isCommunalAvailable, shadeInteractor.shadeMode, - ) { isDeviceUnlocked, shadeMode -> + ) { isDeviceUnlocked, isCommunalAvailable, shadeMode -> buildList { - add(Swipe.Start to Scenes.Communal) + if (isCommunalAvailable) { + add(Swipe.Start to Scenes.Communal) + } val bouncerOrGone = if (isDeviceUnlocked) Scenes.Gone else Scenes.Bouncer diff --git a/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/KeyboardTouchpadTutorialCoreStartable.kt b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/KeyboardTouchpadTutorialCoreStartable.kt index 092a25aa1cad..7bd09b915d1a 100644 --- a/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/KeyboardTouchpadTutorialCoreStartable.kt +++ b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/KeyboardTouchpadTutorialCoreStartable.kt @@ -20,6 +20,7 @@ import android.content.BroadcastReceiver import android.content.Context import android.content.Intent import android.content.IntentFilter +import android.os.Build import android.os.UserHandle import com.android.systemui.CoreStartable import com.android.systemui.broadcast.BroadcastDispatcher @@ -52,13 +53,13 @@ constructor( receiver = object : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { - applicationContext.startActivityAsUser( - Intent( - applicationContext, - KeyboardTouchpadTutorialActivity::class.java - ), - UserHandle.SYSTEM - ) + val activityIntent = + Intent(applicationContext, KeyboardTouchpadTutorialActivity::class.java) + if (Build.IS_DEBUGGABLE) { + // helpful for testing different cases but pointless for public builds + intent.extras?.let { activityIntent.putExtras(it) } + } + applicationContext.startActivityAsUser(activityIntent, UserHandle.SYSTEM) } }, filter = IntentFilter("com.android.systemui.action.KEYBOARD_TOUCHPAD_TUTORIAL"), diff --git a/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/KeyboardTouchpadTutorialMetricsLogger.kt b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/KeyboardTouchpadTutorialMetricsLogger.kt index 144c5ead1bb8..ae6cbbc4315e 100644 --- a/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/KeyboardTouchpadTutorialMetricsLogger.kt +++ b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/KeyboardTouchpadTutorialMetricsLogger.kt @@ -18,8 +18,8 @@ package com.android.systemui.inputdevice.tutorial import com.android.systemui.inputdevice.tutorial.ui.view.KeyboardTouchpadTutorialActivity.Companion.INTENT_TUTORIAL_ENTRY_POINT_CONTEXTUAL_EDU import com.android.systemui.inputdevice.tutorial.ui.view.KeyboardTouchpadTutorialActivity.Companion.INTENT_TUTORIAL_ENTRY_POINT_SCHEDULER -import com.android.systemui.inputdevice.tutorial.ui.view.KeyboardTouchpadTutorialActivity.Companion.INTENT_TUTORIAL_TYPE_KEYBOARD -import com.android.systemui.inputdevice.tutorial.ui.view.KeyboardTouchpadTutorialActivity.Companion.INTENT_TUTORIAL_TYPE_TOUCHPAD +import com.android.systemui.inputdevice.tutorial.ui.view.KeyboardTouchpadTutorialActivity.Companion.INTENT_TUTORIAL_SCOPE_KEYBOARD +import com.android.systemui.inputdevice.tutorial.ui.view.KeyboardTouchpadTutorialActivity.Companion.INTENT_TUTORIAL_SCOPE_TOUCHPAD import com.android.systemui.shared.system.SysUiStatsLog import javax.inject.Inject @@ -37,9 +37,9 @@ class KeyboardTouchpadTutorialMetricsLogger @Inject constructor() { val tutorialType = when (tutorialTypeExtra) { - INTENT_TUTORIAL_TYPE_KEYBOARD -> + INTENT_TUTORIAL_SCOPE_KEYBOARD -> SysUiStatsLog.PERIPHERAL_TUTORIAL_LAUNCHED__TUTORIAL_TYPE__KEYBOARD - INTENT_TUTORIAL_TYPE_TOUCHPAD -> + INTENT_TUTORIAL_SCOPE_TOUCHPAD -> SysUiStatsLog.PERIPHERAL_TUTORIAL_LAUNCHED__TUTORIAL_TYPE__TOUCHPAD else -> SysUiStatsLog.PERIPHERAL_TUTORIAL_LAUNCHED__TUTORIAL_TYPE__BOTH } diff --git a/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/ui/TutorialNotificationCoordinator.kt b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/ui/TutorialNotificationCoordinator.kt index 9dae64921d26..3cba70e39e66 100644 --- a/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/ui/TutorialNotificationCoordinator.kt +++ b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/ui/TutorialNotificationCoordinator.kt @@ -34,10 +34,10 @@ import com.android.systemui.inputdevice.tutorial.domain.interactor.TutorialSched import com.android.systemui.inputdevice.tutorial.ui.view.KeyboardTouchpadTutorialActivity import com.android.systemui.inputdevice.tutorial.ui.view.KeyboardTouchpadTutorialActivity.Companion.INTENT_TUTORIAL_ENTRY_POINT_KEY import com.android.systemui.inputdevice.tutorial.ui.view.KeyboardTouchpadTutorialActivity.Companion.INTENT_TUTORIAL_ENTRY_POINT_SCHEDULER -import com.android.systemui.inputdevice.tutorial.ui.view.KeyboardTouchpadTutorialActivity.Companion.INTENT_TUTORIAL_TYPE_BOTH -import com.android.systemui.inputdevice.tutorial.ui.view.KeyboardTouchpadTutorialActivity.Companion.INTENT_TUTORIAL_TYPE_KEY -import com.android.systemui.inputdevice.tutorial.ui.view.KeyboardTouchpadTutorialActivity.Companion.INTENT_TUTORIAL_TYPE_KEYBOARD -import com.android.systemui.inputdevice.tutorial.ui.view.KeyboardTouchpadTutorialActivity.Companion.INTENT_TUTORIAL_TYPE_TOUCHPAD +import com.android.systemui.inputdevice.tutorial.ui.view.KeyboardTouchpadTutorialActivity.Companion.INTENT_TUTORIAL_SCOPE_ALL +import com.android.systemui.inputdevice.tutorial.ui.view.KeyboardTouchpadTutorialActivity.Companion.INTENT_TUTORIAL_SCOPE_KEY +import com.android.systemui.inputdevice.tutorial.ui.view.KeyboardTouchpadTutorialActivity.Companion.INTENT_TUTORIAL_SCOPE_KEYBOARD +import com.android.systemui.inputdevice.tutorial.ui.view.KeyboardTouchpadTutorialActivity.Companion.INTENT_TUTORIAL_SCOPE_TOUCHPAD import com.android.systemui.res.R import com.android.systemui.settings.UserTracker import javax.inject.Inject @@ -108,7 +108,7 @@ constructor( private fun createPendingIntent(tutorialType: String): PendingIntent { val intent = Intent(context, KeyboardTouchpadTutorialActivity::class.java).apply { - putExtra(INTENT_TUTORIAL_TYPE_KEY, tutorialType) + putExtra(INTENT_TUTORIAL_SCOPE_KEY, tutorialType) putExtra(INTENT_TUTORIAL_ENTRY_POINT_KEY, INTENT_TUTORIAL_ENTRY_POINT_SCHEDULER) flags = Intent.FLAG_ACTIVITY_NEW_TASK } @@ -128,13 +128,13 @@ constructor( NotificationInfo( context.getString(R.string.launch_keyboard_tutorial_notification_title), context.getString(R.string.launch_keyboard_tutorial_notification_content), - INTENT_TUTORIAL_TYPE_KEYBOARD, + INTENT_TUTORIAL_SCOPE_KEYBOARD, ) TutorialType.TOUCHPAD -> NotificationInfo( context.getString(R.string.launch_touchpad_tutorial_notification_title), context.getString(R.string.launch_touchpad_tutorial_notification_content), - INTENT_TUTORIAL_TYPE_TOUCHPAD, + INTENT_TUTORIAL_SCOPE_TOUCHPAD, ) TutorialType.BOTH -> NotificationInfo( @@ -144,7 +144,7 @@ constructor( context.getString( R.string.launch_keyboard_touchpad_tutorial_notification_content ), - INTENT_TUTORIAL_TYPE_BOTH, + INTENT_TUTORIAL_SCOPE_ALL, ) TutorialType.NONE -> null } diff --git a/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/ui/view/KeyboardTouchpadTutorialActivity.kt b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/ui/view/KeyboardTouchpadTutorialActivity.kt index fee08b31bd93..67b307fb7a36 100644 --- a/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/ui/view/KeyboardTouchpadTutorialActivity.kt +++ b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/ui/view/KeyboardTouchpadTutorialActivity.kt @@ -56,10 +56,13 @@ constructor( ) : ComponentActivity() { companion object { - const val INTENT_TUTORIAL_TYPE_KEY = "tutorial_type" - const val INTENT_TUTORIAL_TYPE_TOUCHPAD = "touchpad" - const val INTENT_TUTORIAL_TYPE_KEYBOARD = "keyboard" - const val INTENT_TUTORIAL_TYPE_BOTH = "both" + const val INTENT_TUTORIAL_SCOPE_KEY = "tutorial_scope" + const val INTENT_TUTORIAL_SCOPE_TOUCHPAD = "touchpad" + const val INTENT_TUTORIAL_SCOPE_TOUCHPAD_BACK = "touchpad_back" + const val INTENT_TUTORIAL_SCOPE_TOUCHPAD_HOME = "touchpad_home" + const val INTENT_TUTORIAL_SCOPE_KEYBOARD = "keyboard" + const val INTENT_TUTORIAL_SCOPE_ALL = "all" + const val INTENT_TUTORIAL_ENTRY_POINT_KEY = "entry_point" const val INTENT_TUTORIAL_ENTRY_POINT_SCHEDULER = "scheduler" const val INTENT_TUTORIAL_ENTRY_POINT_CONTEXTUAL_EDU = "contextual_edu" @@ -94,7 +97,7 @@ constructor( if (savedInstanceState == null) { metricsLogger.logPeripheralTutorialLaunched( intent.getStringExtra(INTENT_TUTORIAL_ENTRY_POINT_KEY), - intent.getStringExtra(INTENT_TUTORIAL_TYPE_KEY), + intent.getStringExtra(INTENT_TUTORIAL_SCOPE_KEY), ) logger.logOpenTutorial(TutorialContext.KEYBOARD_TOUCHPAD_TUTORIAL) } diff --git a/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/ui/viewmodel/KeyboardTouchpadTutorialViewModel.kt b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/ui/viewmodel/KeyboardTouchpadTutorialViewModel.kt index 896bdc068154..eeb4b697a5fc 100644 --- a/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/ui/viewmodel/KeyboardTouchpadTutorialViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/ui/viewmodel/KeyboardTouchpadTutorialViewModel.kt @@ -22,15 +22,21 @@ import androidx.lifecycle.LifecycleOwner import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope +import com.android.app.tracing.coroutines.launchTraced as launch import com.android.systemui.inputdevice.tutorial.InputDeviceTutorialLogger import com.android.systemui.inputdevice.tutorial.domain.interactor.ConnectionState import com.android.systemui.inputdevice.tutorial.domain.interactor.KeyboardTouchpadConnectionInteractor -import com.android.systemui.inputdevice.tutorial.ui.view.KeyboardTouchpadTutorialActivity.Companion.INTENT_TUTORIAL_TYPE_KEY -import com.android.systemui.inputdevice.tutorial.ui.view.KeyboardTouchpadTutorialActivity.Companion.INTENT_TUTORIAL_TYPE_KEYBOARD +import com.android.systemui.inputdevice.tutorial.ui.view.KeyboardTouchpadTutorialActivity.Companion.INTENT_TUTORIAL_SCOPE_ALL +import com.android.systemui.inputdevice.tutorial.ui.view.KeyboardTouchpadTutorialActivity.Companion.INTENT_TUTORIAL_SCOPE_KEY +import com.android.systemui.inputdevice.tutorial.ui.view.KeyboardTouchpadTutorialActivity.Companion.INTENT_TUTORIAL_SCOPE_KEYBOARD +import com.android.systemui.inputdevice.tutorial.ui.view.KeyboardTouchpadTutorialActivity.Companion.INTENT_TUTORIAL_SCOPE_TOUCHPAD +import com.android.systemui.inputdevice.tutorial.ui.view.KeyboardTouchpadTutorialActivity.Companion.INTENT_TUTORIAL_SCOPE_TOUCHPAD_BACK +import com.android.systemui.inputdevice.tutorial.ui.view.KeyboardTouchpadTutorialActivity.Companion.INTENT_TUTORIAL_SCOPE_TOUCHPAD_HOME import com.android.systemui.inputdevice.tutorial.ui.viewmodel.RequiredHardware.KEYBOARD import com.android.systemui.inputdevice.tutorial.ui.viewmodel.RequiredHardware.TOUCHPAD import com.android.systemui.inputdevice.tutorial.ui.viewmodel.Screen.ACTION_KEY import com.android.systemui.inputdevice.tutorial.ui.viewmodel.Screen.BACK_GESTURE +import com.android.systemui.inputdevice.tutorial.ui.viewmodel.Screen.HOME_GESTURE import com.android.systemui.touchpad.tutorial.domain.interactor.TouchpadGesturesInteractor import dagger.assisted.Assisted import dagger.assisted.AssistedFactory @@ -42,27 +48,23 @@ import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.filterNot import kotlinx.coroutines.flow.runningFold -import com.android.app.tracing.coroutines.launchTraced as launch class KeyboardTouchpadTutorialViewModel( private val gesturesInteractor: Optional<TouchpadGesturesInteractor>, private val keyboardTouchpadConnectionInteractor: KeyboardTouchpadConnectionInteractor, private val hasTouchpadTutorialScreens: Boolean, private val logger: InputDeviceTutorialLogger, - handle: SavedStateHandle + handle: SavedStateHandle, ) : ViewModel(), DefaultLifecycleObserver { - private fun startingScreen(handle: SavedStateHandle): Screen { - val tutorialType: String? = handle[INTENT_TUTORIAL_TYPE_KEY] - return if (tutorialType == INTENT_TUTORIAL_TYPE_KEYBOARD) ACTION_KEY else BACK_GESTURE - } - private val _screen = MutableStateFlow(startingScreen(handle)) val screen: Flow<Screen> = _screen.filter { it.canBeShown() } private val _closeActivity: MutableStateFlow<Boolean> = MutableStateFlow(false) val closeActivity: StateFlow<Boolean> = _closeActivity + private val screenSequence: ScreenSequence = chooseScreenSequence(handle) + private val screensBackStack = ArrayDeque(listOf(_screen.value)) private var connectionState: ConnectionState = @@ -105,6 +107,33 @@ class KeyboardTouchpadTutorialViewModel( } } + private fun startingScreen(handle: SavedStateHandle): Screen { + val scope: String? = handle[INTENT_TUTORIAL_SCOPE_KEY] + return when (scope) { + INTENT_TUTORIAL_SCOPE_KEYBOARD -> ACTION_KEY + INTENT_TUTORIAL_SCOPE_TOUCHPAD_HOME -> HOME_GESTURE + INTENT_TUTORIAL_SCOPE_TOUCHPAD, + INTENT_TUTORIAL_SCOPE_ALL, + INTENT_TUTORIAL_SCOPE_TOUCHPAD_BACK -> BACK_GESTURE + else -> { + logger.w("Intent didn't specify tutorial scope, starting with default") + BACK_GESTURE + } + } + } + + private fun chooseScreenSequence(handle: SavedStateHandle): ScreenSequence { + val scope: String? = handle[INTENT_TUTORIAL_SCOPE_KEY] + return if ( + scope == INTENT_TUTORIAL_SCOPE_TOUCHPAD_HOME || + scope == INTENT_TUTORIAL_SCOPE_TOUCHPAD_BACK + ) { + SingleScreenOnly + } else { + AllSupportedScreens + } + } + override fun onCleared() { // this shouldn't be needed as onTutorialInvisible should already clear device state but // it'd be really bad if we'd block gestures/shortcuts after leaving tutorial so just to be @@ -121,13 +150,13 @@ class KeyboardTouchpadTutorialViewModel( } fun onDoneButtonClicked() { - var nextScreen = _screen.value.next() + var nextScreen = screenSequence.nextScreen(_screen.value) while (nextScreen != null) { if (requiredHardwarePresent(nextScreen)) { break } logger.logNextScreenMissingHardware(nextScreen) - nextScreen = nextScreen.next() + nextScreen = screenSequence.nextScreen(nextScreen) } if (nextScreen == null) { logger.d("Final screen reached, closing tutorial") @@ -192,33 +221,44 @@ class KeyboardTouchpadTutorialViewModel( override fun <T : ViewModel> create( key: String, modelClass: Class<T>, - handle: SavedStateHandle + handle: SavedStateHandle, ): T = KeyboardTouchpadTutorialViewModel( gesturesInteractor, keyboardTouchpadConnected, hasTouchpadTutorialScreens, logger, - handle + handle, ) as T } + + private interface ScreenSequence { + fun nextScreen(current: Screen): Screen? + } + + private object AllSupportedScreens : ScreenSequence { + override fun nextScreen(current: Screen): Screen? { + return when (current) { + BACK_GESTURE -> HOME_GESTURE + HOME_GESTURE -> ACTION_KEY + ACTION_KEY -> null + } + } + } + + private object SingleScreenOnly : ScreenSequence { + override fun nextScreen(current: Screen): Screen? = null + } } enum class RequiredHardware { TOUCHPAD, - KEYBOARD + KEYBOARD, } enum class Screen(val requiredHardware: RequiredHardware) { BACK_GESTURE(requiredHardware = TOUCHPAD), HOME_GESTURE(requiredHardware = TOUCHPAD), - ACTION_KEY(requiredHardware = KEYBOARD); - - fun next(): Screen? = - when (this) { - BACK_GESTURE -> HOME_GESTURE - HOME_GESTURE -> ACTION_KEY - ACTION_KEY -> null - } + ACTION_KEY(requiredHardware = KEYBOARD), } diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/data/repository/CustomShortcutCategoriesRepository.kt b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/data/repository/CustomShortcutCategoriesRepository.kt index 99cafd3daacb..321fd57d3e8b 100644 --- a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/data/repository/CustomShortcutCategoriesRepository.kt +++ b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/data/repository/CustomShortcutCategoriesRepository.kt @@ -28,6 +28,7 @@ import android.hardware.input.InputManager.CUSTOM_INPUT_GESTURE_RESULT_ERROR_RES import android.hardware.input.InputManager.CUSTOM_INPUT_GESTURE_RESULT_SUCCESS import android.hardware.input.InputSettings import android.hardware.input.KeyGestureEvent +import android.hardware.input.KeyGestureEvent.KeyGestureType import android.util.Log import androidx.annotation.VisibleForTesting import androidx.compose.runtime.mutableStateOf @@ -44,6 +45,8 @@ import com.android.systemui.keyboard.shortcut.shared.model.ShortcutCustomization import com.android.systemui.keyboard.shortcut.shared.model.ShortcutHelperState.Active import com.android.systemui.keyboard.shortcut.shared.model.ShortcutKey import com.android.systemui.settings.UserTracker +import javax.inject.Inject +import kotlin.coroutines.CoroutineContext import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow @@ -52,8 +55,6 @@ import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.withContext -import javax.inject.Inject -import kotlin.coroutines.CoroutineContext @SysUISingleton class CustomShortcutCategoriesRepository @@ -65,7 +66,7 @@ constructor( @Background private val bgCoroutineContext: CoroutineContext, private val shortcutCategoriesUtils: ShortcutCategoriesUtils, private val context: Context, - private val inputGestureMaps: InputGestureMaps + private val inputGestureMaps: InputGestureMaps, ) : ShortcutCategoriesRepository { private val userContext: Context @@ -130,9 +131,7 @@ constructor( emptyList() } else { val customInputGesturesForUser: List<InputGestureData> = - if (InputSettings.isCustomizableInputGesturesFeatureFlagEnabled()) { - inputManager.getCustomInputGestures(/* filter= */ null) - } else emptyList() + getCustomInputGestures() val sources = toInternalGroupSources(customInputGesturesForUser) val supportedKeyCodes = shortcutCategoriesUtils.fetchSupportedKeyCodes( @@ -173,16 +172,20 @@ constructor( .addKeyGestureTypeFromShortcutLabel() .addTriggerFromSelectedKeyCombination() .build() - // TODO(b/379648200) add app launch data for application categories shortcut after - // dynamic - // label/icon mapping implementation + // TODO(b/379648200) add app launch data after dynamic label/icon mapping implementation } catch (e: IllegalArgumentException) { Log.w(TAG, "could not add custom shortcut: $e") return null } } - suspend fun confirmAndSetShortcutCurrentlyBeingCustomized(): ShortcutCustomizationRequestResult { + private fun retrieveInputGestureDataForShortcutBeingDeleted(): InputGestureData? { + val keyGestureType = getKeyGestureTypeFromShortcutBeingDeletedLabel() + return getCustomInputGestures().firstOrNull { it.action.keyGestureType() == keyGestureType } + } + + suspend fun confirmAndSetShortcutCurrentlyBeingCustomized(): + ShortcutCustomizationRequestResult { return withContext(bgCoroutineContext) { val inputGestureData = buildInputGestureDataForShortcutBeingCustomized() @@ -201,24 +204,79 @@ constructor( } } + suspend fun deleteShortcutCurrentlyBeingCustomized(): + ShortcutCustomizationRequestResult { + return withContext(bgCoroutineContext) { + val inputGestureData = + retrieveInputGestureDataForShortcutBeingDeleted() + ?: return@withContext ShortcutCustomizationRequestResult.ERROR_OTHER + return@withContext when ( + val result = inputManager.removeCustomInputGesture(inputGestureData) + ) { + CUSTOM_INPUT_GESTURE_RESULT_SUCCESS -> ShortcutCustomizationRequestResult.SUCCESS + else -> { + Log.w( + TAG, + "Attempted to delete shortcut being customized " + + "${_shortcutBeingCustomized.value} but ran into an error. InputGestureData" + + " = $inputGestureData, error code: $result", + ) + ShortcutCustomizationRequestResult.ERROR_OTHER + } + } + } + } + + private fun getCustomInputGestures(): List<InputGestureData> { + return if (InputSettings.isCustomizableInputGesturesFeatureFlagEnabled()) { + inputManager.getCustomInputGestures(/* filter= */ InputGestureData.Filter.KEY) + } else emptyList() + } + private fun Builder.addKeyGestureTypeFromShortcutLabel(): Builder { + val keyGestureType = getKeyGestureTypeFromShortcutBeingCustomizedLabel() + + if (keyGestureType == null) { + Log.w( + TAG, + "Could not find KeyGestureType for shortcut ${_shortcutBeingCustomized.value}", + ) + return this + } + + return setKeyGestureType(keyGestureType) + } + + @KeyGestureType + private fun getKeyGestureTypeFromShortcutBeingCustomizedLabel(): Int? { val shortcutBeingCustomized = getShortcutBeingCustomized() as? ShortcutCustomizationRequestInfo.Add if (shortcutBeingCustomized == null) { - Log.w(TAG, "User requested to set shortcut but shortcut being customized is null") - return this + Log.w( + TAG, + "Requested key gesture type from label but shortcut being customized is null", + ) + return null } - val keyGestureType = - inputGestureMaps.shortcutLabelToKeyGestureTypeMap[shortcutBeingCustomized.label] + return inputGestureMaps.shortcutLabelToKeyGestureTypeMap[shortcutBeingCustomized.label] + } - if (keyGestureType == null) { - Log.w(TAG, "Could not find KeyGestureType for shortcut $shortcutBeingCustomized") - return this + @KeyGestureType + private fun getKeyGestureTypeFromShortcutBeingDeletedLabel(): Int? { + val shortcutBeingCustomized = + getShortcutBeingCustomized() as? ShortcutCustomizationRequestInfo.Delete + + if (shortcutBeingCustomized == null) { + Log.w( + TAG, + "Requested key gesture type from label but shortcut being customized is null", + ) + return null } - return setKeyGestureType(keyGestureType) + return inputGestureMaps.shortcutLabelToKeyGestureTypeMap[shortcutBeingCustomized.label] } private fun Builder.addTriggerFromSelectedKeyCombination(): Builder { @@ -227,7 +285,7 @@ constructor( Log.w( TAG, "User requested to set shortcut but selected key combination is " + - "$selectedKeyCombination", + "$selectedKeyCombination", ) return this } @@ -235,8 +293,7 @@ constructor( return setTrigger( createKeyTrigger( /* keycode = */ selectedKeyCombination.keyCode, - /* modifierState = */ - shortcutCategoriesUtils.removeUnsupportedModifiers( + /* modifierState = */ shortcutCategoriesUtils.removeUnsupportedModifiers( selectedKeyCombination.modifiers ), ) @@ -256,10 +313,8 @@ constructor( val keyTrigger = gestureData.trigger as KeyTrigger val keyGestureType = gestureData.action.keyGestureType() fetchGroupLabelByGestureType(keyGestureType)?.let { groupLabel -> - toInternalKeyboardShortcutInfo( - keyGestureType, - keyTrigger - )?.let { internalKeyboardShortcutInfo -> + toInternalKeyboardShortcutInfo(keyGestureType, keyTrigger)?.let { + internalKeyboardShortcutInfo -> val group = InternalKeyboardShortcutGroup( label = groupLabel, diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/data/repository/InputGestureMaps.kt b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/data/repository/InputGestureMaps.kt index d228a15e51b4..ecc076178d2d 100644 --- a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/data/repository/InputGestureMaps.kt +++ b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/data/repository/InputGestureMaps.kt @@ -48,9 +48,7 @@ import com.android.systemui.keyboard.shortcut.shared.model.ShortcutCategoryType. import com.android.systemui.res.R import javax.inject.Inject -class InputGestureMaps -@Inject -constructor(private val context: Context) { +class InputGestureMaps @Inject constructor(private val context: Context) { val gestureToShortcutCategoryTypeMap = mapOf( // System Category @@ -180,9 +178,10 @@ constructor(private val context: Context) { ) val shortcutLabelToKeyGestureTypeMap: Map<String, Int> - get() = gestureToInternalKeyboardShortcutInfoLabelResIdMap.entries.associateBy({ - context.getString(it.value) - }) { - it.key - } + get() = + gestureToInternalKeyboardShortcutInfoLabelResIdMap.entries.associateBy({ + context.getString(it.value) + }) { + it.key + } } diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/data/repository/ShortcutCategoriesUtils.kt b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/data/repository/ShortcutCategoriesUtils.kt index 95bc9f66618c..a0897f293624 100644 --- a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/data/repository/ShortcutCategoriesUtils.kt +++ b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/data/repository/ShortcutCategoriesUtils.kt @@ -36,9 +36,9 @@ import com.android.systemui.keyboard.shortcut.shared.model.ShortcutCommand import com.android.systemui.keyboard.shortcut.shared.model.ShortcutIcon import com.android.systemui.keyboard.shortcut.shared.model.ShortcutKey import com.android.systemui.keyboard.shortcut.shared.model.ShortcutSubCategory -import kotlinx.coroutines.withContext import javax.inject.Inject import kotlin.coroutines.CoroutineContext +import kotlinx.coroutines.withContext class ShortcutCategoriesUtils @Inject diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/domain/interactor/ShortcutCustomizationInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/domain/interactor/ShortcutCustomizationInteractor.kt index f4e2f05379bb..7743c53c6900 100644 --- a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/domain/interactor/ShortcutCustomizationInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/domain/interactor/ShortcutCustomizationInteractor.kt @@ -41,7 +41,13 @@ constructor(private val customShortcutRepository: CustomShortcutCategoriesReposi customShortcutRepository.onCustomizationRequested(requestInfo) } - suspend fun confirmAndSetShortcutCurrentlyBeingCustomized(): ShortcutCustomizationRequestResult { + suspend fun confirmAndSetShortcutCurrentlyBeingCustomized(): + ShortcutCustomizationRequestResult { return customShortcutRepository.confirmAndSetShortcutCurrentlyBeingCustomized() } + + suspend fun deleteShortcutCurrentlyBeingCustomized(): + ShortcutCustomizationRequestResult { + return customShortcutRepository.deleteShortcutCurrentlyBeingCustomized() + } } diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/shared/model/ShortcutCategory.kt b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/shared/model/ShortcutCategory.kt index 813a1fcac65d..464805334c2a 100644 --- a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/shared/model/ShortcutCategory.kt +++ b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/shared/model/ShortcutCategory.kt @@ -18,25 +18,31 @@ package com.android.systemui.keyboard.shortcut.shared.model sealed interface ShortcutCategoryType { val isTrusted: Boolean + val includeInCustomization: Boolean data object System : ShortcutCategoryType { override val isTrusted: Boolean = true + override val includeInCustomization: Boolean = true } data object MultiTasking : ShortcutCategoryType { override val isTrusted: Boolean = true + override val includeInCustomization: Boolean = true } data object InputMethodEditor : ShortcutCategoryType { override val isTrusted: Boolean = false + override val includeInCustomization: Boolean = false } data object AppCategories : ShortcutCategoryType { override val isTrusted: Boolean = true + override val includeInCustomization: Boolean = true } data class CurrentApp(val packageName: String) : ShortcutCategoryType { override val isTrusted: Boolean = false + override val includeInCustomization: Boolean = false } } diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/ShortcutCustomizationDialogStarter.kt b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/ShortcutCustomizationDialogStarter.kt index 67caadba0d45..f28618bb8cf4 100644 --- a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/ShortcutCustomizationDialogStarter.kt +++ b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/ShortcutCustomizationDialogStarter.kt @@ -73,22 +73,17 @@ constructor( return dialogFactory.create(dialogDelegate = ShortcutCustomizationDialogDelegate()) { dialog -> val uiState by - viewModel.shortcutCustomizationUiState.collectAsStateWithLifecycle( - initialValue = ShortcutCustomizationUiState.Inactive - ) + viewModel.shortcutCustomizationUiState.collectAsStateWithLifecycle( + initialValue = ShortcutCustomizationUiState.Inactive + ) val coroutineScope = rememberCoroutineScope() ShortcutCustomizationDialog( uiState = uiState, - modifier = Modifier - .width(364.dp) - .wrapContentHeight() - .padding(vertical = 24.dp), + modifier = Modifier.width(364.dp).wrapContentHeight().padding(vertical = 24.dp), onKeyPress = { viewModel.onKeyPressed(it) }, onCancel = { dialog.dismiss() }, - onConfirmSetShortcut = { - coroutineScope.launch { viewModel.onSetShortcut() } - }, - onConfirmDeleteShortcut = { viewModel.onDeleteShortcut() }, + onConfirmSetShortcut = { coroutineScope.launch { viewModel.onSetShortcut() } }, + onConfirmDeleteShortcut = { coroutineScope.launch { viewModel.deleteShortcutCurrentlyBeingCustomized() } }, ) dialog.setOnDismissListener { viewModel.onDialogDismissed() } diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/composable/ShortcutHelper.kt b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/composable/ShortcutHelper.kt index cd13e87029f6..e3675de5d197 100644 --- a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/composable/ShortcutHelper.kt +++ b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/composable/ShortcutHelper.kt @@ -461,7 +461,7 @@ private fun EndSidePanel( SubCategoryContainerDualPane( searchQuery = searchQuery, subCategory = subcategory, - isCustomizing = isCustomizing, + isCustomizing = isCustomizing and category.type.includeInCustomization, onCustomizationRequested = { requestInfo -> when (requestInfo) { is ShortcutCustomizationRequestInfo.Add -> @@ -786,7 +786,7 @@ private fun ShortcutDescriptionText( Text( modifier = modifier, text = textWithHighlightedSearchQuery(shortcut.label, searchQuery), - style = MaterialTheme.typography.bodyMedium, + style = MaterialTheme.typography.titleSmall, color = MaterialTheme.colorScheme.onSurface, ) } @@ -904,7 +904,7 @@ private fun CategoryItemTwoPane( Text( fontSize = 18.sp, color = colors.textColor(selected).value, - style = MaterialTheme.typography.headlineSmall, + style = MaterialTheme.typography.titleSmall, text = label, ) } @@ -1000,9 +1000,11 @@ private fun KeyboardSettings(horizontalPadding: Dp, verticalPadding: Dp, onClick ) { Row(verticalAlignment = Alignment.CenterVertically) { Text( - stringResource(id = R.string.shortcut_helper_keyboard_settings_buttons_label), + text = + stringResource(id = R.string.shortcut_helper_keyboard_settings_buttons_label), color = MaterialTheme.colorScheme.onSurfaceVariant, fontSize = 16.sp, + style = MaterialTheme.typography.titleSmall, ) Spacer(modifier = Modifier.weight(1f)) Icon( diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/viewmodel/ShortcutCustomizationViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/viewmodel/ShortcutCustomizationViewModel.kt index 869682742043..b467bb481443 100644 --- a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/viewmodel/ShortcutCustomizationViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/viewmodel/ShortcutCustomizationViewModel.kt @@ -79,8 +79,7 @@ constructor( } is ShortcutCustomizationRequestInfo.Delete -> { - _shortcutCustomizationUiState.value = - DeleteShortcutDialog(isDialogShowing = false) + _shortcutCustomizationUiState.value = DeleteShortcutDialog(isDialogShowing = false) shortcutCustomizationInteractor.onCustomizationRequested(requestInfo) } } @@ -134,17 +133,23 @@ constructor( } } - fun onDeleteShortcut() { - // TODO(b/373631984) not yet implemented + suspend fun deleteShortcutCurrentlyBeingCustomized() { + val result = + shortcutCustomizationInteractor.deleteShortcutCurrentlyBeingCustomized() + + _shortcutCustomizationUiState.update { uiState -> + when (result) { + ShortcutCustomizationRequestResult.SUCCESS -> ShortcutCustomizationUiState.Inactive + else -> uiState + } + } } private fun getUiStateWithErrorMessage( uiState: ShortcutCustomizationUiState, errorMessage: String, ): ShortcutCustomizationUiState { - return (uiState as? AddShortcutDialog)?.copy( - errorMessage = errorMessage - ) ?: uiState + return (uiState as? AddShortcutDialog)?.copy(errorMessage = errorMessage) ?: uiState } private fun updatePressedKeys(keyEvent: KeyEvent) { diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/GlanceableHubQuickAffordanceConfig.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/GlanceableHubQuickAffordanceConfig.kt index 0b78be128c69..8906156252a6 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/GlanceableHubQuickAffordanceConfig.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/GlanceableHubQuickAffordanceConfig.kt @@ -25,6 +25,7 @@ import com.android.systemui.common.shared.model.Icon import com.android.systemui.communal.data.repository.CommunalSceneRepository import com.android.systemui.communal.domain.interactor.CommunalInteractor import com.android.systemui.communal.shared.model.CommunalScenes +import com.android.systemui.communal.shared.model.CommunalTransitionKeys import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.res.R @@ -98,7 +99,10 @@ constructor( if (SceneContainerFlag.isEnabled) { sceneInteractor.changeScene(Scenes.Communal, "lockscreen to communal from shortcut") } else { - communalSceneRepository.changeScene(CommunalScenes.Communal, null) + communalSceneRepository.changeScene( + CommunalScenes.Communal, + transitionKey = CommunalTransitionKeys.SimpleFade, + ) } return KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDreamingTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDreamingTransitionInteractor.kt index 1e672e23970b..deef2a6c3a4c 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDreamingTransitionInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDreamingTransitionInteractor.kt @@ -21,11 +21,13 @@ import android.annotation.SuppressLint import android.app.DreamManager import com.android.app.animation.Interpolators import com.android.app.tracing.coroutines.launchTraced as launch +import com.android.systemui.Flags.communalHubOnMobile import com.android.systemui.Flags.communalSceneKtfRefactor import com.android.systemui.communal.domain.interactor.CommunalInteractor import com.android.systemui.communal.domain.interactor.CommunalSceneInteractor import com.android.systemui.communal.domain.interactor.CommunalSettingsInteractor import com.android.systemui.communal.shared.model.CommunalScenes +import com.android.systemui.communal.shared.model.CommunalTransitionKeys import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.dagger.qualifiers.Main @@ -48,7 +50,6 @@ import kotlinx.coroutines.FlowPreview import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.debounce import kotlinx.coroutines.flow.filter -import com.android.app.tracing.coroutines.launchTraced as launch @OptIn(ExperimentalCoroutinesApi::class) @SysUISingleton @@ -176,6 +177,9 @@ constructor( communalSceneInteractor.changeScene( newScene = CommunalScenes.Communal, loggingReason = "FromDreamingTransitionInteractor", + transitionKey = + if (communalHubOnMobile()) CommunalTransitionKeys.SimpleFade + else null, ) } else { startTransitionTo( diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/WindowManagerLockscreenVisibilityInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/WindowManagerLockscreenVisibilityInteractor.kt index 364b1a9731cc..9df293bf2c15 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/WindowManagerLockscreenVisibilityInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/WindowManagerLockscreenVisibilityInteractor.kt @@ -112,8 +112,10 @@ constructor( } .distinctUntilChanged() - private val isDeviceEntered by lazy { deviceEntryInteractor.get().isDeviceEntered } - private val isDeviceNotEntered by lazy { isDeviceEntered.map { !it } } + private val isDeviceEnteredDirectly by lazy { + deviceEntryInteractor.get().isDeviceEnteredDirectly + } + private val isDeviceNotEnteredDirectly by lazy { isDeviceEnteredDirectly.map { !it } } /** * Surface visibility, which is either determined by the default visibility when not @@ -126,7 +128,7 @@ constructor( sceneInteractor.get().transitionState.flatMapLatestConflated { state -> when { state.isTransitioning(from = Scenes.Lockscreen, to = Scenes.Gone) -> - isDeviceEntered + isDeviceEnteredDirectly state.isTransitioning(from = Scenes.Bouncer, to = Scenes.Gone) -> (state as Transition).progress.map { progress -> progress > @@ -210,7 +212,7 @@ constructor( when (it.currentScene) { in keyguardScenes -> flowOf(true) in nonKeyguardScenes -> flowOf(false) - in keyguardAgnosticScenes -> isDeviceNotEntered + in keyguardAgnosticScenes -> isDeviceNotEnteredDirectly else -> throw IllegalStateException("Unknown scene: ${it.currentScene}") } @@ -220,7 +222,7 @@ constructor( it.isTransitioningSets(from = keyguardScenes) -> flowOf(true) it.isTransitioningSets(from = nonKeyguardScenes) -> flowOf(false) it.isTransitioningSets(from = keyguardAgnosticScenes) -> - isDeviceNotEntered + isDeviceNotEnteredDirectly else -> throw IllegalStateException("Unknown scene: ${it.fromContent}") } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardPreviewClockViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardPreviewClockViewBinder.kt index 6c03b2489380..ac302dd26365 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardPreviewClockViewBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardPreviewClockViewBinder.kt @@ -17,7 +17,7 @@ package com.android.systemui.keyguard.ui.binder -import android.content.Context +import android.content.res.Resources import android.view.View import android.view.View.INVISIBLE import android.view.View.VISIBLE @@ -34,8 +34,8 @@ import com.android.systemui.keyguard.ui.view.layout.sections.setVisibility import com.android.systemui.keyguard.ui.viewmodel.KeyguardPreviewClockViewModel import com.android.systemui.lifecycle.repeatWhenAttached import com.android.systemui.plugins.clocks.ClockController +import com.android.systemui.plugins.clocks.ClockPreviewConfig import com.android.systemui.shared.clocks.ClockRegistry -import kotlin.reflect.KSuspendFunction1 /** Binder for the small clock view, large clock view. */ object KeyguardPreviewClockViewBinder { @@ -66,11 +66,11 @@ object KeyguardPreviewClockViewBinder { @JvmStatic fun bind( - context: Context, rootView: ConstraintLayout, viewModel: KeyguardPreviewClockViewModel, clockRegistry: ClockRegistry, - updateClockAppearance: KSuspendFunction1<ClockController, Unit>, + updateClockAppearance: suspend (ClockController, Resources) -> Unit, + clockPreviewConfig: ClockPreviewConfig, ) { rootView.repeatWhenAttached { repeatOnLifecycle(Lifecycle.State.STARTED) { @@ -82,7 +82,10 @@ object KeyguardPreviewClockViewBinder { .forEach { rootView.removeView(it) } } lastClock = currentClock - updateClockAppearance(currentClock) + updateClockAppearance( + currentClock, + clockPreviewConfig.previewContext.resources, + ) if (viewModel.shouldHighlightSelectedAffordance) { (currentClock.largeClock.layout.views + @@ -98,7 +101,12 @@ object KeyguardPreviewClockViewBinder { (it.parent as? ViewGroup)?.removeView(it) rootView.addView(it) } - applyPreviewConstraints(context, rootView, currentClock, viewModel) + applyPreviewConstraints( + clockPreviewConfig, + rootView, + currentClock, + viewModel, + ) } } .invokeOnCompletion { @@ -121,14 +129,14 @@ object KeyguardPreviewClockViewBinder { } private fun applyPreviewConstraints( - context: Context, + clockPreviewConfig: ClockPreviewConfig, rootView: ConstraintLayout, previewClock: ClockController, viewModel: KeyguardPreviewClockViewModel, ) { val cs = ConstraintSet().apply { clone(rootView) } - previewClock.largeClock.layout.applyPreviewConstraints(context, cs) - previewClock.smallClock.layout.applyPreviewConstraints(context, cs) + previewClock.largeClock.layout.applyPreviewConstraints(clockPreviewConfig, cs) + previewClock.smallClock.layout.applyPreviewConstraints(clockPreviewConfig, cs) // When selectedClockSize is the initial value, make both clocks invisible to avoid // flickering diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardPreviewSmartspaceViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardPreviewSmartspaceViewBinder.kt index baa681282a0b..e89be5d6ae4c 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardPreviewSmartspaceViewBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardPreviewSmartspaceViewBinder.kt @@ -17,7 +17,6 @@ package com.android.systemui.keyguard.ui.binder -import android.content.Context import android.view.View import androidx.core.view.isInvisible import androidx.lifecycle.Lifecycle @@ -26,16 +25,16 @@ import com.android.app.tracing.coroutines.launchTraced as launch import com.android.systemui.keyguard.shared.model.ClockSizeSetting import com.android.systemui.keyguard.ui.viewmodel.KeyguardPreviewSmartspaceViewModel import com.android.systemui.lifecycle.repeatWhenAttached +import com.android.systemui.plugins.clocks.ClockPreviewConfig /** Binder for the small clock view, large clock view and smartspace. */ object KeyguardPreviewSmartspaceViewBinder { @JvmStatic fun bind( - previewContext: Context, smartspace: View, - splitShadePreview: Boolean, viewModel: KeyguardPreviewSmartspaceViewModel, + clockPreviewConfig: ClockPreviewConfig, ) { smartspace.repeatWhenAttached { repeatOnLifecycle(Lifecycle.State.STARTED) { @@ -44,15 +43,9 @@ object KeyguardPreviewSmartspaceViewBinder { val topPadding = when (it) { ClockSizeSetting.DYNAMIC -> - viewModel.getLargeClockSmartspaceTopPadding( - splitShadePreview, - previewContext, - ) + viewModel.getLargeClockSmartspaceTopPadding(clockPreviewConfig) ClockSizeSetting.SMALL -> - viewModel.getSmallClockSmartspaceTopPadding( - splitShadePreview, - previewContext, - ) + viewModel.getSmallClockSmartspaceTopPadding(clockPreviewConfig) } smartspace.setTopPadding(topPadding) } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardPreviewRenderer.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardPreviewRenderer.kt index ab9cffc05667..9924a3bcdd6a 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardPreviewRenderer.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardPreviewRenderer.kt @@ -22,6 +22,7 @@ import android.content.BroadcastReceiver import android.content.Context import android.content.Intent import android.content.IntentFilter +import android.content.res.Resources import android.graphics.Rect import android.hardware.display.DisplayManager import android.os.Bundle @@ -47,6 +48,7 @@ import androidx.constraintlayout.widget.ConstraintSet.PARENT_ID import androidx.constraintlayout.widget.ConstraintSet.START import androidx.constraintlayout.widget.ConstraintSet.TOP import androidx.core.view.isInvisible +import com.android.app.tracing.coroutines.launchTraced as launch import com.android.internal.policy.SystemBarUtils import com.android.keyguard.ClockEventController import com.android.keyguard.KeyguardClockSwitch @@ -57,6 +59,7 @@ import com.android.systemui.common.ui.ConfigurationState import com.android.systemui.communal.ui.binder.CommunalTutorialIndicatorViewBinder import com.android.systemui.communal.ui.viewmodel.CommunalTutorialIndicatorViewModel import com.android.systemui.coroutines.newTracingContext +import com.android.systemui.customization.R as customR import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.dagger.qualifiers.Main @@ -80,9 +83,11 @@ import com.android.systemui.keyguard.ui.viewmodel.OccludingAppDeviceEntryMessage import com.android.systemui.monet.ColorScheme import com.android.systemui.monet.Style import com.android.systemui.plugins.clocks.ClockController +import com.android.systemui.plugins.clocks.ClockPreviewConfig import com.android.systemui.plugins.clocks.ThemeConfig import com.android.systemui.plugins.clocks.WeatherData import com.android.systemui.res.R +import com.android.systemui.scene.shared.flag.SceneContainerFlag import com.android.systemui.shade.domain.interactor.ShadeInteractor import com.android.systemui.shared.clocks.ClockRegistry import com.android.systemui.shared.clocks.DefaultClockController @@ -105,7 +110,6 @@ import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.Job import kotlinx.coroutines.cancel import kotlinx.coroutines.flow.flowOf -import com.android.app.tracing.coroutines.launchTraced as launch import kotlinx.coroutines.runBlocking import kotlinx.coroutines.withContext import org.json.JSONException @@ -352,8 +356,11 @@ constructor( val topPadding: Int = smartspaceViewModel.getLargeClockSmartspaceTopPadding( - previewInSplitShade(), - previewContext, + ClockPreviewConfig( + previewContext, + getPreviewShadeLayoutWide(display!!), + SceneContainerFlag.isEnabled, + ) ) val startPadding: Int = smartspaceViewModel.getSmartspaceStartPadding(previewContext) val endPadding: Int = smartspaceViewModel.getSmartspaceEndPadding(previewContext) @@ -436,11 +443,15 @@ constructor( setUpClock(previewContext, rootView) if (MigrateClocksToBlueprint.isEnabled) { KeyguardPreviewClockViewBinder.bind( - previewContext, keyguardRootView, clockViewModel, clockRegistry, ::updateClockAppearance, + ClockPreviewConfig( + previewContext, + getPreviewShadeLayoutWide(display!!), + SceneContainerFlag.isEnabled, + ), ) } else { KeyguardPreviewClockViewBinder.bind( @@ -455,10 +466,14 @@ constructor( smartSpaceView?.let { KeyguardPreviewSmartspaceViewBinder.bind( - previewContext, it, - previewInSplitShade(), smartspaceViewModel, + clockPreviewConfig = + ClockPreviewConfig( + previewContext, + getPreviewShadeLayoutWide(display!!), + SceneContainerFlag.isEnabled, + ), ) } setupCommunalTutorialIndicator(keyguardRootView) @@ -552,20 +567,14 @@ constructor( val layoutParams = FrameLayout.LayoutParams( FrameLayout.LayoutParams.WRAP_CONTENT, - resources.getDimensionPixelSize( - com.android.systemui.customization.R.dimen.small_clock_height - ), + resources.getDimensionPixelSize(customR.dimen.small_clock_height), ) layoutParams.topMargin = SystemBarUtils.getStatusBarHeight(previewContext) + - resources.getDimensionPixelSize( - com.android.systemui.customization.R.dimen.small_clock_padding_top - ) + resources.getDimensionPixelSize(customR.dimen.small_clock_padding_top) smallClockHostView.layoutParams = layoutParams smallClockHostView.setPaddingRelative( - /* start = */ resources.getDimensionPixelSize( - com.android.systemui.customization.R.dimen.clock_padding_start - ), + /* start = */ resources.getDimensionPixelSize(customR.dimen.clock_padding_start), /* top = */ 0, /* end = */ 0, /* bottom = */ 0, @@ -637,7 +646,7 @@ constructor( onClockChanged() } - private suspend fun updateClockAppearance(clock: ClockController) { + private suspend fun updateClockAppearance(clock: ClockController, resources: Resources) { if (!MigrateClocksToBlueprint.isEnabled) { clockController.clock = clock } @@ -667,6 +676,11 @@ constructor( if (MigrateClocksToBlueprint.isEnabled) { clockController.clock = clock } + // When set clock to clockController,it will reset fontsize based on context.resources + // We need to override it with overlaid resources + clock.largeClock.events.onFontSettingChanged( + resources.getDimensionPixelSize(customR.dimen.large_clock_text_size).toFloat() + ) } private fun onClockChanged() { @@ -676,7 +690,7 @@ constructor( coroutineScope.launch { val clock = clockRegistry.createCurrentClock() clockController.clock = clock - updateClockAppearance(clock) + updateClockAppearance(clock, context.resources) updateLargeClock(clock) updateSmallClock(clock) } @@ -742,12 +756,14 @@ constructor( smallClockHostView.addView(clock.smallClock.view) } - /* - * When multi_crop_preview_ui_flag is on, we can preview portrait in split shadow direction - * or vice versa. So we need to decide preview direction by width and height - */ - private fun previewInSplitShade(): Boolean { - return width > height + private fun getPreviewShadeLayoutWide(display: Display): Boolean { + return if (display.displayId == 0) { + shadeInteractor.isShadeLayoutWide.value + } else { + // For the unfolded preview in a folded screen; it's landscape by default + // For the folded preview in an unfolded screen; it's portrait by default + display.name == "Inner Display" + } } companion object { diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/AodBurnInSection.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/AodBurnInSection.kt index 8622ffc04601..160380bb09bc 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/AodBurnInSection.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/AodBurnInSection.kt @@ -19,6 +19,7 @@ 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 import androidx.constraintlayout.widget.ConstraintSet.BOTTOM @@ -47,11 +48,15 @@ constructor( visibility = View.GONE } } + override fun addViews(constraintLayout: ConstraintLayout) { if (!MigrateClocksToBlueprint.isEnabled) { return } - + if (emptyView.parent != null) { + // As emptyView is lazy, it might be already attached. + (emptyView.parent as? ViewGroup)?.removeView(emptyView) + } constraintLayout.addView(emptyView) burnInLayer = AodBurnInLayer(context).apply { diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/ClockSection.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/ClockSection.kt index 6c98d5b01e4e..70bf8bca55b9 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/ClockSection.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/ClockSection.kt @@ -235,9 +235,7 @@ constructor( val smallClockBottom = keyguardClockViewModel.getSmallClockTopMargin() + - context.resources.getDimensionPixelSize( - com.android.systemui.customization.R.dimen.small_clock_height - ) + context.resources.getDimensionPixelSize(customR.dimen.small_clock_height) val dateWeatherSmartspaceHeight = getDimen(context, DATE_WEATHER_VIEW_HEIGHT).toFloat() val marginBetweenSmartspaceAndNotification = context.resources.getDimensionPixelSize( diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardClockViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardClockViewModel.kt index 3a7a640be85f..6e30e482bda0 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardClockViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardClockViewModel.kt @@ -16,6 +16,7 @@ package com.android.systemui.keyguard.ui.viewmodel +import android.content.Context import android.content.res.Resources import androidx.annotation.VisibleForTesting import androidx.constraintlayout.helper.widget.Layer @@ -27,7 +28,8 @@ import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.keyguard.domain.interactor.KeyguardClockInteractor import com.android.systemui.keyguard.shared.model.ClockSize import com.android.systemui.keyguard.shared.model.ClockSizeSetting -import com.android.systemui.res.R +import com.android.systemui.plugins.clocks.ClockPreviewConfig +import com.android.systemui.plugins.clocks.DefaultClockFaceLayout.Companion.getSmallClockTopPadding import com.android.systemui.scene.shared.flag.SceneContainerFlag import com.android.systemui.shade.ShadeDisplayAware import com.android.systemui.shade.domain.interactor.ShadeInteractor @@ -46,6 +48,7 @@ import kotlinx.coroutines.flow.stateIn class KeyguardClockViewModel @Inject constructor( + val context: Context, keyguardClockInteractor: KeyguardClockInteractor, @Application private val applicationScope: CoroutineScope, aodNotificationIconViewModel: NotificationIconContainerAlwaysOnDisplayViewModel, @@ -158,16 +161,15 @@ constructor( ) /** Calculates the top margin for the small clock. */ - fun getSmallClockTopMargin(): Int { - val statusBarHeight = systemBarUtils.getStatusBarHeaderHeightKeyguard() - return if (shadeInteractor.isShadeLayoutWide.value) { - resources.getDimensionPixelSize(R.dimen.keyguard_split_shade_top_margin) - - if (SceneContainerFlag.isEnabled) statusBarHeight else 0 - } else { - resources.getDimensionPixelSize(R.dimen.keyguard_clock_top_margin) + - if (!SceneContainerFlag.isEnabled) statusBarHeight else 0 - } - } + fun getSmallClockTopMargin(): Int = + getSmallClockTopPadding( + ClockPreviewConfig( + context, + shadeInteractor.isShadeLayoutWide.value, + SceneContainerFlag.isEnabled, + ), + systemBarUtils.getStatusBarHeaderHeightKeyguard(), + ) val smallClockTopMargin = combine( diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardPreviewSmartspaceViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardPreviewSmartspaceViewModel.kt index 65c0f57b76f5..1c4498212502 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardPreviewSmartspaceViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardPreviewSmartspaceViewModel.kt @@ -17,11 +17,12 @@ package com.android.systemui.keyguard.ui.viewmodel import android.content.Context -import com.android.internal.policy.SystemBarUtils import com.android.systemui.customization.R as customR import com.android.systemui.keyguard.domain.interactor.KeyguardClockInteractor import com.android.systemui.keyguard.shared.model.ClockSizeSetting -import com.android.systemui.res.R +import com.android.systemui.plugins.clocks.ClockPreviewConfig +import com.android.systemui.plugins.clocks.DefaultClockFaceLayout.Companion.getSmallClockTopPadding +import com.android.systemui.statusbar.ui.SystemBarUtilsProxy import javax.inject.Inject import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.StateFlow @@ -35,6 +36,7 @@ constructor( interactor: KeyguardClockInteractor, val smartspaceViewModel: KeyguardSmartspaceViewModel, val clockViewModel: KeyguardClockViewModel, + private val systemBarUtils: SystemBarUtilsProxy, ) { val selectedClockSize: StateFlow<ClockSizeSetting> = interactor.selectedClockSize @@ -59,29 +61,18 @@ constructor( return KeyguardSmartspaceViewModel.getSmartspaceEndMargin(context) } - fun getSmallClockSmartspaceTopPadding(splitShadePreview: Boolean, context: Context): Int { - return getSmallClockTopPadding(splitShadePreview, context) + - context.resources.getDimensionPixelSize( - com.android.systemui.customization.R.dimen.small_clock_height - ) - } - - fun getLargeClockSmartspaceTopPadding(splitShadePreview: Boolean, context: Context): Int { - return getSmallClockTopPadding(splitShadePreview, context) - } - /* * SmallClockTopPadding decides the top position of smartspace */ - private fun getSmallClockTopPadding(splitShadePreview: Boolean, context: Context): Int { - return with(context.resources) { - if (splitShadePreview) { - getDimensionPixelSize(R.dimen.keyguard_split_shade_top_margin) - } else { - getDimensionPixelSize(R.dimen.keyguard_clock_top_margin) + - SystemBarUtils.getStatusBarHeight(context) + - getDimensionPixelSize(customR.dimen.keyguard_smartspace_top_offset) - } - } + fun getSmallClockSmartspaceTopPadding(config: ClockPreviewConfig): Int { + return getSmallClockTopPadding(config, systemBarUtils.getStatusBarHeaderHeightKeyguard()) + + config.previewContext.resources.getDimensionPixelSize(customR.dimen.small_clock_height) + } + + fun getLargeClockSmartspaceTopPadding(clockPreviewConfig: ClockPreviewConfig): Int { + return getSmallClockTopPadding( + clockPreviewConfig, + systemBarUtils.getStatusBarHeaderHeightKeyguard(), + ) } } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenUserActionsViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenUserActionsViewModel.kt index 6f29004d4f3f..618b04700afb 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenUserActionsViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenUserActionsViewModel.kt @@ -23,6 +23,7 @@ import com.android.compose.animation.scene.UserAction import com.android.compose.animation.scene.UserActionResult import com.android.systemui.communal.domain.interactor.CommunalInteractor import com.android.systemui.deviceentry.domain.interactor.DeviceEntryInteractor +import com.android.systemui.scene.domain.interactor.SceneContainerOcclusionInteractor import com.android.systemui.scene.shared.model.Scenes import com.android.systemui.scene.ui.viewmodel.UserActionsViewModel import com.android.systemui.shade.domain.interactor.ShadeInteractor @@ -44,6 +45,7 @@ constructor( private val deviceEntryInteractor: DeviceEntryInteractor, private val communalInteractor: CommunalInteractor, private val shadeInteractor: ShadeInteractor, + private val occlusionInteractor: SceneContainerOcclusionInteractor, ) : UserActionsViewModel() { override suspend fun hydrateActions(setActions: (Map<UserAction, UserActionResult>) -> Unit) { @@ -57,7 +59,8 @@ constructor( deviceEntryInteractor.isUnlocked, communalInteractor.isCommunalAvailable, shadeInteractor.shadeMode, - ) { isDeviceUnlocked, isCommunalAvailable, shadeMode -> + occlusionInteractor.isOccludingActivityShown, + ) { isDeviceUnlocked, isCommunalAvailable, shadeMode, isOccluded -> buildList { if (isCommunalAvailable) { add(Swipe.Start to Scenes.Communal) @@ -67,7 +70,8 @@ constructor( addAll( when (shadeMode) { - ShadeMode.Single -> singleShadeActions() + ShadeMode.Single -> + singleShadeActions(isDownFromTopEdgeEnabled = !isOccluded) ShadeMode.Split -> splitShadeActions() ShadeMode.Dual -> dualShadeActions() } diff --git a/packages/SystemUI/src/com/android/systemui/lifecycle/Hydrator.kt b/packages/SystemUI/src/com/android/systemui/lifecycle/Hydrator.kt index 881228d597b0..93ecae32ac17 100644 --- a/packages/SystemUI/src/com/android/systemui/lifecycle/Hydrator.kt +++ b/packages/SystemUI/src/com/android/systemui/lifecycle/Hydrator.kt @@ -21,11 +21,11 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.snapshots.StateFactoryMarker import com.android.app.tracing.coroutines.launchTraced as launch import com.android.app.tracing.coroutines.traceCoroutine +import com.android.systemui.log.table.TableLogBuffer import kotlinx.coroutines.awaitCancellation import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.StateFlow -import com.android.app.tracing.coroutines.launchTraced as launch /** * Keeps snapshot/Compose [State]s up-to-date. @@ -47,6 +47,12 @@ class Hydrator( * concatenation or templating. */ private val traceName: String, + /** + * An optional [TableLogBuffer] to log emissions to the states. [traceName] will be used as the + * prefix for the columns logged by this [Hydrator], allowing to aggregate multiple hydrators in + * the same table. + */ + private val tableLogBuffer: TableLogBuffer? = null, ) : ExclusiveActivatable() { private val children = mutableListOf<NamedActivatable>() @@ -62,15 +68,8 @@ class Hydrator( * automatically set on the returned [State]. */ @StateFactoryMarker - fun <T> hydratedStateOf( - traceName: String, - source: StateFlow<T>, - ): State<T> { - return hydratedStateOf( - traceName = traceName, - initialValue = source.value, - source = source, - ) + fun <T> hydratedStateOf(traceName: String, source: StateFlow<T>): State<T> { + return hydratedStateOf(traceName = traceName, initialValue = source.value, source = source) } /** @@ -81,26 +80,44 @@ class Hydrator( * performance findings with actual code. One recommendation: prefer whole string literals * instead of some complex concatenation or templating scheme. Use `null` to disable * performance tracing for this state. + * + * If a [TableLogBuffer] was provided, every emission to the flow will be logged using the + * [traceName] as the column name. For this to work correctly, all the states in the same + * hydrator should have different [traceName]. Use `null` to disable logging for this state. + * * @param initialValue The first value to place on the [State] * @param source The upstream [Flow] to collect from; values emitted to it will be automatically * set on the returned [State]. */ @StateFactoryMarker - fun <T> hydratedStateOf( - traceName: String?, - initialValue: T, - source: Flow<T>, - ): State<T> { + fun <T> hydratedStateOf(traceName: String?, initialValue: T, source: Flow<T>): State<T> { check(!isActive) { "Cannot call hydratedStateOf after Hydrator is already active." } val mutableState = mutableStateOf(initialValue) + traceName?.let { name -> + tableLogBuffer?.logChange( + prefix = this.traceName, + columnName = name, + value = initialValue?.toString(), + isInitial = true, + ) + } children.add( NamedActivatable( traceName = traceName, activatable = object : ExclusiveActivatable() { override suspend fun onActivated(): Nothing { - source.collect { mutableState.value = it } + source.collect { + traceName?.let { name -> + tableLogBuffer?.logChange( + prefix = this@Hydrator.traceName, + columnName = name, + value = it?.toString(), + ) + } + mutableState.value = it + } awaitCancellation() } }, @@ -122,8 +139,5 @@ class Hydrator( } } - private data class NamedActivatable( - val traceName: String?, - val activatable: Activatable, - ) + private data class NamedActivatable(val traceName: String?, val activatable: Activatable) } diff --git a/packages/SystemUI/src/com/android/systemui/mediaprojection/data/repository/MediaProjectionManagerRepository.kt b/packages/SystemUI/src/com/android/systemui/mediaprojection/data/repository/MediaProjectionManagerRepository.kt index 35efd751b8fe..7d3094827e17 100644 --- a/packages/SystemUI/src/com/android/systemui/mediaprojection/data/repository/MediaProjectionManagerRepository.kt +++ b/packages/SystemUI/src/com/android/systemui/mediaprojection/data/repository/MediaProjectionManagerRepository.kt @@ -20,6 +20,7 @@ import android.app.ActivityManager.RunningTaskInfo import android.hardware.display.DisplayManager import android.media.projection.MediaProjectionInfo import android.media.projection.MediaProjectionManager +import android.media.projection.StopReason import android.os.Handler import android.view.ContentRecordingSession import android.view.ContentRecordingSession.RECORD_CONTENT_DISPLAY @@ -72,7 +73,7 @@ constructor( } } - override suspend fun stopProjecting() { + override suspend fun stopProjecting(@StopReason stopReason: Int) { withContext(backgroundDispatcher) { logger.log( TAG, @@ -80,7 +81,7 @@ constructor( {}, { "Requesting MediaProjectionManager#stopActiveProjection" }, ) - mediaProjectionManager.stopActiveProjection() + mediaProjectionManager.stopActiveProjection(stopReason) } } diff --git a/packages/SystemUI/src/com/android/systemui/mediaprojection/data/repository/MediaProjectionRepository.kt b/packages/SystemUI/src/com/android/systemui/mediaprojection/data/repository/MediaProjectionRepository.kt index 50182d7a3b33..a01d8c2c98de 100644 --- a/packages/SystemUI/src/com/android/systemui/mediaprojection/data/repository/MediaProjectionRepository.kt +++ b/packages/SystemUI/src/com/android/systemui/mediaprojection/data/repository/MediaProjectionRepository.kt @@ -17,6 +17,7 @@ package com.android.systemui.mediaprojection.data.repository import android.app.ActivityManager.RunningTaskInfo +import android.media.projection.StopReason import com.android.systemui.mediaprojection.data.model.MediaProjectionState import kotlinx.coroutines.flow.Flow @@ -27,7 +28,7 @@ interface MediaProjectionRepository { suspend fun switchProjectedTask(task: RunningTaskInfo) /** Stops the currently active projection. */ - suspend fun stopProjecting() + suspend fun stopProjecting(@StopReason stopReason: Int) /** Represents the current [MediaProjectionState]. */ val mediaProjectionState: Flow<MediaProjectionState> diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java index 80ac2fcd4aa4..0a4e8c660761 100644 --- a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java +++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java @@ -18,6 +18,7 @@ package com.android.systemui.navigationbar.gestural; import static android.content.pm.ActivityInfo.CONFIG_FONT_SCALE; import static android.view.InputDevice.SOURCE_MOUSE; import static android.view.InputDevice.SOURCE_TOUCHPAD; +import static android.view.MotionEvent.TOOL_TYPE_FINGER; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_EXCLUDE_FROM_SCREEN_MAGNIFICATION; import static com.android.systemui.Flags.edgebackGestureHandlerGetRunningTasksBackground; @@ -216,6 +217,7 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack private final int mDisplayId; private final UiThreadContext mUiThreadContext; + private final Handler mBgHandler; private final Executor mBackgroundExecutor; private final Rect mPipExcludedBounds = new Rect(); @@ -378,11 +380,14 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack @Override public void onInputDeviceAdded(int deviceId) { if (isTrackpadDevice(deviceId)) { - boolean wasEmpty = mTrackpadsConnected.isEmpty(); - mTrackpadsConnected.add(deviceId); - if (wasEmpty) { - update(); - } + // This updates the gesture handler state and should be running on the main thread. + mUiThreadContext.getHandler().post(() -> { + boolean wasEmpty = mTrackpadsConnected.isEmpty(); + mTrackpadsConnected.add(deviceId); + if (wasEmpty) { + update(); + } + }); } } @@ -391,10 +396,13 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack @Override public void onInputDeviceRemoved(int deviceId) { - mTrackpadsConnected.remove(deviceId); - if (mTrackpadsConnected.isEmpty()) { - update(); - } + // This updates the gesture handler state and should be running on the main thread. + mUiThreadContext.getHandler().post(() -> { + mTrackpadsConnected.remove(deviceId); + if (mTrackpadsConnected.isEmpty()) { + update(); + } + }); } private void update() { @@ -408,12 +416,12 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack } private boolean isTrackpadDevice(int deviceId) { + // This is a blocking binder call that should run on a bg thread. InputDevice inputDevice = mInputManager.getInputDevice(deviceId); if (inputDevice == null) { return false; } - return inputDevice.getSources() == (InputDevice.SOURCE_MOUSE - | InputDevice.SOURCE_TOUCHPAD); + return inputDevice.getSources() == (SOURCE_MOUSE | SOURCE_TOUCHPAD); } }; @@ -457,6 +465,7 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack mDisplayId = context.getDisplayId(); mUiThreadContext = uiThreadContext; mBackgroundExecutor = backgroundExecutor; + mBgHandler = bgHandler; mUserTracker = userTracker; mOverviewProxyService = overviewProxyService; mSysUiState = sysUiState; @@ -611,9 +620,7 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack mIsAttached = true; mOverviewProxyService.addCallback(mQuickSwitchListener); mSysUiState.addCallback(mSysUiStateCallback); - mInputManager.registerInputDeviceListener( - mInputDeviceListener, - mUiThreadContext.getHandler()); + mInputManager.registerInputDeviceListener(mInputDeviceListener, mBgHandler); int[] inputDevices = mInputManager.getInputDeviceIds(); for (int inputDeviceId : inputDevices) { mInputDeviceListener.onInputDeviceAdded(inputDeviceId); @@ -1089,8 +1096,8 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack && isValidTrackpadBackGesture(true /* isTrackpadEvent */); } else { mAllowGesture = isBackAllowedCommon && !mUsingThreeButtonNav && isWithinInsets - && isWithinTouchRegion((int) ev.getX(), (int) ev.getY()) - && !isButtonPressFromTrackpad(ev); + && isWithinTouchRegion((int) ev.getX(), (int) ev.getY()) + && !isButtonPressFromTrackpad(ev); } if (mAllowGesture) { mEdgeBackPlugin.setIsLeftPanel(mIsOnLeftEdge); @@ -1202,10 +1209,8 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack } private boolean isButtonPressFromTrackpad(MotionEvent ev) { - // We don't allow back for button press from the trackpad, and yet we do with a mouse. - int sources = InputManager.getInstance().getInputDevice(ev.getDeviceId()).getSources(); - int sourceTrackpad = (SOURCE_MOUSE | SOURCE_TOUCHPAD); - return (sources & sourceTrackpad) == sourceTrackpad && ev.getButtonState() != 0; + return ev.getSource() == (SOURCE_MOUSE | SOURCE_TOUCHPAD) + && ev.getToolType(ev.getActionIndex()) == TOOL_TYPE_FINGER; } private void dispatchToBackAnimation(MotionEvent event) { diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFooterViewController.java b/packages/SystemUI/src/com/android/systemui/qs/QSFooterViewController.java index d715f42ed499..dc188c24e02b 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSFooterViewController.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSFooterViewController.java @@ -16,8 +16,11 @@ package com.android.systemui.qs; +import static com.android.systemui.Flags.gsfQuickSettings; + import android.content.ClipData; import android.content.ClipboardManager; +import android.graphics.Typeface; import android.text.TextUtils; import android.view.View; import android.widget.TextView; @@ -64,6 +67,9 @@ public class QSFooterViewController extends ViewController<QSFooterView> impleme mRetailModeInteractor = retailModeInteractor; mBuildText = mView.findViewById(R.id.build); + if (gsfQuickSettings()) { + mBuildText.setTypeface(Typeface.create("gsf-body-medium", Typeface.NORMAL)); + } mPageIndicator = mView.findViewById(R.id.footer_page_indicator); mEditButton = mView.findViewById(android.R.id.edit); } diff --git a/packages/SystemUI/src/com/android/systemui/qs/composefragment/QSFragmentCompose.kt b/packages/SystemUI/src/com/android/systemui/qs/composefragment/QSFragmentCompose.kt index 21c45c550e08..5167d173647e 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/composefragment/QSFragmentCompose.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/composefragment/QSFragmentCompose.kt @@ -233,6 +233,7 @@ constructor( // Only allow scrolling when we are fully expanded. That way, we don't intercept // swipes in lockscreen (when somehow QS is receiving touches). { (scrollState.canScrollForward && viewModel.isQsFullyExpanded) || isCustomizing }, + viewModel::emitMotionEventForFalsingSwipeNested, ) frame.addView( composeView, @@ -718,7 +719,6 @@ constructor( max = QuickSettingsShade.Dimensions.GridMaxHeight ), - containerViewModel.editModeViewModel::startEditing, ) } } @@ -951,6 +951,7 @@ private class FrameLayoutTouchPassthrough( private val clippingEnabledProvider: () -> Boolean, private val clippingTopProvider: () -> Int, private val canScrollForwardQs: () -> Boolean, + private val emitMotionEventForFalsing: () -> Unit, ) : FrameLayout(context) { override fun isTransformedTouchPointInView( x: Float, @@ -967,6 +968,32 @@ private class FrameLayoutTouchPassthrough( val touchSlop = ViewConfiguration.get(context).scaledTouchSlop var downY = 0f + var preventingIntercept = false + + override fun onTouchEvent(event: MotionEvent): Boolean { + val action = event.actionMasked + when (action) { + MotionEvent.ACTION_DOWN -> { + preventingIntercept = false + if (canScrollVertically(1)) { + // If we can scroll down, make sure we're not intercepted by the parent + preventingIntercept = true + parent?.requestDisallowInterceptTouchEvent(true) + } else if (!canScrollVertically(-1)) { + // Don't pass on the touch to the view, because scrolling will unconditionally + // disallow interception even if we can't scroll. + // if a user can't scroll at all, we should never listen to the touch. + return false + } + } + MotionEvent.ACTION_UP -> { + if (preventingIntercept) { + emitMotionEventForFalsing() + } + } + } + return super.onTouchEvent(event) + } override fun onInterceptTouchEvent(ev: MotionEvent): Boolean { // If there's a touch on this view and we can scroll down, we don't want to be intercepted @@ -974,8 +1001,10 @@ private class FrameLayoutTouchPassthrough( when (action) { MotionEvent.ACTION_DOWN -> { + preventingIntercept = false // If we can scroll down, make sure none of our parents intercepts us. if (canScrollForwardQs()) { + preventingIntercept = true parent?.requestDisallowInterceptTouchEvent(true) } downY = ev.y diff --git a/packages/SystemUI/src/com/android/systemui/qs/composefragment/dagger/QSFragmentComposeLog.kt b/packages/SystemUI/src/com/android/systemui/qs/composefragment/dagger/QSFragmentComposeLog.kt new file mode 100644 index 000000000000..5f151eba5c84 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/qs/composefragment/dagger/QSFragmentComposeLog.kt @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.qs.composefragment.dagger + +import javax.inject.Qualifier + +@Qualifier +@MustBeDocumented +@Retention(AnnotationRetention.RUNTIME) +annotation class QSFragmentComposeLog diff --git a/packages/SystemUI/src/com/android/systemui/qs/composefragment/dagger/QSFragmentComposeModule.kt b/packages/SystemUI/src/com/android/systemui/qs/composefragment/dagger/QSFragmentComposeModule.kt index 2ec729223a8d..4c9df116bd97 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/composefragment/dagger/QSFragmentComposeModule.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/composefragment/dagger/QSFragmentComposeModule.kt @@ -18,7 +18,8 @@ package com.android.systemui.qs.composefragment.dagger import android.content.Context import com.android.systemui.dagger.SysUISingleton -import com.android.systemui.dagger.qualifiers.Application +import com.android.systemui.log.table.TableLogBuffer +import com.android.systemui.log.table.TableLogBufferFactory import com.android.systemui.qs.flags.QSComposeFragment import com.android.systemui.shade.ShadeDisplayAware import com.android.systemui.util.Utils @@ -38,5 +39,14 @@ interface QSFragmentComposeModule { fun providesUsingMedia(@ShadeDisplayAware context: Context): Boolean { return QSComposeFragment.isEnabled && Utils.useQsMediaPlayer(context) } + + @Provides + @SysUISingleton + @QSFragmentComposeLog + fun providesQSFragmentComposeViewModelTableLog( + factory: TableLogBufferFactory + ): TableLogBuffer { + return factory.create("QSFragmentComposeViewModel", 200) + } } } diff --git a/packages/SystemUI/src/com/android/systemui/qs/composefragment/viewmodel/QSFragmentComposeViewModel.kt b/packages/SystemUI/src/com/android/systemui/qs/composefragment/viewmodel/QSFragmentComposeViewModel.kt index e3de6d5152e4..02498d69b83d 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/composefragment/viewmodel/QSFragmentComposeViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/composefragment/viewmodel/QSFragmentComposeViewModel.kt @@ -31,6 +31,8 @@ import com.android.app.tracing.coroutines.launchTraced as launch import com.android.keyguard.BouncerPanelExpansionCalculator import com.android.systemui.Dumpable import com.android.systemui.animation.ShadeInterpolation +import com.android.systemui.classifier.Classifier +import com.android.systemui.classifier.domain.interactor.FalsingInteractor import com.android.systemui.common.ui.domain.interactor.ConfigurationInteractor import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.deviceentry.domain.interactor.DeviceEntryInteractor @@ -39,6 +41,7 @@ import com.android.systemui.keyguard.shared.model.Edge import com.android.systemui.keyguard.shared.model.KeyguardState import com.android.systemui.lifecycle.ExclusiveActivatable import com.android.systemui.lifecycle.Hydrator +import com.android.systemui.log.table.TableLogBuffer import com.android.systemui.media.controls.ui.controller.MediaHierarchyManager import com.android.systemui.media.controls.ui.controller.MediaHierarchyManager.Companion.LOCATION_QQS import com.android.systemui.media.controls.ui.controller.MediaHierarchyManager.Companion.LOCATION_QS @@ -48,6 +51,7 @@ import com.android.systemui.media.dagger.MediaModule.QS_PANEL import com.android.systemui.media.dagger.MediaModule.QUICK_QS_PANEL import com.android.systemui.plugins.statusbar.StatusBarStateController import com.android.systemui.qs.FooterActionsController +import com.android.systemui.qs.composefragment.dagger.QSFragmentComposeLog import com.android.systemui.qs.composefragment.dagger.QSFragmentComposeModule import com.android.systemui.qs.footer.ui.viewmodel.FooterActionsViewModel import com.android.systemui.qs.panels.domain.interactor.TileSquishinessInteractor @@ -100,7 +104,9 @@ constructor( @ShadeDisplayAware configurationInteractor: ConfigurationInteractor, private val largeScreenHeaderHelper: LargeScreenHeaderHelper, private val squishinessInteractor: TileSquishinessInteractor, + private val falsingInteractor: FalsingInteractor, private val inFirstPageViewModel: InFirstPageViewModel, + @QSFragmentComposeLog private val tableLogBuffer: TableLogBuffer, mediaInRowInLandscapeViewModelFactory: MediaInRowInLandscapeViewModel.Factory, @Named(QUICK_QS_PANEL) val qqsMediaHost: MediaHost, @Named(QS_PANEL) val qsMediaHost: MediaHost, @@ -112,7 +118,7 @@ constructor( private val qqsMediaInRowViewModel = mediaInRowInLandscapeViewModelFactory.create(LOCATION_QQS) private val qsMediaInRowViewModel = mediaInRowInLandscapeViewModelFactory.create(LOCATION_QS) - private val hydrator = Hydrator("QSFragmentComposeViewModel.hydrator") + private val hydrator = Hydrator("QSFragmentComposeViewModel.hydrator", tableLogBuffer) val footerActionsViewModel = footerActionsViewModelFactory.create(lifecycleScope).also { @@ -434,6 +440,10 @@ constructor( } } + fun emitMotionEventForFalsingSwipeNested() { + falsingInteractor.isFalseTouch(Classifier.QS_SWIPE_NESTED) + } + override suspend fun onActivated(): Nothing { initMediaHosts() // init regardless of using media (same as current QS). coroutineScope { diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java index f8d408054d25..0e64820c984e 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java +++ b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java @@ -15,6 +15,8 @@ */ package com.android.systemui.qs.customize; +import static com.android.systemui.Flags.gsfQuickSettings; + import android.animation.Animator; import android.animation.Animator.AnimatorListener; import android.animation.AnimatorListenerAdapter; @@ -81,6 +83,10 @@ public class QSCustomizer extends LinearLayout { mToolbar.getMenu().add(Menu.NONE, MENU_RESET, 0, com.android.internal.R.string.reset) .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM); mToolbar.setTitle(R.string.qs_edit); + if (gsfQuickSettings()) { + mToolbar.setTitleTextAppearance(context, R.style.TextAppearance_QSEditTitle); + } + mRecyclerView = findViewById(android.R.id.list); mTransparentView = findViewById(R.id.customizer_transparent_view); DefaultItemAnimator animator = new DefaultItemAnimator(); diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java index 829c419fc07f..db778a208b1e 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java +++ b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java @@ -14,12 +14,15 @@ package com.android.systemui.qs.customize; +import static com.android.systemui.Flags.gsfQuickSettings; + import android.content.ComponentName; import android.content.Context; import android.content.res.Resources; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Rect; +import android.graphics.Typeface; import android.graphics.drawable.Drawable; import android.os.Handler; import android.view.LayoutInflater; @@ -309,6 +312,10 @@ public class TileAdapter extends RecyclerView.Adapter<Holder> implements TileSta if (viewType == TYPE_HEADER) { View v = inflater.inflate(R.layout.qs_customize_header, parent, false); v.setMinimumHeight(calculateHeaderMinHeight(context)); + if (gsfQuickSettings()) { + ((TextView) v.findViewById(android.R.id.title)).setTypeface( + Typeface.create("gsf-label-large", Typeface.NORMAL)); + } return new Holder(v); } if (viewType == TYPE_DIVIDER) { diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/EditModeButton.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/EditModeButton.kt new file mode 100644 index 000000000000..c2764f9f338b --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/EditModeButton.kt @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.qs.panels.ui.compose + +import androidx.compose.foundation.shape.CornerSize +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Edit +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.LocalContentColor +import androidx.compose.material3.MaterialTheme +import androidx.compose.runtime.Composable +import androidx.compose.runtime.CompositionLocalProvider +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.unit.dp +import com.android.systemui.lifecycle.rememberViewModel +import com.android.systemui.qs.panels.ui.viewmodel.EditModeButtonViewModel +import com.android.systemui.qs.ui.compose.borderOnFocus +import com.android.systemui.res.R + +@Composable +fun EditModeButton( + viewModelFactory: EditModeButtonViewModel.Factory, + modifier: Modifier = Modifier, +) { + val viewModel = rememberViewModel(traceName = "EditModeButton") { viewModelFactory.create() } + CompositionLocalProvider( + value = LocalContentColor provides MaterialTheme.colorScheme.onSurface + ) { + IconButton( + onClick = viewModel::onButtonClick, + shape = RoundedCornerShape(CornerSize(28.dp)), + modifier = + modifier.borderOnFocus( + color = MaterialTheme.colorScheme.secondary, + cornerSize = CornerSize(24.dp), + ), + ) { + Icon( + imageVector = Icons.Default.Edit, + contentDescription = stringResource(id = R.string.qs_edit), + ) + } + } +} diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/EditTileListState.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/EditTileListState.kt index c729c7c15176..14abfa2313d8 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/EditTileListState.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/EditTileListState.kt @@ -68,29 +68,16 @@ class EditTileListState( return _tiles.indexOfFirst { it is TileGridCell && it.tile.tileSpec == tileSpec } } - /** - * Whether the tile with this [TileSpec] is currently an icon in the [EditTileListState] - * - * @return true if the tile is an icon, false if it's large, null if the tile isn't in the list - */ - fun isIcon(tileSpec: TileSpec): Boolean? { - val index = indexOf(tileSpec) - return if (index != -1) { - val cell = _tiles[index] - cell as TileGridCell - return cell.isIcon - } else { - null - } - } - - /** Toggle the size of the tile corresponding to the [TileSpec] */ - fun toggleSize(tileSpec: TileSpec) { + /** Resize the tile corresponding to the [TileSpec] to [toIcon] */ + fun resizeTile(tileSpec: TileSpec, toIcon: Boolean) { val fromIndex = indexOf(tileSpec) if (fromIndex != -1) { - val cell = _tiles.removeAt(fromIndex) - cell as TileGridCell - _tiles.add(fromIndex, cell.copy(width = if (cell.isIcon) largeTilesSpan else 1)) + val cell = _tiles[fromIndex] as TileGridCell + + if (cell.isIcon == toIcon) return + + _tiles.removeAt(fromIndex) + _tiles.add(fromIndex, cell.copy(width = if (toIcon) 1 else largeTilesSpan)) regenerateGrid(fromIndex) } } diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/GridLayout.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/GridLayout.kt index 0d375817b705..a22eb3a8d517 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/GridLayout.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/GridLayout.kt @@ -27,12 +27,7 @@ import com.android.systemui.qs.pipeline.shared.TileSpec /** A layout of tiles, indicating how they should be composed when showing in QS or in edit mode. */ interface GridLayout { - @Composable - fun SceneScope.TileGrid( - tiles: List<TileViewModel>, - modifier: Modifier, - editModeStart: () -> Unit, - ) + @Composable fun SceneScope.TileGrid(tiles: List<TileViewModel>, modifier: Modifier) @Composable fun EditTileGrid( diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/PaginatedGridLayout.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/PaginatedGridLayout.kt index 789fdebc36eb..b6dbf4db57a4 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/PaginatedGridLayout.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/PaginatedGridLayout.kt @@ -16,6 +16,7 @@ package com.android.systemui.qs.panels.ui.compose +import android.view.MotionEvent import androidx.compose.foundation.layout.Arrangement.spacedBy import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.PaddingValues @@ -29,22 +30,15 @@ import androidx.compose.foundation.pager.HorizontalPager import androidx.compose.foundation.pager.PagerState import androidx.compose.foundation.pager.rememberPagerState import androidx.compose.foundation.shape.CornerSize -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.Edit -import androidx.compose.material3.Icon -import androidx.compose.material3.IconButton -import androidx.compose.material3.LocalContentColor import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable -import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.DisposableEffect import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.remember import androidx.compose.runtime.snapshotFlow import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.res.stringResource +import androidx.compose.ui.input.pointer.pointerInteropFilter import androidx.compose.ui.unit.dp import com.android.compose.animation.scene.SceneScope import com.android.compose.modifiers.padding @@ -55,10 +49,10 @@ import com.android.systemui.lifecycle.rememberViewModel import com.android.systemui.qs.panels.dagger.PaginatedBaseLayoutType import com.android.systemui.qs.panels.ui.compose.Dimensions.FooterHeight import com.android.systemui.qs.panels.ui.compose.Dimensions.InterPageSpacing +import com.android.systemui.qs.panels.ui.viewmodel.EditModeButtonViewModel import com.android.systemui.qs.panels.ui.viewmodel.PaginatedGridViewModel import com.android.systemui.qs.panels.ui.viewmodel.TileViewModel import com.android.systemui.qs.ui.compose.borderOnFocus -import com.android.systemui.res.R import javax.inject.Inject class PaginatedGridLayout @@ -68,11 +62,7 @@ constructor( @PaginatedBaseLayoutType private val delegateGridLayout: PaginatableGridLayout, ) : GridLayout by delegateGridLayout { @Composable - override fun SceneScope.TileGrid( - tiles: List<TileViewModel>, - modifier: Modifier, - editModeStart: () -> Unit, - ) { + override fun SceneScope.TileGrid(tiles: List<TileViewModel>, modifier: Modifier) { val viewModel = rememberViewModel(traceName = "PaginatedGridLayout-TileGrid") { viewModelFactory.create() @@ -115,7 +105,13 @@ constructor( state = pagerState, modifier = Modifier.sysuiResTag("qs_pager") - .padding(horizontal = { -contentPaddingValue.roundToPx() }), + .padding(horizontal = { -contentPaddingValue.roundToPx() }) + .pointerInteropFilter { event -> + if (event.actionMasked == MotionEvent.ACTION_UP) { + viewModel.registerSideSwipeGesture() + } + false + }, contentPadding = contentPadding, pageSpacing = if (pages.size > 1) InterPageSpacing else 0.dp, beyondViewportPageCount = 1, @@ -123,14 +119,12 @@ constructor( ) { val page = pages[it] - with(delegateGridLayout) { - TileGrid(tiles = page, modifier = Modifier, editModeStart = {}) - } + with(delegateGridLayout) { TileGrid(tiles = page, modifier = Modifier) } } FooterBar( buildNumberViewModelFactory = viewModel.buildNumberViewModelFactory, pagerState = pagerState, - editModeStart = editModeStart, + editButtonViewModelFactory = viewModel.editModeButtonViewModelFactory, ) } } @@ -145,7 +139,7 @@ private object Dimensions { private fun FooterBar( buildNumberViewModelFactory: BuildNumberViewModel.Factory, pagerState: PagerState, - editModeStart: () -> Unit, + editButtonViewModelFactory: EditModeButtonViewModel.Factory, ) { // Use requiredHeight so it won't be squished if the view doesn't quite fit. As this is // expected to be inside a scrollable container, this should not be an issue. @@ -181,24 +175,7 @@ private fun FooterBar( ) Row(Modifier.weight(1f)) { Spacer(modifier = Modifier.weight(1f)) - CompositionLocalProvider( - value = LocalContentColor provides MaterialTheme.colorScheme.onSurface - ) { - IconButton( - onClick = editModeStart, - shape = RoundedCornerShape(CornerSize(28.dp)), - modifier = - Modifier.borderOnFocus( - color = MaterialTheme.colorScheme.secondary, - cornerSize = CornerSize(FooterHeight / 2), - ), - ) { - Icon( - imageVector = Icons.Default.Edit, - contentDescription = stringResource(id = R.string.qs_edit), - ) - } - } + EditModeButton(viewModelFactory = editButtonViewModelFactory) } } } diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/TileGrid.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/TileGrid.kt index 1a5297b10e37..6c1906bb906f 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/TileGrid.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/TileGrid.kt @@ -24,13 +24,9 @@ import com.android.compose.animation.scene.SceneScope import com.android.systemui.qs.panels.ui.viewmodel.TileGridViewModel @Composable -fun SceneScope.TileGrid( - viewModel: TileGridViewModel, - modifier: Modifier = Modifier, - editModeStart: () -> Unit, -) { +fun SceneScope.TileGrid(viewModel: TileGridViewModel, modifier: Modifier = Modifier) { val gridLayout by viewModel.gridLayout.collectAsStateWithLifecycle() val tiles by viewModel.tileViewModels.collectAsStateWithLifecycle(emptyList()) - with(gridLayout) { TileGrid(tiles, modifier, editModeStart) } + with(gridLayout) { TileGrid(tiles, modifier) } } diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/infinitegrid/EditTile.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/infinitegrid/EditTile.kt index 31ea60e2f0bc..c6141a1a7cc2 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/infinitegrid/EditTile.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/infinitegrid/EditTile.kt @@ -20,7 +20,6 @@ package com.android.systemui.qs.panels.ui.compose.infinitegrid import androidx.compose.animation.AnimatedContent import androidx.compose.animation.AnimatedVisibility -import androidx.compose.animation.core.Animatable import androidx.compose.animation.core.animateDpAsState import androidx.compose.animation.core.animateFloatAsState import androidx.compose.animation.fadeIn @@ -75,7 +74,6 @@ import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.rememberUpdatedState import androidx.compose.runtime.setValue -import androidx.compose.runtime.snapshotFlow import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip @@ -124,8 +122,12 @@ import com.android.systemui.qs.panels.ui.compose.infinitegrid.CommonTileDefaults import com.android.systemui.qs.panels.ui.compose.infinitegrid.EditModeTileDefaults.CurrentTilesGridPadding import com.android.systemui.qs.panels.ui.compose.selection.MutableSelectionState import com.android.systemui.qs.panels.ui.compose.selection.ResizableTileContainer -import com.android.systemui.qs.panels.ui.compose.selection.TileWidths +import com.android.systemui.qs.panels.ui.compose.selection.ResizingState +import com.android.systemui.qs.panels.ui.compose.selection.ResizingState.ResizeOperation +import com.android.systemui.qs.panels.ui.compose.selection.ResizingState.ResizeOperation.FinalResizeOperation +import com.android.systemui.qs.panels.ui.compose.selection.ResizingState.ResizeOperation.TemporaryResizeOperation import com.android.systemui.qs.panels.ui.compose.selection.clearSelectionTile +import com.android.systemui.qs.panels.ui.compose.selection.rememberResizingState import com.android.systemui.qs.panels.ui.compose.selection.rememberSelectionState import com.android.systemui.qs.panels.ui.compose.selection.selectableTile import com.android.systemui.qs.panels.ui.model.GridCell @@ -136,10 +138,10 @@ import com.android.systemui.qs.panels.ui.viewmodel.EditTileViewModel import com.android.systemui.qs.pipeline.shared.TileSpec import com.android.systemui.qs.shared.model.groupAndSort import com.android.systemui.res.R +import kotlin.math.max import kotlin.math.roundToInt import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.delay -import kotlinx.coroutines.flow.collectLatest object TileType @@ -181,15 +183,7 @@ fun DefaultEditTileGrid( onStopEditing: () -> Unit, onReset: (() -> Unit)?, ) { - val currentListState by rememberUpdatedState(listState) - val selectionState = - rememberSelectionState( - onResize = { currentListState.toggleSize(it) }, - onResizeEnd = { spec -> - // Commit the size currently in the list - currentListState.isIcon(spec)?.let { onResize(spec, it) } - }, - ) + val selectionState = rememberSelectionState() val reset: (() -> Unit)? = if (onReset != null) { { @@ -349,10 +343,21 @@ private fun CurrentTilesGrid( } .testTag(CURRENT_TILES_GRID_TEST_TAG), ) { - EditTiles(cells, columns, listState, selectionState, coroutineScope, largeTilesSpan) { spec - -> - // Toggle the current size of the tile - currentListState.isIcon(spec)?.let { onResize(spec, !it) } + EditTiles(cells, columns, listState, selectionState, coroutineScope, largeTilesSpan) { + resizingOperation -> + when (resizingOperation) { + is TemporaryResizeOperation -> { + currentListState.resizeTile(resizingOperation.spec, resizingOperation.toIcon) + } + is FinalResizeOperation -> { + // Commit the new size of the tile + onResize(resizingOperation.spec, resizingOperation.toIcon) + + // Mark the selection as automatic in case the tile ends up moving to a + // different row with its new size. + selectionState.select(resizingOperation.spec, manual = false) + } + } } } } @@ -373,7 +378,7 @@ private fun AvailableTileGrid( // Available tiles Column( - verticalArrangement = spacedBy(CommonTileDefaults.TileArrangementPadding), + verticalArrangement = spacedBy(TileArrangementPadding), horizontalAlignment = Alignment.Start, modifier = Modifier.fillMaxWidth().wrapContentHeight().testTag(AVAILABLE_TILES_GRID_TEST_TAG), @@ -387,7 +392,7 @@ private fun AvailableTileGrid( ) tiles.chunked(columns).forEach { row -> Row( - horizontalArrangement = spacedBy(CommonTileDefaults.TileArrangementPadding), + horizontalArrangement = spacedBy(TileArrangementPadding), modifier = Modifier.fillMaxWidth().height(IntrinsicSize.Max), ) { row.forEachIndexed { index, tileGridCell -> @@ -436,7 +441,7 @@ fun LazyGridScope.EditTiles( selectionState: MutableSelectionState, coroutineScope: CoroutineScope, largeTilesSpan: Int, - onToggleSize: (spec: TileSpec) -> Unit, + onResize: (operation: ResizeOperation) -> Unit, ) { items( count = cells.size, @@ -464,7 +469,7 @@ fun LazyGridScope.EditTiles( index = index, dragAndDropState = dragAndDropState, selectionState = selectionState, - onToggleSize = onToggleSize, + onResize = onResize, coroutineScope = coroutineScope, bounceableInfo = cells.bounceableInfo(index, columns), largeTilesSpan = largeTilesSpan, @@ -482,7 +487,7 @@ private fun TileGridCell( index: Int, dragAndDropState: DragAndDropState, selectionState: MutableSelectionState, - onToggleSize: (spec: TileSpec) -> Unit, + onResize: (operation: ResizeOperation) -> Unit, coroutineScope: CoroutineScope, largeTilesSpan: Int, bounceableInfo: BounceableInfo, @@ -511,28 +516,47 @@ private fun TileGridCell( selected = selectionState.selection?.tileSpec == cell.tile.tileSpec } - // Current base, min and max width of this tile - var tileWidths: TileWidths? by remember { mutableStateOf(null) } - val padding = with(LocalDensity.current) { TileArrangementPadding.roundToPx() } + val state = rememberResizingState(cell.tile.tileSpec, cell.isIcon) + + val progress: () -> Float = { + if (selected) { + // If selected, return the manual progress from the drag + state.progress() + } else { + // Else, return the target progress for the tile format + if (cell.isIcon) 0f else 1f + } + } + + if (!selected) { + // Update the draggable anchor state when the tile's size is not manually toggled + LaunchedEffect(cell.isIcon) { state.updateCurrentValue(cell.isIcon) } + } else { + // If the tile is selected, listen to new target values from the draggable anchor to toggle + // the tile's size + LaunchedEffect(state.temporaryResizeOperation) { onResize(state.temporaryResizeOperation) } + LaunchedEffect(state.finalResizeOperation) { onResize(state.finalResizeOperation) } + } + + val totalPadding = + with(LocalDensity.current) { (largeTilesSpan - 1) * TileArrangementPadding.roundToPx() } ResizableTileContainer( selected = selected, - selectionState = selectionState, + state = state, selectionAlpha = { selectionAlpha }, selectionColor = selectionColor, - tileWidths = { tileWidths }, modifier = modifier .height(TileHeight) .fillMaxWidth() .onSizeChanged { // Grab the size before the bounceable to get the idle width - val totalPadding = (largeTilesSpan - 1) * padding val min = if (cell.isIcon) it.width else (it.width - totalPadding) / largeTilesSpan val max = if (cell.isIcon) (it.width * largeTilesSpan) + totalPadding else it.width - tileWidths = TileWidths(it.width, min, max) + state.updateAnchors(min.toFloat(), max.toFloat()) } .bounceable( bounceable = currentBounceableInfo.bounceable, @@ -552,7 +576,7 @@ private fun TileGridCell( listOf( // TODO(b/367748260): Add final accessibility actions CustomAccessibilityAction("Toggle size") { - onToggleSize(cell.tile.tileSpec) + onResize(FinalResizeOperation(cell.tile.tileSpec, !cell.isIcon)) true } ) @@ -567,24 +591,7 @@ private fun TileGridCell( ) .tileBackground(colors.background) ) { - val targetValue = if (cell.isIcon) 0f else 1f - val animatedProgress = remember { Animatable(targetValue) } - - val resizingState = selectionState.resizingState?.takeIf { selected } - LaunchedEffect(targetValue, resizingState) { - if (resizingState == null) { - animatedProgress.animateTo(targetValue) - } else { - snapshotFlow { resizingState.progression } - .collectLatest { animatedProgress.snapTo(it) } - } - } - - EditTile( - tile = cell.tile, - tileWidths = { tileWidths }, - progress = { animatedProgress.value }, - ) + EditTile(tile = cell.tile, state = state, progress = progress) } } } @@ -651,7 +658,7 @@ private fun SpacerGridCell(modifier: Modifier = Modifier) { @Composable fun EditTile( tile: EditTileViewModel, - tileWidths: () -> TileWidths?, + state: ResizingState, progress: () -> Float, colors: TileColors = EditModeTileDefaults.editTileColors(), ) { @@ -661,12 +668,16 @@ fun EditTile( verticalAlignment = Alignment.CenterVertically, modifier = Modifier.layout { measurable, constraints -> + val (min, max) = state.bounds + val currentProgress = progress() // Always display the tile using the large size and trust the parent composable // to clip the content as needed. This stop the labels from being truncated. - val width = tileWidths()?.max ?: constraints.maxWidth + val width = + max?.roundToInt()?.takeIf { it > constraints.maxWidth } + ?: constraints.maxWidth val placeable = measurable.measure(constraints.copy(minWidth = width, maxWidth = width)) - val currentProgress = progress() + val startPadding = if (currentProgress == 0f) { // Find the center of the max width when the tile is icon only @@ -675,7 +686,7 @@ fun EditTile( // Find the center of the minimum width to hold the same position as the // tile is resized. val basePadding = - tileWidths()?.min?.let { iconHorizontalCenter(it) } ?: 0f + min?.let { iconHorizontalCenter(it.roundToInt()) } ?: 0f // Large tiles, represented with a progress of 1f, have a 0.dp padding basePadding * (1f - currentProgress) } diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/infinitegrid/InfiniteGridLayout.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/infinitegrid/InfiniteGridLayout.kt index 29ff1715dea2..cb857ae5efc6 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/infinitegrid/InfiniteGridLayout.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/infinitegrid/InfiniteGridLayout.kt @@ -55,11 +55,7 @@ constructor( ) : PaginatableGridLayout { @Composable - override fun SceneScope.TileGrid( - tiles: List<TileViewModel>, - modifier: Modifier, - editModeStart: () -> Unit, - ) { + override fun SceneScope.TileGrid(tiles: List<TileViewModel>, modifier: Modifier) { DisposableEffect(tiles) { val token = Any() tiles.forEach { it.startListening(token) } diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/selection/MutableSelectionState.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/selection/MutableSelectionState.kt index 1d36aee4eb85..c6c6dcaa896c 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/selection/MutableSelectionState.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/selection/MutableSelectionState.kt @@ -27,11 +27,8 @@ import com.android.systemui.qs.pipeline.shared.TileSpec /** Creates the state of the current selected tile that is remembered across compositions. */ @Composable -fun rememberSelectionState( - onResize: (TileSpec) -> Unit, - onResizeEnd: (TileSpec) -> Unit, -): MutableSelectionState { - return remember { MutableSelectionState(onResize, onResizeEnd) } +fun rememberSelectionState(): MutableSelectionState { + return remember { MutableSelectionState() } } /** @@ -41,47 +38,18 @@ fun rememberSelectionState( data class Selection(val tileSpec: TileSpec, val manual: Boolean) /** Holds the state of the current selection. */ -class MutableSelectionState( - val onResize: (TileSpec) -> Unit, - private val onResizeEnd: (TileSpec) -> Unit, -) { +class MutableSelectionState { private var _selection = mutableStateOf<Selection?>(null) - private var _resizingState = mutableStateOf<ResizingState?>(null) /** The [Selection] if a tile is selected, null if not. */ val selection by _selection - /** The [ResizingState] of the selected tile is currently being resized, null if not. */ - val resizingState by _resizingState - fun select(tileSpec: TileSpec, manual: Boolean) { _selection.value = Selection(tileSpec, manual) } fun unSelect() { _selection.value = null - onResizingDragEnd() - } - - fun onResizingDrag(offset: Float) { - _resizingState.value?.onDrag(offset) - } - - fun onResizingDragStart(tileWidths: TileWidths) { - _selection.value?.let { - _resizingState.value = ResizingState(tileWidths) { onResize(it.tileSpec) } - } - } - - fun onResizingDragEnd() { - _resizingState.value = null - _selection.value?.let { - onResizeEnd(it.tileSpec) - - // Mark the selection as automatic in case the tile ends up moving to a different - // row with its new size. - _selection.value = it.copy(manual = false) - } } } diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/selection/ResizingState.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/selection/ResizingState.kt index 41c3de55af70..b27c08077834 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/selection/ResizingState.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/selection/ResizingState.kt @@ -16,56 +16,77 @@ package com.android.systemui.qs.panels.ui.compose.selection +import androidx.compose.foundation.gestures.AnchoredDraggableState +import androidx.compose.foundation.gestures.DraggableAnchors +import androidx.compose.foundation.gestures.animateTo +import androidx.compose.runtime.Composable +import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableFloatStateOf -import androidx.compose.runtime.mutableIntStateOf -import androidx.compose.runtime.setValue -import com.android.systemui.qs.panels.ui.compose.selection.ResizingDefaults.RESIZING_THRESHOLD +import androidx.compose.runtime.remember +import com.android.systemui.qs.panels.ui.compose.selection.ResizingState.ResizeOperation.FinalResizeOperation +import com.android.systemui.qs.panels.ui.compose.selection.ResizingState.ResizeOperation.TemporaryResizeOperation +import com.android.systemui.qs.pipeline.shared.TileSpec -class ResizingState(val widths: TileWidths, private val onResize: () -> Unit) { - /** Total drag offset of this resize operation. */ - private var totalOffset by mutableFloatStateOf(0f) - - /** Width in pixels of the resizing tile. */ - var width by mutableIntStateOf(widths.base) +@Composable +fun rememberResizingState(tileSpec: TileSpec, startsAsIcon: Boolean): ResizingState { + return remember(tileSpec) { ResizingState(tileSpec, startsAsIcon) } +} - /** Progression between icon (0) and large (1) sizes. */ - val progression - get() = calculateProgression() +enum class QSDragAnchor { + Icon, + Large, +} - // Whether the tile is currently over the threshold and should be a large tile - private var passedThreshold: Boolean = passedThreshold(progression) +class ResizingState(tileSpec: TileSpec, startsAsIcon: Boolean) { + val anchoredDraggableState = + AnchoredDraggableState(if (startsAsIcon) QSDragAnchor.Icon else QSDragAnchor.Large) - fun onDrag(offset: Float) { - totalOffset += offset - width = (widths.base + totalOffset).toInt().coerceIn(widths.min, widths.max) + val bounds by derivedStateOf { + anchoredDraggableState.anchors.minPosition().takeIf { !it.isNaN() } to + anchoredDraggableState.anchors.maxPosition().takeIf { !it.isNaN() } + } - passedThreshold(progression).let { - // Resize if we went over the threshold - if (passedThreshold != it) { - passedThreshold = it - onResize() - } - } + val temporaryResizeOperation by derivedStateOf { + TemporaryResizeOperation( + tileSpec, + toIcon = anchoredDraggableState.currentValue == QSDragAnchor.Icon, + ) } - private fun passedThreshold(progression: Float): Boolean { - return progression >= RESIZING_THRESHOLD + val finalResizeOperation by derivedStateOf { + FinalResizeOperation( + tileSpec, + toIcon = anchoredDraggableState.settledValue == QSDragAnchor.Icon, + ) } - /** The progression of the resizing tile between an icon tile (0f) and a large tile (1f) */ - private fun calculateProgression(): Float { - return ((width - widths.min) / (widths.max - widths.min).toFloat()).coerceIn(0f, 1f) + fun updateAnchors(min: Float, max: Float) { + anchoredDraggableState.updateAnchors( + DraggableAnchors { + QSDragAnchor.Icon at min + QSDragAnchor.Large at max + } + ) } -} -/** Holds the width of a tile as well as its min and max widths */ -data class TileWidths(val base: Int, val min: Int, val max: Int) { - init { - check(max > min) { "The max width needs to be larger than the min width." } + suspend fun updateCurrentValue(isIcon: Boolean) { + anchoredDraggableState.animateTo(if (isIcon) QSDragAnchor.Icon else QSDragAnchor.Large) } -} -private object ResizingDefaults { - const val RESIZING_THRESHOLD = .25f + fun progress(): Float = anchoredDraggableState.progress(QSDragAnchor.Icon, QSDragAnchor.Large) + + /** + * Represents a resizing operation for a tile. + * + * @property spec The tile's [TileSpec] + * @property toIcon The new size for the tile. + */ + sealed class ResizeOperation private constructor(val spec: TileSpec, val toIcon: Boolean) { + /** A temporary resizing operation, used while a resizing movement is in motion. */ + class TemporaryResizeOperation(spec: TileSpec, toIcon: Boolean) : + ResizeOperation(spec, toIcon) + + /** A final resizing operation, used while a resizing movement is done. */ + class FinalResizeOperation(spec: TileSpec, toIcon: Boolean) : ResizeOperation(spec, toIcon) + } } diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/selection/Selection.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/selection/Selection.kt index 8a345ce97c84..a187ff135cbb 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/selection/Selection.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/selection/Selection.kt @@ -19,10 +19,10 @@ package com.android.systemui.qs.panels.ui.compose.selection import androidx.compose.animation.core.Spring import androidx.compose.animation.core.animateDpAsState import androidx.compose.animation.core.animateFloatAsState -import androidx.compose.animation.core.animateIntAsState import androidx.compose.animation.core.spring import androidx.compose.foundation.Canvas -import androidx.compose.foundation.gestures.detectHorizontalDragGestures +import androidx.compose.foundation.gestures.Orientation +import androidx.compose.foundation.gestures.anchoredDraggable import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.BoxScope import androidx.compose.foundation.layout.size @@ -30,6 +30,7 @@ import androidx.compose.foundation.systemGestureExclusion import androidx.compose.material3.LocalMinimumInteractiveComponentSize import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable +import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.getValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier @@ -40,16 +41,15 @@ import androidx.compose.ui.geometry.Rect import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.SolidColor import androidx.compose.ui.graphics.drawscope.Stroke -import androidx.compose.ui.input.pointer.pointerInput import androidx.compose.ui.layout.layout import androidx.compose.ui.unit.Constraints import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.toSize import androidx.compose.ui.zIndex -import com.android.compose.modifiers.thenIf import com.android.systemui.qs.panels.ui.compose.infinitegrid.CommonTileDefaults.InactiveCornerRadius import com.android.systemui.qs.panels.ui.compose.selection.SelectionDefaults.ResizingDotSize import com.android.systemui.qs.panels.ui.compose.selection.SelectionDefaults.SelectedBorderWidth +import kotlin.math.roundToInt /** * Places a dot to handle resizing drag events. Use this on tiles to resize. @@ -58,31 +58,24 @@ import com.android.systemui.qs.panels.ui.compose.selection.SelectionDefaults.Sel * selected. * * @param selected whether resizing drag events should be handled - * @param selectionState the [MutableSelectionState] on the grid + * @param state the [ResizingState] for the tile * @param selectionAlpha the animated value for the dot and border alpha * @param selectionColor the [Color] of the dot and border - * @param tileWidths the [TileWidths] of the selected tile */ @Composable fun ResizableTileContainer( selected: Boolean, - selectionState: MutableSelectionState, + state: ResizingState, selectionAlpha: () -> Float, selectionColor: Color, - tileWidths: () -> TileWidths?, modifier: Modifier = Modifier, content: @Composable BoxScope.() -> Unit = {}, ) { - Box( - modifier - .resizable(selected, selectionState, tileWidths) - .selectionBorder(selectionColor, selectionAlpha) - ) { + Box(modifier.resizable(selected, state).selectionBorder(selectionColor, selectionAlpha)) { content() ResizingHandle( enabled = selected, - selectionState = selectionState, - tileWidths = tileWidths, + state = state, modifier = // Higher zIndex to make sure the handle is drawn above the content Modifier.zIndex(2f), @@ -91,12 +84,7 @@ fun ResizableTileContainer( } @Composable -private fun ResizingHandle( - enabled: Boolean, - selectionState: MutableSelectionState, - tileWidths: () -> TileWidths?, - modifier: Modifier = Modifier, -) { +private fun ResizingHandle(enabled: Boolean, state: ResizingState, modifier: Modifier = Modifier) { // Manually creating the touch target around the resizing dot to ensure that the next tile // does not receive the touch input accidentally. val minTouchTargetSize = LocalMinimumInteractiveComponentSize.current @@ -112,21 +100,12 @@ private fun ResizingHandle( ) } } - .thenIf(enabled) { - Modifier.systemGestureExclusion { Rect(Offset.Zero, it.size.toSize()) } - .pointerInput(Unit) { - detectHorizontalDragGestures( - onHorizontalDrag = { _, offset -> - selectionState.onResizingDrag(offset) - }, - onDragStart = { - tileWidths()?.let { selectionState.onResizingDragStart(it) } - }, - onDragEnd = selectionState::onResizingDragEnd, - onDragCancel = selectionState::onResizingDragEnd, - ) - } - } + .systemGestureExclusion { Rect(Offset.Zero, it.size.toSize()) } + .anchoredDraggable( + enabled = enabled, + state = state.anchoredDraggableState, + orientation = Orientation.Horizontal, + ) ) { ResizingDot(enabled = enabled, modifier = Modifier.align(Alignment.Center)) } @@ -165,23 +144,15 @@ private fun Modifier.selectionBorder( } @Composable -private fun Modifier.resizable( - selected: Boolean, - selectionState: MutableSelectionState, - tileWidths: () -> TileWidths?, -): Modifier { +private fun Modifier.resizable(selected: Boolean, state: ResizingState): Modifier { if (!selected) return zIndex(1f) - // Animated diff between the current width and the resized width of the tile. We can't use - // animateContentSize here as the tile is sometimes unbounded. - val remainingOffset by - animateIntAsState( - selectionState.resizingState?.let { tileWidths()?.base?.minus(it.width) ?: 0 } ?: 0, - label = "QSEditTileWidthOffset", - ) return zIndex(2f).layout { measurable, constraints -> + val isIdle by derivedStateOf { state.progress().let { it == 0f || it == 1f } } // Grab the width from the resizing state if a resize is in progress - val width = selectionState.resizingState?.width ?: (constraints.maxWidth - remainingOffset) + val width = + state.anchoredDraggableState.requireOffset().roundToInt().takeIf { !isIdle } + ?: constraints.maxWidth val placeable = measurable.measure(constraints.copy(minWidth = width, maxWidth = width)) layout(constraints.maxWidth, placeable.height) { placeable.place(0, 0) } } diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/viewmodel/EditModeButtonViewModel.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/viewmodel/EditModeButtonViewModel.kt new file mode 100644 index 000000000000..b033473a91e5 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/viewmodel/EditModeButtonViewModel.kt @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.qs.panels.ui.viewmodel + +import com.android.systemui.classifier.domain.interactor.FalsingInteractor +import com.android.systemui.plugins.FalsingManager +import dagger.assisted.AssistedFactory +import dagger.assisted.AssistedInject + +class EditModeButtonViewModel +@AssistedInject +constructor( + private val editModeViewModel: EditModeViewModel, + private val falsingInteractor: FalsingInteractor, +) { + + fun onButtonClick() { + if (!falsingInteractor.isFalseTap(FalsingManager.LOW_PENALTY)) { + editModeViewModel.startEditing() + } + } + + @AssistedFactory + interface Factory { + fun create(): EditModeButtonViewModel + } +} diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/viewmodel/PaginatedGridViewModel.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/viewmodel/PaginatedGridViewModel.kt index bff330b98fda..4a18872ad6f6 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/viewmodel/PaginatedGridViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/viewmodel/PaginatedGridViewModel.kt @@ -17,6 +17,8 @@ package com.android.systemui.qs.panels.ui.viewmodel import androidx.compose.runtime.getValue +import com.android.systemui.classifier.Classifier.QS_SWIPE_SIDE +import com.android.systemui.classifier.domain.interactor.FalsingInteractor import com.android.systemui.development.ui.viewmodel.BuildNumberViewModel import com.android.systemui.lifecycle.ExclusiveActivatable import com.android.systemui.lifecycle.Hydrator @@ -36,6 +38,8 @@ constructor( paginatedGridInteractor: PaginatedGridInteractor, inFirstPageViewModel: InFirstPageViewModel, val buildNumberViewModelFactory: BuildNumberViewModel.Factory, + val editModeButtonViewModelFactory: EditModeButtonViewModel.Factory, + private val falsingInteractor: FalsingInteractor, ) : IconTilesViewModel by iconTilesViewModel, ExclusiveActivatable() { private val hydrator = Hydrator("PaginatedGridViewModel") @@ -53,6 +57,10 @@ constructor( val columns: Int get() = columnsWithMediaViewModel.columns + fun registerSideSwipeGesture() { + falsingInteractor.isFalseTouch(QS_SWIPE_SIDE) + } + override suspend fun onActivated(): Nothing { coroutineScope { launch { hydrator.activate() } diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt index 1fb76f1eaa7f..b7ebce247ec9 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt @@ -27,6 +27,7 @@ import android.content.res.Resources.ID_NULL import android.graphics.Color import android.graphics.PorterDuff import android.graphics.Rect +import android.graphics.Typeface import android.graphics.drawable.Drawable import android.graphics.drawable.GradientDrawable import android.graphics.drawable.LayerDrawable @@ -308,6 +309,14 @@ constructor( } setLabelColor(getLabelColorForState(QSTile.State.DEFAULT_STATE)) setSecondaryLabelColor(getSecondaryLabelColorForState(QSTile.State.DEFAULT_STATE)) + + if (Flags.gsfQuickSettings()) { + label.apply { + typeface = Typeface.create("gsf-title-small-emphasized", Typeface.NORMAL) + } + secondaryLabel.apply { typeface = Typeface.create("gsf-label-medium", Typeface.NORMAL) } + } + addView(labelContainer) } diff --git a/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/DisabledContentInteractor.kt b/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/DisabledContentInteractor.kt new file mode 100644 index 000000000000..d7c3b6b43c71 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/DisabledContentInteractor.kt @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.scene.domain.interactor + +import com.android.compose.animation.scene.ContentKey +import com.android.compose.animation.scene.UserAction +import com.android.compose.animation.scene.UserActionResult +import com.android.systemui.scene.shared.model.Overlays +import com.android.systemui.scene.shared.model.Scenes +import com.android.systemui.statusbar.disableflags.domain.interactor.DisableFlagsInteractor +import com.android.systemui.statusbar.disableflags.shared.model.DisableFlagsModel +import javax.inject.Inject +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.collectLatest +import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.distinctUntilChanged +import kotlinx.coroutines.flow.map + +class DisabledContentInteractor +@Inject +constructor(private val disableFlagsInteractor: DisableFlagsInteractor) { + + /** Returns `true` if the given [key] is disabled; `false` if it's enabled */ + fun isDisabled( + key: ContentKey, + disabledFlags: DisableFlagsModel = disableFlagsInteractor.disableFlags.value, + ): Boolean { + return with(disabledFlags) { + when (key) { + Scenes.Shade, + Overlays.NotificationsShade -> !isShadeEnabled() + Scenes.QuickSettings, + Overlays.QuickSettingsShade -> !isQuickSettingsEnabled() + else -> false + } + } + } + + /** Runs the given [block] each time that [key] becomes disabled. */ + suspend fun repeatWhenDisabled(key: ContentKey, block: suspend (disabled: ContentKey) -> Unit) { + disableFlagsInteractor.disableFlags + .map { isDisabled(key) } + .distinctUntilChanged() + .collectLatest { isDisabled -> + if (isDisabled) { + block(key) + } + } + } + + /** + * Returns a filtered version of [unfiltered], without action-result entries that would navigate + * to disabled scenes. + */ + fun filteredUserActions( + unfiltered: Flow<Map<UserAction, UserActionResult>> + ): Flow<Map<UserAction, UserActionResult>> { + return combine(disableFlagsInteractor.disableFlags, unfiltered) { + disabledFlags, + unfilteredMap -> + unfilteredMap.filterValues { actionResult -> + val destination = + when (actionResult) { + is UserActionResult.ChangeScene -> actionResult.toScene + is UserActionResult.ShowOverlay -> actionResult.overlay + is UserActionResult.ReplaceByOverlay -> actionResult.overlay + else -> null + } + if (destination != null) { + // results that lead to a disabled destination get filtered out. + !isDisabled(key = destination, disabledFlags = disabledFlags) + } else { + // Action results that don't lead to a destination are never filtered out. + true + } + } + } + } +} diff --git a/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/SceneInteractor.kt b/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/SceneInteractor.kt index f20e5a54f6ed..d83d74e4e538 100644 --- a/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/SceneInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/SceneInteractor.kt @@ -21,6 +21,8 @@ import com.android.compose.animation.scene.ObservableTransitionState import com.android.compose.animation.scene.OverlayKey import com.android.compose.animation.scene.SceneKey import com.android.compose.animation.scene.TransitionKey +import com.android.compose.animation.scene.UserAction +import com.android.compose.animation.scene.UserActionResult import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.deviceentry.domain.interactor.DeviceUnlockedInteractor @@ -64,6 +66,7 @@ constructor( private val sceneFamilyResolvers: Lazy<Map<SceneKey, @JvmSuppressWildcards SceneResolver>>, private val deviceUnlockedInteractor: Lazy<DeviceUnlockedInteractor>, private val keyguardEnabledInteractor: Lazy<KeyguardEnabledInteractor>, + private val disabledContentInteractor: DisabledContentInteractor, ) { interface OnSceneAboutToChangeListener { @@ -465,6 +468,10 @@ constructor( return false } + if (disabledContentInteractor.isDisabled(to)) { + return false + } + val inMidTransitionFromGone = (transitionState.value as? ObservableTransitionState.Transition)?.fromContent == Scenes.Gone @@ -503,6 +510,10 @@ constructor( " Logging reason for overlay change was: $loggingReason" } + if (to != null && disabledContentInteractor.isDisabled(to)) { + return false + } + val isFromValid = (from == null) || (from in currentOverlays.value) val isToValid = (to == null) || (to !in currentOverlays.value && to in repository.allContentKeys) @@ -517,4 +528,14 @@ constructor( /** Returns `true` if [scene] can be resolved from [family]. */ fun isSceneInFamily(scene: SceneKey, family: SceneKey): Boolean = sceneFamilyResolvers.get()[family]?.includesScene(scene) == true + + /** + * Returns a filtered version of [unfiltered], without action-result entries that would navigate + * to disabled scenes. + */ + fun filteredUserActions( + unfiltered: Flow<Map<UserAction, UserActionResult>> + ): Flow<Map<UserAction, UserActionResult>> { + return disabledContentInteractor.filteredUserActions(unfiltered) + } } 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 aece5c65ce12..8d8c24eae9e2 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 @@ -19,7 +19,6 @@ package com.android.systemui.scene.domain.startable import android.app.StatusBarManager -import com.android.app.tracing.coroutines.launchTraced as launch import com.android.compose.animation.scene.ObservableTransitionState import com.android.compose.animation.scene.SceneKey import com.android.internal.logging.UiEventLogger @@ -56,6 +55,7 @@ import com.android.systemui.power.domain.interactor.PowerInteractor import com.android.systemui.power.shared.model.WakeSleepReason import com.android.systemui.scene.data.model.asIterable import com.android.systemui.scene.data.model.sceneStackOf +import com.android.systemui.scene.domain.interactor.DisabledContentInteractor import com.android.systemui.scene.domain.interactor.SceneBackInteractor import com.android.systemui.scene.domain.interactor.SceneContainerOcclusionInteractor import com.android.systemui.scene.domain.interactor.SceneInteractor @@ -103,6 +103,7 @@ import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.mapNotNull import kotlinx.coroutines.flow.stateIn +import kotlinx.coroutines.launch /** * Hooks up business logic that manipulates the state of the [SceneInteractor] for the system UI @@ -144,6 +145,7 @@ constructor( private val alternateBouncerInteractor: AlternateBouncerInteractor, private val vibratorHelper: VibratorHelper, private val msdlPlayer: MSDLPlayer, + private val disabledContentInteractor: DisabledContentInteractor, ) : CoreStartable { private val centralSurfaces: CentralSurfaces? get() = centralSurfacesOptLazy.get().getOrNull() @@ -281,6 +283,7 @@ constructor( handlePowerState() handleDreamState() handleShadeTouchability() + handleDisableFlags() } private fun handleBouncerImeVisibility() { @@ -565,6 +568,38 @@ constructor( } } + private fun handleDisableFlags() { + applicationScope.launch { + launch { + sceneInteractor.currentScene.collectLatest { currentScene -> + disabledContentInteractor.repeatWhenDisabled(currentScene) { + switchToScene( + targetSceneKey = SceneFamilies.Home, + loggingReason = + "Current scene ${currentScene.debugName} became" + " disabled", + ) + } + } + } + + launch { + sceneInteractor.currentOverlays.collectLatest { overlays -> + overlays.forEach { overlay -> + launch { + disabledContentInteractor.repeatWhenDisabled(overlay) { + sceneInteractor.hideOverlay( + overlay = overlay, + loggingReason = + "Overlay ${overlay.debugName} became" + " disabled", + ) + } + } + } + } + } + } + } + private fun handleDeviceEntryHapticsWhileDeviceLocked() { applicationScope.launch { deviceEntryInteractor.isDeviceEntered.collectLatest { isDeviceEntered -> diff --git a/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModel.kt b/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModel.kt index 32d5cb460cd8..c1e8032aa9e5 100644 --- a/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModel.kt @@ -280,6 +280,16 @@ constructor( } } + /** + * Returns a filtered version of [unfiltered], without action-result entries that would navigate + * to disabled scenes. + */ + fun filteredUserActions( + unfiltered: Flow<Map<UserAction, UserActionResult>> + ): Flow<Map<UserAction, UserActionResult>> { + return sceneInteractor.filteredUserActions(unfiltered) + } + /** Defines interface for classes that can handle externally-reported [MotionEvent]s. */ interface MotionEventHandler { /** Notifies that a [MotionEvent] has occurred. */ diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeDisplayAwareModule.kt b/packages/SystemUI/src/com/android/systemui/shade/ShadeDisplayAwareModule.kt index 4f73a3456cad..0b36e685d914 100644 --- a/packages/SystemUI/src/com/android/systemui/shade/ShadeDisplayAwareModule.kt +++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeDisplayAwareModule.kt @@ -17,9 +17,9 @@ package com.android.systemui.shade import android.content.Context +import android.content.MutableContextWrapper import android.content.res.Resources import android.view.LayoutInflater -import android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY import com.android.systemui.CoreStartable import com.android.systemui.common.ui.ConfigurationState import com.android.systemui.common.ui.ConfigurationStateImpl @@ -29,17 +29,20 @@ import com.android.systemui.common.ui.data.repository.ConfigurationRepositoryImp import com.android.systemui.common.ui.domain.interactor.ConfigurationInteractor import com.android.systemui.common.ui.domain.interactor.ConfigurationInteractorImpl import com.android.systemui.dagger.SysUISingleton -import com.android.systemui.res.R +import com.android.systemui.scene.ui.view.WindowRootView import com.android.systemui.shade.data.repository.ShadeDisplaysRepository import com.android.systemui.shade.data.repository.ShadeDisplaysRepositoryImpl +import com.android.systemui.shade.domain.interactor.ShadeDisplaysInteractor import com.android.systemui.shade.shared.flag.ShadeWindowGoesAround import com.android.systemui.statusbar.phone.ConfigurationControllerImpl import com.android.systemui.statusbar.phone.ConfigurationForwarder import com.android.systemui.statusbar.policy.ConfigurationController +import dagger.BindsOptionalOf import dagger.Module import dagger.Provides import dagger.multibindings.ClassKey import dagger.multibindings.IntoMap +import javax.inject.Provider /** * Module responsible for managing display-specific components and resources for the notification @@ -53,7 +56,7 @@ import dagger.multibindings.IntoMap * By using this dedicated module, we ensure the notification shade window always utilizes the * correct display context and resources, regardless of the display it's on. */ -@Module +@Module(includes = [OptionalShadeDisplayAwareBindings::class]) object ShadeDisplayAwareModule { /** Creates a new context for the shade window. */ @@ -62,9 +65,7 @@ object ShadeDisplayAwareModule { @SysUISingleton fun provideShadeDisplayAwareContext(context: Context): Context { return if (ShadeWindowGoesAround.isEnabled) { - context - .createWindowContext(context.display, TYPE_APPLICATION_OVERLAY, /* options= */ null) - .apply { setTheme(R.style.Theme_SystemUI) } + MutableContextWrapper(context) } else { context } @@ -172,4 +173,20 @@ object ShadeDisplayAwareModule { CoreStartable.NOP } } + + @Provides + @IntoMap + @ClassKey(ShadeDisplaysInteractor::class) + fun provideShadeDisplaysInteractor(impl: Provider<ShadeDisplaysInteractor>): CoreStartable { + return if (ShadeWindowGoesAround.isEnabled) { + impl.get() + } else { + CoreStartable.NOP + } + } +} + +@Module +internal interface OptionalShadeDisplayAwareBindings { + @BindsOptionalOf fun bindOptionalOfWindowRootView(): WindowRootView } diff --git a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeDisplaysInteractor.kt b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeDisplaysInteractor.kt index 1055dcb55d5f..432d5f553fbb 100644 --- a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeDisplaysInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeDisplaysInteractor.kt @@ -16,8 +16,13 @@ package com.android.systemui.shade.domain.interactor +import android.content.ComponentCallbacks import android.content.Context +import android.content.MutableContextWrapper +import android.content.res.Configuration +import android.content.res.Resources import android.util.Log +import android.view.WindowManager import android.view.WindowManager.LayoutParams.TYPE_NOTIFICATION_SHADE import com.android.app.tracing.coroutines.launchTraced import com.android.app.tracing.traceSection @@ -33,6 +38,8 @@ import com.android.systemui.shade.ShadeWindowLayoutParams import com.android.systemui.shade.data.repository.ShadeDisplaysRepository import com.android.systemui.shade.shared.flag.ShadeWindowGoesAround import com.android.systemui.statusbar.phone.ConfigurationForwarder +import com.android.systemui.util.kotlin.getOrNull +import java.util.Optional import javax.inject.Inject import kotlin.coroutines.CoroutineContext import kotlinx.coroutines.CoroutineScope @@ -43,15 +50,29 @@ import kotlinx.coroutines.withContext class ShadeDisplaysInteractor @Inject constructor( - private val shadeRootView: WindowRootView, + optionalShadeRootView: Optional<WindowRootView>, private val shadePositionRepository: ShadeDisplaysRepository, @ShadeDisplayAware private val shadeContext: Context, + @ShadeDisplayAware private val shadeResources: Resources, private val displayWindowPropertiesRepository: DisplayWindowPropertiesRepository, @Background private val bgScope: CoroutineScope, - @ShadeDisplayAware private val configurationForwarder: ConfigurationForwarder, - @Main private val mainContext: CoroutineContext, + @ShadeDisplayAware private val shadeConfigurationForwarder: ConfigurationForwarder, + @Main private val mainThreadContext: CoroutineContext, ) : CoreStartable { + private val shadeRootView = + optionalShadeRootView.getOrNull() + ?: error( + """ + ShadeRootView must be provided for this ShadeDisplayInteractor to work. + If it is not, it means this is being instantiated in a SystemUI variant that shouldn't. + """ + .trimIndent() + ) + // TODO: b/362719719 - Get rid of this callback as the root view should automatically get the + // correct configuration once it's moved to another window. + private var unregisterConfigChangedCallbacks: (() -> Unit)? = null + override fun start() { ShadeWindowGoesAround.isUnexpectedlyInLegacyMode() bgScope.launchTraced(TAG) { @@ -60,43 +81,86 @@ constructor( } /** Tries to move the shade. If anything wrong happens, fails gracefully without crashing. */ - private suspend fun moveShadeWindowTo(destinationDisplayId: Int) { - val currentId = shadeRootView.display.displayId - if (currentId == destinationDisplayId) { + private suspend fun moveShadeWindowTo(destinationId: Int) { + Log.d(TAG, "Trying to move shade window to display with id $destinationId") + val currentDisplay = shadeRootView.display + if (currentDisplay == null) { + Log.w(TAG, "Current shade display is null") + return + } + val currentId = currentDisplay.displayId + if (currentId == destinationId) { Log.w(TAG, "Trying to move the shade to a display it was already in") return } try { - moveShadeWindow(fromId = currentId, toId = destinationDisplayId) + moveShadeWindow(fromId = currentId, toId = destinationId) } catch (e: IllegalStateException) { Log.e( TAG, - "Unable to move the shade window from display $currentId to $destinationDisplayId", + "Unable to move the shade window from display $currentId to $destinationId", e, ) } } private suspend fun moveShadeWindow(fromId: Int, toId: Int) { - val sourceProperties = getDisplayWindowProperties(fromId) - val destinationProperties = getDisplayWindowProperties(toId) - traceSection({ "MovingShadeWindow from $fromId to $toId" }) { - withContext(mainContext) { - traceSection("removeView") { - sourceProperties.windowManager.removeView(shadeRootView) - } - traceSection("addView") { - destinationProperties.windowManager.addView( - shadeRootView, - ShadeWindowLayoutParams.create(shadeContext), - ) - } + val (_, _, _, sourceWm) = getDisplayWindowProperties(fromId) + val (_, _, destContext, destWm) = getDisplayWindowProperties(toId) + withContext(mainThreadContext) { + traceSection({ "MovingShadeWindow from $fromId to $toId" }) { + removeShade(sourceWm) + addShade(destWm) + overrideContextAndResources(newContext = destContext) + registerConfigurationChange(destContext) + } + traceSection("ShadeDisplaysInteractor#onConfigurationChanged") { + dispatchConfigurationChanged(destContext.resources.configuration) } } - traceSection("SecondaryShadeInteractor#onConfigurationChanged") { - configurationForwarder.onConfigurationChanged( - destinationProperties.context.resources.configuration - ) + } + + private fun removeShade(wm: WindowManager): Unit = + traceSection("removeView") { wm.removeView(shadeRootView) } + + private fun addShade(wm: WindowManager): Unit = + traceSection("addView") { + wm.addView(shadeRootView, ShadeWindowLayoutParams.create(shadeContext)) + } + + private fun overrideContextAndResources(newContext: Context) { + val contextWrapper = + shadeContext as? MutableContextWrapper + ?: error("Shade context is not a MutableContextWrapper!") + contextWrapper.baseContext = newContext + // Override needed in case someone is keeping a reference to the resources from the old + // context. + // TODO: b/362719719 - This shouldn't be needed, as resources should be updated when the + // window is moved to the new display automatically. + shadeResources.impl = shadeContext.resources.impl + } + + private fun dispatchConfigurationChanged(newConfig: Configuration) { + shadeConfigurationForwarder.onConfigurationChanged(newConfig) + shadeRootView.dispatchConfigurationChanged(newConfig) + shadeRootView.requestLayout() + } + + private fun registerConfigurationChange(context: Context) { + // we should keep only one at the time. + unregisterConfigChangedCallbacks?.invoke() + val callback = + object : ComponentCallbacks { + override fun onConfigurationChanged(newConfig: Configuration) { + dispatchConfigurationChanged(newConfig) + } + + override fun onLowMemory() {} + } + context.registerComponentCallbacks(callback) + unregisterConfigChangedCallbacks = { + context.unregisterComponentCallbacks(callback) + unregisterConfigChangedCallbacks = null } } @@ -105,6 +169,6 @@ constructor( } private companion object { - const val TAG = "SecondaryShadeInteractor" + const val TAG = "ShadeDisplaysInteractor" } } diff --git a/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeHeaderViewModel.kt b/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeHeaderViewModel.kt index 45516aa69cd7..0d847d84c820 100644 --- a/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeHeaderViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeHeaderViewModel.kt @@ -23,6 +23,7 @@ import android.icu.text.DateFormat import android.icu.text.DisplayContext import android.os.UserHandle import android.provider.Settings +import com.android.app.tracing.coroutines.launchTraced as launch import com.android.systemui.broadcast.BroadcastDispatcher import com.android.systemui.lifecycle.ExclusiveActivatable import com.android.systemui.plugins.ActivityStarter @@ -48,7 +49,6 @@ import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.onEach -import com.android.app.tracing.coroutines.launchTraced as launch /** Models UI state for the shade header. */ class ShadeHeaderViewModel @@ -87,10 +87,6 @@ constructor( /** Whether or not the privacy chip is enabled in the device privacy config. */ val isPrivacyChipEnabled: StateFlow<Boolean> = privacyChipInteractor.isChipEnabled - private val _isDisabled = MutableStateFlow(false) - /** Whether or not the Shade Header should be disabled based on disableFlags. */ - val isDisabled: StateFlow<Boolean> = _isDisabled.asStateFlow() - private val longerPattern = context.getString(R.string.abbrev_wday_month_day_no_year_alarm) private val shorterPattern = context.getString(R.string.abbrev_month_day_no_year) private val longerDateFormat = MutableStateFlow(getFormatFromPattern(longerPattern)) @@ -132,8 +128,6 @@ constructor( .collect { _mobileSubIds.value = it } } - launch { shadeInteractor.isQsEnabled.map { !it }.collect { _isDisabled.value = it } } - awaitCancellation() } } diff --git a/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeUserActions.kt b/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeUserActions.kt index b0777c9e20b9..dd1b58c47b63 100644 --- a/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeUserActions.kt +++ b/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeUserActions.kt @@ -27,24 +27,28 @@ import com.android.systemui.scene.ui.viewmodel.SceneContainerEdge /** Returns collection of [UserAction] to [UserActionResult] pairs for opening the single shade. */ fun singleShadeActions( - requireTwoPointersForTopEdgeForQs: Boolean = false + isDownFromTopEdgeEnabled: Boolean = true, + requireTwoPointersForTopEdgeForQs: Boolean = false, ): Array<Pair<UserAction, UserActionResult>> { val shadeUserActionResult = UserActionResult(Scenes.Shade, isIrreversible = true) val qsSceneUserActionResult = UserActionResult(Scenes.QuickSettings, isIrreversible = true) - return arrayOf( - // Swiping down, not from the edge, always goes to shade. - Swipe.Down to shadeUserActionResult, - Swipe.Down(pointerCount = 2) to shadeUserActionResult, - - // Swiping down from the top edge. - swipeDownFromTop(pointerCount = 1) to - if (requireTwoPointersForTopEdgeForQs) { - shadeUserActionResult - } else { - qsSceneUserActionResult - }, - swipeDownFromTop(pointerCount = 2) to qsSceneUserActionResult, - ) + return buildList { + // Swiping down, not from the edge, always goes to shade. + add(Swipe.Down to shadeUserActionResult) + add(Swipe.Down(pointerCount = 2) to shadeUserActionResult) + if (isDownFromTopEdgeEnabled) { + add( + swipeDownFromTop(pointerCount = 1) to + if (requireTwoPointersForTopEdgeForQs) { + shadeUserActionResult + } else { + qsSceneUserActionResult + } + ) + add(swipeDownFromTop(pointerCount = 2) to qsSceneUserActionResult) + } + } + .toTypedArray() } /** Returns collection of [UserAction] to [UserActionResult] pairs for opening the split shade. */ diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/chips/mediaprojection/domain/interactor/MediaProjectionChipInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/chips/mediaprojection/domain/interactor/MediaProjectionChipInteractor.kt index af238f697a18..49c44798d2ea 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/chips/mediaprojection/domain/interactor/MediaProjectionChipInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/chips/mediaprojection/domain/interactor/MediaProjectionChipInteractor.kt @@ -17,6 +17,7 @@ package com.android.systemui.statusbar.chips.mediaprojection.domain.interactor import android.content.pm.PackageManager +import android.media.projection.StopReason import com.android.app.tracing.coroutines.launchTraced as launch import com.android.systemui.Flags import com.android.systemui.dagger.SysUISingleton @@ -105,7 +106,7 @@ constructor( /** Stops the currently active projection. */ fun stopProjecting() { - scope.launch { mediaProjectionRepository.stopProjecting() } + scope.launch { mediaProjectionRepository.stopProjecting(StopReason.STOP_PRIVACY_CHIP) } } companion object { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/dagger/StatusBarModule.kt b/packages/SystemUI/src/com/android/systemui/statusbar/dagger/StatusBarModule.kt index 434120051039..9b24d451f9cb 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/dagger/StatusBarModule.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/dagger/StatusBarModule.kt @@ -27,6 +27,8 @@ import com.android.systemui.log.LogBufferFactory import com.android.systemui.statusbar.core.StatusBarConnectedDisplays import com.android.systemui.statusbar.data.StatusBarDataLayerModule import com.android.systemui.statusbar.data.repository.LightBarControllerStore +import com.android.systemui.statusbar.phone.AutoHideController +import com.android.systemui.statusbar.phone.AutoHideControllerImpl import com.android.systemui.statusbar.phone.LightBarController import com.android.systemui.statusbar.phone.StatusBarContentInsetsProvider import com.android.systemui.statusbar.phone.StatusBarContentInsetsProviderImpl @@ -79,6 +81,8 @@ interface StatusBarModule { implFactory: StatusBarWindowControllerImpl.Factory ): StatusBarWindowController.Factory + @Binds @SysUISingleton fun autoHideController(impl: AutoHideControllerImpl): AutoHideController + companion object { @Provides diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ColorizedFgsCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ColorizedFgsCoordinator.java index 47a04291dd49..733b986b5422 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ColorizedFgsCoordinator.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ColorizedFgsCoordinator.java @@ -20,13 +20,21 @@ import static android.app.NotificationManager.IMPORTANCE_MIN; import android.app.Notification; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + import com.android.systemui.statusbar.notification.collection.ListEntry; import com.android.systemui.statusbar.notification.collection.NotifPipeline; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.collection.coordinator.dagger.CoordinatorScope; +import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifComparator; +import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifPromoter; import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifSectioner; +import com.android.systemui.statusbar.notification.promoted.PromotedNotificationUi; import com.android.systemui.statusbar.notification.stack.NotificationPriorityBucketKt; +import com.google.common.primitives.Booleans; + import javax.inject.Inject; /** @@ -44,12 +52,21 @@ public class ColorizedFgsCoordinator implements Coordinator { @Override public void attach(NotifPipeline pipeline) { + if (PromotedNotificationUi.isEnabled()) { + pipeline.addPromoter(mPromotedOngoingPromoter); + } } public NotifSectioner getSectioner() { return mNotifSectioner; } + private final NotifPromoter mPromotedOngoingPromoter = new NotifPromoter("PromotedOngoing") { + @Override + public boolean shouldPromoteToTopLevel(NotificationEntry child) { + return isPromotedOngoing(child); + } + }; /** * Puts colorized foreground service and call notifications into its own section. @@ -64,11 +81,30 @@ public class ColorizedFgsCoordinator implements Coordinator { } return false; } + + private NotifComparator mPreferPromoted = new NotifComparator("PreferPromoted") { + @Override + public int compare(@NonNull ListEntry o1, @NonNull ListEntry o2) { + return -1 * Booleans.compare( + isPromotedOngoing(o1.getRepresentativeEntry()), + isPromotedOngoing(o2.getRepresentativeEntry())); + } + }; + + @Nullable + @Override + public NotifComparator getComparator() { + if (PromotedNotificationUi.isEnabled()) { + return mPreferPromoted; + } else { + return null; + } + } }; /** Determines if the given notification is a colorized or call notification */ public static boolean isRichOngoing(NotificationEntry entry) { - return isColorizedForegroundService(entry) || isCall(entry); + return isPromotedOngoing(entry) || isColorizedForegroundService(entry) || isCall(entry); } private static boolean isColorizedForegroundService(NotificationEntry entry) { @@ -78,6 +114,11 @@ public class ColorizedFgsCoordinator implements Coordinator { && entry.getImportance() > IMPORTANCE_MIN; } + private static boolean isPromotedOngoing(NotificationEntry entry) { + // NOTE: isPromotedOngoing already checks the android.app.ui_rich_ongoing flag. + return entry != null && entry.getSbn().getNotification().isPromotedOngoing(); + } + private static boolean isCall(NotificationEntry entry) { Notification notification = entry.getSbn().getNotification(); return entry.getImportance() > IMPORTANCE_MIN diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java index a90a1053e01c..0480212e4d59 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java @@ -36,6 +36,7 @@ import android.content.res.Resources; import android.graphics.Canvas; import android.graphics.Path; import android.graphics.Point; +import android.graphics.Rect; import android.graphics.drawable.AnimatedVectorDrawable; import android.graphics.drawable.AnimationDrawable; import android.graphics.drawable.Drawable; @@ -108,6 +109,7 @@ import com.android.systemui.statusbar.notification.row.shared.AsyncGroupHeaderVi import com.android.systemui.statusbar.notification.row.shared.LockscreenOtpRedaction; import com.android.systemui.statusbar.notification.row.wrapper.NotificationCompactMessagingTemplateViewWrapper; import com.android.systemui.statusbar.notification.row.wrapper.NotificationViewWrapper; +import com.android.systemui.statusbar.notification.shared.NotificationAddXOnHoverToDismiss; import com.android.systemui.statusbar.notification.shared.NotificationContentAlphaOptimization; import com.android.systemui.statusbar.notification.shared.TransparentHeaderFix; import com.android.systemui.statusbar.notification.stack.AmbientState; @@ -125,6 +127,7 @@ import com.android.systemui.statusbar.policy.SmartReplyConstants; import com.android.systemui.statusbar.policy.dagger.RemoteInputViewSubcomponent; import com.android.systemui.util.Compile; import com.android.systemui.util.DumpUtilsKt; +import com.android.systemui.util.ListenerSet; import com.android.systemui.wmshell.BubblesManager; import java.io.PrintWriter; @@ -430,6 +433,10 @@ public class ExpandableNotificationRow extends ActivatableNotificationView private float mBottomRoundnessDuringLaunchAnimation; private float mSmallRoundness; + private ListenerSet<DismissButtonTargetVisibilityListener> + mDismissButtonTargetVisibilityListeners + = new ListenerSet(); + public NotificationContentView[] getLayouts() { return Arrays.copyOf(mLayouts, mLayouts.length); } @@ -739,6 +746,73 @@ public class ExpandableNotificationRow extends ActivatableNotificationView } } + public interface DismissButtonTargetVisibilityListener { + // Called when the notification dismiss button's target visibility changes. + // NOTE: This can be called when the dismiss button already has the target visibility. + void onTargetVisibilityChanged(boolean targetVisible); + } + + public void addDismissButtonTargetStateListener( + DismissButtonTargetVisibilityListener listener) { + if (NotificationAddXOnHoverToDismiss.isUnexpectedlyInLegacyMode()) { + return; + } + + mDismissButtonTargetVisibilityListeners.addIfAbsent(listener); + } + + public void removeDismissButtonTargetStateListener( + DismissButtonTargetVisibilityListener listener) { + if (NotificationAddXOnHoverToDismiss.isUnexpectedlyInLegacyMode()) { + return; + } + + mDismissButtonTargetVisibilityListeners.remove(listener); + } + + @Override + public boolean onInterceptHoverEvent(MotionEvent event) { + if (!NotificationAddXOnHoverToDismiss.isEnabled()) { + return super.onInterceptHoverEvent(event); + } + + // Do not bother checking the dismiss button's target visibility if the notification cannot + // be dismissed. + if (!canEntryBeDismissed()) { + return false; + } + + final Boolean targetVisible = getDismissButtonTargetVisibilityIfAny(event); + if (targetVisible != null) { + for (DismissButtonTargetVisibilityListener listener : + mDismissButtonTargetVisibilityListeners) { + listener.onTargetVisibilityChanged(targetVisible.booleanValue()); + } + } + + // Do not consume the hover event so that children still have a chance to process it. + return false; + } + + private @Nullable Boolean getDismissButtonTargetVisibilityIfAny(MotionEvent event) { + // Returns the dismiss button's target visibility resulted by `event`. Returns null if the + // target visibility should not change. + + if (event.getAction() == MotionEvent.ACTION_HOVER_EXIT) { + // The notification dismiss button should be hidden when the hover exit event is located + // outside of the notification. NOTE: The hover exit event can be inside the + // notification if hover moves from one hoverable child to another. + final Rect localBounds = new Rect(0, 0, this.getWidth(), this.getActualHeight()); + if (!localBounds.contains((int) event.getX(), (int) event.getY())) { + return Boolean.FALSE; + } + } else if (event.getAction() == MotionEvent.ACTION_HOVER_ENTER) { + return Boolean.TRUE; + } + + return null; + } + private void updateLimitsForView(NotificationContentView layout) { View contractedView = layout.getContractedChild(); boolean customView = contractedView != null @@ -1536,6 +1610,10 @@ public class ExpandableNotificationRow extends ActivatableNotificationView return mPrivateLayout.getSingleLineView(); } + /** + * Whether this row is displayed over the unoccluded lockscreen. Returns false on the + * locked shade. + */ public boolean isOnKeyguard() { return mOnKeyguard; } @@ -2214,6 +2292,10 @@ public class ExpandableNotificationRow extends ActivatableNotificationView mTranslateableViews.remove(mGutsStub); // We don't handle focus highlight in this view, it's done in background drawable instead setDefaultFocusHighlightEnabled(false); + + if (NotificationAddXOnHoverToDismiss.isEnabled()) { + addDismissButtonTargetStateListener(findViewById(R.id.backgroundNormal)); + } } /** @@ -2820,7 +2902,8 @@ public class ExpandableNotificationRow extends ActivatableNotificationView } } - void setOnKeyguard(boolean onKeyguard) { + /** @see #isOnKeyguard() */ + public void setOnKeyguard(boolean onKeyguard) { if (onKeyguard != mOnKeyguard) { boolean wasAboveShelf = isAboveShelf(); final boolean wasExpanded = isExpanded(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java index baad616cbf02..ffe1b6f88302 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java @@ -41,6 +41,7 @@ import com.android.systemui.plugins.FalsingManager; import com.android.systemui.plugins.PluginManager; import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin; import com.android.systemui.plugins.statusbar.StatusBarStateController; +import com.android.systemui.scene.shared.flag.SceneContainerFlag; import com.android.systemui.statusbar.SmartReplyController; import com.android.systemui.statusbar.notification.ColorUpdateLogger; import com.android.systemui.statusbar.notification.FeedbackIcon; @@ -378,15 +379,19 @@ public class ExpandableNotificationRowController implements NotifViewController mView.getEntry().setInitializationTime(mClock.elapsedRealtime()); mPluginManager.addPluginListener(mView, NotificationMenuRowPlugin.class, false /* Allow multiple */); - mView.setOnKeyguard(mStatusBarStateController.getState() == KEYGUARD); - mStatusBarStateController.addCallback(mStatusBarStateListener); + if (!SceneContainerFlag.isEnabled()) { + mView.setOnKeyguard(mStatusBarStateController.getState() == KEYGUARD); + mStatusBarStateController.addCallback(mStatusBarStateListener); + } mSettingsController.addCallback(BUBBLES_SETTING_URI, mSettingsListener); } @Override public void onViewDetachedFromWindow(View v) { mPluginManager.removePluginListener(mView); - mStatusBarStateController.removeCallback(mStatusBarStateListener); + if (!SceneContainerFlag.isEnabled()) { + mStatusBarStateController.removeCallback(mStatusBarStateListener); + } mSettingsController.removeCallback(BUBBLES_SETTING_URI, mSettingsListener); } }); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBackgroundView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBackgroundView.java index d0db5145e0ff..34ef63944f14 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBackgroundView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBackgroundView.java @@ -21,7 +21,9 @@ import static com.android.systemui.util.ColorUtilKt.hexColorString; import android.content.Context; import android.content.res.ColorStateList; import android.graphics.Canvas; +import android.graphics.Path; import android.graphics.PorterDuff; +import android.graphics.Rect; import android.graphics.drawable.Drawable; import android.graphics.drawable.GradientDrawable; import android.graphics.drawable.LayerDrawable; @@ -36,6 +38,7 @@ import com.android.internal.util.ContrastColorUtil; import com.android.settingslib.Utils; import com.android.systemui.Dumpable; import com.android.systemui.res.R; +import com.android.systemui.statusbar.notification.shared.NotificationAddXOnHoverToDismiss; import com.android.systemui.util.DrawableDumpKt; import java.io.PrintWriter; @@ -44,7 +47,8 @@ import java.util.Arrays; /** * A view that can be used for both the dimmed and normal background of an notification. */ -public class NotificationBackgroundView extends View implements Dumpable { +public class NotificationBackgroundView extends View implements Dumpable, + ExpandableNotificationRow.DismissButtonTargetVisibilityListener { private final boolean mDontModifyCorners; private Drawable mBackground; @@ -66,6 +70,11 @@ public class NotificationBackgroundView extends View implements Dumpable { private final ColorStateList mLightColoredStatefulColors; private final ColorStateList mDarkColoredStatefulColors; private final int mNormalColor; + private final int convexR = 9; + private final int concaveR = 22; + + // True only if the dismiss button is visible. + private boolean mDrawDismissButtonCutout = false; public NotificationBackgroundView(Context context, AttributeSet attrs) { super(context, attrs); @@ -80,6 +89,18 @@ public class NotificationBackgroundView extends View implements Dumpable { } @Override + public void onTargetVisibilityChanged(boolean targetVisible) { + if (NotificationAddXOnHoverToDismiss.isUnexpectedlyInLegacyMode()) { + return; + } + + if (mDrawDismissButtonCutout != targetVisible) { + mDrawDismissButtonCutout = targetVisible; + invalidate(); + } + } + + @Override protected void onDraw(Canvas canvas) { if (mClipTopAmount + mClipBottomAmount < getActualHeight() || mExpandAnimationRunning) { canvas.save(); @@ -87,12 +108,87 @@ public class NotificationBackgroundView extends View implements Dumpable { canvas.clipRect(0, mClipTopAmount, getWidth(), getActualHeight() - mClipBottomAmount); } - draw(canvas, mBackground); + + if (!NotificationAddXOnHoverToDismiss.isEnabled()) { + draw(canvas, mBackground); + canvas.restore(); + return; + } + + Rect backgroundBounds = null; + if (mBackground != null || mDrawDismissButtonCutout) { + backgroundBounds = calculateBackgroundBounds(); + } + + if (mDrawDismissButtonCutout) { + canvas.clipPath(calculateDismissButtonCutoutPath(backgroundBounds)); + } + + if (mBackground != null) { + mBackground.setBounds(backgroundBounds); + mBackground.draw(canvas); + } + canvas.restore(); } } + private Path calculateDismissButtonCutoutPath(Rect backgroundBounds) { + // TODO(b/365585705): Adapt to RTL after the UX design is finalized. + + NotificationAddXOnHoverToDismiss.isUnexpectedlyInLegacyMode(); + + Path path = new Path(); + + final int left = backgroundBounds.left; + final int right = backgroundBounds.right; + final int top = backgroundBounds.top; + final int bottom = backgroundBounds.bottom; + + // Generate the path clockwise from the left-top corner. + path.moveTo(left, top); + path.lineTo(right - 2 * convexR - concaveR, top); + path.quadTo(right - convexR - concaveR, top, right - convexR - concaveR, + top + convexR); + path.quadTo(right - convexR - concaveR, top + convexR + concaveR, right - convexR, + top + convexR + concaveR); + path.quadTo(right, top + convexR + concaveR, right, top + 2 * convexR + concaveR); + path.lineTo(right, bottom); + path.lineTo(left, bottom); + path.lineTo(left, top); + + return path; + } + + private Rect calculateBackgroundBounds() { + NotificationAddXOnHoverToDismiss.isUnexpectedlyInLegacyMode(); + + int top = 0; + int bottom = getActualHeight(); + if (mBottomIsRounded + && mBottomAmountClips + && !mExpandAnimationRunning) { + bottom -= mClipBottomAmount; + } + final boolean isRtl = isLayoutRtl(); + final int width = getWidth(); + final int actualWidth = getActualWidth(); + + int left = isRtl ? width - actualWidth : 0; + int right = isRtl ? width : actualWidth; + + if (mExpandAnimationRunning) { + // Horizontally center this background view inside of the container + left = (int) ((width - actualWidth) / 2.0f); + right = (int) (left + actualWidth); + } + + return new Rect(left, top, right, bottom); + } + private void draw(Canvas canvas, Drawable drawable) { + NotificationAddXOnHoverToDismiss.assertInLegacyMode(); + if (drawable != null) { int top = 0; int bottom = getActualHeight(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationHeaderViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationHeaderViewWrapper.java index b622defbef98..e9eecdd8a26f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationHeaderViewWrapper.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationHeaderViewWrapper.java @@ -16,6 +16,9 @@ package com.android.systemui.statusbar.notification.row.wrapper; +import static android.view.View.GONE; +import static android.view.View.VISIBLE; + import static com.android.systemui.statusbar.notification.TransformState.TRANSFORM_Y; import android.app.Notification; @@ -48,6 +51,7 @@ import com.android.systemui.statusbar.notification.Roundable; import com.android.systemui.statusbar.notification.RoundableState; import com.android.systemui.statusbar.notification.TransformState; import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow; +import com.android.systemui.statusbar.notification.shared.NotificationAddXOnHoverToDismiss; import java.util.Stack; @@ -115,6 +119,10 @@ public class NotificationHeaderViewWrapper extends NotificationViewWrapper imple resolveHeaderViews(); addFeedbackOnClickListener(row); addCloseButtonOnClickListener(row); + + if (NotificationAddXOnHoverToDismiss.isEnabled()) { + mRow.addDismissButtonTargetStateListener(mHoverListener); + } } @Override @@ -166,13 +174,34 @@ public class NotificationHeaderViewWrapper extends NotificationViewWrapper imple } } + private ExpandableNotificationRow.DismissButtonTargetVisibilityListener mHoverListener = new + ExpandableNotificationRow.DismissButtonTargetVisibilityListener() { + @Override + public void onTargetVisibilityChanged(boolean targetVisible) { + NotificationAddXOnHoverToDismiss.isUnexpectedlyInLegacyMode(); + + if (mCloseButton != null) { + mCloseButton.setVisibility(targetVisible ? VISIBLE : GONE); + } + } + }; + + @Override + public void setRemoved() { + super.setRemoved(); + + if (NotificationAddXOnHoverToDismiss.isEnabled()) { + mRow.removeDismissButtonTargetStateListener(mHoverListener); + } + } + /** * Shows the given feedback icon, or hides the icon if null. */ @Override public void setFeedbackIcon(@Nullable FeedbackIcon icon) { if (mFeedbackIcon != null) { - mFeedbackIcon.setVisibility(icon != null ? View.VISIBLE : View.GONE); + mFeedbackIcon.setVisibility(icon != null ? VISIBLE : GONE); if (icon != null) { if (mFeedbackIcon instanceof ImageButton) { ((ImageButton) mFeedbackIcon).setImageResource(icon.getIconRes()); @@ -266,7 +295,7 @@ public class NotificationHeaderViewWrapper extends NotificationViewWrapper imple boolean expandable, View.OnClickListener onClickListener, boolean requestLayout) { - mExpandButton.setVisibility(expandable ? View.VISIBLE : View.GONE); + mExpandButton.setVisibility(expandable ? VISIBLE : GONE); mExpandButton.setOnClickListener(expandable ? onClickListener : null); if (mAltExpandTarget != null) { mAltExpandTarget.setOnClickListener(expandable ? onClickListener : null); @@ -294,7 +323,7 @@ public class NotificationHeaderViewWrapper extends NotificationViewWrapper imple @Override public void setRecentlyAudiblyAlerted(boolean audiblyAlerted) { if (mAudiblyAlertedIcon != null) { - mAudiblyAlertedIcon.setVisibility(audiblyAlerted ? View.VISIBLE : View.GONE); + mAudiblyAlertedIcon.setVisibility(audiblyAlerted ? VISIBLE : GONE); } } @@ -371,6 +400,7 @@ public class NotificationHeaderViewWrapper extends NotificationViewWrapper imple ((DateTimeView) timeView).setTime(whenMillis); } } + protected void addTransformedViews(View... views) { for (View view : views) { if (view != null) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/shared/NotificationAddXOnHoverToDismiss.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/shared/NotificationAddXOnHoverToDismiss.kt new file mode 100644 index 000000000000..0961874b2276 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/shared/NotificationAddXOnHoverToDismiss.kt @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.statusbar.notification.shared + +import com.android.systemui.Flags +import com.android.systemui.flags.FlagToken +import com.android.systemui.flags.RefactorFlagUtils + +/** Helper for reading or using the notification dismiss button on hover flag state. */ +@Suppress("NOTHING_TO_INLINE") +object NotificationAddXOnHoverToDismiss { + const val FLAG_NAME = Flags.FLAG_NOTIFICATION_ADD_X_ON_HOVER_TO_DISMISS + + val token: FlagToken + get() = FlagToken(FLAG_NAME, isEnabled) + + @JvmStatic + inline val isEnabled + get() = Flags.notificationAddXOnHoverToDismiss() + + @JvmStatic + inline fun isUnexpectedlyInLegacyMode() = + RefactorFlagUtils.isUnexpectedlyInLegacyMode(isEnabled, FLAG_NAME) + + @JvmStatic + inline fun assertInLegacyMode() = RefactorFlagUtils.assertInLegacyMode(isEnabled, FLAG_NAME) +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationListContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationListContainer.java index 5c9a0b939dc7..f85545ef95f8 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationListContainer.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationListContainer.java @@ -100,6 +100,9 @@ public interface NotificationListContainer extends */ void addContainerViewAt(View v, int index); + /** Sets whether the notificatios are displayed on the unoccluded lockscreen. */ + void setOnLockscreen(boolean isOnKeyguard); + /** * Sets the maximum number of notifications to display. * diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java index 57af8ea19722..bddf6dffe7c0 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java @@ -575,6 +575,7 @@ public class NotificationStackScrollLayout @Nullable private SplitShadeStateController mSplitShadeStateController = null; private boolean mIsSmallLandscapeLockscreenEnabled = false; private boolean mSuppressHeightUpdates; + private boolean mIsOnLockscreen; /** Pass splitShadeStateController to view and update split shade */ public void passSplitShadeStateController(SplitShadeStateController splitShadeStateController) { @@ -3228,9 +3229,12 @@ public class NotificationStackScrollLayout private void onViewAddedInternal(ExpandableView child) { updateHideSensitiveForChild(child); child.setOnHeightChangedListener(mOnChildHeightChangedListener); - if (child instanceof ExpandableNotificationRow) { + if (child instanceof ExpandableNotificationRow row) { NotificationEntry entry = ((ExpandableNotificationRow) child).getEntry(); entry.addOnSensitivityChangedListener(mOnChildSensitivityChangedListener); + if (SceneContainerFlag.isEnabled()) { + row.setOnKeyguard(mIsOnLockscreen); + } } generateAddAnimation(child, false /* fromMoreCard */); updateAnimationState(child); @@ -4752,8 +4756,11 @@ public class NotificationStackScrollLayout } } - void goToFullShade(long delay) { - SceneContainerFlag.assertInLegacyMode(); + /** + * Requests an animation for the next stack height update, to animate from the constrained stack + * displayed on the lock screen, to the scrollable stack displayed in the expanded shade. + */ + public void animateGoToFullShade(long delay) { mGoToFullShadeNeedsAnimation = true; mGoToFullShadeDelay = delay; mNeedsAnimation = true; @@ -5356,12 +5363,38 @@ public class NotificationStackScrollLayout shelf.bind(mAmbientState, this, mController.getNotificationRoundnessManager()); } + /** + * Whether the notifications are displayed over the unoccluded lockscreen. Returns false on the + * locked shade. + */ + public boolean isOnLockscreen() { + if (SceneContainerFlag.isUnexpectedlyInLegacyMode()) return false; + return mIsOnLockscreen; + } + + /** @see #isOnLockscreen() */ + public void setOnLockscreen(boolean isOnLockscreen) { + if (SceneContainerFlag.isUnexpectedlyInLegacyMode()) return; + if (mIsOnLockscreen != isOnLockscreen) { + mIsOnLockscreen = isOnLockscreen; + for (int i = 0; i < getChildCount(); i++) { + View child = getChildAt(i); + if (child instanceof ExpandableNotificationRow childRow) { + childRow.setOnKeyguard(isOnLockscreen); + } + } + } + } + public void setMaxDisplayedNotifications(int maxDisplayedNotifications) { if (mMaxDisplayedNotifications != maxDisplayedNotifications) { mMaxDisplayedNotifications = maxDisplayedNotifications; if (SceneContainerFlag.isEnabled()) { updateIntrinsicStackHeight(); updateStackEndHeightAndStackHeight(mAmbientState.getExpansionFraction()); + if (maxDisplayedNotifications == -1) { + animateGoToFullShade(0); + } } else { updateContentHeight(); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java index dc1a191ce233..3d7501deafc7 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java @@ -1222,7 +1222,7 @@ public class NotificationStackScrollLayoutController implements Dumpable { public void goToFullShade(long delay) { SceneContainerFlag.assertInLegacyMode(); - mView.goToFullShade(delay); + mView.animateGoToFullShade(delay); } public void setOverScrollAmount(float amount, boolean onTop, boolean animate, @@ -1603,6 +1603,12 @@ public class NotificationStackScrollLayoutController implements Dumpable { } } + /** Sets whether the NSSL is displayed over the unoccluded Lockscreen. */ + public void setOnLockscreen(boolean isOnLockscreen) { + if (SceneContainerFlag.isUnexpectedlyInLegacyMode()) return; + mNotificationListContainer.setOnLockscreen(isOnLockscreen); + } + /** * Set the maximum number of notifications that can currently be displayed */ @@ -2029,6 +2035,11 @@ public class NotificationStackScrollLayoutController implements Dumpable { } @Override + public void setOnLockscreen(boolean isOnLockscreen) { + mView.setOnLockscreen(isOnLockscreen); + } + + @Override public void setMaxDisplayedNotifications(int maxNotifications) { mView.setMaxDisplayedNotifications(maxNotifications); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/SharedNotificationContainerBinder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/SharedNotificationContainerBinder.kt index 4a55dfaaf7ea..ea714608ea66 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/SharedNotificationContainerBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/SharedNotificationContainerBinder.kt @@ -118,8 +118,12 @@ constructor( } launch { - viewModel.getMaxNotifications(calculateMaxNotifications).collect { - controller.setMaxDisplayedNotifications(it) + viewModel.getLockscreenDisplayConfig(calculateMaxNotifications).collect { + (isOnLockscreen, maxNotifications) -> + if (SceneContainerFlag.isEnabled) { + controller.setOnLockscreen(isOnLockscreen) + } + controller.setMaxDisplayedNotifications(maxNotifications) } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModel.kt index fb60f266e188..a55a165d9b66 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModel.kt @@ -718,9 +718,11 @@ constructor( * When expanding or when the user is interacting with the shade, keep the count stable; do not * emit a value. */ - fun getMaxNotifications(calculateSpace: (Float, Boolean) -> Int): Flow<Int> { + fun getLockscreenDisplayConfig( + calculateSpace: (Float, Boolean) -> Int + ): Flow<LockscreenDisplayConfig> { val showLimitedNotifications = isOnLockscreenWithoutShade - val showUnlimitedNotifications = + val showUnlimitedNotificationsAndIsOnLockScreen = combine( isOnLockscreen, keyguardInteractor.statusBarState, @@ -730,28 +732,42 @@ constructor( ) .onStart { emit(false) }, ) { isOnLockscreen, statusBarState, showAllNotifications -> - statusBarState == SHADE_LOCKED || !isOnLockscreen || showAllNotifications + (statusBarState == SHADE_LOCKED || !isOnLockscreen || showAllNotifications) to + isOnLockscreen } + @Suppress("UNCHECKED_CAST") return combineTransform( showLimitedNotifications, - showUnlimitedNotifications, + showUnlimitedNotificationsAndIsOnLockScreen, shadeInteractor.isUserInteracting, availableHeight, interactor.notificationStackChanged, interactor.useExtraShelfSpace, ) { flows -> val showLimitedNotifications = flows[0] as Boolean - val showUnlimitedNotifications = flows[1] as Boolean + val (showUnlimitedNotifications, isOnLockscreen) = + flows[1] as Pair<Boolean, Boolean> val isUserInteracting = flows[2] as Boolean val availableHeight = flows[3] as Float val useExtraShelfSpace = flows[5] as Boolean if (!isUserInteracting) { if (showLimitedNotifications) { - emit(calculateSpace(availableHeight, useExtraShelfSpace)) + emit( + LockscreenDisplayConfig( + isOnLockscreen = isOnLockscreen, + maxNotifications = + calculateSpace(availableHeight, useExtraShelfSpace), + ) + ) } else if (showUnlimitedNotifications) { - emit(-1) + emit( + LockscreenDisplayConfig( + isOnLockscreen = isOnLockscreen, + maxNotifications = -1, + ) + ) } } } @@ -775,9 +791,9 @@ constructor( SceneContainerFlag.assertInLegacyMode() return combine( - getMaxNotifications(calculateMaxNotifications).map { - val height = calculateHeight(it) - if (it == 0) { + getLockscreenDisplayConfig(calculateMaxNotifications).map { (_, maxNotifications) -> + val height = calculateHeight(maxNotifications) + if (maxNotifications == 0) { height - shelfHeight } else { height @@ -815,4 +831,13 @@ constructor( */ data class FloatAtEnd(val width: Int) : HorizontalPosition } + + /** + * Data class representing a configuration for displaying Notifications on the Lockscreen. + * + * @param isOnLockscreen is the user on the lockscreen + * @param maxNotifications Limit for the max number of top-level Notifications to be displayed. + * A value of -1 indicates no limit. + */ + data class LockscreenDisplayConfig(val isOnLockscreen: Boolean, val maxNotifications: Int) } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoHideController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoHideController.kt new file mode 100644 index 000000000000..636e1c45bc81 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoHideController.kt @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.statusbar.phone + +import android.content.Context +import android.view.MotionEvent +import com.android.systemui.statusbar.AutoHideUiElement +import java.io.PrintWriter + +/** + * Controls the auto-hide behavior of system bars (status bar, navigation bar). + * + * This interface provides methods to manage the auto-hide schedule of system bars, allowing them to + * be shown or hidden. + */ +interface AutoHideController { + /** + * Sets a [AutoHideUiElement] status bar that should be controlled by the [AutoHideController]. + */ + fun setStatusBar(element: AutoHideUiElement) + + /** + * Sets a [AutoHideUiElement] navigation bar that should be controlled by the + * [AutoHideController]. + */ + fun setNavigationBar(element: AutoHideUiElement) + + /** Resumes the auto-hide behavior that was previously suspended. */ + fun resumeSuspendedAutoHide() + + /** Suspends the auto-hide behavior. */ + fun suspendAutoHide() + + /** Schedules or cancels auto hide behavior based on current system bar state. */ + fun touchAutoHide() + + /** Hides system bars on user touch if the interaction requires them to be hidden. */ + fun checkUserAutoHide(event: MotionEvent) + + /** Called when work should stop and resources should be released. */ + fun stop() + + /** Dumps the current state of the [AutoHideController] */ + fun dump(pw: PrintWriter) + + /** Injectable factory for creating a [AutoHideController]. */ + interface Factory { + /** Create an [AutoHideController] */ + fun create(context: Context): AutoHideController + } +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoHideController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoHideControllerImpl.java index 1358cfd3e8da..4fbfbb254064 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoHideController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoHideControllerImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018 The Android Open Source Project + * Copyright (C) 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -28,7 +28,6 @@ import android.view.accessibility.AccessibilityManager; import androidx.annotation.NonNull; -import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.statusbar.AutoHideUiElement; @@ -36,9 +35,7 @@ import java.io.PrintWriter; import javax.inject.Inject; -/** A controller to control all auto-hide things. Also see {@link AutoHideUiElement}. */ -@SysUISingleton -public class AutoHideController { +public class AutoHideControllerImpl implements AutoHideController { private static final String TAG = "AutoHideController"; private static final int AUTO_HIDE_TIMEOUT_MS = 2250; private static final int USER_AUTO_HIDE_TIMEOUT_MS = 350; @@ -61,7 +58,7 @@ public class AutoHideController { }; @Inject - public AutoHideController(Context context, + public AutoHideControllerImpl(Context context, @Main Handler handler, IWindowManager iWindowManager) { mAccessibilityManager = context.getSystemService(AccessibilityManager.class); @@ -70,18 +67,12 @@ public class AutoHideController { mDisplayId = context.getDisplayId(); } - /** - * Sets a {@link AutoHideUiElement} status bar that should be controlled by the - * {@link AutoHideController}. - */ + @Override public void setStatusBar(AutoHideUiElement element) { mStatusBar = element; } - /** - * Sets a {@link AutoHideUiElement} navigation bar that should be controlled by the - * {@link AutoHideController}. - */ + @Override public void setNavigationBar(AutoHideUiElement element) { mNavigationBar = element; } @@ -102,6 +93,7 @@ public class AutoHideController { } } + @Override public void resumeSuspendedAutoHide() { if (mAutoHideSuspended) { scheduleAutoHide(); @@ -112,6 +104,7 @@ public class AutoHideController { } } + @Override public void suspendAutoHide() { mHandler.removeCallbacks(mAutoHide); Runnable checkBarModesRunnable = getCheckBarModesRunnable(); @@ -121,7 +114,7 @@ public class AutoHideController { mAutoHideSuspended = isAnyTransientBarShown(); } - /** Schedules or cancels auto hide behavior based on current system bar state. */ + @Override public void touchAutoHide() { // update transient bar auto hide if (isAnyTransientBarShown()) { @@ -156,6 +149,7 @@ public class AutoHideController { FLAG_CONTENT_CONTROLS); } + @Override public void checkUserAutoHide(MotionEvent event) { boolean shouldHide = isAnyTransientBarShown() && event.getAction() == MotionEvent.ACTION_OUTSIDE // touch outside the source bar. @@ -196,6 +190,12 @@ public class AutoHideController { return false; } + @Override + public void stop() { + mHandler.removeCallbacks(mAutoHide); + } + + @Override public void dump(@NonNull PrintWriter pw) { pw.println("AutoHideController:"); pw.println("\tmAutoHideSuspended=" + mAutoHideSuspended); @@ -205,10 +205,7 @@ public class AutoHideController { pw.println("\tgetUserAutoHideTimeout=" + getUserAutoHideTimeout()); } - /** - * Injectable factory for creating a {@link AutoHideController}. - */ - public static class Factory { + public static class Factory implements AutoHideController.Factory { private final Handler mHandler; private final IWindowManager mIWindowManager; @@ -219,8 +216,9 @@ public class AutoHideController { } /** Create an {@link AutoHideController} */ + @Override public AutoHideController create(Context context) { - return new AutoHideController(context, mHandler, mIWindowManager); + return new AutoHideControllerImpl(context, mHandler, mIWindowManager); } } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoHideControllerStore.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoHideControllerStore.kt new file mode 100644 index 000000000000..744f96918eef --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoHideControllerStore.kt @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.statusbar.phone + +import android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR +import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.dagger.qualifiers.Background +import com.android.systemui.display.data.repository.DisplayRepository +import com.android.systemui.display.data.repository.DisplayWindowPropertiesRepository +import com.android.systemui.display.data.repository.PerDisplayStore +import com.android.systemui.display.data.repository.PerDisplayStoreImpl +import com.android.systemui.display.data.repository.SingleDisplayStore +import com.android.systemui.statusbar.core.StatusBarConnectedDisplays +import javax.inject.Inject +import kotlinx.coroutines.CoroutineScope + +/** Provides per display instances of [AutoHideController] */ +interface AutoHideControllerStore : PerDisplayStore<AutoHideController> + +@SysUISingleton +class MultiDisplayAutoHideControllerStore +@Inject +constructor( + @Background backgroundApplicationScope: CoroutineScope, + displayRepository: DisplayRepository, + private val displayWindowPropertiesRepository: DisplayWindowPropertiesRepository, + private val autoHideControllerFactory: AutoHideControllerImpl.Factory, +) : + AutoHideControllerStore, + PerDisplayStoreImpl<AutoHideController>(backgroundApplicationScope, displayRepository) { + + init { + StatusBarConnectedDisplays.assertInNewMode() + } + + override fun createInstanceForDisplay(displayId: Int): AutoHideController { + val displayWindowProperties = + displayWindowPropertiesRepository.get(displayId, TYPE_STATUS_BAR) + return autoHideControllerFactory.create(displayWindowProperties.context) + } + + override suspend fun onDisplayRemovalAction(instance: AutoHideController) { + instance.stop() + } + + override val instanceClass = AutoHideController::class.java +} + +@SysUISingleton +class SingleDisplayAutoHideControllerStore +@Inject +constructor(defaultController: AutoHideController) : + AutoHideControllerStore, + PerDisplayStore<AutoHideController> by SingleDisplayStore(defaultController) { + + init { + StatusBarConnectedDisplays.assertInLegacyMode() + } +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.kt index 58386b0cad7c..ee8c1ae6c5f9 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.kt @@ -35,7 +35,12 @@ import com.android.systemui.statusbar.data.repository.PrivacyDotViewControllerSt import com.android.systemui.statusbar.data.repository.PrivacyDotWindowControllerStoreModule import com.android.systemui.statusbar.data.repository.StatusBarModeRepositoryStore import com.android.systemui.statusbar.events.PrivacyDotViewControllerModule +import com.android.systemui.statusbar.phone.AutoHideController +import com.android.systemui.statusbar.phone.AutoHideControllerImpl +import com.android.systemui.statusbar.phone.AutoHideControllerStore import com.android.systemui.statusbar.phone.CentralSurfacesCommandQueueCallbacks +import com.android.systemui.statusbar.phone.MultiDisplayAutoHideControllerStore +import com.android.systemui.statusbar.phone.SingleDisplayAutoHideControllerStore import com.android.systemui.statusbar.window.StatusBarWindowControllerStore import com.android.systemui.statusbar.window.data.repository.StatusBarWindowStateRepositoryStore import com.android.systemui.statusbar.window.data.repository.StatusBarWindowStateRepositoryStoreImpl @@ -75,6 +80,9 @@ interface StatusBarPhoneModule { @Binds fun statusBarInitializer(@Default impl: StatusBarInitializerImpl): StatusBarInitializer + @Binds + fun autoHideControllerFactory(impl: AutoHideControllerImpl.Factory): AutoHideController.Factory + companion object { /** Binds {@link StatusBarInitializer} as a {@link CoreStartable}. */ @Provides @@ -186,5 +194,18 @@ interface StatusBarPhoneModule { singleDisplayStoreLazy.get() } } + + @Provides + @SysUISingleton + fun autoHideStore( + singleDisplayLazy: Lazy<SingleDisplayAutoHideControllerStore>, + multiDisplayLazy: Lazy<MultiDisplayAutoHideControllerStore>, + ): AutoHideControllerStore { + return if (StatusBarConnectedDisplays.isEnabled) { + multiDisplayLazy.get() + } else { + singleDisplayLazy.get() + } + } } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastControllerImpl.java index a115baad257d..52f80fbf50fd 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastControllerImpl.java @@ -24,6 +24,7 @@ import android.media.MediaRouter; import android.media.MediaRouter.RouteInfo; import android.media.projection.MediaProjectionInfo; import android.media.projection.MediaProjectionManager; +import android.media.projection.StopReason; import android.os.Handler; import android.util.ArrayMap; @@ -190,7 +191,7 @@ public class CastControllerImpl implements CastController { if (isProjection) { final MediaProjectionInfo projection = (MediaProjectionInfo) device.getTag(); if (Objects.equals(mProjectionManager.getActiveProjectionInfo(), projection)) { - mProjectionManager.stopActiveProjection(); + mProjectionManager.stopActiveProjection(StopReason.STOP_QS_TILE); } else { mLogger.logStopCastingNoProjection(projection); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/animation/ActivityTransitionAnimatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/animation/ActivityTransitionAnimatorTest.kt index 425aad2bd43c..4aaa82e4a16d 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/animation/ActivityTransitionAnimatorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/animation/ActivityTransitionAnimatorTest.kt @@ -404,7 +404,7 @@ class ActivityTransitionAnimatorTest : SysuiTestCase() { @Test fun creatingRunnerWithLazyInitializationThrows_whenTheFlagsAreDisabled() { assertThrows(IllegalStateException::class.java) { - activityTransitionAnimator.createRunner(controller, initializeLazily = true) + activityTransitionAnimator.createRunner(controller, longLived = true) } } @@ -414,7 +414,7 @@ class ActivityTransitionAnimatorTest : SysuiTestCase() { ) @Test fun runnerCreatesDelegateLazily_whenPostingTimeouts() { - val runner = activityTransitionAnimator.createRunner(controller, initializeLazily = true) + val runner = activityTransitionAnimator.createRunner(controller, longLived = true) assertNull(runner.delegate) runner.postTimeouts() assertNotNull(runner.delegate) @@ -426,7 +426,7 @@ class ActivityTransitionAnimatorTest : SysuiTestCase() { ) @Test fun runnerCreatesDelegateLazily_onAnimationStart() { - val runner = activityTransitionAnimator.createRunner(controller, initializeLazily = true) + val runner = activityTransitionAnimator.createRunner(controller, longLived = true) assertNull(runner.delegate) // The delegate is cleaned up after execution (which happens in another thread), so what we @@ -458,7 +458,7 @@ class ActivityTransitionAnimatorTest : SysuiTestCase() { ) @Test fun runnerCreatesDelegateLazily_onAnimationTakeover() { - val runner = activityTransitionAnimator.createRunner(controller, initializeLazily = true) + val runner = activityTransitionAnimator.createRunner(controller, longLived = true) assertNull(runner.delegate) // The delegate is cleaned up after execution (which happens in another thread), so what we @@ -489,7 +489,7 @@ class ActivityTransitionAnimatorTest : SysuiTestCase() { ) @Test fun animationTakeoverThrows_whenTheFlagsAreDisabled() { - val runner = activityTransitionAnimator.createRunner(controller, initializeLazily = false) + val runner = activityTransitionAnimator.createRunner(controller, longLived = false) assertThrows(IllegalStateException::class.java) { runner.takeOverAnimation( arrayOf(fakeWindow()), diff --git a/packages/SystemUI/tests/src/com/android/systemui/broadcast/BroadcastDispatcherTest.kt b/packages/SystemUI/tests/src/com/android/systemui/broadcast/BroadcastDispatcherTest.kt index 2c1718176571..bfbdc50c32b2 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/broadcast/BroadcastDispatcherTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/broadcast/BroadcastDispatcherTest.kt @@ -24,9 +24,9 @@ import android.os.Handler import android.os.Looper import android.os.PatternMatcher import android.os.UserHandle -import androidx.test.filters.SmallTest import android.testing.AndroidTestingRunner import android.testing.TestableLooper +import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.broadcast.logging.BroadcastDispatcherLogger import com.android.systemui.dump.DumpManager @@ -40,8 +40,9 @@ import java.util.concurrent.Executor import junit.framework.Assert.assertSame import kotlinx.coroutines.flow.collect import kotlinx.coroutines.launch +import kotlinx.coroutines.test.UnconfinedTestDispatcher import kotlinx.coroutines.test.advanceUntilIdle -import kotlinx.coroutines.test.runBlockingTest +import kotlinx.coroutines.test.runTest import org.junit.Before import org.junit.Test import org.junit.runner.RunWith @@ -68,39 +69,28 @@ class BroadcastDispatcherTest : SysuiTestCase() { val DEFAULT_PERMISSION: String? = null fun <T> capture(argumentCaptor: ArgumentCaptor<T>): T = argumentCaptor.capture() + const val TEST_ACTION = "TEST_ACTION" const val TEST_SCHEME = "TEST_SCHEME" const val TEST_PATH = "TEST_PATH" const val TEST_TYPE = "test/type" } - @Mock - private lateinit var mockContext: Context - @Mock - private lateinit var mockUBRUser0: UserBroadcastDispatcher - @Mock - private lateinit var mockUBRUser1: UserBroadcastDispatcher - @Mock - private lateinit var broadcastReceiver: BroadcastReceiver - @Mock - private lateinit var broadcastReceiverOther: BroadcastReceiver - @Mock - private lateinit var intentFilter: IntentFilter - @Mock - private lateinit var intentFilterOther: IntentFilter - @Mock - private lateinit var mockHandler: Handler - @Mock - private lateinit var logger: BroadcastDispatcherLogger - @Mock - private lateinit var userTracker: UserTracker - @Mock - private lateinit var removalPendingStore: PendingRemovalStore + @Mock private lateinit var mockContext: Context + @Mock private lateinit var mockUBRUser0: UserBroadcastDispatcher + @Mock private lateinit var mockUBRUser1: UserBroadcastDispatcher + @Mock private lateinit var broadcastReceiver: BroadcastReceiver + @Mock private lateinit var broadcastReceiverOther: BroadcastReceiver + @Mock private lateinit var intentFilter: IntentFilter + @Mock private lateinit var intentFilterOther: IntentFilter + @Mock private lateinit var mockHandler: Handler + @Mock private lateinit var logger: BroadcastDispatcherLogger + @Mock private lateinit var userTracker: UserTracker + @Mock private lateinit var removalPendingStore: PendingRemovalStore private lateinit var mainExecutor: Executor - @Captor - private lateinit var argumentCaptor: ArgumentCaptor<ReceiverData> + @Captor private lateinit var argumentCaptor: ArgumentCaptor<ReceiverData> private lateinit var testableLooper: TestableLooper private lateinit var broadcastDispatcher: BroadcastDispatcher @@ -112,7 +102,8 @@ class BroadcastDispatcherTest : SysuiTestCase() { mainExecutor = FakeExecutor(FakeSystemClock()) `when`(mockContext.mainExecutor).thenReturn(mainExecutor) - broadcastDispatcher = TestBroadcastDispatcher( + broadcastDispatcher = + TestBroadcastDispatcher( mockContext, mainExecutor, testableLooper.looper, @@ -121,7 +112,8 @@ class BroadcastDispatcherTest : SysuiTestCase() { logger, userTracker, removalPendingStore, - mapOf(0 to mockUBRUser0, 1 to mockUBRUser1)) + mapOf(0 to mockUBRUser0, 1 to mockUBRUser1), + ) // These should be valid filters `when`(intentFilter.countActions()).thenReturn(1) @@ -131,10 +123,18 @@ class BroadcastDispatcherTest : SysuiTestCase() { @Test fun testAddingReceiverToCorrectUBR() { - broadcastDispatcher.registerReceiverWithHandler(broadcastReceiver, intentFilter, - mockHandler, user0) broadcastDispatcher.registerReceiverWithHandler( - broadcastReceiverOther, intentFilterOther, mockHandler, user1) + broadcastReceiver, + intentFilter, + mockHandler, + user0, + ) + broadcastDispatcher.registerReceiverWithHandler( + broadcastReceiverOther, + intentFilterOther, + mockHandler, + user1, + ) testableLooper.processAllMessages() @@ -152,7 +152,11 @@ class BroadcastDispatcherTest : SysuiTestCase() { fun testAddingReceiverToCorrectUBR_executor() { broadcastDispatcher.registerReceiver(broadcastReceiver, intentFilter, mainExecutor, user0) broadcastDispatcher.registerReceiver( - broadcastReceiverOther, intentFilterOther, mainExecutor, user1) + broadcastReceiverOther, + intentFilterOther, + mainExecutor, + user1, + ) testableLooper.processAllMessages() @@ -169,7 +173,10 @@ class BroadcastDispatcherTest : SysuiTestCase() { @Test fun testAddReceiverDefaultFlag_handler() { broadcastDispatcher.registerReceiverWithHandler( - broadcastReceiver, intentFilter, mockHandler) + broadcastReceiver, + intentFilter, + mockHandler, + ) testableLooper.processAllMessages() verify(mockUBRUser0).registerReceiver(capture(argumentCaptor), eq(DEFAULT_FLAG)) @@ -183,7 +190,11 @@ class BroadcastDispatcherTest : SysuiTestCase() { val flag = 3 broadcastDispatcher.registerReceiverWithHandler( - broadcastReceiver, intentFilter, mockHandler, flags = flag) + broadcastReceiver, + intentFilter, + mockHandler, + flags = flag, + ) testableLooper.processAllMessages() verify(mockUBRUser0).registerReceiver(capture(argumentCaptor), eq(flag)) @@ -212,7 +223,7 @@ class BroadcastDispatcherTest : SysuiTestCase() { broadcastReceiver, intentFilter, flags = flag, - permission = permission + permission = permission, ) testableLooper.processAllMessages() @@ -250,10 +261,18 @@ class BroadcastDispatcherTest : SysuiTestCase() { @Test fun testRemovingReceiversRemovesFromAllUBR() { - broadcastDispatcher.registerReceiverWithHandler(broadcastReceiver, intentFilter, - mockHandler, user0) - broadcastDispatcher.registerReceiverWithHandler(broadcastReceiver, intentFilter, - mockHandler, user1) + broadcastDispatcher.registerReceiverWithHandler( + broadcastReceiver, + intentFilter, + mockHandler, + user0, + ) + broadcastDispatcher.registerReceiverWithHandler( + broadcastReceiver, + intentFilter, + mockHandler, + user1, + ) broadcastDispatcher.unregisterReceiver(broadcastReceiver) @@ -265,10 +284,18 @@ class BroadcastDispatcherTest : SysuiTestCase() { @Test fun testRemoveReceiverFromUser() { - broadcastDispatcher.registerReceiverWithHandler(broadcastReceiver, intentFilter, - mockHandler, user0) - broadcastDispatcher.registerReceiverWithHandler(broadcastReceiver, intentFilter, - mockHandler, user1) + broadcastDispatcher.registerReceiverWithHandler( + broadcastReceiver, + intentFilter, + mockHandler, + user0, + ) + broadcastDispatcher.registerReceiverWithHandler( + broadcastReceiver, + intentFilter, + mockHandler, + user1, + ) broadcastDispatcher.unregisterReceiverForUser(broadcastReceiver, user0) @@ -282,13 +309,17 @@ class BroadcastDispatcherTest : SysuiTestCase() { fun testRegisterCurrentAsActualUser() { `when`(userTracker.userId).thenReturn(user1.identifier) - broadcastDispatcher.registerReceiverWithHandler(broadcastReceiver, intentFilter, - mockHandler, UserHandle.CURRENT) + broadcastDispatcher.registerReceiverWithHandler( + broadcastReceiver, + intentFilter, + mockHandler, + UserHandle.CURRENT, + ) testableLooper.processAllMessages() - verify(mockUBRUser1).registerReceiver( - capture(argumentCaptor), eq(Context.RECEIVER_EXPORTED)) + verify(mockUBRUser1) + .registerReceiver(capture(argumentCaptor), eq(Context.RECEIVER_EXPORTED)) assertSame(broadcastReceiver, argumentCaptor.value.receiver) } @@ -300,41 +331,38 @@ class BroadcastDispatcherTest : SysuiTestCase() { @Test(expected = IllegalArgumentException::class) fun testFilterMustNotContainDataScheme() { - val testFilter = IntentFilter(TEST_ACTION).apply { - addDataScheme(TEST_SCHEME) - } + val testFilter = IntentFilter(TEST_ACTION).apply { addDataScheme(TEST_SCHEME) } broadcastDispatcher.registerReceiver(broadcastReceiver, testFilter) } @Test(expected = IllegalArgumentException::class) fun testFilterMustNotContainDataAuthority() { - val testFilter = IntentFilter(TEST_ACTION).apply { - addDataAuthority(mock(IntentFilter.AuthorityEntry::class.java)) - } + val testFilter = + IntentFilter(TEST_ACTION).apply { + addDataAuthority(mock(IntentFilter.AuthorityEntry::class.java)) + } broadcastDispatcher.registerReceiver(broadcastReceiver, testFilter) } @Test(expected = IllegalArgumentException::class) fun testFilterMustNotContainDataPath() { - val testFilter = IntentFilter(TEST_ACTION).apply { - addDataPath(TEST_PATH, PatternMatcher.PATTERN_LITERAL) - } + val testFilter = + IntentFilter(TEST_ACTION).apply { + addDataPath(TEST_PATH, PatternMatcher.PATTERN_LITERAL) + } broadcastDispatcher.registerReceiver(broadcastReceiver, testFilter) } @Test(expected = IllegalArgumentException::class) fun testFilterMustNotContainDataType() { - val testFilter = IntentFilter(TEST_ACTION).apply { - addDataType(TEST_TYPE) - } + val testFilter = IntentFilter(TEST_ACTION).apply { addDataType(TEST_TYPE) } broadcastDispatcher.registerReceiver(broadcastReceiver, testFilter) } @Test(expected = IllegalArgumentException::class) fun testFilterMustNotSetPriority() { - val testFilter = IntentFilter(TEST_ACTION).apply { - priority = IntentFilter.SYSTEM_HIGH_PRIORITY - } + val testFilter = + IntentFilter(TEST_ACTION).apply { priority = IntentFilter.SYSTEM_HIGH_PRIORITY } broadcastDispatcher.registerReceiver(broadcastReceiver, testFilter) } @@ -366,12 +394,14 @@ class BroadcastDispatcherTest : SysuiTestCase() { val inOrderUser0 = inOrder(mockUBRUser0, removalPendingStore) inOrderUser0.verify(mockUBRUser0).unregisterReceiver(broadcastReceiver) - inOrderUser0.verify(removalPendingStore) + inOrderUser0 + .verify(removalPendingStore) .clearPendingRemoval(broadcastReceiver, UserHandle.USER_ALL) val inOrderUser1 = inOrder(mockUBRUser1, removalPendingStore) inOrderUser1.verify(mockUBRUser1).unregisterReceiver(broadcastReceiver) - inOrderUser1.verify(removalPendingStore) + inOrderUser1 + .verify(removalPendingStore) .clearPendingRemoval(broadcastReceiver, UserHandle.USER_ALL) } @@ -385,21 +415,21 @@ class BroadcastDispatcherTest : SysuiTestCase() { val inOrderUser1 = inOrder(mockUBRUser1, removalPendingStore) inOrderUser1.verify(mockUBRUser1).unregisterReceiver(broadcastReceiver) - inOrderUser1.verify(removalPendingStore) + inOrderUser1 + .verify(removalPendingStore) .clearPendingRemoval(broadcastReceiver, user1.identifier) } @Test - fun testBroadcastFlow() = runBlockingTest { - val flow = broadcastDispatcher.broadcastFlow(intentFilter, user1) { intent, receiver -> - intent to receiver - } + fun testBroadcastFlow() = runTest(UnconfinedTestDispatcher()) { + val flow = + broadcastDispatcher.broadcastFlow(intentFilter, user1) { intent, receiver -> + intent to receiver + } // Collect the values into collectedValues. val collectedValues = mutableListOf<Pair<Intent, BroadcastReceiver>>() - val job = launch { - flow.collect { collectedValues.add(it) } - } + val job = launch { flow.collect { collectedValues.add(it) } } testableLooper.processAllMessages() verify(mockUBRUser1).registerReceiver(capture(argumentCaptor), eq(DEFAULT_FLAG)) @@ -436,17 +466,18 @@ class BroadcastDispatcherTest : SysuiTestCase() { logger: BroadcastDispatcherLogger, userTracker: UserTracker, removalPendingStore: PendingRemovalStore, - var mockUBRMap: Map<Int, UserBroadcastDispatcher> - ) : BroadcastDispatcher( - context, - mainExecutor, - backgroundRunningLooper, - backgroundRunningExecutor, - dumpManager, - logger, - userTracker, - removalPendingStore - ) { + var mockUBRMap: Map<Int, UserBroadcastDispatcher>, + ) : + BroadcastDispatcher( + context, + mainExecutor, + backgroundRunningLooper, + backgroundRunningExecutor, + dumpManager, + logger, + userTracker, + removalPendingStore, + ) { override fun createUBRForUser(userId: Int): UserBroadcastDispatcher { return mockUBRMap.getOrDefault(userId, mock(UserBroadcastDispatcher::class.java)) } diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyboard/shortcut/ui/viewmodel/ShortcutCustomizationViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyboard/shortcut/ui/viewmodel/ShortcutCustomizationViewModelTest.kt index f706cf6980e1..d0ce34c2d68d 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyboard/shortcut/ui/viewmodel/ShortcutCustomizationViewModelTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/keyboard/shortcut/ui/viewmodel/ShortcutCustomizationViewModelTest.kt @@ -23,18 +23,20 @@ import android.hardware.input.InputManager.CUSTOM_INPUT_GESTURE_RESULT_ERROR_OTH import android.hardware.input.InputManager.CUSTOM_INPUT_GESTURE_RESULT_ERROR_RESERVED_GESTURE import android.hardware.input.InputManager.CUSTOM_INPUT_GESTURE_RESULT_SUCCESS import android.hardware.input.fakeInputManager -import android.os.SystemClock -import android.view.KeyEvent.ACTION_DOWN -import android.view.KeyEvent.KEYCODE_A -import android.view.KeyEvent.META_CTRL_ON -import android.view.KeyEvent.META_META_ON -import androidx.compose.ui.input.key.KeyEvent import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.coroutines.collectLastValue -import com.android.systemui.keyboard.shortcut.shared.model.ShortcutCategoryType -import com.android.systemui.keyboard.shortcut.shared.model.ShortcutCustomizationRequestInfo +import com.android.systemui.keyboard.shortcut.data.source.TestShortcuts.allAppsInputGestureData +import com.android.systemui.keyboard.shortcut.data.source.TestShortcuts.expectedStandardAddShortcutUiState +import com.android.systemui.keyboard.shortcut.data.source.TestShortcuts.expectedStandardDeleteShortcutUiState +import com.android.systemui.keyboard.shortcut.data.source.TestShortcuts.goHomeInputGestureData +import com.android.systemui.keyboard.shortcut.data.source.TestShortcuts.keyDownEventWithActionKeyPressed +import com.android.systemui.keyboard.shortcut.data.source.TestShortcuts.keyDownEventWithoutActionKeyPressed +import com.android.systemui.keyboard.shortcut.data.source.TestShortcuts.keyUpEventWithActionKeyPressed +import com.android.systemui.keyboard.shortcut.data.source.TestShortcuts.standardAddCustomShortcutRequestInfo +import com.android.systemui.keyboard.shortcut.data.source.TestShortcuts.standardAddShortcutRequest +import com.android.systemui.keyboard.shortcut.data.source.TestShortcuts.standardDeleteCustomShortcutRequestInfo import com.android.systemui.keyboard.shortcut.shared.model.ShortcutKey import com.android.systemui.keyboard.shortcut.shortcutCustomizationViewModelFactory import com.android.systemui.keyboard.shortcut.shortcutHelperTestHelper @@ -97,7 +99,7 @@ class ShortcutCustomizationViewModelTest : SysuiTestCase() { @Test fun uiState_correctlyUpdatedWhenDeleteShortcutCustomizationIsRequested() { testScope.runTest { - viewModel.onShortcutCustomizationRequested(standardDeleteShortcutRequest) + viewModel.onShortcutCustomizationRequested(standardDeleteCustomShortcutRequestInfo) val uiState by collectLastValue(viewModel.shortcutCustomizationUiState) assertThat(uiState).isEqualTo(expectedStandardDeleteShortcutUiState) @@ -120,7 +122,7 @@ class ShortcutCustomizationViewModelTest : SysuiTestCase() { fun uiState_consumedOnDeleteDialogShown() { testScope.runTest { val uiState by collectLastValue(viewModel.shortcutCustomizationUiState) - viewModel.onShortcutCustomizationRequested(standardDeleteShortcutRequest) + viewModel.onShortcutCustomizationRequested(standardDeleteCustomShortcutRequestInfo) viewModel.onDialogShown() assertThat( @@ -168,7 +170,7 @@ class ShortcutCustomizationViewModelTest : SysuiTestCase() { fun uiState_errorMessage_isEmptyByDefault() { testScope.runTest { val uiState by collectLastValue(viewModel.shortcutCustomizationUiState) - viewModel.onShortcutCustomizationRequested(allAppsShortcutCustomizationRequest) + viewModel.onShortcutCustomizationRequested(standardAddCustomShortcutRequestInfo) viewModel.onDialogShown() assertThat((uiState as ShortcutCustomizationUiState.AddShortcutDialog).errorMessage) @@ -227,6 +229,21 @@ class ShortcutCustomizationViewModelTest : SysuiTestCase() { } @Test + fun uiState_becomesInactiveAfterSuccessfullyDeletingShortcut() { + testScope.runTest { + val uiState by collectLastValue(viewModel.shortcutCustomizationUiState) + whenever(inputManager.getCustomInputGestures(any())) + .thenReturn(listOf(goHomeInputGestureData, allAppsInputGestureData)) + whenever(inputManager.removeCustomInputGesture(any())) + .thenReturn(CUSTOM_INPUT_GESTURE_RESULT_SUCCESS) + + openDeleteShortcutDialogAndDeleteShortcut() + + assertThat(uiState).isEqualTo(ShortcutCustomizationUiState.Inactive) + } + } + + @Test fun onKeyPressed_handlesKeyEvents_whereActionKeyIsAlsoPressed() { testScope.runTest { viewModel.onShortcutCustomizationRequested(standardAddShortcutRequest) @@ -281,7 +298,7 @@ class ShortcutCustomizationViewModelTest : SysuiTestCase() { } private suspend fun openAddShortcutDialogAndSetShortcut() { - viewModel.onShortcutCustomizationRequested(allAppsShortcutCustomizationRequest) + viewModel.onShortcutCustomizationRequested(standardAddCustomShortcutRequestInfo) viewModel.onDialogShown() viewModel.onKeyPressed(keyDownEventWithActionKeyPressed) @@ -290,71 +307,10 @@ class ShortcutCustomizationViewModelTest : SysuiTestCase() { viewModel.onSetShortcut() } - private val keyDownEventWithoutActionKeyPressed = - KeyEvent( - android.view.KeyEvent( - /* downTime = */ SystemClock.uptimeMillis(), - /* eventTime = */ SystemClock.uptimeMillis(), - /* action = */ ACTION_DOWN, - /* code = */ KEYCODE_A, - /* repeat = */ 0, - /* metaState = */ META_CTRL_ON, - ) - ) - - private val keyDownEventWithActionKeyPressed = - KeyEvent( - android.view.KeyEvent( - /* downTime = */ SystemClock.uptimeMillis(), - /* eventTime = */ SystemClock.uptimeMillis(), - /* action = */ ACTION_DOWN, - /* code = */ KEYCODE_A, - /* repeat = */ 0, - /* metaState = */ META_CTRL_ON or META_META_ON, - ) - ) - - private val keyUpEventWithActionKeyPressed = - KeyEvent( - android.view.KeyEvent( - /* downTime = */ SystemClock.uptimeMillis(), - /* eventTime = */ SystemClock.uptimeMillis(), - /* action = */ ACTION_DOWN, - /* code = */ KEYCODE_A, - /* repeat = */ 0, - /* metaState = */ 0, - ) - ) - - private val standardAddShortcutRequest = - ShortcutCustomizationRequestInfo.Add( - label = "Standard shortcut", - categoryType = ShortcutCategoryType.System, - subCategoryLabel = "Standard subcategory", - ) - - private val standardDeleteShortcutRequest = - ShortcutCustomizationRequestInfo.Delete( - label = "Standard shortcut", - categoryType = ShortcutCategoryType.System, - subCategoryLabel = "Standard subcategory", - ) - - private val allAppsShortcutCustomizationRequest = - ShortcutCustomizationRequestInfo.Add( - label = "Open apps list", - categoryType = ShortcutCategoryType.System, - subCategoryLabel = "System controls", - ) - - private val expectedStandardAddShortcutUiState = - ShortcutCustomizationUiState.AddShortcutDialog( - shortcutLabel = "Standard shortcut", - defaultCustomShortcutModifierKey = - ShortcutKey.Icon.ResIdIcon(R.drawable.ic_ksh_key_meta), - isDialogShowing = false, - ) - - private val expectedStandardDeleteShortcutUiState = - ShortcutCustomizationUiState.DeleteShortcutDialog(isDialogShowing = false) + private suspend fun openDeleteShortcutDialogAndDeleteShortcut() { + viewModel.onShortcutCustomizationRequested(standardDeleteCustomShortcutRequestInfo) + viewModel.onDialogShown() + + viewModel.deleteShortcutCurrentlyBeingCustomized() + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaSwitchingControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaSwitchingControllerTest.java index bf4ef509ac80..eb1b44b75247 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaSwitchingControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaSwitchingControllerTest.java @@ -59,6 +59,7 @@ import android.os.Bundle; import android.os.PowerExemptionManager; import android.os.RemoteException; import android.os.UserHandle; +import android.platform.test.annotations.DisableFlags; import android.platform.test.annotations.EnableFlags; import android.service.notification.StatusBarNotification; import android.testing.TestableLooper; @@ -242,10 +243,14 @@ public class MediaSwitchingControllerTest extends SysuiTestCase { mLocalMediaManager = spy(mMediaSwitchingController.mLocalMediaManager); when(mLocalMediaManager.isPreferenceRouteListingExist()).thenReturn(false); mMediaSwitchingController.mLocalMediaManager = mLocalMediaManager; + mMediaSwitchingController.mInputRouteManager = new InputRouteManager(mContext, mAudioManager); mInputRouteManager = spy(mMediaSwitchingController.mInputRouteManager); mMediaSwitchingController.mInputRouteManager = mInputRouteManager; + when(mAudioManager.getDevices(AudioManager.GET_DEVICES_INPUTS)) + .thenReturn(new AudioDeviceInfo[0]); + MediaDescription.Builder builder = new MediaDescription.Builder(); builder.setTitle(TEST_SONG); builder.setSubtitle(TEST_ARTIST); @@ -483,11 +488,11 @@ public class MediaSwitchingControllerTest extends SysuiTestCase { verify(mMediaDevice2, never()).setRangeZone(anyInt()); } + @DisableFlags(Flags.FLAG_ENABLE_AUDIO_INPUT_DEVICE_ROUTING_AND_VOLUME_CONTROL) @Test public void onDeviceListUpdate_verifyDeviceListCallback() { // This test relies on mMediaSwitchingController.start being called while the selected - // device - // list has exactly one item, and that item's id is: + // device list has exactly one item, and that item's id is: // - Different from both ids in mMediaDevices. // - Different from the id of the route published by the device under test (usually the // built-in speakers). @@ -511,16 +516,54 @@ public class MediaSwitchingControllerTest extends SysuiTestCase { assertThat(devices.containsAll(mMediaDevices)).isTrue(); assertThat(devices.size()).isEqualTo(mMediaDevices.size()); + // There should be 2 non-MediaDevice items: the "Speakers & Display" title, and the "Connect + // a device" button. assertThat(mMediaSwitchingController.getMediaItemList().size()) .isEqualTo(mMediaDevices.size() + 2); verify(mCb).onDeviceListChanged(); } + @EnableFlags(Flags.FLAG_ENABLE_AUDIO_INPUT_DEVICE_ROUTING_AND_VOLUME_CONTROL) + @Test + public void onDeviceListUpdate_verifyDeviceListCallback_inputRouting() { + // This test relies on mMediaSwitchingController.start being called while the selected + // device list has exactly one item, and that item's id is: + // - Different from both ids in mMediaDevices. + // - Different from the id of the route published by the device under test (usually the + // built-in speakers). + // So mock the selected device to respect these two preconditions. + MediaDevice mockSelectedMediaDevice = Mockito.mock(MediaDevice.class); + when(mockSelectedMediaDevice.getId()).thenReturn(TEST_DEVICE_3_ID); + doReturn(List.of(mockSelectedMediaDevice)) + .when(mLocalMediaManager) + .getSelectedMediaDevice(); + + mMediaSwitchingController.start(mCb); + reset(mCb); + + mMediaSwitchingController.onDeviceListUpdate(mMediaDevices); + final List<MediaDevice> devices = new ArrayList<>(); + for (MediaItem item : mMediaSwitchingController.getMediaItemList()) { + if (item.getMediaDevice().isPresent()) { + devices.add(item.getMediaDevice().get()); + } + } + + assertThat(devices.containsAll(mMediaDevices)).isTrue(); + assertThat(devices.size()).isEqualTo(mMediaDevices.size()); + // When input routing is enabled, there should be 4 non-MediaDevice items: one for + // the "Output" title, one for the "Speakers & Displays" title, one for the "Connect a + // device" button, and one for the "Input" title. + assertThat(mMediaSwitchingController.getMediaItemList().size()) + .isEqualTo(mMediaDevices.size() + 4); + verify(mCb).onDeviceListChanged(); + } + + @DisableFlags(Flags.FLAG_ENABLE_AUDIO_INPUT_DEVICE_ROUTING_AND_VOLUME_CONTROL) @Test public void advanced_onDeviceListUpdateWithConnectedDeviceRemote_verifyItemSize() { // This test relies on mMediaSwitchingController.start being called while the selected - // device - // list has exactly one item, and that item's id is: + // device list has exactly one item, and that item's id is: // - Different from both ids in mMediaDevices. // - Different from the id of the route published by the device under test (usually the // built-in speakers). @@ -547,6 +590,7 @@ public class MediaSwitchingControllerTest extends SysuiTestCase { assertThat(devices.containsAll(mMediaDevices)).isTrue(); assertThat(devices.size()).isEqualTo(mMediaDevices.size()); + // There should be 1 non-MediaDevice item: the "Speakers & Display" title. assertThat(mMediaSwitchingController.getMediaItemList().size()) .isEqualTo(mMediaDevices.size() + 1); verify(mCb).onDeviceListChanged(); @@ -554,6 +598,45 @@ public class MediaSwitchingControllerTest extends SysuiTestCase { @EnableFlags(Flags.FLAG_ENABLE_AUDIO_INPUT_DEVICE_ROUTING_AND_VOLUME_CONTROL) @Test + public void advanced_onDeviceListUpdateWithConnectedDeviceRemote_verifyItemSize_inputRouting() { + // This test relies on mMediaSwitchingController.start being called while the selected + // device list has exactly one item, and that item's id is: + // - Different from both ids in mMediaDevices. + // - Different from the id of the route published by the device under test (usually the + // built-in speakers). + // So mock the selected device to respect these two preconditions. + MediaDevice mockSelectedMediaDevice = Mockito.mock(MediaDevice.class); + when(mockSelectedMediaDevice.getId()).thenReturn(TEST_DEVICE_3_ID); + doReturn(List.of(mockSelectedMediaDevice)) + .when(mLocalMediaManager) + .getSelectedMediaDevice(); + + when(mMediaDevice1.getFeatures()) + .thenReturn(ImmutableList.of(MediaRoute2Info.FEATURE_REMOTE_PLAYBACK)); + when(mLocalMediaManager.getCurrentConnectedDevice()).thenReturn(mMediaDevice1); + mMediaSwitchingController.start(mCb); + reset(mCb); + + mMediaSwitchingController.onDeviceListUpdate(mMediaDevices); + final List<MediaDevice> devices = new ArrayList<>(); + for (MediaItem item : mMediaSwitchingController.getMediaItemList()) { + if (item.getMediaDevice().isPresent()) { + devices.add(item.getMediaDevice().get()); + } + } + + assertThat(devices.containsAll(mMediaDevices)).isTrue(); + assertThat(devices.size()).isEqualTo(mMediaDevices.size()); + // When input routing is enabled, there should be 3 non-MediaDevice items: one for + // the "Output" title, one for the "Speakers & Displays" title, and one for the "Input" + // title. + assertThat(mMediaSwitchingController.getMediaItemList().size()) + .isEqualTo(mMediaDevices.size() + 3); + verify(mCb).onDeviceListChanged(); + } + + @EnableFlags(Flags.FLAG_ENABLE_AUDIO_INPUT_DEVICE_ROUTING_AND_VOLUME_CONTROL) + @Test public void onInputDeviceListUpdate_verifyDeviceListCallback() { AudioDeviceInfo[] audioDeviceInfos = {}; when(mAudioManager.getDevices(AudioManager.GET_DEVICES_INPUTS)) diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/brightness/ui/viewmodel/BrightnessSliderViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/brightness/ui/viewmodel/BrightnessSliderViewModelKosmos.kt index e36ad427b43e..35e85bb1e68d 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/brightness/ui/viewmodel/BrightnessSliderViewModelKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/brightness/ui/viewmodel/BrightnessSliderViewModelKosmos.kt @@ -18,6 +18,7 @@ package com.android.systemui.brightness.ui.viewmodel import com.android.systemui.brightness.domain.interactor.brightnessPolicyEnforcementInteractor import com.android.systemui.brightness.domain.interactor.screenBrightnessInteractor +import com.android.systemui.classifier.domain.interactor.falsingInteractor import com.android.systemui.haptics.slider.sliderHapticsViewModelFactory import com.android.systemui.kosmos.Kosmos import com.android.systemui.settings.brightness.domain.interactor.brightnessMirrorShowingInteractor @@ -33,6 +34,7 @@ val Kosmos.brightnessSliderViewModelFactory: BrightnessSliderViewModel.Factory b hapticsViewModelFactory = sliderHapticsViewModelFactory, brightnessMirrorShowingInteractor = brightnessMirrorShowingInteractor, supportsMirroring = allowsMirroring, + falsingInteractor = falsingInteractor, brightnessWarningToast = brightnessWarningToast, ) } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/dreams/ui/viewmodel/DreamUserActionsViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/dreams/ui/viewmodel/DreamUserActionsViewModelKosmos.kt index b24b3ad05117..71746b505a48 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/dreams/ui/viewmodel/DreamUserActionsViewModelKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/dreams/ui/viewmodel/DreamUserActionsViewModelKosmos.kt @@ -16,6 +16,7 @@ package com.android.systemui.dreams.ui.viewmodel +import com.android.systemui.communal.domain.interactor.communalInteractor import com.android.systemui.deviceentry.domain.interactor.deviceUnlockedInteractor import com.android.systemui.kosmos.Kosmos import com.android.systemui.shade.domain.interactor.shadeInteractor @@ -23,6 +24,7 @@ import com.android.systemui.shade.domain.interactor.shadeInteractor val Kosmos.dreamUserActionsViewModel by Kosmos.Fixture { DreamUserActionsViewModel( + communalInteractor = communalInteractor, deviceUnlockedInteractor = deviceUnlockedInteractor, shadeInteractor = shadeInteractor, ) diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyboard/shortcut/KeyboardShortcutHelperKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyboard/shortcut/KeyboardShortcutHelperKosmos.kt index 721c0b8339db..2c8581608739 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyboard/shortcut/KeyboardShortcutHelperKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyboard/shortcut/KeyboardShortcutHelperKosmos.kt @@ -102,10 +102,7 @@ val Kosmos.defaultShortcutCategoriesRepository by ) } -val Kosmos.inputGestureMaps by - Kosmos.Fixture { - InputGestureMaps(applicationContext) - } +val Kosmos.inputGestureMaps by Kosmos.Fixture { InputGestureMaps(applicationContext) } val Kosmos.customShortcutCategoriesRepository by Kosmos.Fixture { @@ -116,7 +113,7 @@ val Kosmos.customShortcutCategoriesRepository by testDispatcher, shortcutCategoriesUtils, applicationContext, - inputGestureMaps + inputGestureMaps, ) } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardClockViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardClockViewModelKosmos.kt index b5e6f75c7915..c0b39b1df7d5 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardClockViewModelKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardClockViewModelKosmos.kt @@ -16,6 +16,7 @@ package com.android.systemui.keyguard.ui.viewmodel +import android.content.applicationContext import android.content.res.mainResources import com.android.systemui.common.ui.domain.interactor.configurationInteractor import com.android.systemui.keyguard.domain.interactor.keyguardClockInteractor @@ -28,12 +29,13 @@ import com.android.systemui.statusbar.ui.systemBarUtilsProxy val Kosmos.keyguardClockViewModel by Kosmos.Fixture { KeyguardClockViewModel( + context = applicationContext, keyguardClockInteractor = keyguardClockInteractor, applicationScope = applicationCoroutineScope, aodNotificationIconViewModel = notificationIconContainerAlwaysOnDisplayViewModel, shadeInteractor = shadeInteractor, systemBarUtils = systemBarUtilsProxy, configurationInteractor = configurationInteractor, - resources = mainResources + resources = mainResources, ) } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenUserActionsViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenUserActionsViewModelKosmos.kt index a25b29fd18cb..2311c0a23db8 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenUserActionsViewModelKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenUserActionsViewModelKosmos.kt @@ -20,6 +20,7 @@ import com.android.systemui.communal.domain.interactor.communalInteractor import com.android.systemui.deviceentry.domain.interactor.deviceEntryInteractor import com.android.systemui.kosmos.Kosmos import com.android.systemui.kosmos.Kosmos.Fixture +import com.android.systemui.scene.domain.interactor.sceneContainerOcclusionInteractor import com.android.systemui.shade.domain.interactor.shadeInteractor val Kosmos.lockscreenUserActionsViewModel by Fixture { @@ -27,5 +28,6 @@ val Kosmos.lockscreenUserActionsViewModel by Fixture { deviceEntryInteractor = deviceEntryInteractor, communalInteractor = communalInteractor, shadeInteractor = shadeInteractor, + occlusionInteractor = sceneContainerOcclusionInteractor, ) } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/kosmos/GeneralKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/kosmos/GeneralKosmos.kt index 72cb1dfe38db..1556058d51ba 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/kosmos/GeneralKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/kosmos/GeneralKosmos.kt @@ -1,8 +1,12 @@ package com.android.systemui.kosmos import com.android.systemui.SysuiTestCase +import com.android.systemui.coroutines.FlowValue import com.android.systemui.coroutines.collectLastValue +import com.android.systemui.coroutines.collectValues import com.android.systemui.kosmos.Kosmos.Fixture +import com.android.systemui.settings.brightness.ui.BrightnessWarningToast +import com.android.systemui.util.mockito.mock import kotlin.coroutines.CoroutineContext import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.test.StandardTestDispatcher @@ -32,12 +36,15 @@ fun Kosmos.useStandardTestDispatcher() = apply { testDispatcher = StandardTestDi fun Kosmos.useUnconfinedTestDispatcher() = apply { testDispatcher = UnconfinedTestDispatcher() } var Kosmos.testScope by Fixture { TestScope(testDispatcher) } -var Kosmos.applicationCoroutineScope by Fixture { testScope.backgroundScope } +var Kosmos.backgroundScope by Fixture { testScope.backgroundScope } +var Kosmos.applicationCoroutineScope by Fixture { backgroundScope } var Kosmos.testCase: SysuiTestCase by Fixture() var Kosmos.backgroundCoroutineContext: CoroutineContext by Fixture { - testScope.backgroundScope.coroutineContext + backgroundScope.coroutineContext } var Kosmos.mainCoroutineContext: CoroutineContext by Fixture { testScope.coroutineContext } +var Kosmos.brightnessWarningToast: BrightnessWarningToast by + Kosmos.Fixture { mock<BrightnessWarningToast>() } /** * Run this test body with a [Kosmos] as receiver, and using the [testScope] currently installed in @@ -49,3 +56,5 @@ fun Kosmos.runTest(testBody: suspend Kosmos.() -> Unit) = fun Kosmos.runCurrent() = testScope.runCurrent() fun <T> Kosmos.collectLastValue(flow: Flow<T>) = testScope.collectLastValue(flow) + +fun <T> Kosmos.collectValues(flow: Flow<T>): FlowValue<List<T>> = testScope.collectValues(flow) diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/mediaprojection/data/repository/FakeMediaProjectionRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/mediaprojection/data/repository/FakeMediaProjectionRepository.kt index d631f926176d..e6256a58a365 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/mediaprojection/data/repository/FakeMediaProjectionRepository.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/mediaprojection/data/repository/FakeMediaProjectionRepository.kt @@ -17,6 +17,7 @@ package com.android.systemui.mediaprojection.data.repository import android.app.ActivityManager +import android.media.projection.StopReason import com.android.systemui.mediaprojection.data.model.MediaProjectionState import kotlinx.coroutines.flow.MutableStateFlow @@ -28,7 +29,7 @@ class FakeMediaProjectionRepository : MediaProjectionRepository { var stopProjectingInvoked = false - override suspend fun stopProjecting() { + override suspend fun stopProjecting(@StopReason stopReason: Int) { stopProjectingInvoked = true } } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/composefragment/viewmodel/QSFragmentComposeViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/composefragment/viewmodel/QSFragmentComposeViewModelKosmos.kt index 45d5b387fea0..c574463eb258 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/composefragment/viewmodel/QSFragmentComposeViewModelKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/composefragment/viewmodel/QSFragmentComposeViewModelKosmos.kt @@ -18,10 +18,12 @@ package com.android.systemui.qs.composefragment.viewmodel import android.content.res.mainResources import androidx.lifecycle.LifecycleCoroutineScope +import com.android.systemui.classifier.domain.interactor.falsingInteractor import com.android.systemui.common.ui.domain.interactor.configurationInteractor import com.android.systemui.deviceentry.domain.interactor.deviceEntryInteractor import com.android.systemui.keyguard.domain.interactor.keyguardTransitionInteractor import com.android.systemui.kosmos.Kosmos +import com.android.systemui.log.table.logcatTableLogBuffer import com.android.systemui.media.controls.ui.view.qqsMediaHost import com.android.systemui.media.controls.ui.view.qsMediaHost import com.android.systemui.qs.composefragment.dagger.usingMediaInComposeFragment @@ -57,7 +59,9 @@ val Kosmos.qsFragmentComposeViewModelFactory by configurationInteractor, largeScreenHeaderHelper, tileSquishinessInteractor, + falsingInteractor, inFirstPageViewModel, + logcatTableLogBuffer(this@Fixture), mediaInRowInLandscapeViewModelFactory, qqsMediaHost, qsMediaHost, diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/panels/ui/viewmodel/EditModeButtonViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/panels/ui/viewmodel/EditModeButtonViewModelKosmos.kt new file mode 100644 index 000000000000..b8d3ff425f20 --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/panels/ui/viewmodel/EditModeButtonViewModelKosmos.kt @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.qs.panels.ui.viewmodel + +import com.android.systemui.classifier.domain.interactor.falsingInteractor +import com.android.systemui.kosmos.Kosmos + +val Kosmos.editModeButtonViewModelFactory by + Kosmos.Fixture { + object : EditModeButtonViewModel.Factory { + override fun create(): EditModeButtonViewModel { + return EditModeButtonViewModel(editModeViewModel, falsingInteractor) + } + } + } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/panels/ui/viewmodel/PaginatedGridViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/panels/ui/viewmodel/PaginatedGridViewModelKosmos.kt index 2e80293eafff..5c71ba2f8bbd 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/panels/ui/viewmodel/PaginatedGridViewModelKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/panels/ui/viewmodel/PaginatedGridViewModelKosmos.kt @@ -16,6 +16,7 @@ package com.android.systemui.qs.panels.ui.viewmodel +import com.android.systemui.classifier.domain.interactor.falsingInteractor import com.android.systemui.development.ui.viewmodel.buildNumberViewModelFactory import com.android.systemui.kosmos.Kosmos import com.android.systemui.qs.panels.domain.interactor.paginatedGridInteractor @@ -28,5 +29,7 @@ val Kosmos.paginatedGridViewModel by paginatedGridInteractor, inFirstPageViewModel, buildNumberViewModelFactory, + editModeButtonViewModelFactory, + falsingInteractor, ) } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/domain/interactor/DisabledContentInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/domain/interactor/DisabledContentInteractorKosmos.kt new file mode 100644 index 000000000000..12d4e90dc469 --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/domain/interactor/DisabledContentInteractorKosmos.kt @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.scene.domain.interactor + +import com.android.systemui.kosmos.Kosmos +import com.android.systemui.kosmos.Kosmos.Fixture +import com.android.systemui.statusbar.disableflags.domain.interactor.disableFlagsInteractor + +val Kosmos.disabledContentInteractor by Fixture { + DisabledContentInteractor(disableFlagsInteractor = disableFlagsInteractor) +} diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/domain/interactor/SceneInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/domain/interactor/SceneInteractorKosmos.kt index f84c3bdfdaf1..eb352baab0e4 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/domain/interactor/SceneInteractorKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/domain/interactor/SceneInteractorKosmos.kt @@ -33,5 +33,6 @@ val Kosmos.sceneInteractor: SceneInteractor by sceneFamilyResolvers = { sceneFamilyResolvers }, deviceUnlockedInteractor = { deviceUnlockedInteractor }, keyguardEnabledInteractor = { keyguardEnabledInteractor }, + disabledContentInteractor = disabledContentInteractor, ) } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/domain/startable/SceneContainerStartableKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/domain/startable/SceneContainerStartableKosmos.kt index 7e6a7271c561..82b5f6332b23 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/domain/startable/SceneContainerStartableKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/domain/startable/SceneContainerStartableKosmos.kt @@ -37,6 +37,7 @@ import com.android.systemui.kosmos.Kosmos.Fixture import com.android.systemui.kosmos.testScope import com.android.systemui.model.sysUiState import com.android.systemui.power.domain.interactor.powerInteractor +import com.android.systemui.scene.domain.interactor.disabledContentInteractor import com.android.systemui.scene.domain.interactor.sceneBackInteractor import com.android.systemui.scene.domain.interactor.sceneContainerOcclusionInteractor import com.android.systemui.scene.domain.interactor.sceneInteractor @@ -83,5 +84,6 @@ val Kosmos.sceneContainerStartable by Fixture { alternateBouncerInteractor = alternateBouncerInteractor, vibratorHelper = vibratorHelper, msdlPlayer = msdlPlayer, + disabledContentInteractor = disabledContentInteractor, ) } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/phone/AutoHideKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/phone/AutoHideKosmos.kt index 090ce31bd43c..951ae59ebcf1 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/phone/AutoHideKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/phone/AutoHideKosmos.kt @@ -16,9 +16,36 @@ package com.android.systemui.statusbar.phone +import android.content.Context +import android.os.Handler +import android.view.IWindowManager +import com.android.systemui.display.data.repository.displayRepository +import com.android.systemui.display.data.repository.fakeDisplayWindowPropertiesRepository import com.android.systemui.kosmos.Kosmos -import com.android.systemui.util.mockito.mock +import com.android.systemui.kosmos.applicationCoroutineScope +import org.mockito.Mockito.mock -val Kosmos.mockAutoHideController by Kosmos.Fixture { mock<AutoHideController>() } +val Kosmos.mockAutoHideController: AutoHideController by + Kosmos.Fixture { mock(AutoHideController::class.java) } var Kosmos.autoHideController by Kosmos.Fixture { mockAutoHideController } + +val Kosmos.fakeAutoHideControllerFactory by Kosmos.Fixture { FakeAutoHideControllerFactory() } + +val Kosmos.multiDisplayAutoHideControllerStore by + Kosmos.Fixture { + MultiDisplayAutoHideControllerStore( + applicationCoroutineScope, + displayRepository, + fakeDisplayWindowPropertiesRepository, + fakeAutoHideControllerFactory, + ) + } + +class FakeAutoHideControllerFactory : + AutoHideControllerImpl.Factory(mock(Handler::class.java), mock(IWindowManager::class.java)) { + + override fun create(context: Context): AutoHideControllerImpl { + return mock(AutoHideControllerImpl::class.java) + } +} diff --git a/ravenwood/tools/hoststubgen/test-tiny-framework/Android.bp b/ravenwood/tools/hoststubgen/test-tiny-framework/Android.bp index 1570549ec27d..483c4be7633b 100644 --- a/ravenwood/tools/hoststubgen/test-tiny-framework/Android.bp +++ b/ravenwood/tools/hoststubgen/test-tiny-framework/Android.bp @@ -156,6 +156,7 @@ python_test_host { ], data: [ "golden-output/*.txt", + "golden-output.RELEASE_TARGET_JAVA_21/*.txt", ], java_data: [ "hoststubgen-test-tiny-framework-orig-dump", diff --git a/ravenwood/tools/hoststubgen/test-tiny-framework/golden-output.RELEASE_TARGET_JAVA_21/01-hoststubgen-test-tiny-framework-orig-dump.txt b/ravenwood/tools/hoststubgen/test-tiny-framework/golden-output.RELEASE_TARGET_JAVA_21/01-hoststubgen-test-tiny-framework-orig-dump.txt new file mode 100644 index 000000000000..5e5ca62b49f0 --- /dev/null +++ b/ravenwood/tools/hoststubgen/test-tiny-framework/golden-output.RELEASE_TARGET_JAVA_21/01-hoststubgen-test-tiny-framework-orig-dump.txt @@ -0,0 +1,3697 @@ +## 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: 65 + 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: + x: #x(#x=[e#x.#x]) + java.lang.annotation.Target( + value=[Ljava/lang/annotation/ElementType;.TYPE] + ) + x: #x(#x=e#x.#x) + java.lang.annotation.Retention( + value=Ljava/lang/annotation/RetentionPolicy;.CLASS + ) +## Class: android/hosttest/annotation/HostSideTestIgnore.class + Compiled from "HostSideTestIgnore.java" +public interface android.hosttest.annotation.HostSideTestIgnore extends java.lang.annotation.Annotation + minor version: 0 + major version: 65 + flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION + this_class: #x // android/hosttest/annotation/HostSideTestIgnore + super_class: #x // java/lang/Object + interfaces: 1, fields: 0, methods: 0, attributes: 2 +} +SourceFile: "HostSideTestIgnore.java" +RuntimeVisibleAnnotations: + x: #x(#x=[e#x.#x,e#x.#x]) + java.lang.annotation.Target( + value=[Ljava/lang/annotation/ElementType;.METHOD,Ljava/lang/annotation/ElementType;.CONSTRUCTOR] + ) + x: #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: 65 + 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: + x: #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] + ) + x: #x(#x=e#x.#x) + java.lang.annotation.Retention( + value=Ljava/lang/annotation/RetentionPolicy;.CLASS + ) +## Class: android/hosttest/annotation/HostSideTestRedirect.class + Compiled from "HostSideTestRedirect.java" +public interface android.hosttest.annotation.HostSideTestRedirect extends java.lang.annotation.Annotation + minor version: 0 + major version: 65 + flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION + this_class: #x // android/hosttest/annotation/HostSideTestRedirect + super_class: #x // java/lang/Object + interfaces: 1, fields: 0, methods: 0, attributes: 2 +} +SourceFile: "HostSideTestRedirect.java" +RuntimeVisibleAnnotations: + x: #x(#x=[e#x.#x]) + java.lang.annotation.Target( + value=[Ljava/lang/annotation/ElementType;.METHOD] + ) + x: #x(#x=e#x.#x) + java.lang.annotation.Retention( + value=Ljava/lang/annotation/RetentionPolicy;.CLASS + ) +## Class: android/hosttest/annotation/HostSideTestRedirectionClass.class + Compiled from "HostSideTestRedirectionClass.java" +public interface android.hosttest.annotation.HostSideTestRedirectionClass extends java.lang.annotation.Annotation + minor version: 0 + major version: 65 + flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION + this_class: #x // android/hosttest/annotation/HostSideTestRedirectionClass + 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: "HostSideTestRedirectionClass.java" +RuntimeVisibleAnnotations: + x: #x(#x=[e#x.#x]) + java.lang.annotation.Target( + value=[Ljava/lang/annotation/ElementType;.TYPE] + ) + x: #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: 65 + 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: + x: #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] + ) + x: #x(#x=e#x.#x) + java.lang.annotation.Retention( + value=Ljava/lang/annotation/RetentionPolicy;.CLASS + ) +## Class: android/hosttest/annotation/HostSideTestStaticInitializerKeep.class + Compiled from "HostSideTestStaticInitializerKeep.java" +public interface android.hosttest.annotation.HostSideTestStaticInitializerKeep extends java.lang.annotation.Annotation + minor version: 0 + major version: 65 + flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION + this_class: #x // android/hosttest/annotation/HostSideTestStaticInitializerKeep + super_class: #x // java/lang/Object + interfaces: 1, fields: 0, methods: 0, attributes: 2 +} +SourceFile: "HostSideTestStaticInitializerKeep.java" +RuntimeVisibleAnnotations: + x: #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] + ) + x: #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: 65 + 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: + x: #x(#x=[e#x.#x]) + java.lang.annotation.Target( + value=[Ljava/lang/annotation/ElementType;.METHOD] + ) + x: #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: 65 + 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: + x: #x(#x=[e#x.#x,e#x.#x]) + java.lang.annotation.Target( + value=[Ljava/lang/annotation/ElementType;.METHOD,Ljava/lang/annotation/ElementType;.CONSTRUCTOR] + ) + x: #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: 65 + 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: + x: #x(#x=[e#x.#x]) + java.lang.annotation.Target( + value=[Ljava/lang/annotation/ElementType;.TYPE] + ) + x: #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: 65 + 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: + x: #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/IPretendingAidl$Stub$Proxy.class + Compiled from "IPretendingAidl.java" +public class com.android.hoststubgen.test.tinyframework.IPretendingAidl$Stub$Proxy + minor version: 0 + major version: 65 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub$Proxy + super_class: #x // java/lang/Object + interfaces: 0, fields: 0, methods: 2, attributes: 3 + public com.android.hoststubgen.test.tinyframework.IPretendingAidl$Stub$Proxy(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub$Proxy; + + public static int addTwo(int); + descriptor: (I)I + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=2, locals=1, args_size=1 + x: iload_0 + x: iconst_2 + x: iadd + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 4 0 a I +} +SourceFile: "IPretendingAidl.java" +NestHost: class com/android/hoststubgen/test/tinyframework/IPretendingAidl +InnerClasses: + public static #x= #x of #x; // Stub=class com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub of class com/android/hoststubgen/test/tinyframework/IPretendingAidl + public static #x= #x of #x; // Proxy=class com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub$Proxy of class com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub +## Class: com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub.class + Compiled from "IPretendingAidl.java" +public class com.android.hoststubgen.test.tinyframework.IPretendingAidl$Stub + minor version: 0 + major version: 65 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub + super_class: #x // java/lang/Object + interfaces: 0, fields: 0, methods: 2, attributes: 3 + public com.android.hoststubgen.test.tinyframework.IPretendingAidl$Stub(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub; + + public static int addOne(int); + descriptor: (I)I + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=2, locals=1, args_size=1 + x: iload_0 + x: iconst_1 + x: iadd + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 4 0 a I +} +SourceFile: "IPretendingAidl.java" +NestHost: class com/android/hoststubgen/test/tinyframework/IPretendingAidl +InnerClasses: + public static #x= #x of #x; // Stub=class com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub of class com/android/hoststubgen/test/tinyframework/IPretendingAidl + public static #x= #x of #x; // Proxy=class com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub$Proxy of class com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub +## Class: com/android/hoststubgen/test/tinyframework/IPretendingAidl.class + Compiled from "IPretendingAidl.java" +public interface com.android.hoststubgen.test.tinyframework.IPretendingAidl + minor version: 0 + major version: 65 + flags: (0x0601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT + this_class: #x // com/android/hoststubgen/test/tinyframework/IPretendingAidl + super_class: #x // java/lang/Object + interfaces: 0, fields: 0, methods: 0, attributes: 3 +} +SourceFile: "IPretendingAidl.java" +NestMembers: + com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub + com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub$Proxy +InnerClasses: + public static #x= #x of #x; // Stub=class com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub of class com/android/hoststubgen/test/tinyframework/IPretendingAidl + public static #x= #x of #x; // Proxy=class com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub$Proxy of class com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub +## Class: com/android/hoststubgen/test/tinyframework/R$Nested.class + Compiled from "R.java" +public class com.android.hoststubgen.test.tinyframework.R$Nested + minor version: 0 + major version: 65 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/R$Nested + super_class: #x // java/lang/Object + interfaces: 0, fields: 1, methods: 2, attributes: 3 + public static int[] ARRAY; + descriptor: [I + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + + public com.android.hoststubgen.test.tinyframework.R$Nested(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/R$Nested; + + static {}; + descriptor: ()V + flags: (0x0008) ACC_STATIC + Code: + stack=4, locals=0, args_size=0 + x: iconst_1 + x: newarray int + x: dup + x: iconst_0 + x: iconst_1 + x: iastore + x: putstatic #x // Field ARRAY:[I + x: return + LineNumberTable: +} +SourceFile: "R.java" +NestHost: class com/android/hoststubgen/test/tinyframework/R +InnerClasses: + public static #x= #x of #x; // Nested=class com/android/hoststubgen/test/tinyframework/R$Nested of class com/android/hoststubgen/test/tinyframework/R +## Class: com/android/hoststubgen/test/tinyframework/R.class + Compiled from "R.java" +public class com.android.hoststubgen.test.tinyframework.R + minor version: 0 + major version: 65 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/R + super_class: #x // java/lang/Object + interfaces: 0, fields: 0, methods: 1, attributes: 3 + public com.android.hoststubgen.test.tinyframework.R(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/R; +} +SourceFile: "R.java" +NestMembers: + com/android/hoststubgen/test/tinyframework/R$Nested +InnerClasses: + public static #x= #x of #x; // Nested=class com/android/hoststubgen/test/tinyframework/R$Nested of class com/android/hoststubgen/test/tinyframework/R +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotations.class + Compiled from "TinyFrameworkAnnotations.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkAnnotations + minor version: 0 + major version: 65 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotations + super_class: #x // java/lang/Object + interfaces: 0, fields: 2, methods: 9, attributes: 2 + public int keep; + descriptor: I + flags: (0x0001) ACC_PUBLIC + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestKeep + + public int remove; + descriptor: I + flags: (0x0001) ACC_PUBLIC + + public com.android.hoststubgen.test.tinyframework.TinyFrameworkAnnotations(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=2, locals=1, args_size=1 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: aload_0 + x: iconst_1 + x: putfield #x // Field keep:I + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 10 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotations; + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestKeep + + public int addOne(int); + descriptor: (I)I + flags: (0x0001) ACC_PUBLIC + Code: + stack=2, locals=2, args_size=2 + x: iload_1 + x: iconst_1 + x: iadd + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 4 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotations; + 0 4 1 value I + RuntimeInvisibleAnnotations: + x: #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 + x: new #x // class java/lang/RuntimeException + x: dup + x: invokespecial #x // Method java/lang/RuntimeException."<init>":()V + x: athrow + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 8 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotations; + 0 8 1 foo Ljava/lang/String; + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestRemove + + public int addTwo(int); + descriptor: (I)I + flags: (0x0001) ACC_PUBLIC + Code: + stack=3, locals=2, args_size=2 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String not supported on host side + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 10 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotations; + 0 10 1 value I + RuntimeInvisibleAnnotations: + x: #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 + x: iload_1 + x: iconst_2 + x: iadd + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 4 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotations; + 0 4 1 value I + + public static native int nativeAddThree(int); + descriptor: (I)I + flags: (0x0109) ACC_PUBLIC, ACC_STATIC, ACC_NATIVE + RuntimeInvisibleAnnotations: + x: #x(#x=s#x) + android.hosttest.annotation.HostSideTestSubstitute( + suffix="_host" + ) + + private static int nativeAddThree_host(int); + descriptor: (I)I + flags: (0x000a) ACC_PRIVATE, ACC_STATIC + Code: + stack=2, locals=1, args_size=1 + x: iload_0 + x: iconst_3 + x: iadd + x: 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 + x: ldc #x // String This value shouldn\'t be seen on the host side. + x: areturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 3 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotations; + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestThrow + + public int toBeIgnored(); + descriptor: ()I + flags: (0x0001) ACC_PUBLIC + Code: + stack=3, locals=1, args_size=1 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String not supported on host side + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 10 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotations; + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestIgnore +} +SourceFile: "TinyFrameworkAnnotations.java" +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestKeep + x: #x(#x=s#x) + android.hosttest.annotation.HostSideTestClassLoadHook( + value="com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook.onClassLoaded" + ) +## 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: 65 + 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 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: 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 + x: getstatic #x // Field sLoadedClasses:Ljava/util/Set; + x: aload_0 + x: invokeinterface #x, 2 // InterfaceMethod java/util/Set.add:(Ljava/lang/Object;)Z + x: pop + x: 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 + x: new #x // class java/util/HashSet + x: dup + x: invokespecial #x // Method java/util/HashSet."<init>":()V + x: putstatic #x // Field sLoadedClasses:Ljava/util/Set; + x: return + LineNumberTable: +} +SourceFile: "TinyFrameworkClassLoadHook.java" +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestWholeClassKeep +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWideAnnotations.class + Compiled from "TinyFrameworkClassWideAnnotations.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassWideAnnotations + minor version: 0 + major version: 65 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWideAnnotations + super_class: #x // java/lang/Object + interfaces: 0, fields: 2, methods: 6, attributes: 2 + public int keep; + descriptor: I + flags: (0x0001) ACC_PUBLIC + + public int remove; + descriptor: I + flags: (0x0001) ACC_PUBLIC + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestRemove + + public com.android.hoststubgen.test.tinyframework.TinyFrameworkClassWideAnnotations(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=2, locals=1, args_size=1 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: aload_0 + x: iconst_1 + x: putfield #x // Field keep:I + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 10 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassWideAnnotations; + + public int addOne(int); + descriptor: (I)I + flags: (0x0001) ACC_PUBLIC + Code: + stack=2, locals=2, args_size=2 + x: iload_1 + x: iconst_1 + x: iadd + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 4 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassWideAnnotations; + 0 4 1 value I + + public int addTwo(int); + descriptor: (I)I + flags: (0x0001) ACC_PUBLIC + Code: + stack=3, locals=2, args_size=2 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String not supported on host side + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 10 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassWideAnnotations; + 0 10 1 value I + RuntimeInvisibleAnnotations: + x: #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 + x: iload_1 + x: iconst_2 + x: iadd + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 4 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassWideAnnotations; + 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 + x: new #x // class java/lang/RuntimeException + x: dup + x: invokespecial #x // Method java/lang/RuntimeException."<init>":()V + x: athrow + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 8 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassWideAnnotations; + 0 8 1 foo Ljava/lang/String; + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestRemove + + public java.lang.String unsupportedMethod(); + descriptor: ()Ljava/lang/String; + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: ldc #x // String This value shouldn\'t be seen on the host side. + x: areturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 3 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassWideAnnotations; + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestThrow +} +SourceFile: "TinyFrameworkClassWideAnnotations.java" +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestWholeClassKeep +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializerDefault.class + Compiled from "TinyFrameworkClassWithInitializerDefault.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassWithInitializerDefault + minor version: 0 + major version: 65 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializerDefault + super_class: #x // java/lang/Object + interfaces: 0, fields: 2, methods: 2, attributes: 2 + public static boolean sInitialized; + descriptor: Z + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestKeep + + public static java.lang.Object sObject; + descriptor: Ljava/lang/Object; + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestKeep + + public com.android.hoststubgen.test.tinyframework.TinyFrameworkClassWithInitializerDefault(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializerDefault; + + static {}; + descriptor: ()V + flags: (0x0008) ACC_STATIC + Code: + stack=2, locals=0, args_size=0 + x: iconst_1 + x: putstatic #x // Field sInitialized:Z + x: new #x // class java/lang/Object + x: dup + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: putstatic #x // Field sObject:Ljava/lang/Object; + x: return + LineNumberTable: +} +SourceFile: "TinyFrameworkClassWithInitializerDefault.java" +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestKeep +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializerStub.class + Compiled from "TinyFrameworkClassWithInitializerStub.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassWithInitializerStub + minor version: 0 + major version: 65 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializerStub + super_class: #x // java/lang/Object + interfaces: 0, fields: 2, methods: 2, attributes: 2 + public static boolean sInitialized; + descriptor: Z + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestKeep + + public static java.lang.Object sObject; + descriptor: Ljava/lang/Object; + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestKeep + + public com.android.hoststubgen.test.tinyframework.TinyFrameworkClassWithInitializerStub(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializerStub; + + static {}; + descriptor: ()V + flags: (0x0008) ACC_STATIC + Code: + stack=2, locals=0, args_size=0 + x: iconst_1 + x: putstatic #x // Field sInitialized:Z + x: new #x // class java/lang/Object + x: dup + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: putstatic #x // Field sObject:Ljava/lang/Object; + x: return + LineNumberTable: +} +SourceFile: "TinyFrameworkClassWithInitializerStub.java" +RuntimeInvisibleAnnotations: + x: #x(#x=s#x) + android.hosttest.annotation.HostSideTestClassLoadHook( + value="com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook.onClassLoaded" + ) + x: #x() + android.hosttest.annotation.HostSideTestKeep + x: #x() + android.hosttest.annotation.HostSideTestStaticInitializerKeep +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex.class + Compiled from "TinyFrameworkEnumComplex.java" +public final class com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex extends java.lang.Enum<com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex> + minor version: 0 + major version: 65 + flags: (0x4031) ACC_PUBLIC, ACC_FINAL, ACC_SUPER, ACC_ENUM + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex + super_class: #x // java/lang/Enum + interfaces: 0, fields: 6, methods: 7, attributes: 3 + public static final com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex RED; + descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + flags: (0x4019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestKeep + + public static final com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex GREEN; + descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + flags: (0x4019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestKeep + + public static final com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex BLUE; + descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + flags: (0x4019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestKeep + + private final java.lang.String mLongName; + descriptor: Ljava/lang/String; + flags: (0x0012) ACC_PRIVATE, ACC_FINAL + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestKeep + + private final java.lang.String mShortName; + descriptor: Ljava/lang/String; + flags: (0x0012) ACC_PRIVATE, ACC_FINAL + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestKeep + + private static final com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex[] $VALUES; + descriptor: [Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + flags: (0x101a) ACC_PRIVATE, ACC_STATIC, ACC_FINAL, ACC_SYNTHETIC + + public static com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex[] values(); + descriptor: ()[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=1, locals=0, args_size=0 + x: getstatic #x // Field $VALUES:[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + x: invokevirtual #x // Method "[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex;".clone:()Ljava/lang/Object; + x: checkcast #x // class "[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex;" + x: areturn + LineNumberTable: + + public static com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex valueOf(java.lang.String); + descriptor: (Ljava/lang/String;)Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=2, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex + x: aload_0 + x: invokestatic #x // Method java/lang/Enum.valueOf:(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum; + x: checkcast #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex + x: areturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 10 0 name Ljava/lang/String; + MethodParameters: + Name Flags + <no name> mandated + + private com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex(java.lang.String, java.lang.String); + descriptor: (Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;)V + flags: (0x0002) ACC_PRIVATE + Code: + stack=3, locals=5, args_size=5 + x: aload_0 + x: aload_1 + x: iload_2 + x: invokespecial #x // Method java/lang/Enum."<init>":(Ljava/lang/String;I)V + x: aload_0 + x: aload_3 + x: putfield #x // Field mLongName:Ljava/lang/String; + x: aload_0 + x: aload 4 + x: putfield #x // Field mShortName:Ljava/lang/String; + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 18 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + 0 18 3 longName Ljava/lang/String; + 0 18 4 shortName Ljava/lang/String; + MethodParameters: + Name Flags + <no name> synthetic + <no name> synthetic + <no name> + <no name> + Signature: #x // (Ljava/lang/String;Ljava/lang/String;)V + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestKeep + + public java.lang.String getLongName(); + descriptor: ()Ljava/lang/String; + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: aload_0 + x: getfield #x // Field mLongName:Ljava/lang/String; + x: areturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestKeep + + public java.lang.String getShortName(); + descriptor: ()Ljava/lang/String; + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: aload_0 + x: getfield #x // Field mShortName:Ljava/lang/String; + x: areturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestKeep + + private static com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex[] $values(); + descriptor: ()[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC + Code: + stack=4, locals=0, args_size=0 + x: iconst_3 + x: anewarray #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex + x: dup + x: iconst_0 + x: getstatic #x // Field RED:Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + x: aastore + x: dup + x: iconst_1 + x: getstatic #x // Field GREEN:Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + x: aastore + x: dup + x: iconst_2 + x: getstatic #x // Field BLUE:Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + x: aastore + x: areturn + LineNumberTable: + + static {}; + descriptor: ()V + flags: (0x0008) ACC_STATIC + Code: + stack=6, locals=0, args_size=0 + x: new #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex + x: dup + x: ldc #x // String RED + x: iconst_0 + x: ldc #x // String Red + x: ldc #x // String R + x: invokespecial #x // Method "<init>":(Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;)V + x: putstatic #x // Field RED:Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + x: new #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex + x: dup + x: ldc #x // String GREEN + x: iconst_1 + x: ldc #x // String Green + x: ldc #x // String G + x: invokespecial #x // Method "<init>":(Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;)V + x: putstatic #x // Field GREEN:Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + x: new #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex + x: dup + x: ldc #x // String BLUE + x: iconst_2 + x: ldc #x // String Blue + x: ldc #x // String B + x: invokespecial #x // Method "<init>":(Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;)V + x: putstatic #x // Field BLUE:Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + x: invokestatic #x // Method $values:()[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + x: putstatic #x // Field $VALUES:[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + x: return + LineNumberTable: +} +Signature: #x // Ljava/lang/Enum<Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex;>; +SourceFile: "TinyFrameworkEnumComplex.java" +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestKeep +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple.class + Compiled from "TinyFrameworkEnumSimple.java" +public final class com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple extends java.lang.Enum<com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple> + minor version: 0 + major version: 65 + flags: (0x4031) ACC_PUBLIC, ACC_FINAL, ACC_SUPER, ACC_ENUM + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple + super_class: #x // java/lang/Enum + interfaces: 0, fields: 3, methods: 5, attributes: 3 + public static final com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple CAT; + descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple; + flags: (0x4019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestKeep + + public static final com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple DOG; + descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple; + flags: (0x4019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestKeep + + private static final com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple[] $VALUES; + descriptor: [Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple; + flags: (0x101a) ACC_PRIVATE, ACC_STATIC, ACC_FINAL, ACC_SYNTHETIC + + public static com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple[] values(); + descriptor: ()[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple; + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=1, locals=0, args_size=0 + x: getstatic #x // Field $VALUES:[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple; + x: invokevirtual #x // Method "[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple;".clone:()Ljava/lang/Object; + x: checkcast #x // class "[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple;" + x: areturn + LineNumberTable: + + public static com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple valueOf(java.lang.String); + descriptor: (Ljava/lang/String;)Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple; + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=2, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple + x: aload_0 + x: invokestatic #x // Method java/lang/Enum.valueOf:(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum; + x: checkcast #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple + x: areturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 10 0 name Ljava/lang/String; + MethodParameters: + Name Flags + <no name> mandated + + private com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple(); + descriptor: (Ljava/lang/String;I)V + flags: (0x0002) ACC_PRIVATE + Code: + stack=3, locals=3, args_size=3 + x: aload_0 + x: aload_1 + x: iload_2 + x: invokespecial #x // Method java/lang/Enum."<init>":(Ljava/lang/String;I)V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 7 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple; + MethodParameters: + Name Flags + <no name> synthetic + <no name> synthetic + Signature: #x // ()V + + private static com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple[] $values(); + descriptor: ()[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple; + flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC + Code: + stack=4, locals=0, args_size=0 + x: iconst_2 + x: anewarray #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple + x: dup + x: iconst_0 + x: getstatic #x // Field CAT:Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple; + x: aastore + x: dup + x: iconst_1 + x: getstatic #x // Field DOG:Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple; + x: aastore + x: areturn + LineNumberTable: + + static {}; + descriptor: ()V + flags: (0x0008) ACC_STATIC + Code: + stack=4, locals=0, args_size=0 + x: new #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple + x: dup + x: ldc #x // String CAT + x: iconst_0 + x: invokespecial #x // Method "<init>":(Ljava/lang/String;I)V + x: putstatic #x // Field CAT:Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple; + x: new #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple + x: dup + x: ldc #x // String DOG + x: iconst_1 + x: invokespecial #x // Method "<init>":(Ljava/lang/String;I)V + x: putstatic #x // Field DOG:Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple; + x: invokestatic #x // Method $values:()[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple; + x: putstatic #x // Field $VALUES:[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple; + x: return + LineNumberTable: +} +Signature: #x // Ljava/lang/Enum<Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple;>; +SourceFile: "TinyFrameworkEnumSimple.java" +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestKeep +## 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: 65 + 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 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: 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 + x: new #x // class java/lang/IllegalStateException + x: dup + x: ldc #x // String Inner exception + x: invokespecial #x // Method java/lang/IllegalStateException."<init>":(Ljava/lang/String;)V + x: athrow + x: astore_0 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Outer exception + x: aload_0 + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;Ljava/lang/Throwable;)V + x: 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: + x: #x() + android.hosttest.annotation.HostSideTestWholeClassKeep +## 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: 65 + 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: 17, attributes: 1 + public int stub; + 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 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: aload_0 + x: iconst_1 + x: putfield #x // Field stub:I + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 10 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 + x: iload_1 + x: iconst_1 + x: iadd + x: 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 + x: new #x // class java/lang/RuntimeException + x: dup + x: invokespecial #x // Method java/lang/RuntimeException."<init>":()V + x: 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 java.lang.String toBeIgnoredObj(); + descriptor: ()Ljava/lang/String; + flags: (0x0001) ACC_PUBLIC + Code: + stack=2, locals=1, args_size=1 + x: new #x // class java/lang/RuntimeException + x: dup + x: invokespecial #x // Method java/lang/RuntimeException."<init>":()V + x: athrow + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 8 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy; + + public void toBeIgnoredV(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=2, locals=1, args_size=1 + x: new #x // class java/lang/RuntimeException + x: dup + x: invokespecial #x // Method java/lang/RuntimeException."<init>":()V + x: athrow + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 8 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy; + + public boolean toBeIgnoredZ(); + descriptor: ()Z + flags: (0x0001) ACC_PUBLIC + Code: + stack=2, locals=1, args_size=1 + x: new #x // class java/lang/RuntimeException + x: dup + x: invokespecial #x // Method java/lang/RuntimeException."<init>":()V + x: athrow + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 8 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy; + + public byte toBeIgnoredB(); + descriptor: ()B + flags: (0x0001) ACC_PUBLIC + Code: + stack=2, locals=1, args_size=1 + x: new #x // class java/lang/RuntimeException + x: dup + x: invokespecial #x // Method java/lang/RuntimeException."<init>":()V + x: athrow + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 8 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy; + + public char toBeIgnoredC(); + descriptor: ()C + flags: (0x0001) ACC_PUBLIC + Code: + stack=2, locals=1, args_size=1 + x: new #x // class java/lang/RuntimeException + x: dup + x: invokespecial #x // Method java/lang/RuntimeException."<init>":()V + x: athrow + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 8 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy; + + public short toBeIgnoredS(); + descriptor: ()S + flags: (0x0001) ACC_PUBLIC + Code: + stack=2, locals=1, args_size=1 + x: new #x // class java/lang/RuntimeException + x: dup + x: invokespecial #x // Method java/lang/RuntimeException."<init>":()V + x: athrow + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 8 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy; + + public int toBeIgnoredI(); + descriptor: ()I + flags: (0x0001) ACC_PUBLIC + Code: + stack=2, locals=1, args_size=1 + x: new #x // class java/lang/RuntimeException + x: dup + x: invokespecial #x // Method java/lang/RuntimeException."<init>":()V + x: athrow + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 8 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy; + + public float toBeIgnoredF(); + descriptor: ()F + flags: (0x0001) ACC_PUBLIC + Code: + stack=2, locals=1, args_size=1 + x: new #x // class java/lang/RuntimeException + x: dup + x: invokespecial #x // Method java/lang/RuntimeException."<init>":()V + x: athrow + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 8 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy; + + public double toBeIgnoredD(); + descriptor: ()D + flags: (0x0001) ACC_PUBLIC + Code: + stack=2, locals=1, args_size=1 + x: new #x // class java/lang/RuntimeException + x: dup + x: invokespecial #x // Method java/lang/RuntimeException."<init>":()V + x: athrow + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 8 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy; + + public int addTwo(int); + descriptor: (I)I + flags: (0x0001) ACC_PUBLIC + Code: + stack=3, locals=2, args_size=2 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String not supported on host side + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: 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 + x: iload_1 + x: iconst_2 + x: iadd + x: 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 + x: iload_0 + x: iconst_3 + x: iadd + x: 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 + x: ldc #x // String This value shouldn\'t be seen on the host side. + x: areturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 3 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy; +} +SourceFile: "TinyFrameworkForTextPolicy.java" +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested.class + Compiled from "TinyFrameworkLambdas.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkLambdas$Nested + minor version: 0 + major version: 65 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested + super_class: #x // java/lang/Object + interfaces: 0, fields: 2, methods: 8, 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;>; + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestKeep + + 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;>; + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestKeep + + public com.android.hoststubgen.test.tinyframework.TinyFrameworkLambdas$Nested(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=2, locals=1, args_size=1 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: aload_0 + x: invokedynamic #x, 0 // InvokeDynamic #x:get:()Ljava/util/function/Supplier; + x: putfield #x // Field mSupplier:Ljava/util/function/Supplier; + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 14 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested; + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestKeep + + public java.util.function.Supplier<java.lang.Integer> getSupplier(); + descriptor: ()Ljava/util/function/Supplier; + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: invokedynamic #x, 0 // InvokeDynamic #x:get:()Ljava/util/function/Supplier; + x: areturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 6 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested; + Signature: #x // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>; + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestKeep + + public static java.util.function.Supplier<java.lang.Integer> getSupplier_static(); + descriptor: ()Ljava/util/function/Supplier; + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=1, locals=0, args_size=0 + x: invokedynamic #x, 0 // InvokeDynamic #x:get:()Ljava/util/function/Supplier; + x: areturn + LineNumberTable: + Signature: #x // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>; + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestKeep + + private static java.lang.Integer lambda$getSupplier_static$3(); + descriptor: ()Ljava/lang/Integer; + flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC + Code: + stack=1, locals=0, args_size=0 + x: bipush 8 + x: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; + x: areturn + LineNumberTable: + + private static java.lang.Integer lambda$getSupplier$2(); + descriptor: ()Ljava/lang/Integer; + flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC + Code: + stack=1, locals=0, args_size=0 + x: bipush 7 + x: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; + x: areturn + LineNumberTable: + + private static java.lang.Integer lambda$static$1(); + descriptor: ()Ljava/lang/Integer; + flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC + Code: + stack=1, locals=0, args_size=0 + x: bipush 6 + x: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; + x: areturn + LineNumberTable: + + private static java.lang.Integer lambda$new$0(); + descriptor: ()Ljava/lang/Integer; + flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC + Code: + stack=1, locals=0, args_size=0 + x: iconst_5 + x: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; + x: areturn + LineNumberTable: + + static {}; + descriptor: ()V + flags: (0x0008) ACC_STATIC + Code: + stack=1, locals=0, args_size=0 + x: invokedynamic #x, 0 // InvokeDynamic #x:get:()Ljava/util/function/Supplier; + x: putstatic #x // Field sSupplier:Ljava/util/function/Supplier; + x: return + LineNumberTable: +} +SourceFile: "TinyFrameworkLambdas.java" +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestKeep + x: #x() + android.hosttest.annotation.HostSideTestStaticInitializerKeep +NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas +BootstrapMethods: + x: #x REF_invokeStatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite; + Method arguments: + #x ()Ljava/lang/Object; + #x REF_invokeStatic com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested.lambda$new$0:()Ljava/lang/Integer; + #x ()Ljava/lang/Integer; + x: #x REF_invokeStatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite; + Method arguments: + #x ()Ljava/lang/Object; + #x REF_invokeStatic com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested.lambda$getSupplier$2:()Ljava/lang/Integer; + #x ()Ljava/lang/Integer; + x: #x REF_invokeStatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite; + Method arguments: + #x ()Ljava/lang/Object; + #x REF_invokeStatic com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested.lambda$getSupplier_static$3:()Ljava/lang/Integer; + #x ()Ljava/lang/Integer; + x: #x REF_invokeStatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite; + Method arguments: + #x ()Ljava/lang/Object; + #x REF_invokeStatic com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested.lambda$static$1:()Ljava/lang/Integer; + #x ()Ljava/lang/Integer; +InnerClasses: + public static #x= #x of #x; // Nested=class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested of class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas + public static final #x= #x of #x; // Lookup=class java/lang/invoke/MethodHandles$Lookup of class java/lang/invoke/MethodHandles +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas.class + Compiled from "TinyFrameworkLambdas.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkLambdas + minor version: 0 + major version: 65 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas + super_class: #x // java/lang/Object + interfaces: 0, fields: 2, methods: 8, 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;>; + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestKeep + + 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;>; + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestKeep + + public com.android.hoststubgen.test.tinyframework.TinyFrameworkLambdas(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=2, locals=1, args_size=1 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: aload_0 + x: invokedynamic #x, 0 // InvokeDynamic #x:get:()Ljava/util/function/Supplier; + x: putfield #x // Field mSupplier:Ljava/util/function/Supplier; + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 14 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas; + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestKeep + + public java.util.function.Supplier<java.lang.Integer> getSupplier(); + descriptor: ()Ljava/util/function/Supplier; + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: invokedynamic #x, 0 // InvokeDynamic #x:get:()Ljava/util/function/Supplier; + x: areturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 6 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas; + Signature: #x // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>; + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestKeep + + public static java.util.function.Supplier<java.lang.Integer> getSupplier_static(); + descriptor: ()Ljava/util/function/Supplier; + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=1, locals=0, args_size=0 + x: invokedynamic #x, 0 // InvokeDynamic #x:get:()Ljava/util/function/Supplier; + x: areturn + LineNumberTable: + Signature: #x // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>; + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestKeep + + private static java.lang.Integer lambda$getSupplier_static$3(); + descriptor: ()Ljava/lang/Integer; + flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC + Code: + stack=1, locals=0, args_size=0 + x: iconst_4 + x: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; + x: areturn + LineNumberTable: + + private static java.lang.Integer lambda$getSupplier$2(); + descriptor: ()Ljava/lang/Integer; + flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC + Code: + stack=1, locals=0, args_size=0 + x: iconst_3 + x: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; + x: areturn + LineNumberTable: + + private static java.lang.Integer lambda$static$1(); + descriptor: ()Ljava/lang/Integer; + flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC + Code: + stack=1, locals=0, args_size=0 + x: iconst_2 + x: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; + x: areturn + LineNumberTable: + + private static java.lang.Integer lambda$new$0(); + descriptor: ()Ljava/lang/Integer; + flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC + Code: + stack=1, locals=0, args_size=0 + x: iconst_1 + x: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; + x: areturn + LineNumberTable: + + static {}; + descriptor: ()V + flags: (0x0008) ACC_STATIC + Code: + stack=1, locals=0, args_size=0 + x: invokedynamic #x, 0 // InvokeDynamic #x:get:()Ljava/util/function/Supplier; + x: putstatic #x // Field sSupplier:Ljava/util/function/Supplier; + x: return + LineNumberTable: +} +SourceFile: "TinyFrameworkLambdas.java" +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestKeep + x: #x() + android.hosttest.annotation.HostSideTestStaticInitializerKeep +NestMembers: + com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested +BootstrapMethods: + x: #x REF_invokeStatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite; + Method arguments: + #x ()Ljava/lang/Object; + #x REF_invokeStatic com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas.lambda$new$0:()Ljava/lang/Integer; + #x ()Ljava/lang/Integer; + x: #x REF_invokeStatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite; + Method arguments: + #x ()Ljava/lang/Object; + #x REF_invokeStatic com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas.lambda$getSupplier$2:()Ljava/lang/Integer; + #x ()Ljava/lang/Integer; + x: #x REF_invokeStatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite; + Method arguments: + #x ()Ljava/lang/Object; + #x REF_invokeStatic com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas.lambda$getSupplier_static$3:()Ljava/lang/Integer; + #x ()Ljava/lang/Integer; + x: #x REF_invokeStatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite; + Method arguments: + #x ()Ljava/lang/Object; + #x REF_invokeStatic com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas.lambda$static$1:()Ljava/lang/Integer; + #x ()Ljava/lang/Integer; +InnerClasses: + public static #x= #x of #x; // Nested=class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested of class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas + public static final #x= #x of #x; // Lookup=class java/lang/invoke/MethodHandles$Lookup of class java/lang/invoke/MethodHandles +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo.class + Compiled from "TinyFrameworkMethodCallReplace.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace$ReplaceTo + minor version: 0 + major version: 65 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo + super_class: #x // java/lang/Object + interfaces: 0, fields: 0, methods: 3, attributes: 3 + public com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace$ReplaceTo(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo; + + public static void startThread(java.lang.Thread); + descriptor: (Ljava/lang/Thread;)V + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=2, locals=1, args_size=1 + x: aload_0 + x: iconst_1 + x: invokevirtual #x // Method java/lang/Thread.setDaemon:(Z)V + x: aload_0 + x: invokevirtual #x // Method java/lang/Thread.start:()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 10 0 thread Ljava/lang/Thread; + + public static int add(int, int); + descriptor: (II)I + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=2, locals=2, args_size=2 + x: iload_0 + x: iload_1 + x: iadd + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 4 0 a I + 0 4 1 b I +} +SourceFile: "TinyFrameworkMethodCallReplace.java" +NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace +InnerClasses: + public static #x= #x of #x; // ReplaceTo=class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo of class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace.class + Compiled from "TinyFrameworkMethodCallReplace.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace + minor version: 0 + major version: 65 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace + super_class: #x // java/lang/Object + interfaces: 0, fields: 0, methods: 5, attributes: 5 + public com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace; + + public static boolean nonStaticMethodCallReplaceTester() throws java.lang.Exception; + descriptor: ()Z + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=3, locals=2, args_size=0 + x: new #x // class java/util/concurrent/atomic/AtomicBoolean + x: dup + x: iconst_0 + x: invokespecial #x // Method java/util/concurrent/atomic/AtomicBoolean."<init>":(Z)V + x: astore_0 + x: new #x // class java/lang/Thread + x: dup + x: aload_0 + x: invokedynamic #x, 0 // InvokeDynamic #x:run:(Ljava/util/concurrent/atomic/AtomicBoolean;)Ljava/lang/Runnable; + x: invokespecial #x // Method java/lang/Thread."<init>":(Ljava/lang/Runnable;)V + x: astore_1 + x: aload_1 + x: invokevirtual #x // Method java/lang/Thread.start:()V + x: aload_1 + x: invokevirtual #x // Method java/lang/Thread.join:()V + x: aload_0 + x: invokevirtual #x // Method java/util/concurrent/atomic/AtomicBoolean.get:()Z + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 9 27 0 ab Ljava/util/concurrent/atomic/AtomicBoolean; + 23 13 1 th Ljava/lang/Thread; + Exceptions: + throws java.lang.Exception + + public static int staticMethodCallReplaceTester(); + descriptor: ()I + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=2, locals=0, args_size=0 + x: iconst_1 + x: iconst_2 + x: invokestatic #x // Method originalAdd:(II)I + x: ireturn + LineNumberTable: + + private static int originalAdd(int, int); + descriptor: (II)I + flags: (0x000a) ACC_PRIVATE, ACC_STATIC + Code: + stack=2, locals=2, args_size=2 + x: iload_0 + x: iload_1 + x: iadd + x: iconst_1 + x: isub + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 6 0 a I + 0 6 1 b I + + private static void lambda$nonStaticMethodCallReplaceTester$0(java.util.concurrent.atomic.AtomicBoolean); + descriptor: (Ljava/util/concurrent/atomic/AtomicBoolean;)V + flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC + Code: + stack=2, locals=1, args_size=1 + x: aload_0 + x: invokestatic #x // Method java/lang/Thread.currentThread:()Ljava/lang/Thread; + x: invokevirtual #x // Method java/lang/Thread.isDaemon:()Z + x: invokevirtual #x // Method java/util/concurrent/atomic/AtomicBoolean.set:(Z)V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 11 0 ab Ljava/util/concurrent/atomic/AtomicBoolean; +} +SourceFile: "TinyFrameworkMethodCallReplace.java" +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestWholeClassKeep +NestMembers: + com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo +BootstrapMethods: + x: #x REF_invokeStatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite; + Method arguments: + #x ()V + #x REF_invokeStatic com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace.lambda$nonStaticMethodCallReplaceTester$0:(Ljava/util/concurrent/atomic/AtomicBoolean;)V + #x ()V +InnerClasses: + public static #x= #x of #x; // ReplaceTo=class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo of class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace + public static final #x= #x of #x; // Lookup=class java/lang/invoke/MethodHandles$Lookup of class java/lang/invoke/MethodHandles +## 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: 65 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNative + super_class: #x // java/lang/Object + interfaces: 0, fields: 1, methods: 14, attributes: 2 + int value; + descriptor: I + flags: (0x0000) + + public com.android.hoststubgen.test.tinyframework.TinyFrameworkNative(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: 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 + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestRedirect + + 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 + x: iload_0 + x: invokestatic #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.nativeAddTwo:(I)I + x: 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 + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestRedirect + + 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 + x: lload_0 + x: lload_2 + x: invokestatic #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.nativeLongPlus:(JJ)J + x: lreturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 6 0 arg1 J + 0 6 2 arg2 J + + public void setValue(int); + descriptor: (I)V + flags: (0x0001) ACC_PUBLIC + Code: + stack=2, locals=2, args_size=2 + x: aload_0 + x: iload_1 + x: putfield #x // Field value:I + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 6 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative; + 0 6 1 v I + + public native int nativeNonStaticAddToValue(int); + descriptor: (I)I + flags: (0x0101) ACC_PUBLIC, ACC_NATIVE + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestRedirect + + public int nativeNonStaticAddToValue_should_be_like_this(int); + descriptor: (I)I + flags: (0x0001) ACC_PUBLIC + Code: + stack=2, locals=2, args_size=2 + x: aload_0 + x: iload_1 + x: invokestatic #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.nativeNonStaticAddToValue:(Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative;I)I + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 6 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative; + 0 6 1 arg I + + public static native void nativeStillNotSupported(); + descriptor: ()V + flags: (0x0109) ACC_PUBLIC, ACC_STATIC, ACC_NATIVE + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestThrow + + public static native void nativeStillKeep(); + descriptor: ()V + flags: (0x0109) ACC_PUBLIC, ACC_STATIC, ACC_NATIVE + + public static void nativeStillNotSupported_should_be_like_this(); + descriptor: ()V + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=2, locals=0, args_size=0 + x: new #x // class java/lang/RuntimeException + x: dup + x: invokespecial #x // Method java/lang/RuntimeException."<init>":()V + x: athrow + LineNumberTable: + + public static native byte nativeBytePlus(byte, byte); + descriptor: (BB)B + flags: (0x0109) ACC_PUBLIC, ACC_STATIC, ACC_NATIVE + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestRedirect + + public void notNativeRedirected(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=2, locals=1, args_size=1 + x: new #x // class java/lang/RuntimeException + x: dup + x: invokespecial #x // Method java/lang/RuntimeException."<init>":()V + x: athrow + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 8 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative; + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestRedirect + + public static void notNativeStaticRedirected(); + descriptor: ()V + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=2, locals=0, args_size=0 + x: new #x // class java/lang/RuntimeException + x: dup + x: invokespecial #x // Method java/lang/RuntimeException."<init>":()V + x: athrow + LineNumberTable: + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestRedirect +} +SourceFile: "TinyFrameworkNative.java" +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestWholeClassKeep + x: #x(#x=s#x) + android.hosttest.annotation.HostSideTestRedirectionClass( + 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: 65 + 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: 7, attributes: 2 + public com.android.hoststubgen.test.tinyframework.TinyFrameworkNative_host(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: 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 + x: iload_0 + x: iconst_2 + x: iadd + x: 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 + x: lload_0 + x: lload_2 + x: ladd + x: lreturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 4 0 arg1 J + 0 4 2 arg2 J + + public static int nativeNonStaticAddToValue(com.android.hoststubgen.test.tinyframework.TinyFrameworkNative, int); + descriptor: (Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative;I)I + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=2, locals=2, args_size=2 + x: aload_0 + x: getfield #x // Field com/android/hoststubgen/test/tinyframework/TinyFrameworkNative.value:I + x: iload_1 + x: iadd + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 7 0 source Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative; + 0 7 1 arg I + + public static byte nativeBytePlus(byte, byte); + descriptor: (BB)B + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=2, locals=2, args_size=2 + x: iload_0 + x: iload_1 + x: iadd + x: i2b + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 arg1 B + 0 5 1 arg2 B + + public static void notNativeRedirected(com.android.hoststubgen.test.tinyframework.TinyFrameworkNative); + descriptor: (Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative;)V + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=0, locals=1, args_size=1 + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 1 0 source Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative; + + public static void notNativeStaticRedirected(); + descriptor: ()V + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=0, locals=0, args_size=0 + x: return + LineNumberTable: +} +SourceFile: "TinyFrameworkNative_host.java" +RuntimeInvisibleAnnotations: + x: #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: 65 + flags: (0x0020) ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1 + super_class: #x // java/lang/Object + interfaces: 1, fields: 0, methods: 3, attributes: 5 + 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=1, locals=2, args_size=2 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1; + 0 5 1 this$0 Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses; + MethodParameters: + Name Flags + <no name> final mandated + + public java.lang.Integer get(); + descriptor: ()Ljava/lang/Integer; + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: iconst_1 + x: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; + x: 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 + x: aload_0 + x: invokevirtual #x // Method get:()Ljava/lang/Integer; + x: 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: 65 + 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 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: 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 + x: iconst_2 + x: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; + x: 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 + x: aload_0 + x: invokevirtual #x // Method get:()Ljava/lang/Integer; + x: 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: 65 + flags: (0x0020) ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3 + super_class: #x // java/lang/Object + interfaces: 1, fields: 0, methods: 3, attributes: 5 + 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=1, locals=2, args_size=2 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3; + 0 5 1 this$0 Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses; + MethodParameters: + Name Flags + <no name> final mandated + + public java.lang.Integer get(); + descriptor: ()Ljava/lang/Integer; + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: iconst_3 + x: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; + x: 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 + x: aload_0 + x: invokevirtual #x // Method get:()Ljava/lang/Integer; + x: 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: 65 + 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 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: 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 + x: iconst_4 + x: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; + x: 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 + x: aload_0 + x: invokevirtual #x // Method get:()Ljava/lang/Integer; + x: 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: 65 + 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 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: aload_0 + x: iload_1 + x: putfield #x // Field value:I + x: 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: 65 + 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: 1, methods: 1, attributes: 3 + public int value; + descriptor: I + flags: (0x0001) ACC_PUBLIC + + 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 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: aload_0 + x: iconst_5 + x: putfield #x // Field value:I + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 10 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass; + 0 10 1 this$0 Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses; + MethodParameters: + Name Flags + <no name> final mandated +} +SourceFile: "TinyFrameworkNestedClasses.java" +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: 65 + 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 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: 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 + x: bipush 7 + x: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; + x: 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 + x: aload_0 + x: invokevirtual #x // Method get:()Ljava/lang/Integer; + x: 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$Double$NestedClass.class + Compiled from "TinyFrameworkNestedClasses.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$StaticNestedClass$Double$NestedClass + minor version: 0 + major version: 65 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$Double$NestedClass + super_class: #x // java/lang/Object + interfaces: 0, fields: 1, methods: 1, attributes: 3 + public int value; + descriptor: I + flags: (0x0001) ACC_PUBLIC + + public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$StaticNestedClass$Double$NestedClass(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=2, locals=1, args_size=1 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: aload_0 + x: bipush 8 + x: putfield #x // Field value:I + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 11 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$Double$NestedClass; +} +SourceFile: "TinyFrameworkNestedClasses.java" +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 + public static #x= #x of #x; // Double$NestedClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$Double$NestedClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass +## 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: 65 + 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: 3 + 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 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: aload_0 + x: bipush 6 + x: putfield #x // Field value:I + x: 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 + x: new #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1 + x: dup + x: invokespecial #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1."<init>":()V + x: areturn + LineNumberTable: + Signature: #x // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>; +} +SourceFile: "TinyFrameworkNestedClasses.java" +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 + public static #x= #x of #x; // Double$NestedClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$Double$NestedClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass +## 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: 65 + 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 + x: aload_0 + x: iload_1 + x: invokespecial #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass."<init>":(I)V + x: 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: 65 + 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 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: aload_0 + x: new #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1 + x: dup + x: aload_0 + x: invokespecial #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1."<init>":(Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;)V + x: putfield #x // Field mSupplier:Ljava/util/function/Supplier; + x: 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 + x: new #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3 + x: dup + x: aload_0 + x: invokespecial #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3."<init>":(Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;)V + x: 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 + x: new #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4 + x: dup + x: invokespecial #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4."<init>":()V + x: 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 + x: new #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2 + x: dup + x: invokespecial #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2."<init>":()V + x: putstatic #x // Field sSupplier:Ljava/util/function/Supplier; + x: return + LineNumberTable: +} +SourceFile: "TinyFrameworkNestedClasses.java" +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestWholeClassKeep +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$Double$NestedClass + 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 + public static #x= #x of #x; // Double$NestedClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$Double$NestedClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass + #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1 +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkPackageRedirect.class + Compiled from "TinyFrameworkPackageRedirect.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkPackageRedirect + minor version: 0 + major version: 65 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkPackageRedirect + super_class: #x // java/lang/Object + interfaces: 0, fields: 0, methods: 2, attributes: 2 + public com.android.hoststubgen.test.tinyframework.TinyFrameworkPackageRedirect(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkPackageRedirect; + + public static int foo(int); + descriptor: (I)I + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=3, locals=1, args_size=1 + x: new #x // class com/unsupported/UnsupportedClass + x: dup + x: iload_0 + x: invokespecial #x // Method com/unsupported/UnsupportedClass."<init>":(I)V + x: invokevirtual #x // Method com/unsupported/UnsupportedClass.getValue:()I + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 12 0 value I +} +SourceFile: "TinyFrameworkPackageRedirect.java" +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestWholeClassKeep +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkRenamedClassCaller.class + Compiled from "TinyFrameworkRenamedClassCaller.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkRenamedClassCaller + minor version: 0 + major version: 65 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkRenamedClassCaller + super_class: #x // java/lang/Object + interfaces: 0, fields: 0, methods: 2, attributes: 2 + public com.android.hoststubgen.test.tinyframework.TinyFrameworkRenamedClassCaller(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkRenamedClassCaller; + + public static int foo(int); + descriptor: (I)I + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=3, locals=1, args_size=1 + x: new #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed + x: dup + x: iload_0 + x: invokespecial #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed."<init>":(I)V + x: invokevirtual #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed.getValue:()I + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 12 0 value I +} +SourceFile: "TinyFrameworkRenamedClassCaller.java" +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestWholeClassKeep +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed.class + Compiled from "TinyFrameworkToBeRenamed.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkToBeRenamed + minor version: 0 + major version: 65 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed + super_class: #x // java/lang/Object + interfaces: 0, fields: 1, methods: 2, attributes: 2 + private final int mValue; + descriptor: I + flags: (0x0012) ACC_PRIVATE, ACC_FINAL + + public com.android.hoststubgen.test.tinyframework.TinyFrameworkToBeRenamed(int); + descriptor: (I)V + flags: (0x0001) ACC_PUBLIC + Code: + stack=2, locals=2, args_size=2 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: aload_0 + x: iload_1 + x: putfield #x // Field mValue:I + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 10 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed; + 0 10 1 value I + + public int getValue(); + descriptor: ()I + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: aload_0 + x: getfield #x // Field mValue:I + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed; +} +SourceFile: "TinyFrameworkToBeRenamed.java" +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestWholeClassKeep +## Class: com/android/hoststubgen/test/tinyframework/packagetest/A.class + Compiled from "A.java" +public class com.android.hoststubgen.test.tinyframework.packagetest.A + minor version: 0 + major version: 65 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/packagetest/A + super_class: #x // java/lang/Object + interfaces: 0, fields: 0, methods: 1, attributes: 1 + public com.android.hoststubgen.test.tinyframework.packagetest.A(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/packagetest/A; +} +SourceFile: "A.java" +## Class: com/android/hoststubgen/test/tinyframework/packagetest/B.class + Compiled from "B.java" +public class com.android.hoststubgen.test.tinyframework.packagetest.B + minor version: 0 + major version: 65 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/packagetest/B + super_class: #x // java/lang/Object + interfaces: 0, fields: 0, methods: 1, attributes: 1 + public com.android.hoststubgen.test.tinyframework.packagetest.B(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/packagetest/B; +} +SourceFile: "B.java" +## Class: com/android/hoststubgen/test/tinyframework/packagetest/sub/A.class + Compiled from "A.java" +public class com.android.hoststubgen.test.tinyframework.packagetest.sub.A + minor version: 0 + major version: 65 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/packagetest/sub/A + super_class: #x // java/lang/Object + interfaces: 0, fields: 0, methods: 1, attributes: 1 + public com.android.hoststubgen.test.tinyframework.packagetest.sub.A(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/packagetest/sub/A; +} +SourceFile: "A.java" +## Class: com/android/hoststubgen/test/tinyframework/packagetest/sub/B.class + Compiled from "B.java" +public class com.android.hoststubgen.test.tinyframework.packagetest.sub.B + minor version: 0 + major version: 65 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/packagetest/sub/B + super_class: #x // java/lang/Object + interfaces: 0, fields: 0, methods: 1, attributes: 1 + public com.android.hoststubgen.test.tinyframework.packagetest.sub.B(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/packagetest/sub/B; +} +SourceFile: "B.java" +## Class: com/android/hoststubgen/test/tinyframework/subclasstest/C1.class + Compiled from "C1.java" +public class com.android.hoststubgen.test.tinyframework.subclasstest.C1 + minor version: 0 + major version: 65 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/C1 + super_class: #x // java/lang/Object + interfaces: 0, fields: 0, methods: 1, attributes: 1 + public com.android.hoststubgen.test.tinyframework.subclasstest.C1(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/subclasstest/C1; +} +SourceFile: "C1.java" +## Class: com/android/hoststubgen/test/tinyframework/subclasstest/C2.class + Compiled from "C2.java" +public class com.android.hoststubgen.test.tinyframework.subclasstest.C2 extends com.android.hoststubgen.test.tinyframework.subclasstest.C1 + minor version: 0 + major version: 65 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/C2 + super_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/C1 + interfaces: 0, fields: 0, methods: 1, attributes: 1 + public com.android.hoststubgen.test.tinyframework.subclasstest.C2(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: aload_0 + x: invokespecial #x // Method com/android/hoststubgen/test/tinyframework/subclasstest/C1."<init>":()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/subclasstest/C2; +} +SourceFile: "C2.java" +## Class: com/android/hoststubgen/test/tinyframework/subclasstest/C3.class + Compiled from "C3.java" +public class com.android.hoststubgen.test.tinyframework.subclasstest.C3 extends com.android.hoststubgen.test.tinyframework.subclasstest.C2 + minor version: 0 + major version: 65 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/C3 + super_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/C2 + interfaces: 0, fields: 0, methods: 1, attributes: 1 + public com.android.hoststubgen.test.tinyframework.subclasstest.C3(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: aload_0 + x: invokespecial #x // Method com/android/hoststubgen/test/tinyframework/subclasstest/C2."<init>":()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/subclasstest/C3; +} +SourceFile: "C3.java" +## Class: com/android/hoststubgen/test/tinyframework/subclasstest/CA.class + Compiled from "CA.java" +public class com.android.hoststubgen.test.tinyframework.subclasstest.CA + minor version: 0 + major version: 65 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/CA + super_class: #x // java/lang/Object + interfaces: 0, fields: 0, methods: 1, attributes: 1 + public com.android.hoststubgen.test.tinyframework.subclasstest.CA(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/subclasstest/CA; +} +SourceFile: "CA.java" +## Class: com/android/hoststubgen/test/tinyframework/subclasstest/CB.class + Compiled from "CB.java" +public class com.android.hoststubgen.test.tinyframework.subclasstest.CB + minor version: 0 + major version: 65 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/CB + super_class: #x // java/lang/Object + interfaces: 0, fields: 0, methods: 1, attributes: 1 + public com.android.hoststubgen.test.tinyframework.subclasstest.CB(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/subclasstest/CB; +} +SourceFile: "CB.java" +## Class: com/android/hoststubgen/test/tinyframework/subclasstest/Class_C1.class + Compiled from "Class_C1.java" +public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_C1 extends com.android.hoststubgen.test.tinyframework.subclasstest.C1 + minor version: 0 + major version: 65 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/Class_C1 + super_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/C1 + interfaces: 0, fields: 0, methods: 1, attributes: 1 + public com.android.hoststubgen.test.tinyframework.subclasstest.Class_C1(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: aload_0 + x: invokespecial #x // Method com/android/hoststubgen/test/tinyframework/subclasstest/C1."<init>":()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/subclasstest/Class_C1; +} +SourceFile: "Class_C1.java" +## Class: com/android/hoststubgen/test/tinyframework/subclasstest/Class_C2.class + Compiled from "Class_C2.java" +public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_C2 extends com.android.hoststubgen.test.tinyframework.subclasstest.C2 + minor version: 0 + major version: 65 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/Class_C2 + super_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/C2 + interfaces: 0, fields: 0, methods: 1, attributes: 1 + public com.android.hoststubgen.test.tinyframework.subclasstest.Class_C2(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: aload_0 + x: invokespecial #x // Method com/android/hoststubgen/test/tinyframework/subclasstest/C2."<init>":()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/subclasstest/Class_C2; +} +SourceFile: "Class_C2.java" +## Class: com/android/hoststubgen/test/tinyframework/subclasstest/Class_C3.class + Compiled from "Class_C3.java" +public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_C3 extends com.android.hoststubgen.test.tinyframework.subclasstest.C3 + minor version: 0 + major version: 65 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/Class_C3 + super_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/C3 + interfaces: 0, fields: 0, methods: 1, attributes: 1 + public com.android.hoststubgen.test.tinyframework.subclasstest.Class_C3(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: aload_0 + x: invokespecial #x // Method com/android/hoststubgen/test/tinyframework/subclasstest/C3."<init>":()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/subclasstest/Class_C3; +} +SourceFile: "Class_C3.java" +## Class: com/android/hoststubgen/test/tinyframework/subclasstest/Class_CA.class + Compiled from "Class_CA.java" +public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_CA extends com.android.hoststubgen.test.tinyframework.subclasstest.CA + minor version: 0 + major version: 65 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/Class_CA + super_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/CA + interfaces: 0, fields: 0, methods: 1, attributes: 1 + public com.android.hoststubgen.test.tinyframework.subclasstest.Class_CA(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: aload_0 + x: invokespecial #x // Method com/android/hoststubgen/test/tinyframework/subclasstest/CA."<init>":()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/subclasstest/Class_CA; +} +SourceFile: "Class_CA.java" +## Class: com/android/hoststubgen/test/tinyframework/subclasstest/Class_CB.class + Compiled from "Class_CB.java" +public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_CB extends com.android.hoststubgen.test.tinyframework.subclasstest.CB + minor version: 0 + major version: 65 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/Class_CB + super_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/CB + interfaces: 0, fields: 0, methods: 1, attributes: 1 + public com.android.hoststubgen.test.tinyframework.subclasstest.Class_CB(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: aload_0 + x: invokespecial #x // Method com/android/hoststubgen/test/tinyframework/subclasstest/CB."<init>":()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/subclasstest/Class_CB; +} +SourceFile: "Class_CB.java" +## Class: com/android/hoststubgen/test/tinyframework/subclasstest/Class_CB_IA.class + Compiled from "Class_CB_IA.java" +public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_CB_IA extends com.android.hoststubgen.test.tinyframework.subclasstest.CB implements com.android.hoststubgen.test.tinyframework.subclasstest.IA + minor version: 0 + major version: 65 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/Class_CB_IA + super_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/CB + interfaces: 1, fields: 0, methods: 1, attributes: 1 + public com.android.hoststubgen.test.tinyframework.subclasstest.Class_CB_IA(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: aload_0 + x: invokespecial #x // Method com/android/hoststubgen/test/tinyframework/subclasstest/CB."<init>":()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/subclasstest/Class_CB_IA; +} +SourceFile: "Class_CB_IA.java" +## Class: com/android/hoststubgen/test/tinyframework/subclasstest/Class_I1.class + Compiled from "Class_I1.java" +public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_I1 implements com.android.hoststubgen.test.tinyframework.subclasstest.I1 + minor version: 0 + major version: 65 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/Class_I1 + super_class: #x // java/lang/Object + interfaces: 1, fields: 0, methods: 1, attributes: 1 + public com.android.hoststubgen.test.tinyframework.subclasstest.Class_I1(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/subclasstest/Class_I1; +} +SourceFile: "Class_I1.java" +## Class: com/android/hoststubgen/test/tinyframework/subclasstest/Class_I1_IA.class + Compiled from "Class_I1_IA.java" +public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_I1_IA implements com.android.hoststubgen.test.tinyframework.subclasstest.I1,com.android.hoststubgen.test.tinyframework.subclasstest.IA + minor version: 0 + major version: 65 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/Class_I1_IA + super_class: #x // java/lang/Object + interfaces: 2, fields: 0, methods: 1, attributes: 1 + public com.android.hoststubgen.test.tinyframework.subclasstest.Class_I1_IA(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/subclasstest/Class_I1_IA; +} +SourceFile: "Class_I1_IA.java" +## Class: com/android/hoststubgen/test/tinyframework/subclasstest/Class_I2.class + Compiled from "Class_I2.java" +public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_I2 implements com.android.hoststubgen.test.tinyframework.subclasstest.I2 + minor version: 0 + major version: 65 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/Class_I2 + super_class: #x // java/lang/Object + interfaces: 1, fields: 0, methods: 1, attributes: 1 + public com.android.hoststubgen.test.tinyframework.subclasstest.Class_I2(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/subclasstest/Class_I2; +} +SourceFile: "Class_I2.java" +## Class: com/android/hoststubgen/test/tinyframework/subclasstest/Class_I3.class + Compiled from "Class_I3.java" +public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_I3 implements com.android.hoststubgen.test.tinyframework.subclasstest.I3 + minor version: 0 + major version: 65 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/Class_I3 + super_class: #x // java/lang/Object + interfaces: 1, fields: 0, methods: 1, attributes: 1 + public com.android.hoststubgen.test.tinyframework.subclasstest.Class_I3(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/subclasstest/Class_I3; +} +SourceFile: "Class_I3.java" +## Class: com/android/hoststubgen/test/tinyframework/subclasstest/Class_I3_IA.class + Compiled from "Class_I3_IA.java" +public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_I3_IA implements com.android.hoststubgen.test.tinyframework.subclasstest.I3,com.android.hoststubgen.test.tinyframework.subclasstest.IA + minor version: 0 + major version: 65 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/Class_I3_IA + super_class: #x // java/lang/Object + interfaces: 2, fields: 0, methods: 1, attributes: 1 + public com.android.hoststubgen.test.tinyframework.subclasstest.Class_I3_IA(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/subclasstest/Class_I3_IA; +} +SourceFile: "Class_I3_IA.java" +## Class: com/android/hoststubgen/test/tinyframework/subclasstest/Class_IA.class + Compiled from "Class_IA.java" +public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_IA implements com.android.hoststubgen.test.tinyframework.subclasstest.IA + minor version: 0 + major version: 65 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/Class_IA + super_class: #x // java/lang/Object + interfaces: 1, fields: 0, methods: 1, attributes: 1 + public com.android.hoststubgen.test.tinyframework.subclasstest.Class_IA(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/subclasstest/Class_IA; +} +SourceFile: "Class_IA.java" +## Class: com/android/hoststubgen/test/tinyframework/subclasstest/Class_IA_I1.class + Compiled from "Class_IA_I1.java" +public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_IA_I1 implements com.android.hoststubgen.test.tinyframework.subclasstest.IA,com.android.hoststubgen.test.tinyframework.subclasstest.I1 + minor version: 0 + major version: 65 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/Class_IA_I1 + super_class: #x // java/lang/Object + interfaces: 2, fields: 0, methods: 1, attributes: 1 + public com.android.hoststubgen.test.tinyframework.subclasstest.Class_IA_I1(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/subclasstest/Class_IA_I1; +} +SourceFile: "Class_IA_I1.java" +## Class: com/android/hoststubgen/test/tinyframework/subclasstest/Class_IA_I3.class + Compiled from "Class_IA_I3.java" +public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_IA_I3 implements com.android.hoststubgen.test.tinyframework.subclasstest.IA,com.android.hoststubgen.test.tinyframework.subclasstest.I3 + minor version: 0 + major version: 65 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/Class_IA_I3 + super_class: #x // java/lang/Object + interfaces: 2, fields: 0, methods: 1, attributes: 1 + public com.android.hoststubgen.test.tinyframework.subclasstest.Class_IA_I3(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/subclasstest/Class_IA_I3; +} +SourceFile: "Class_IA_I3.java" +## Class: com/android/hoststubgen/test/tinyframework/subclasstest/Class_IB.class + Compiled from "Class_IB.java" +public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_IB implements com.android.hoststubgen.test.tinyframework.subclasstest.IB + minor version: 0 + major version: 65 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/Class_IB + super_class: #x // java/lang/Object + interfaces: 1, fields: 0, methods: 1, attributes: 1 + public com.android.hoststubgen.test.tinyframework.subclasstest.Class_IB(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/subclasstest/Class_IB; +} +SourceFile: "Class_IB.java" +## Class: com/android/hoststubgen/test/tinyframework/subclasstest/Class_IB_IA.class + Compiled from "Class_IB_IA.java" +public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_IB_IA implements com.android.hoststubgen.test.tinyframework.subclasstest.IB,com.android.hoststubgen.test.tinyframework.subclasstest.IA + minor version: 0 + major version: 65 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/Class_IB_IA + super_class: #x // java/lang/Object + interfaces: 2, fields: 0, methods: 1, attributes: 1 + public com.android.hoststubgen.test.tinyframework.subclasstest.Class_IB_IA(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/subclasstest/Class_IB_IA; +} +SourceFile: "Class_IB_IA.java" +## Class: com/android/hoststubgen/test/tinyframework/subclasstest/Class_None.class + Compiled from "Class_None.java" +public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_None + minor version: 0 + major version: 65 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/Class_None + super_class: #x // java/lang/Object + interfaces: 0, fields: 0, methods: 1, attributes: 1 + public com.android.hoststubgen.test.tinyframework.subclasstest.Class_None(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/subclasstest/Class_None; +} +SourceFile: "Class_None.java" +## Class: com/android/hoststubgen/test/tinyframework/subclasstest/I1.class + Compiled from "I1.java" +public interface com.android.hoststubgen.test.tinyframework.subclasstest.I1 + minor version: 0 + major version: 65 + flags: (0x0601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT + this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/I1 + super_class: #x // java/lang/Object + interfaces: 0, fields: 0, methods: 0, attributes: 1 +} +SourceFile: "I1.java" +## Class: com/android/hoststubgen/test/tinyframework/subclasstest/I2.class + Compiled from "I2.java" +public interface com.android.hoststubgen.test.tinyframework.subclasstest.I2 extends com.android.hoststubgen.test.tinyframework.subclasstest.I1 + minor version: 0 + major version: 65 + flags: (0x0601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT + this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/I2 + super_class: #x // java/lang/Object + interfaces: 1, fields: 0, methods: 0, attributes: 1 +} +SourceFile: "I2.java" +## Class: com/android/hoststubgen/test/tinyframework/subclasstest/I3.class + Compiled from "I3.java" +public interface com.android.hoststubgen.test.tinyframework.subclasstest.I3 extends com.android.hoststubgen.test.tinyframework.subclasstest.I2 + minor version: 0 + major version: 65 + flags: (0x0601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT + this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/I3 + super_class: #x // java/lang/Object + interfaces: 1, fields: 0, methods: 0, attributes: 1 +} +SourceFile: "I3.java" +## Class: com/android/hoststubgen/test/tinyframework/subclasstest/IA.class + Compiled from "IA.java" +public interface com.android.hoststubgen.test.tinyframework.subclasstest.IA + minor version: 0 + major version: 65 + flags: (0x0601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT + this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/IA + super_class: #x // java/lang/Object + interfaces: 0, fields: 0, methods: 0, attributes: 1 +} +SourceFile: "IA.java" +## Class: com/android/hoststubgen/test/tinyframework/subclasstest/IB.class + Compiled from "IB.java" +public interface com.android.hoststubgen.test.tinyframework.subclasstest.IB + minor version: 0 + major version: 65 + flags: (0x0601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT + this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/IB + super_class: #x // java/lang/Object + interfaces: 0, fields: 0, methods: 0, attributes: 1 +} +SourceFile: "IB.java" +## Class: com/supported/UnsupportedClass.class + Compiled from "UnsupportedClass.java" +public class com.supported.UnsupportedClass + minor version: 0 + major version: 65 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/supported/UnsupportedClass + super_class: #x // java/lang/Object + interfaces: 0, fields: 1, methods: 2, attributes: 2 + private final int mValue; + descriptor: I + flags: (0x0012) ACC_PRIVATE, ACC_FINAL + + public com.supported.UnsupportedClass(int); + descriptor: (I)V + flags: (0x0001) ACC_PUBLIC + Code: + stack=2, locals=2, args_size=2 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: aload_0 + x: iload_1 + x: putfield #x // Field mValue:I + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 10 0 this Lcom/supported/UnsupportedClass; + 0 10 1 value I + + public int getValue(); + descriptor: ()I + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: aload_0 + x: getfield #x // Field mValue:I + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lcom/supported/UnsupportedClass; +} +SourceFile: "UnsupportedClass.java" +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestWholeClassKeep +## Class: com/unsupported/UnsupportedClass.class + Compiled from "UnsupportedClass.java" +public class com.unsupported.UnsupportedClass + minor version: 0 + major version: 65 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/unsupported/UnsupportedClass + super_class: #x // java/lang/Object + interfaces: 0, fields: 0, methods: 2, attributes: 2 + public com.unsupported.UnsupportedClass(int); + descriptor: (I)V + flags: (0x0001) ACC_PUBLIC + Code: + stack=3, locals=2, args_size=2 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String This class is not supported + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 14 0 this Lcom/unsupported/UnsupportedClass; + 0 14 1 value I + + public int getValue(); + descriptor: ()I + flags: (0x0001) ACC_PUBLIC + Code: + stack=3, locals=1, args_size=1 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String This class is not supported + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 10 0 this Lcom/unsupported/UnsupportedClass; +} +SourceFile: "UnsupportedClass.java" +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestWholeClassKeep diff --git a/ravenwood/tools/hoststubgen/test-tiny-framework/golden-output.RELEASE_TARGET_JAVA_21/03-hoststubgen-test-tiny-framework-host-dump.txt b/ravenwood/tools/hoststubgen/test-tiny-framework/golden-output.RELEASE_TARGET_JAVA_21/03-hoststubgen-test-tiny-framework-host-dump.txt new file mode 100644 index 000000000000..84a8373008d7 --- /dev/null +++ b/ravenwood/tools/hoststubgen/test-tiny-framework/golden-output.RELEASE_TARGET_JAVA_21/03-hoststubgen-test-tiny-framework-host-dump.txt @@ -0,0 +1,3727 @@ +## 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: 65 + 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 + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +} +SourceFile: "HostSideTestClassLoadHook.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + x: #x(#x=[e#x.#x]) + java.lang.annotation.Target( + value=[Ljava/lang/annotation/ElementType;.TYPE] + ) + x: #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: 65 + 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: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + x: #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] + ) + x: #x(#x=e#x.#x) + java.lang.annotation.Retention( + value=Ljava/lang/annotation/RetentionPolicy;.CLASS + ) +## Class: android/hosttest/annotation/HostSideTestRedirect.class + Compiled from "HostSideTestRedirect.java" +public interface android.hosttest.annotation.HostSideTestRedirect extends java.lang.annotation.Annotation + minor version: 0 + major version: 65 + flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION + this_class: #x // android/hosttest/annotation/HostSideTestRedirect + super_class: #x // java/lang/Object + interfaces: 1, fields: 0, methods: 0, attributes: 2 +} +SourceFile: "HostSideTestRedirect.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + x: #x(#x=[e#x.#x]) + java.lang.annotation.Target( + value=[Ljava/lang/annotation/ElementType;.METHOD] + ) + x: #x(#x=e#x.#x) + java.lang.annotation.Retention( + value=Ljava/lang/annotation/RetentionPolicy;.CLASS + ) +## Class: android/hosttest/annotation/HostSideTestRedirectionClass.class + Compiled from "HostSideTestRedirectionClass.java" +public interface android.hosttest.annotation.HostSideTestRedirectionClass extends java.lang.annotation.Annotation + minor version: 0 + major version: 65 + flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION + this_class: #x // android/hosttest/annotation/HostSideTestRedirectionClass + 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 + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +} +SourceFile: "HostSideTestRedirectionClass.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + x: #x(#x=[e#x.#x]) + java.lang.annotation.Target( + value=[Ljava/lang/annotation/ElementType;.TYPE] + ) + x: #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: 65 + 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: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + x: #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] + ) + x: #x(#x=e#x.#x) + java.lang.annotation.Retention( + value=Ljava/lang/annotation/RetentionPolicy;.CLASS + ) +## Class: android/hosttest/annotation/HostSideTestStaticInitializerKeep.class + Compiled from "HostSideTestStaticInitializerKeep.java" +public interface android.hosttest.annotation.HostSideTestStaticInitializerKeep extends java.lang.annotation.Annotation + minor version: 0 + major version: 65 + flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION + this_class: #x // android/hosttest/annotation/HostSideTestStaticInitializerKeep + super_class: #x // java/lang/Object + interfaces: 1, fields: 0, methods: 0, attributes: 2 +} +SourceFile: "HostSideTestStaticInitializerKeep.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + x: #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] + ) + x: #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: 65 + 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 + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +} +SourceFile: "HostSideTestSubstitute.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + x: #x(#x=[e#x.#x]) + java.lang.annotation.Target( + value=[Ljava/lang/annotation/ElementType;.METHOD] + ) + x: #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: 65 + 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: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + x: #x(#x=[e#x.#x,e#x.#x]) + java.lang.annotation.Target( + value=[Ljava/lang/annotation/ElementType;.METHOD,Ljava/lang/annotation/ElementType;.CONSTRUCTOR] + ) + x: #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: 65 + 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: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + x: #x(#x=[e#x.#x]) + java.lang.annotation.Target( + value=[Ljava/lang/annotation/ElementType;.TYPE] + ) + x: #x(#x=e#x.#x) + java.lang.annotation.Retention( + value=Ljava/lang/annotation/RetentionPolicy;.CLASS + ) +## Class: com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub$Proxy.class + Compiled from "IPretendingAidl.java" +public class com.android.hoststubgen.test.tinyframework.IPretendingAidl$Stub$Proxy + minor version: 0 + major version: 65 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub$Proxy + super_class: #x // java/lang/Object + interfaces: 0, fields: 0, methods: 2, attributes: 4 + public com.android.hoststubgen.test.tinyframework.IPretendingAidl$Stub$Proxy(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub$Proxy; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + public static int addTwo(int); + descriptor: (I)I + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=2, locals=1, args_size=1 + x: iload_0 + x: iconst_2 + x: iadd + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 4 0 a I + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +} +InnerClasses: + public static #x= #x of #x; // Stub=class com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub of class com/android/hoststubgen/test/tinyframework/IPretendingAidl + public static #x= #x of #x; // Proxy=class com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub$Proxy of class com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub +SourceFile: "IPretendingAidl.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +NestHost: class com/android/hoststubgen/test/tinyframework/IPretendingAidl +## Class: com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub.class + Compiled from "IPretendingAidl.java" +public class com.android.hoststubgen.test.tinyframework.IPretendingAidl$Stub + minor version: 0 + major version: 65 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub + super_class: #x // java/lang/Object + interfaces: 0, fields: 0, methods: 2, attributes: 4 + public com.android.hoststubgen.test.tinyframework.IPretendingAidl$Stub(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + public static int addOne(int); + descriptor: (I)I + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=2, locals=1, args_size=1 + x: iload_0 + x: iconst_1 + x: iadd + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 4 0 a I + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +} +InnerClasses: + public static #x= #x of #x; // Stub=class com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub of class com/android/hoststubgen/test/tinyframework/IPretendingAidl + public static #x= #x of #x; // Proxy=class com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub$Proxy of class com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub +SourceFile: "IPretendingAidl.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +NestHost: class com/android/hoststubgen/test/tinyframework/IPretendingAidl +## Class: com/android/hoststubgen/test/tinyframework/IPretendingAidl.class + Compiled from "IPretendingAidl.java" +public interface com.android.hoststubgen.test.tinyframework.IPretendingAidl + minor version: 0 + major version: 65 + flags: (0x0601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT + this_class: #x // com/android/hoststubgen/test/tinyframework/IPretendingAidl + super_class: #x // java/lang/Object + interfaces: 0, fields: 0, methods: 0, attributes: 4 +} +InnerClasses: + public static #x= #x of #x; // Stub=class com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub of class com/android/hoststubgen/test/tinyframework/IPretendingAidl + public static #x= #x of #x; // Proxy=class com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub$Proxy of class com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub +SourceFile: "IPretendingAidl.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +NestMembers: + com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub + com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub$Proxy +## Class: com/android/hoststubgen/test/tinyframework/R$Nested.class + Compiled from "R.java" +public class com.android.hoststubgen.test.tinyframework.R$Nested + minor version: 0 + major version: 65 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/R$Nested + super_class: #x // java/lang/Object + interfaces: 0, fields: 1, methods: 2, attributes: 4 + public static int[] ARRAY; + descriptor: [I + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + public com.android.hoststubgen.test.tinyframework.R$Nested(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/R$Nested; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + static {}; + descriptor: ()V + flags: (0x0008) ACC_STATIC + Code: + stack=4, locals=0, args_size=0 + x: iconst_1 + x: newarray int + x: dup + x: iconst_0 + x: iconst_1 + x: iastore + x: putstatic #x // Field ARRAY:[I + x: return + LineNumberTable: + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +} +InnerClasses: + public static #x= #x of #x; // Nested=class com/android/hoststubgen/test/tinyframework/R$Nested of class com/android/hoststubgen/test/tinyframework/R +SourceFile: "R.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +NestHost: class com/android/hoststubgen/test/tinyframework/R +## Class: com/android/hoststubgen/test/tinyframework/R.class + Compiled from "R.java" +public class com.android.hoststubgen.test.tinyframework.R + minor version: 0 + major version: 65 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/R + super_class: #x // java/lang/Object + interfaces: 0, fields: 0, methods: 1, attributes: 4 + public com.android.hoststubgen.test.tinyframework.R(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/R; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +} +InnerClasses: + public static #x= #x of #x; // Nested=class com/android/hoststubgen/test/tinyframework/R$Nested of class com/android/hoststubgen/test/tinyframework/R +SourceFile: "R.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +NestMembers: + com/android/hoststubgen/test/tinyframework/R$Nested +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotations.class + Compiled from "TinyFrameworkAnnotations.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkAnnotations + minor version: 0 + major version: 65 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotations + super_class: #x // java/lang/Object + interfaces: 0, fields: 1, methods: 7, attributes: 3 + public int keep; + descriptor: I + flags: (0x0001) ACC_PUBLIC + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestKeep + + private static {}; + descriptor: ()V + flags: (0x000a) ACC_PRIVATE, ACC_STATIC + Code: + stack=2, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotations + x: ldc #x // String com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook.onClassLoaded + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V + x: return + + public com.android.hoststubgen.test.tinyframework.TinyFrameworkAnnotations(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=2, locals=1, args_size=1 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: aload_0 + x: iconst_1 + x: putfield #x // Field keep:I + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 10 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotations; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestKeep + + public int addOne(int); + descriptor: (I)I + flags: (0x0001) ACC_PUBLIC + Code: + stack=2, locals=2, args_size=2 + x: iload_1 + x: iconst_1 + x: iadd + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 4 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotations; + 0 4 1 value I + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestKeep + + public int addTwo(int); + descriptor: (I)I + flags: (0x0001) ACC_PUBLIC + Code: + stack=2, locals=2, args_size=2 + x: iload_1 + x: iconst_2 + x: iadd + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 4 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotations; + 0 4 1 value I + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsSubstitute + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + public static int nativeAddThree(int); + descriptor: (I)I + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=2, locals=1, args_size=1 + x: iload_0 + x: iconst_3 + x: iadd + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 4 0 value I + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsSubstitute + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + public java.lang.String unsupportedMethod(); + descriptor: ()Ljava/lang/String; + flags: (0x0001) ACC_PUBLIC + Code: + stack=3, locals=1, args_size=1 + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onThrowMethodCalled:()V + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Unreachable + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsThrow + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestThrow + + public int toBeIgnored(); + descriptor: ()I + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: iconst_0 + x: ireturn + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsIgnore + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestIgnore +} +SourceFile: "TinyFrameworkAnnotations.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestKeep + x: #x(#x=s#x) + android.hosttest.annotation.HostSideTestClassLoadHook( + value="com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook.onClassLoaded" + ) +## 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: 65 + 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<*>;>; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + private com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook(); + descriptor: ()V + flags: (0x0002) ACC_PRIVATE + Code: + stack=1, locals=1, args_size=1 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassLoadHook; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + 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 + x: getstatic #x // Field sLoadedClasses:Ljava/util/Set; + x: aload_0 + x: invokeinterface #x, 2 // InterfaceMethod java/util/Set.add:(Ljava/lang/Object;)Z + x: pop + x: 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 + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + static {}; + descriptor: ()V + flags: (0x0008) ACC_STATIC + Code: + stack=2, locals=0, args_size=0 + x: new #x // class java/util/HashSet + x: dup + x: invokespecial #x // Method java/util/HashSet."<init>":()V + x: putstatic #x // Field sLoadedClasses:Ljava/util/Set; + x: return + LineNumberTable: + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +} +SourceFile: "TinyFrameworkClassLoadHook.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestWholeClassKeep +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWideAnnotations.class + Compiled from "TinyFrameworkClassWideAnnotations.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassWideAnnotations + minor version: 0 + major version: 65 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWideAnnotations + super_class: #x // java/lang/Object + interfaces: 0, fields: 1, methods: 4, attributes: 3 + public int keep; + descriptor: I + flags: (0x0001) ACC_PUBLIC + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + public com.android.hoststubgen.test.tinyframework.TinyFrameworkClassWideAnnotations(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=2, locals=1, args_size=1 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: aload_0 + x: iconst_1 + x: putfield #x // Field keep:I + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 10 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassWideAnnotations; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + public int addOne(int); + descriptor: (I)I + flags: (0x0001) ACC_PUBLIC + Code: + stack=2, locals=2, args_size=2 + x: iload_1 + x: iconst_1 + x: iadd + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 4 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassWideAnnotations; + 0 4 1 value I + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + public int addTwo(int); + descriptor: (I)I + flags: (0x0001) ACC_PUBLIC + Code: + stack=2, locals=2, args_size=2 + x: iload_1 + x: iconst_2 + x: iadd + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 4 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassWideAnnotations; + 0 4 1 value I + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsSubstitute + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + public java.lang.String unsupportedMethod(); + descriptor: ()Ljava/lang/String; + flags: (0x0001) ACC_PUBLIC + Code: + stack=3, locals=1, args_size=1 + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onThrowMethodCalled:()V + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Unreachable + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsThrow + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestThrow +} +SourceFile: "TinyFrameworkClassWideAnnotations.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestWholeClassKeep +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializerDefault.class + Compiled from "TinyFrameworkClassWithInitializerDefault.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassWithInitializerDefault + minor version: 0 + major version: 65 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializerDefault + super_class: #x // java/lang/Object + interfaces: 0, fields: 2, methods: 0, attributes: 3 + public static boolean sInitialized; + descriptor: Z + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestKeep + + public static java.lang.Object sObject; + descriptor: Ljava/lang/Object; + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestKeep + +} +SourceFile: "TinyFrameworkClassWithInitializerDefault.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestKeep +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializerStub.class + Compiled from "TinyFrameworkClassWithInitializerStub.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassWithInitializerStub + minor version: 0 + major version: 65 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializerStub + super_class: #x // java/lang/Object + interfaces: 0, fields: 2, methods: 1, attributes: 3 + public static boolean sInitialized; + descriptor: Z + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestKeep + + public static java.lang.Object sObject; + descriptor: Ljava/lang/Object; + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestKeep + + static {}; + descriptor: ()V + flags: (0x0008) ACC_STATIC + Code: + stack=2, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializerStub + x: ldc #x // String com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook.onClassLoaded + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V + x: iconst_1 + x: putstatic #x // Field sInitialized:Z + x: new #x // class java/lang/Object + x: dup + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: putstatic #x // Field sObject:Ljava/lang/Object; + x: return + LineNumberTable: + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +} +SourceFile: "TinyFrameworkClassWithInitializerStub.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +RuntimeInvisibleAnnotations: + x: #x(#x=s#x) + android.hosttest.annotation.HostSideTestClassLoadHook( + value="com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook.onClassLoaded" + ) + x: #x() + android.hosttest.annotation.HostSideTestKeep + x: #x() + android.hosttest.annotation.HostSideTestStaticInitializerKeep +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex.class + Compiled from "TinyFrameworkEnumComplex.java" +public final class com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex extends java.lang.Enum<com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex> + minor version: 0 + major version: 65 + flags: (0x4031) ACC_PUBLIC, ACC_FINAL, ACC_SUPER, ACC_ENUM + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex + super_class: #x // java/lang/Enum + interfaces: 0, fields: 6, methods: 7, attributes: 4 + public static final com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex RED; + descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + flags: (0x4019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestKeep + + public static final com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex GREEN; + descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + flags: (0x4019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestKeep + + public static final com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex BLUE; + descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + flags: (0x4019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestKeep + + private final java.lang.String mLongName; + descriptor: Ljava/lang/String; + flags: (0x0012) ACC_PRIVATE, ACC_FINAL + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestKeep + + private final java.lang.String mShortName; + descriptor: Ljava/lang/String; + flags: (0x0012) ACC_PRIVATE, ACC_FINAL + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestKeep + + private static final com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex[] $VALUES; + descriptor: [Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + flags: (0x101a) ACC_PRIVATE, ACC_STATIC, ACC_FINAL, ACC_SYNTHETIC + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + public static com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex[] values(); + descriptor: ()[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=1, locals=0, args_size=0 + x: getstatic #x // Field $VALUES:[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + x: invokevirtual #x // Method "[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex;".clone:()Ljava/lang/Object; + x: checkcast #x // class "[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex;" + x: areturn + LineNumberTable: + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + public static com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex valueOf(java.lang.String); + descriptor: (Ljava/lang/String;)Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=2, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex + x: aload_0 + x: invokestatic #x // Method java/lang/Enum.valueOf:(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum; + x: checkcast #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex + x: areturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 10 0 name Ljava/lang/String; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + MethodParameters: + Name Flags + <no name> mandated + + private com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex(java.lang.String, java.lang.String); + descriptor: (Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;)V + flags: (0x0002) ACC_PRIVATE + Code: + stack=3, locals=5, args_size=5 + x: aload_0 + x: aload_1 + x: iload_2 + x: invokespecial #x // Method java/lang/Enum."<init>":(Ljava/lang/String;I)V + x: aload_0 + x: aload_3 + x: putfield #x // Field mLongName:Ljava/lang/String; + x: aload_0 + x: aload 4 + x: putfield #x // Field mShortName:Ljava/lang/String; + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 18 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + 0 18 3 longName Ljava/lang/String; + 0 18 4 shortName Ljava/lang/String; + Signature: #x // (Ljava/lang/String;Ljava/lang/String;)V + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestKeep + MethodParameters: + Name Flags + <no name> synthetic + <no name> synthetic + <no name> + <no name> + + public java.lang.String getLongName(); + descriptor: ()Ljava/lang/String; + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: aload_0 + x: getfield #x // Field mLongName:Ljava/lang/String; + x: areturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestKeep + + public java.lang.String getShortName(); + descriptor: ()Ljava/lang/String; + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: aload_0 + x: getfield #x // Field mShortName:Ljava/lang/String; + x: areturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestKeep + + private static com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex[] $values(); + descriptor: ()[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC + Code: + stack=4, locals=0, args_size=0 + x: iconst_3 + x: anewarray #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex + x: dup + x: iconst_0 + x: getstatic #x // Field RED:Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + x: aastore + x: dup + x: iconst_1 + x: getstatic #x // Field GREEN:Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + x: aastore + x: dup + x: iconst_2 + x: getstatic #x // Field BLUE:Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + x: aastore + x: areturn + LineNumberTable: + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + static {}; + descriptor: ()V + flags: (0x0008) ACC_STATIC + Code: + stack=6, locals=0, args_size=0 + x: new #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex + x: dup + x: ldc #x // String RED + x: iconst_0 + x: ldc #x // String Red + x: ldc #x // String R + x: invokespecial #x // Method "<init>":(Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;)V + x: putstatic #x // Field RED:Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + x: new #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex + x: dup + x: ldc #x // String GREEN + x: iconst_1 + x: ldc #x // String Green + x: ldc #x // String G + x: invokespecial #x // Method "<init>":(Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;)V + x: putstatic #x // Field GREEN:Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + x: new #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex + x: dup + x: ldc #x // String BLUE + x: iconst_2 + x: ldc #x // String Blue + x: ldc #x // String B + x: invokespecial #x // Method "<init>":(Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;)V + x: putstatic #x // Field BLUE:Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + x: invokestatic #x // Method $values:()[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + x: putstatic #x // Field $VALUES:[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + x: return + LineNumberTable: + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +} +Signature: #x // Ljava/lang/Enum<Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex;>; +SourceFile: "TinyFrameworkEnumComplex.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestKeep +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple.class + Compiled from "TinyFrameworkEnumSimple.java" +public final class com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple extends java.lang.Enum<com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple> + minor version: 0 + major version: 65 + flags: (0x4031) ACC_PUBLIC, ACC_FINAL, ACC_SUPER, ACC_ENUM + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple + super_class: #x // java/lang/Enum + interfaces: 0, fields: 3, methods: 5, attributes: 4 + public static final com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple CAT; + descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple; + flags: (0x4019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestKeep + + public static final com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple DOG; + descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple; + flags: (0x4019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestKeep + + private static final com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple[] $VALUES; + descriptor: [Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple; + flags: (0x101a) ACC_PRIVATE, ACC_STATIC, ACC_FINAL, ACC_SYNTHETIC + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + public static com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple[] values(); + descriptor: ()[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple; + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=1, locals=0, args_size=0 + x: getstatic #x // Field $VALUES:[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple; + x: invokevirtual #x // Method "[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple;".clone:()Ljava/lang/Object; + x: checkcast #x // class "[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple;" + x: areturn + LineNumberTable: + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + public static com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple valueOf(java.lang.String); + descriptor: (Ljava/lang/String;)Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple; + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=2, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple + x: aload_0 + x: invokestatic #x // Method java/lang/Enum.valueOf:(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum; + x: checkcast #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple + x: areturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 10 0 name Ljava/lang/String; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + MethodParameters: + Name Flags + <no name> mandated + + private com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple(); + descriptor: (Ljava/lang/String;I)V + flags: (0x0002) ACC_PRIVATE + Code: + stack=3, locals=3, args_size=3 + x: aload_0 + x: aload_1 + x: iload_2 + x: invokespecial #x // Method java/lang/Enum."<init>":(Ljava/lang/String;I)V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 7 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple; + Signature: #x // ()V + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + MethodParameters: + Name Flags + <no name> synthetic + <no name> synthetic + + private static com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple[] $values(); + descriptor: ()[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple; + flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC + Code: + stack=4, locals=0, args_size=0 + x: iconst_2 + x: anewarray #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple + x: dup + x: iconst_0 + x: getstatic #x // Field CAT:Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple; + x: aastore + x: dup + x: iconst_1 + x: getstatic #x // Field DOG:Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple; + x: aastore + x: areturn + LineNumberTable: + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + static {}; + descriptor: ()V + flags: (0x0008) ACC_STATIC + Code: + stack=4, locals=0, args_size=0 + x: new #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple + x: dup + x: ldc #x // String CAT + x: iconst_0 + x: invokespecial #x // Method "<init>":(Ljava/lang/String;I)V + x: putstatic #x // Field CAT:Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple; + x: new #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple + x: dup + x: ldc #x // String DOG + x: iconst_1 + x: invokespecial #x // Method "<init>":(Ljava/lang/String;I)V + x: putstatic #x // Field DOG:Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple; + x: invokestatic #x // Method $values:()[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple; + x: putstatic #x // Field $VALUES:[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple; + x: return + LineNumberTable: + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +} +Signature: #x // Ljava/lang/Enum<Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple;>; +SourceFile: "TinyFrameworkEnumSimple.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestKeep +## 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: 65 + 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 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkExceptionTester; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + public static int testException(); + descriptor: ()I + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=4, locals=1, args_size=0 + x: new #x // class java/lang/IllegalStateException + x: dup + x: ldc #x // String Inner exception + x: invokespecial #x // Method java/lang/IllegalStateException."<init>":(Ljava/lang/String;)V + x: athrow + x: astore_0 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Outer exception + x: aload_0 + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;Ljava/lang/Throwable;)V + x: 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; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +} +SourceFile: "TinyFrameworkExceptionTester.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestWholeClassKeep +## 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: 65 + 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: 15, attributes: 2 + public int stub; + descriptor: I + flags: (0x0001) ACC_PUBLIC + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + private static {}; + descriptor: ()V + flags: (0x000a) ACC_PRIVATE, ACC_STATIC + Code: + stack=2, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy + x: ldc #x // String com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook.onClassLoaded + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V + x: return + + public com.android.hoststubgen.test.tinyframework.TinyFrameworkForTextPolicy(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=2, locals=1, args_size=1 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: aload_0 + x: iconst_1 + x: putfield #x // Field stub:I + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 10 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + public int addOne(int); + descriptor: (I)I + flags: (0x0001) ACC_PUBLIC + Code: + stack=2, locals=2, args_size=2 + x: iload_1 + x: iconst_1 + x: iadd + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 4 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy; + 0 4 1 value I + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + public java.lang.String toBeIgnoredObj(); + descriptor: ()Ljava/lang/String; + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: aconst_null + x: areturn + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsIgnore + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + public void toBeIgnoredV(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=0, locals=1, args_size=1 + x: return + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsIgnore + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + public boolean toBeIgnoredZ(); + descriptor: ()Z + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: iconst_0 + x: ireturn + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsIgnore + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + public byte toBeIgnoredB(); + descriptor: ()B + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: iconst_0 + x: ireturn + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsIgnore + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + public char toBeIgnoredC(); + descriptor: ()C + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: iconst_0 + x: ireturn + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsIgnore + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + public short toBeIgnoredS(); + descriptor: ()S + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: iconst_0 + x: ireturn + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsIgnore + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + public int toBeIgnoredI(); + descriptor: ()I + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: iconst_0 + x: ireturn + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsIgnore + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + public float toBeIgnoredF(); + descriptor: ()F + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: fconst_0 + x: freturn + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsIgnore + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + public double toBeIgnoredD(); + descriptor: ()D + flags: (0x0001) ACC_PUBLIC + Code: + stack=2, locals=1, args_size=1 + x: dconst_0 + x: dreturn + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsIgnore + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + public int addTwo(int); + descriptor: (I)I + flags: (0x0001) ACC_PUBLIC + Code: + stack=2, locals=2, args_size=2 + x: iload_1 + x: iconst_2 + x: iadd + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 4 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy; + 0 4 1 value I + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsSubstitute + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + public static int nativeAddThree(int); + descriptor: (I)I + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=2, locals=1, args_size=1 + x: iload_0 + x: iconst_3 + x: iadd + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 4 0 value I + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsSubstitute + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + public java.lang.String unsupportedMethod(); + descriptor: ()Ljava/lang/String; + flags: (0x0001) ACC_PUBLIC + Code: + stack=3, locals=1, args_size=1 + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onThrowMethodCalled:()V + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Unreachable + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsThrow + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +} +SourceFile: "TinyFrameworkForTextPolicy.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested.class + Compiled from "TinyFrameworkLambdas.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkLambdas$Nested + minor version: 0 + major version: 65 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested + super_class: #x // java/lang/Object + interfaces: 0, fields: 2, methods: 8, attributes: 6 + 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;>; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestKeep + + 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;>; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestKeep + + public com.android.hoststubgen.test.tinyframework.TinyFrameworkLambdas$Nested(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=2, locals=1, args_size=1 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: aload_0 + x: invokedynamic #x, 0 // InvokeDynamic #x:get:()Ljava/util/function/Supplier; + x: putfield #x // Field mSupplier:Ljava/util/function/Supplier; + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 14 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestKeep + + public java.util.function.Supplier<java.lang.Integer> getSupplier(); + descriptor: ()Ljava/util/function/Supplier; + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: invokedynamic #x, 0 // InvokeDynamic #x:get:()Ljava/util/function/Supplier; + x: areturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 6 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested; + Signature: #x // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestKeep + + public static java.util.function.Supplier<java.lang.Integer> getSupplier_static(); + descriptor: ()Ljava/util/function/Supplier; + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=1, locals=0, args_size=0 + x: invokedynamic #x, 0 // InvokeDynamic #x:get:()Ljava/util/function/Supplier; + x: areturn + LineNumberTable: + Signature: #x // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestKeep + + private static java.lang.Integer lambda$getSupplier_static$3(); + descriptor: ()Ljava/lang/Integer; + flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC + Code: + stack=1, locals=0, args_size=0 + x: bipush 8 + x: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; + x: areturn + LineNumberTable: + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + private static java.lang.Integer lambda$getSupplier$2(); + descriptor: ()Ljava/lang/Integer; + flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC + Code: + stack=1, locals=0, args_size=0 + x: bipush 7 + x: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; + x: areturn + LineNumberTable: + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + private static java.lang.Integer lambda$static$1(); + descriptor: ()Ljava/lang/Integer; + flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC + Code: + stack=1, locals=0, args_size=0 + x: bipush 6 + x: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; + x: areturn + LineNumberTable: + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + private static java.lang.Integer lambda$new$0(); + descriptor: ()Ljava/lang/Integer; + flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC + Code: + stack=1, locals=0, args_size=0 + x: iconst_5 + x: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; + x: areturn + LineNumberTable: + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + static {}; + descriptor: ()V + flags: (0x0008) ACC_STATIC + Code: + stack=1, locals=0, args_size=0 + x: invokedynamic #x, 0 // InvokeDynamic #x:get:()Ljava/util/function/Supplier; + x: putstatic #x // Field sSupplier:Ljava/util/function/Supplier; + x: return + LineNumberTable: + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +} +InnerClasses: + public static #x= #x of #x; // Nested=class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested of class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas + public static final #x= #x of #x; // Lookup=class java/lang/invoke/MethodHandles$Lookup of class java/lang/invoke/MethodHandles +SourceFile: "TinyFrameworkLambdas.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestKeep + x: #x() + android.hosttest.annotation.HostSideTestStaticInitializerKeep +BootstrapMethods: + x: #x REF_invokeStatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite; + Method arguments: + #x ()Ljava/lang/Object; + #x REF_invokeStatic com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested.lambda$new$0:()Ljava/lang/Integer; + #x ()Ljava/lang/Integer; + x: #x REF_invokeStatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite; + Method arguments: + #x ()Ljava/lang/Object; + #x REF_invokeStatic com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested.lambda$getSupplier$2:()Ljava/lang/Integer; + #x ()Ljava/lang/Integer; + x: #x REF_invokeStatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite; + Method arguments: + #x ()Ljava/lang/Object; + #x REF_invokeStatic com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested.lambda$getSupplier_static$3:()Ljava/lang/Integer; + #x ()Ljava/lang/Integer; + x: #x REF_invokeStatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite; + Method arguments: + #x ()Ljava/lang/Object; + #x REF_invokeStatic com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested.lambda$static$1:()Ljava/lang/Integer; + #x ()Ljava/lang/Integer; +NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas.class + Compiled from "TinyFrameworkLambdas.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkLambdas + minor version: 0 + major version: 65 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas + super_class: #x // java/lang/Object + interfaces: 0, fields: 2, methods: 8, attributes: 6 + 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;>; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestKeep + + 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;>; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestKeep + + public com.android.hoststubgen.test.tinyframework.TinyFrameworkLambdas(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=2, locals=1, args_size=1 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: aload_0 + x: invokedynamic #x, 0 // InvokeDynamic #x:get:()Ljava/util/function/Supplier; + x: putfield #x // Field mSupplier:Ljava/util/function/Supplier; + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 14 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestKeep + + public java.util.function.Supplier<java.lang.Integer> getSupplier(); + descriptor: ()Ljava/util/function/Supplier; + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: invokedynamic #x, 0 // InvokeDynamic #x:get:()Ljava/util/function/Supplier; + x: areturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 6 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas; + Signature: #x // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestKeep + + public static java.util.function.Supplier<java.lang.Integer> getSupplier_static(); + descriptor: ()Ljava/util/function/Supplier; + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=1, locals=0, args_size=0 + x: invokedynamic #x, 0 // InvokeDynamic #x:get:()Ljava/util/function/Supplier; + x: areturn + LineNumberTable: + Signature: #x // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestKeep + + private static java.lang.Integer lambda$getSupplier_static$3(); + descriptor: ()Ljava/lang/Integer; + flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC + Code: + stack=1, locals=0, args_size=0 + x: iconst_4 + x: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; + x: areturn + LineNumberTable: + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + private static java.lang.Integer lambda$getSupplier$2(); + descriptor: ()Ljava/lang/Integer; + flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC + Code: + stack=1, locals=0, args_size=0 + x: iconst_3 + x: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; + x: areturn + LineNumberTable: + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + private static java.lang.Integer lambda$static$1(); + descriptor: ()Ljava/lang/Integer; + flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC + Code: + stack=1, locals=0, args_size=0 + x: iconst_2 + x: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; + x: areturn + LineNumberTable: + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + private static java.lang.Integer lambda$new$0(); + descriptor: ()Ljava/lang/Integer; + flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC + Code: + stack=1, locals=0, args_size=0 + x: iconst_1 + x: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; + x: areturn + LineNumberTable: + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + static {}; + descriptor: ()V + flags: (0x0008) ACC_STATIC + Code: + stack=1, locals=0, args_size=0 + x: invokedynamic #x, 0 // InvokeDynamic #x:get:()Ljava/util/function/Supplier; + x: putstatic #x // Field sSupplier:Ljava/util/function/Supplier; + x: return + LineNumberTable: + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +} +InnerClasses: + public static #x= #x of #x; // Nested=class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested of class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas + public static final #x= #x of #x; // Lookup=class java/lang/invoke/MethodHandles$Lookup of class java/lang/invoke/MethodHandles +SourceFile: "TinyFrameworkLambdas.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestKeep + x: #x() + android.hosttest.annotation.HostSideTestStaticInitializerKeep +BootstrapMethods: + x: #x REF_invokeStatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite; + Method arguments: + #x ()Ljava/lang/Object; + #x REF_invokeStatic com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas.lambda$new$0:()Ljava/lang/Integer; + #x ()Ljava/lang/Integer; + x: #x REF_invokeStatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite; + Method arguments: + #x ()Ljava/lang/Object; + #x REF_invokeStatic com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas.lambda$getSupplier$2:()Ljava/lang/Integer; + #x ()Ljava/lang/Integer; + x: #x REF_invokeStatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite; + Method arguments: + #x ()Ljava/lang/Object; + #x REF_invokeStatic com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas.lambda$getSupplier_static$3:()Ljava/lang/Integer; + #x ()Ljava/lang/Integer; + x: #x REF_invokeStatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite; + Method arguments: + #x ()Ljava/lang/Object; + #x REF_invokeStatic com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas.lambda$static$1:()Ljava/lang/Integer; + #x ()Ljava/lang/Integer; +NestMembers: + com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo.class + Compiled from "TinyFrameworkMethodCallReplace.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace$ReplaceTo + minor version: 0 + major version: 65 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo + super_class: #x // java/lang/Object + interfaces: 0, fields: 0, methods: 3, attributes: 4 + public com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace$ReplaceTo(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + public static void startThread(java.lang.Thread); + descriptor: (Ljava/lang/Thread;)V + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=2, locals=1, args_size=1 + x: aload_0 + x: iconst_1 + x: invokevirtual #x // Method java/lang/Thread.setDaemon:(Z)V + x: aload_0 + x: invokevirtual #x // Method java/lang/Thread.start:()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 10 0 thread Ljava/lang/Thread; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + public static int add(int, int); + descriptor: (II)I + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=2, locals=2, args_size=2 + x: iload_0 + x: iload_1 + x: iadd + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 4 0 a I + 0 4 1 b I + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +} +InnerClasses: + public static #x= #x of #x; // ReplaceTo=class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo of class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace +SourceFile: "TinyFrameworkMethodCallReplace.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace.class + Compiled from "TinyFrameworkMethodCallReplace.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace + minor version: 0 + major version: 65 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace + super_class: #x // java/lang/Object + interfaces: 0, fields: 0, methods: 4, attributes: 6 + public com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + public static boolean nonStaticMethodCallReplaceTester() throws java.lang.Exception; + descriptor: ()Z + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=3, locals=2, args_size=0 + x: new #x // class java/util/concurrent/atomic/AtomicBoolean + x: dup + x: iconst_0 + x: invokespecial #x // Method java/util/concurrent/atomic/AtomicBoolean."<init>":(Z)V + x: astore_0 + x: new #x // class java/lang/Thread + x: dup + x: aload_0 + x: invokedynamic #x, 0 // InvokeDynamic #x:run:(Ljava/util/concurrent/atomic/AtomicBoolean;)Ljava/lang/Runnable; + x: invokespecial #x // Method java/lang/Thread."<init>":(Ljava/lang/Runnable;)V + x: astore_1 + x: aload_1 + x: invokestatic #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo.startThread:(Ljava/lang/Thread;)V + x: aload_1 + x: invokevirtual #x // Method java/lang/Thread.join:()V + x: aload_0 + x: invokevirtual #x // Method java/util/concurrent/atomic/AtomicBoolean.get:()Z + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 9 27 0 ab Ljava/util/concurrent/atomic/AtomicBoolean; + 23 13 1 th Ljava/lang/Thread; + Exceptions: + throws java.lang.Exception + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + public static int staticMethodCallReplaceTester(); + descriptor: ()I + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=2, locals=0, args_size=0 + x: iconst_1 + x: iconst_2 + x: invokestatic #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo.add:(II)I + x: ireturn + LineNumberTable: + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + private static void lambda$nonStaticMethodCallReplaceTester$0(java.util.concurrent.atomic.AtomicBoolean); + descriptor: (Ljava/util/concurrent/atomic/AtomicBoolean;)V + flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC + Code: + stack=2, locals=1, args_size=1 + x: aload_0 + x: invokestatic #x // Method java/lang/Thread.currentThread:()Ljava/lang/Thread; + x: invokevirtual #x // Method java/lang/Thread.isDaemon:()Z + x: invokevirtual #x // Method java/util/concurrent/atomic/AtomicBoolean.set:(Z)V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 11 0 ab Ljava/util/concurrent/atomic/AtomicBoolean; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +} +InnerClasses: + public static #x= #x of #x; // ReplaceTo=class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo of class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace + public static final #x= #x of #x; // Lookup=class java/lang/invoke/MethodHandles$Lookup of class java/lang/invoke/MethodHandles +SourceFile: "TinyFrameworkMethodCallReplace.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestWholeClassKeep +BootstrapMethods: + x: #x REF_invokeStatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite; + Method arguments: + #x ()V + #x REF_invokeStatic com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace.lambda$nonStaticMethodCallReplaceTester$0:(Ljava/util/concurrent/atomic/AtomicBoolean;)V + #x ()V +NestMembers: + com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo +## 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: 65 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNative + super_class: #x // java/lang/Object + interfaces: 0, fields: 1, methods: 14, attributes: 3 + int value; + descriptor: I + flags: (0x0000) + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + public com.android.hoststubgen.test.tinyframework.TinyFrameworkNative(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + public static int nativeAddTwo(int); + descriptor: (I)I + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=1, locals=1, args_size=1 + x: iload_0 + x: invokestatic #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.nativeAddTwo:(I)I + x: ireturn + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsSubstitute + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestRedirect + + 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 + x: iload_0 + x: invokestatic #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.nativeAddTwo:(I)I + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 arg I + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + public static long nativeLongPlus(long, long); + descriptor: (JJ)J + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=4, locals=4, args_size=2 + x: lload_0 + x: lload_2 + x: invokestatic #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.nativeLongPlus:(JJ)J + x: lreturn + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsSubstitute + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestRedirect + + 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 + x: lload_0 + x: lload_2 + x: invokestatic #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.nativeLongPlus:(JJ)J + x: lreturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 6 0 arg1 J + 0 6 2 arg2 J + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + public void setValue(int); + descriptor: (I)V + flags: (0x0001) ACC_PUBLIC + Code: + stack=2, locals=2, args_size=2 + x: aload_0 + x: iload_1 + x: putfield #x // Field value:I + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 6 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative; + 0 6 1 v I + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + public int nativeNonStaticAddToValue(int); + descriptor: (I)I + flags: (0x0001) ACC_PUBLIC + Code: + stack=2, locals=2, args_size=2 + x: aload_0 + x: iload_1 + x: invokestatic #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.nativeNonStaticAddToValue:(Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative;I)I + x: ireturn + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsSubstitute + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestRedirect + + public int nativeNonStaticAddToValue_should_be_like_this(int); + descriptor: (I)I + flags: (0x0001) ACC_PUBLIC + Code: + stack=2, locals=2, args_size=2 + x: aload_0 + x: iload_1 + x: invokestatic #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.nativeNonStaticAddToValue:(Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative;I)I + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 6 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative; + 0 6 1 arg I + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + public static void nativeStillNotSupported(); + descriptor: ()V + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=3, locals=0, args_size=0 + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onThrowMethodCalled:()V + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Unreachable + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsThrow + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestThrow + + public static native void nativeStillKeep(); + descriptor: ()V + flags: (0x0109) ACC_PUBLIC, ACC_STATIC, ACC_NATIVE + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + public static void nativeStillNotSupported_should_be_like_this(); + descriptor: ()V + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=2, locals=0, args_size=0 + x: new #x // class java/lang/RuntimeException + x: dup + x: invokespecial #x // Method java/lang/RuntimeException."<init>":()V + x: athrow + LineNumberTable: + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + public static byte nativeBytePlus(byte, byte); + descriptor: (BB)B + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=2, locals=2, args_size=2 + x: iload_0 + x: iload_1 + x: invokestatic #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.nativeBytePlus:(BB)B + x: ireturn + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsSubstitute + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestRedirect + + public void notNativeRedirected(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: aload_0 + x: invokestatic #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.notNativeRedirected:(Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative;)V + x: return + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsSubstitute + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestRedirect + + public static void notNativeStaticRedirected(); + descriptor: ()V + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=0, locals=0, args_size=0 + x: invokestatic #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.notNativeStaticRedirected:()V + x: return + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsSubstitute + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestRedirect +} +SourceFile: "TinyFrameworkNative.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestWholeClassKeep + x: #x(#x=s#x) + android.hosttest.annotation.HostSideTestRedirectionClass( + 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: 65 + 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: 7, attributes: 3 + public com.android.hoststubgen.test.tinyframework.TinyFrameworkNative_host(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + public static int nativeAddTwo(int); + descriptor: (I)I + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=2, locals=1, args_size=1 + x: iload_0 + x: iconst_2 + x: iadd + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 4 0 arg I + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + public static long nativeLongPlus(long, long); + descriptor: (JJ)J + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=4, locals=4, args_size=2 + x: lload_0 + x: lload_2 + x: ladd + x: lreturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 4 0 arg1 J + 0 4 2 arg2 J + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + public static int nativeNonStaticAddToValue(com.android.hoststubgen.test.tinyframework.TinyFrameworkNative, int); + descriptor: (Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative;I)I + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=2, locals=2, args_size=2 + x: aload_0 + x: getfield #x // Field com/android/hoststubgen/test/tinyframework/TinyFrameworkNative.value:I + x: iload_1 + x: iadd + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 7 0 source Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative; + 0 7 1 arg I + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + public static byte nativeBytePlus(byte, byte); + descriptor: (BB)B + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=2, locals=2, args_size=2 + x: iload_0 + x: iload_1 + x: iadd + x: i2b + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 arg1 B + 0 5 1 arg2 B + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + public static void notNativeRedirected(com.android.hoststubgen.test.tinyframework.TinyFrameworkNative); + descriptor: (Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative;)V + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=0, locals=1, args_size=1 + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 1 0 source Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + public static void notNativeStaticRedirected(); + descriptor: ()V + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=0, locals=0, args_size=0 + x: return + LineNumberTable: + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +} +SourceFile: "TinyFrameworkNative_host.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +RuntimeInvisibleAnnotations: + x: #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: 65 + flags: (0x0020) ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1 + super_class: #x // java/lang/Object + interfaces: 1, fields: 0, methods: 3, attributes: 6 + 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=1, locals=2, args_size=2 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1; + 0 5 1 this$0 Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + MethodParameters: + Name Flags + <no name> final mandated + + public java.lang.Integer get(); + descriptor: ()Ljava/lang/Integer; + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: iconst_1 + x: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; + x: areturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + 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 + x: aload_0 + x: invokevirtual #x // Method get:()Ljava/lang/Integer; + x: areturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +} +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: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +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: 65 + 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 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + public java.lang.Integer get(); + descriptor: ()Ljava/lang/Integer; + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: iconst_2 + x: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; + x: areturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + 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 + x: aload_0 + x: invokevirtual #x // Method get:()Ljava/lang/Integer; + x: areturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +} +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: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +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: 65 + flags: (0x0020) ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3 + super_class: #x // java/lang/Object + interfaces: 1, fields: 0, methods: 3, attributes: 6 + 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=1, locals=2, args_size=2 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3; + 0 5 1 this$0 Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + MethodParameters: + Name Flags + <no name> final mandated + + public java.lang.Integer get(); + descriptor: ()Ljava/lang/Integer; + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: iconst_3 + x: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; + x: areturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + 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 + x: aload_0 + x: invokevirtual #x // Method get:()Ljava/lang/Integer; + x: areturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +} +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: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +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: 65 + 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 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + public java.lang.Integer get(); + descriptor: ()Ljava/lang/Integer; + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: iconst_4 + x: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; + x: areturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + 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 + x: aload_0 + x: invokevirtual #x // Method get:()Ljava/lang/Integer; + x: areturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +} +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: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +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: 65 + 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 + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$BaseClass(int); + descriptor: (I)V + flags: (0x0001) ACC_PUBLIC + Code: + stack=2, locals=2, args_size=2 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: aload_0 + x: iload_1 + x: putfield #x // Field value:I + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 10 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass; + 0 10 1 x I + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +} +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: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +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: 65 + 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: 1, methods: 1, attributes: 4 + public int value; + descriptor: I + flags: (0x0001) ACC_PUBLIC + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + 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 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: aload_0 + x: iconst_5 + x: putfield #x // Field value:I + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 10 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass; + 0 10 1 this$0 Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + MethodParameters: + Name Flags + <no name> final mandated +} +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: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +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: 65 + 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 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + public java.lang.Integer get(); + descriptor: ()Ljava/lang/Integer; + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: bipush 7 + x: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; + x: areturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 6 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + 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 + x: aload_0 + x: invokevirtual #x // Method get:()Ljava/lang/Integer; + x: areturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +} +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: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$Double$NestedClass.class + Compiled from "TinyFrameworkNestedClasses.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$StaticNestedClass$Double$NestedClass + minor version: 0 + major version: 65 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$Double$NestedClass + super_class: #x // java/lang/Object + interfaces: 0, fields: 1, methods: 1, attributes: 4 + public int value; + descriptor: I + flags: (0x0001) ACC_PUBLIC + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$StaticNestedClass$Double$NestedClass(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=2, locals=1, args_size=1 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: aload_0 + x: bipush 8 + x: putfield #x // Field value:I + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 11 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$Double$NestedClass; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +} +InnerClasses: + public static #x= #x of #x; // StaticNestedClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses + public static #x= #x of #x; // Double$NestedClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$Double$NestedClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass +SourceFile: "TinyFrameworkNestedClasses.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +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: 65 + 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 + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$StaticNestedClass(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=2, locals=1, args_size=1 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: aload_0 + x: bipush 6 + x: putfield #x // Field value:I + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 11 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + 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 + x: new #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1 + x: dup + x: invokespecial #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1."<init>":()V + x: areturn + LineNumberTable: + Signature: #x // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +} +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 + public static #x= #x of #x; // Double$NestedClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$Double$NestedClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass +SourceFile: "TinyFrameworkNestedClasses.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +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: 65 + 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 + x: aload_0 + x: iload_1 + x: invokespecial #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass."<init>":(I)V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 6 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass; + 0 6 1 x I + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +} +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: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +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: 65 + 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;>; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + 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;>; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=1, args_size=1 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: aload_0 + x: new #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1 + x: dup + x: aload_0 + x: invokespecial #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1."<init>":(Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;)V + x: putfield #x // Field mSupplier:Ljava/util/function/Supplier; + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 17 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + 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 + x: new #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3 + x: dup + x: aload_0 + x: invokespecial #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3."<init>":(Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;)V + x: 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;>; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + 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 + x: new #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4 + x: dup + x: invokespecial #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4."<init>":()V + x: areturn + LineNumberTable: + Signature: #x // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + static {}; + descriptor: ()V + flags: (0x0008) ACC_STATIC + Code: + stack=2, locals=0, args_size=0 + x: new #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2 + x: dup + x: invokespecial #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2."<init>":()V + x: putstatic #x // Field sSupplier:Ljava/util/function/Supplier; + x: return + LineNumberTable: + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +} +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 + public static #x= #x of #x; // Double$NestedClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$Double$NestedClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass + #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1 +SourceFile: "TinyFrameworkNestedClasses.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestWholeClassKeep +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$Double$NestedClass + 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 +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkPackageRedirect.class + Compiled from "TinyFrameworkPackageRedirect.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkPackageRedirect + minor version: 0 + major version: 65 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkPackageRedirect + super_class: #x // java/lang/Object + interfaces: 0, fields: 0, methods: 2, attributes: 3 + public com.android.hoststubgen.test.tinyframework.TinyFrameworkPackageRedirect(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkPackageRedirect; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + public static int foo(int); + descriptor: (I)I + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=3, locals=1, args_size=1 + x: new #x // class com/supported/UnsupportedClass + x: dup + x: iload_0 + x: invokespecial #x // Method com/supported/UnsupportedClass."<init>":(I)V + x: invokevirtual #x // Method com/supported/UnsupportedClass.getValue:()I + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 12 0 value I + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +} +SourceFile: "TinyFrameworkPackageRedirect.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestWholeClassKeep +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkRenamedClassCaller.class + Compiled from "TinyFrameworkRenamedClassCaller.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkRenamedClassCaller + minor version: 0 + major version: 65 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkRenamedClassCaller + super_class: #x // java/lang/Object + interfaces: 0, fields: 0, methods: 2, attributes: 3 + public com.android.hoststubgen.test.tinyframework.TinyFrameworkRenamedClassCaller(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkRenamedClassCaller; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + public static int foo(int); + descriptor: (I)I + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=3, locals=1, args_size=1 + x: new #x // class rename_prefix/com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed + x: dup + x: iload_0 + x: invokespecial #x // Method rename_prefix/com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed."<init>":(I)V + x: invokevirtual #x // Method rename_prefix/com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed.getValue:()I + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 12 0 value I + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +} +SourceFile: "TinyFrameworkRenamedClassCaller.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestWholeClassKeep +## Class: com/android/hoststubgen/test/tinyframework/packagetest/A.class + Compiled from "A.java" +public class com.android.hoststubgen.test.tinyframework.packagetest.A + minor version: 0 + major version: 65 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/packagetest/A + super_class: #x // java/lang/Object + interfaces: 0, fields: 0, methods: 0, attributes: 2 +} +SourceFile: "A.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +## Class: com/android/hoststubgen/test/tinyframework/packagetest/sub/A.class + Compiled from "A.java" +public class com.android.hoststubgen.test.tinyframework.packagetest.sub.A + minor version: 0 + major version: 65 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/packagetest/sub/A + super_class: #x // java/lang/Object + interfaces: 0, fields: 0, methods: 0, attributes: 2 +} +SourceFile: "A.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +## Class: com/android/hoststubgen/test/tinyframework/subclasstest/C1.class + Compiled from "C1.java" +public class com.android.hoststubgen.test.tinyframework.subclasstest.C1 + minor version: 0 + major version: 65 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/C1 + super_class: #x // java/lang/Object + interfaces: 0, fields: 0, methods: 0, attributes: 2 +} +SourceFile: "C1.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +## Class: com/android/hoststubgen/test/tinyframework/subclasstest/C2.class + Compiled from "C2.java" +public class com.android.hoststubgen.test.tinyframework.subclasstest.C2 extends com.android.hoststubgen.test.tinyframework.subclasstest.C1 + minor version: 0 + major version: 65 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/C2 + super_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/C1 + interfaces: 0, fields: 0, methods: 0, attributes: 2 +} +SourceFile: "C2.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +## Class: com/android/hoststubgen/test/tinyframework/subclasstest/C3.class + Compiled from "C3.java" +public class com.android.hoststubgen.test.tinyframework.subclasstest.C3 extends com.android.hoststubgen.test.tinyframework.subclasstest.C2 + minor version: 0 + major version: 65 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/C3 + super_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/C2 + interfaces: 0, fields: 0, methods: 0, attributes: 2 +} +SourceFile: "C3.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +## Class: com/android/hoststubgen/test/tinyframework/subclasstest/CA.class + Compiled from "CA.java" +public class com.android.hoststubgen.test.tinyframework.subclasstest.CA + minor version: 0 + major version: 65 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/CA + super_class: #x // java/lang/Object + interfaces: 0, fields: 0, methods: 0, attributes: 2 +} +SourceFile: "CA.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +## Class: com/android/hoststubgen/test/tinyframework/subclasstest/CB.class + Compiled from "CB.java" +public class com.android.hoststubgen.test.tinyframework.subclasstest.CB + minor version: 0 + major version: 65 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/CB + super_class: #x // java/lang/Object + interfaces: 0, fields: 0, methods: 0, attributes: 2 +} +SourceFile: "CB.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +## Class: com/android/hoststubgen/test/tinyframework/subclasstest/Class_C1.class + Compiled from "Class_C1.java" +public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_C1 extends com.android.hoststubgen.test.tinyframework.subclasstest.C1 + minor version: 0 + major version: 65 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/Class_C1 + super_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/C1 + interfaces: 0, fields: 0, methods: 0, attributes: 2 +} +SourceFile: "Class_C1.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +## Class: com/android/hoststubgen/test/tinyframework/subclasstest/Class_C2.class + Compiled from "Class_C2.java" +public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_C2 extends com.android.hoststubgen.test.tinyframework.subclasstest.C2 + minor version: 0 + major version: 65 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/Class_C2 + super_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/C2 + interfaces: 0, fields: 0, methods: 0, attributes: 2 +} +SourceFile: "Class_C2.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +## Class: com/android/hoststubgen/test/tinyframework/subclasstest/Class_C3.class + Compiled from "Class_C3.java" +public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_C3 extends com.android.hoststubgen.test.tinyframework.subclasstest.C3 + minor version: 0 + major version: 65 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/Class_C3 + super_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/C3 + interfaces: 0, fields: 0, methods: 0, attributes: 2 +} +SourceFile: "Class_C3.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +## Class: com/android/hoststubgen/test/tinyframework/subclasstest/Class_I1.class + Compiled from "Class_I1.java" +public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_I1 implements com.android.hoststubgen.test.tinyframework.subclasstest.I1 + minor version: 0 + major version: 65 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/Class_I1 + super_class: #x // java/lang/Object + interfaces: 1, fields: 0, methods: 0, attributes: 2 +} +SourceFile: "Class_I1.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +## Class: com/android/hoststubgen/test/tinyframework/subclasstest/Class_I1_IA.class + Compiled from "Class_I1_IA.java" +public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_I1_IA implements com.android.hoststubgen.test.tinyframework.subclasstest.I1,com.android.hoststubgen.test.tinyframework.subclasstest.IA + minor version: 0 + major version: 65 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/Class_I1_IA + super_class: #x // java/lang/Object + interfaces: 2, fields: 0, methods: 0, attributes: 2 +} +SourceFile: "Class_I1_IA.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +## Class: com/android/hoststubgen/test/tinyframework/subclasstest/Class_I2.class + Compiled from "Class_I2.java" +public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_I2 implements com.android.hoststubgen.test.tinyframework.subclasstest.I2 + minor version: 0 + major version: 65 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/Class_I2 + super_class: #x // java/lang/Object + interfaces: 1, fields: 0, methods: 0, attributes: 2 +} +SourceFile: "Class_I2.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +## Class: com/android/hoststubgen/test/tinyframework/subclasstest/Class_I3.class + Compiled from "Class_I3.java" +public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_I3 implements com.android.hoststubgen.test.tinyframework.subclasstest.I3 + minor version: 0 + major version: 65 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/Class_I3 + super_class: #x // java/lang/Object + interfaces: 1, fields: 0, methods: 0, attributes: 2 +} +SourceFile: "Class_I3.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +## Class: com/android/hoststubgen/test/tinyframework/subclasstest/I1.class + Compiled from "I1.java" +public interface com.android.hoststubgen.test.tinyframework.subclasstest.I1 + minor version: 0 + major version: 65 + flags: (0x0601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT + this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/I1 + super_class: #x // java/lang/Object + interfaces: 0, fields: 0, methods: 0, attributes: 2 +} +SourceFile: "I1.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +## Class: com/android/hoststubgen/test/tinyframework/subclasstest/I2.class + Compiled from "I2.java" +public interface com.android.hoststubgen.test.tinyframework.subclasstest.I2 extends com.android.hoststubgen.test.tinyframework.subclasstest.I1 + minor version: 0 + major version: 65 + flags: (0x0601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT + this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/I2 + super_class: #x // java/lang/Object + interfaces: 1, fields: 0, methods: 0, attributes: 2 +} +SourceFile: "I2.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +## Class: com/android/hoststubgen/test/tinyframework/subclasstest/I3.class + Compiled from "I3.java" +public interface com.android.hoststubgen.test.tinyframework.subclasstest.I3 extends com.android.hoststubgen.test.tinyframework.subclasstest.I2 + minor version: 0 + major version: 65 + flags: (0x0601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT + this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/I3 + super_class: #x // java/lang/Object + interfaces: 1, fields: 0, methods: 0, attributes: 2 +} +SourceFile: "I3.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +## Class: com/android/hoststubgen/test/tinyframework/subclasstest/IA.class + Compiled from "IA.java" +public interface com.android.hoststubgen.test.tinyframework.subclasstest.IA + minor version: 0 + major version: 65 + flags: (0x0601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT + this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/IA + super_class: #x // java/lang/Object + interfaces: 0, fields: 0, methods: 0, attributes: 2 +} +SourceFile: "IA.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +## Class: com/android/hoststubgen/test/tinyframework/subclasstest/IB.class + Compiled from "IB.java" +public interface com.android.hoststubgen.test.tinyframework.subclasstest.IB + minor version: 0 + major version: 65 + flags: (0x0601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT + this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/IB + super_class: #x // java/lang/Object + interfaces: 0, fields: 0, methods: 0, attributes: 2 +} +SourceFile: "IB.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +## Class: com/supported/UnsupportedClass.class + Compiled from "UnsupportedClass.java" +public class com.supported.UnsupportedClass + minor version: 0 + major version: 65 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/supported/UnsupportedClass + super_class: #x // java/lang/Object + interfaces: 0, fields: 1, methods: 2, attributes: 3 + private final int mValue; + descriptor: I + flags: (0x0012) ACC_PRIVATE, ACC_FINAL + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + public com.supported.UnsupportedClass(int); + descriptor: (I)V + flags: (0x0001) ACC_PUBLIC + Code: + stack=2, locals=2, args_size=2 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: aload_0 + x: iload_1 + x: putfield #x // Field mValue:I + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 10 0 this Lcom/supported/UnsupportedClass; + 0 10 1 value I + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + public int getValue(); + descriptor: ()I + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: aload_0 + x: getfield #x // Field mValue:I + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lcom/supported/UnsupportedClass; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +} +SourceFile: "UnsupportedClass.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestWholeClassKeep +## Class: com/unsupported/UnsupportedClass.class + Compiled from "UnsupportedClass.java" +public class com.unsupported.UnsupportedClass + minor version: 0 + major version: 65 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/unsupported/UnsupportedClass + super_class: #x // java/lang/Object + interfaces: 0, fields: 0, methods: 2, attributes: 3 + public com.unsupported.UnsupportedClass(int); + descriptor: (I)V + flags: (0x0001) ACC_PUBLIC + Code: + stack=3, locals=2, args_size=2 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String This class is not supported + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 14 0 this Lcom/unsupported/UnsupportedClass; + 0 14 1 value I + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + public int getValue(); + descriptor: ()I + flags: (0x0001) ACC_PUBLIC + Code: + stack=3, locals=1, args_size=1 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String This class is not supported + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 10 0 this Lcom/unsupported/UnsupportedClass; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +} +SourceFile: "UnsupportedClass.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestWholeClassKeep +## Class: rename_prefix/com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed.class + Compiled from "TinyFrameworkToBeRenamed.java" +public class rename_prefix.com.android.hoststubgen.test.tinyframework.TinyFrameworkToBeRenamed + minor version: 0 + major version: 65 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // rename_prefix/com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed + super_class: #x // java/lang/Object + interfaces: 0, fields: 1, methods: 2, attributes: 3 + private final int mValue; + descriptor: I + flags: (0x0012) ACC_PRIVATE, ACC_FINAL + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + public rename_prefix.com.android.hoststubgen.test.tinyframework.TinyFrameworkToBeRenamed(int); + descriptor: (I)V + flags: (0x0001) ACC_PUBLIC + Code: + stack=2, locals=2, args_size=2 + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: aload_0 + x: iload_1 + x: putfield #x // Field mValue:I + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 10 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed; + 0 10 1 value I + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + public int getValue(); + descriptor: ()I + flags: (0x0001) ACC_PUBLIC + Code: + stack=1, locals=1, args_size=1 + x: aload_0 + x: getfield #x // Field mValue:I + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +} +SourceFile: "TinyFrameworkToBeRenamed.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestWholeClassKeep diff --git a/ravenwood/tools/hoststubgen/test-tiny-framework/golden-output.RELEASE_TARGET_JAVA_21/13-hoststubgen-test-tiny-framework-host-ext-dump.txt b/ravenwood/tools/hoststubgen/test-tiny-framework/golden-output.RELEASE_TARGET_JAVA_21/13-hoststubgen-test-tiny-framework-host-ext-dump.txt new file mode 100644 index 000000000000..49769e648bbf --- /dev/null +++ b/ravenwood/tools/hoststubgen/test-tiny-framework/golden-output.RELEASE_TARGET_JAVA_21/13-hoststubgen-test-tiny-framework-host-ext-dump.txt @@ -0,0 +1,4896 @@ +## 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: 65 + 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: 2, attributes: 2 + private static {}; + descriptor: ()V + flags: (0x000a) ACC_PRIVATE, ACC_STATIC + Code: + stack=2, locals=0, args_size=0 + x: ldc #x // class android/hosttest/annotation/HostSideTestClassLoadHook + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V + x: return + + public abstract java.lang.String value(); + descriptor: ()Ljava/lang/String; + flags: (0x0401) ACC_PUBLIC, ACC_ABSTRACT + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +} +SourceFile: "HostSideTestClassLoadHook.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + x: #x(#x=[e#x.#x]) + java.lang.annotation.Target( + value=[Ljava/lang/annotation/ElementType;.TYPE] + ) + x: #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: 65 + 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: 1, attributes: 2 + private static {}; + descriptor: ()V + flags: (0x000a) ACC_PRIVATE, ACC_STATIC + Code: + stack=2, locals=0, args_size=0 + x: ldc #x // class android/hosttest/annotation/HostSideTestKeep + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V + x: return +} +SourceFile: "HostSideTestKeep.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + x: #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] + ) + x: #x(#x=e#x.#x) + java.lang.annotation.Retention( + value=Ljava/lang/annotation/RetentionPolicy;.CLASS + ) +## Class: android/hosttest/annotation/HostSideTestRedirect.class + Compiled from "HostSideTestRedirect.java" +public interface android.hosttest.annotation.HostSideTestRedirect extends java.lang.annotation.Annotation + minor version: 0 + major version: 65 + flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION + this_class: #x // android/hosttest/annotation/HostSideTestRedirect + super_class: #x // java/lang/Object + interfaces: 1, fields: 0, methods: 1, attributes: 2 + private static {}; + descriptor: ()V + flags: (0x000a) ACC_PRIVATE, ACC_STATIC + Code: + stack=2, locals=0, args_size=0 + x: ldc #x // class android/hosttest/annotation/HostSideTestRedirect + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V + x: return +} +SourceFile: "HostSideTestRedirect.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + x: #x(#x=[e#x.#x]) + java.lang.annotation.Target( + value=[Ljava/lang/annotation/ElementType;.METHOD] + ) + x: #x(#x=e#x.#x) + java.lang.annotation.Retention( + value=Ljava/lang/annotation/RetentionPolicy;.CLASS + ) +## Class: android/hosttest/annotation/HostSideTestRedirectionClass.class + Compiled from "HostSideTestRedirectionClass.java" +public interface android.hosttest.annotation.HostSideTestRedirectionClass extends java.lang.annotation.Annotation + minor version: 0 + major version: 65 + flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION + this_class: #x // android/hosttest/annotation/HostSideTestRedirectionClass + super_class: #x // java/lang/Object + interfaces: 1, fields: 0, methods: 2, attributes: 2 + private static {}; + descriptor: ()V + flags: (0x000a) ACC_PRIVATE, ACC_STATIC + Code: + stack=2, locals=0, args_size=0 + x: ldc #x // class android/hosttest/annotation/HostSideTestRedirectionClass + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V + x: return + + public abstract java.lang.String value(); + descriptor: ()Ljava/lang/String; + flags: (0x0401) ACC_PUBLIC, ACC_ABSTRACT + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +} +SourceFile: "HostSideTestRedirectionClass.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + x: #x(#x=[e#x.#x]) + java.lang.annotation.Target( + value=[Ljava/lang/annotation/ElementType;.TYPE] + ) + x: #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: 65 + 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: 1, attributes: 2 + private static {}; + descriptor: ()V + flags: (0x000a) ACC_PRIVATE, ACC_STATIC + Code: + stack=2, locals=0, args_size=0 + x: ldc #x // class android/hosttest/annotation/HostSideTestRemove + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V + x: return +} +SourceFile: "HostSideTestRemove.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + x: #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] + ) + x: #x(#x=e#x.#x) + java.lang.annotation.Retention( + value=Ljava/lang/annotation/RetentionPolicy;.CLASS + ) +## Class: android/hosttest/annotation/HostSideTestStaticInitializerKeep.class + Compiled from "HostSideTestStaticInitializerKeep.java" +public interface android.hosttest.annotation.HostSideTestStaticInitializerKeep extends java.lang.annotation.Annotation + minor version: 0 + major version: 65 + flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION + this_class: #x // android/hosttest/annotation/HostSideTestStaticInitializerKeep + super_class: #x // java/lang/Object + interfaces: 1, fields: 0, methods: 1, attributes: 2 + private static {}; + descriptor: ()V + flags: (0x000a) ACC_PRIVATE, ACC_STATIC + Code: + stack=2, locals=0, args_size=0 + x: ldc #x // class android/hosttest/annotation/HostSideTestStaticInitializerKeep + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V + x: return +} +SourceFile: "HostSideTestStaticInitializerKeep.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + x: #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] + ) + x: #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: 65 + 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: 2, attributes: 2 + private static {}; + descriptor: ()V + flags: (0x000a) ACC_PRIVATE, ACC_STATIC + Code: + stack=2, locals=0, args_size=0 + x: ldc #x // class android/hosttest/annotation/HostSideTestSubstitute + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V + x: return + + public abstract java.lang.String suffix(); + descriptor: ()Ljava/lang/String; + flags: (0x0401) ACC_PUBLIC, ACC_ABSTRACT + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +} +SourceFile: "HostSideTestSubstitute.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + x: #x(#x=[e#x.#x]) + java.lang.annotation.Target( + value=[Ljava/lang/annotation/ElementType;.METHOD] + ) + x: #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: 65 + 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: 1, attributes: 2 + private static {}; + descriptor: ()V + flags: (0x000a) ACC_PRIVATE, ACC_STATIC + Code: + stack=2, locals=0, args_size=0 + x: ldc #x // class android/hosttest/annotation/HostSideTestThrow + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V + x: return +} +SourceFile: "HostSideTestThrow.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + x: #x(#x=[e#x.#x,e#x.#x]) + java.lang.annotation.Target( + value=[Ljava/lang/annotation/ElementType;.METHOD,Ljava/lang/annotation/ElementType;.CONSTRUCTOR] + ) + x: #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: 65 + 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: 1, attributes: 2 + private static {}; + descriptor: ()V + flags: (0x000a) ACC_PRIVATE, ACC_STATIC + Code: + stack=2, locals=0, args_size=0 + x: ldc #x // class android/hosttest/annotation/HostSideTestWholeClassKeep + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V + x: return +} +SourceFile: "HostSideTestWholeClassKeep.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + x: #x(#x=[e#x.#x]) + java.lang.annotation.Target( + value=[Ljava/lang/annotation/ElementType;.TYPE] + ) + x: #x(#x=e#x.#x) + java.lang.annotation.Retention( + value=Ljava/lang/annotation/RetentionPolicy;.CLASS + ) +## Class: com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub$Proxy.class + Compiled from "IPretendingAidl.java" +public class com.android.hoststubgen.test.tinyframework.IPretendingAidl$Stub$Proxy + minor version: 0 + major version: 65 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub$Proxy + super_class: #x // java/lang/Object + interfaces: 0, fields: 0, methods: 3, attributes: 4 + private static {}; + descriptor: ()V + flags: (0x000a) ACC_PRIVATE, ACC_STATIC + Code: + stack=2, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub$Proxy + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V + x: return + + public com.android.hoststubgen.test.tinyframework.IPretendingAidl$Stub$Proxy(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub$Proxy + x: ldc #x // String <init> + x: ldc #x // String ()V + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 5 0 this Lcom/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub$Proxy; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + public static int addTwo(int); + descriptor: (I)I + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub$Proxy + x: ldc #x // String addTwo + x: ldc #x // String (I)I + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: iload_0 + x: iconst_2 + x: iadd + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 4 0 a I + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +} +InnerClasses: + public static #x= #x of #x; // Stub=class com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub of class com/android/hoststubgen/test/tinyframework/IPretendingAidl + public static #x= #x of #x; // Proxy=class com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub$Proxy of class com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub +SourceFile: "IPretendingAidl.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +NestHost: class com/android/hoststubgen/test/tinyframework/IPretendingAidl +## Class: com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub.class + Compiled from "IPretendingAidl.java" +public class com.android.hoststubgen.test.tinyframework.IPretendingAidl$Stub + minor version: 0 + major version: 65 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub + super_class: #x // java/lang/Object + interfaces: 0, fields: 0, methods: 3, attributes: 4 + private static {}; + descriptor: ()V + flags: (0x000a) ACC_PRIVATE, ACC_STATIC + Code: + stack=2, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V + x: return + + public com.android.hoststubgen.test.tinyframework.IPretendingAidl$Stub(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub + x: ldc #x // String <init> + x: ldc #x // String ()V + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 5 0 this Lcom/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + public static int addOne(int); + descriptor: (I)I + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub + x: ldc #x // String addOne + x: ldc #x // String (I)I + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: iload_0 + x: iconst_1 + x: iadd + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 4 0 a I + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +} +InnerClasses: + public static #x= #x of #x; // Stub=class com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub of class com/android/hoststubgen/test/tinyframework/IPretendingAidl + public static #x= #x of #x; // Proxy=class com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub$Proxy of class com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub +SourceFile: "IPretendingAidl.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +NestHost: class com/android/hoststubgen/test/tinyframework/IPretendingAidl +## Class: com/android/hoststubgen/test/tinyframework/IPretendingAidl.class + Compiled from "IPretendingAidl.java" +public interface com.android.hoststubgen.test.tinyframework.IPretendingAidl + minor version: 0 + major version: 65 + flags: (0x0601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT + this_class: #x // com/android/hoststubgen/test/tinyframework/IPretendingAidl + super_class: #x // java/lang/Object + interfaces: 0, fields: 0, methods: 1, attributes: 4 + private static {}; + descriptor: ()V + flags: (0x000a) ACC_PRIVATE, ACC_STATIC + Code: + stack=2, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/IPretendingAidl + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V + x: return +} +InnerClasses: + public static #x= #x of #x; // Stub=class com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub of class com/android/hoststubgen/test/tinyframework/IPretendingAidl + public static #x= #x of #x; // Proxy=class com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub$Proxy of class com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub +SourceFile: "IPretendingAidl.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +NestMembers: + com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub + com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub$Proxy +## Class: com/android/hoststubgen/test/tinyframework/R$Nested.class + Compiled from "R.java" +public class com.android.hoststubgen.test.tinyframework.R$Nested + minor version: 0 + major version: 65 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/R$Nested + super_class: #x // java/lang/Object + interfaces: 0, fields: 1, methods: 2, attributes: 4 + public static int[] ARRAY; + descriptor: [I + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + public com.android.hoststubgen.test.tinyframework.R$Nested(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/R$Nested + x: ldc #x // String <init> + x: ldc #x // String ()V + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 5 0 this Lcom/android/hoststubgen/test/tinyframework/R$Nested; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + static {}; + descriptor: ()V + flags: (0x0008) ACC_STATIC + Code: + stack=4, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/R$Nested + x: ldc #x // String <clinit> + x: ldc #x // String ()V + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: ldc #x // class com/android/hoststubgen/test/tinyframework/R$Nested + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V + x: iconst_1 + x: newarray int + x: dup + x: iconst_0 + x: iconst_1 + x: iastore + x: putstatic #x // Field ARRAY:[I + x: return + LineNumberTable: + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +} +InnerClasses: + public static #x= #x of #x; // Nested=class com/android/hoststubgen/test/tinyframework/R$Nested of class com/android/hoststubgen/test/tinyframework/R +SourceFile: "R.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +NestHost: class com/android/hoststubgen/test/tinyframework/R +## Class: com/android/hoststubgen/test/tinyframework/R.class + Compiled from "R.java" +public class com.android.hoststubgen.test.tinyframework.R + minor version: 0 + major version: 65 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/R + super_class: #x // java/lang/Object + interfaces: 0, fields: 0, methods: 2, attributes: 4 + private static {}; + descriptor: ()V + flags: (0x000a) ACC_PRIVATE, ACC_STATIC + Code: + stack=2, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/R + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V + x: return + + public com.android.hoststubgen.test.tinyframework.R(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/R + x: ldc #x // String <init> + x: ldc #x // String ()V + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 5 0 this Lcom/android/hoststubgen/test/tinyframework/R; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +} +InnerClasses: + public static #x= #x of #x; // Nested=class com/android/hoststubgen/test/tinyframework/R$Nested of class com/android/hoststubgen/test/tinyframework/R +SourceFile: "R.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +NestMembers: + com/android/hoststubgen/test/tinyframework/R$Nested +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotations.class + Compiled from "TinyFrameworkAnnotations.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkAnnotations + minor version: 0 + major version: 65 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotations + super_class: #x // java/lang/Object + interfaces: 0, fields: 1, methods: 7, attributes: 3 + public int keep; + descriptor: I + flags: (0x0001) ACC_PUBLIC + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestKeep + + private static {}; + descriptor: ()V + flags: (0x000a) ACC_PRIVATE, ACC_STATIC + Code: + stack=2, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotations + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotations + x: ldc #x // String com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook.onClassLoaded + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V + x: return + + public com.android.hoststubgen.test.tinyframework.TinyFrameworkAnnotations(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotations + x: ldc #x // String <init> + x: ldc #x // String ()V + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: aload_0 + x: iconst_1 + x: putfield #x // Field keep:I + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 10 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotations; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestKeep + + public int addOne(int); + descriptor: (I)I + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=2, args_size=2 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotations + x: ldc #x // String addOne + x: ldc #x // String (I)I + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: iload_1 + x: iconst_1 + x: iadd + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 4 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotations; + 11 4 1 value I + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestKeep + + public int addTwo(int); + descriptor: (I)I + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=2, args_size=2 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotations + x: ldc #x // String addTwo + x: ldc #x // String (I)I + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: iload_1 + x: iconst_2 + x: iadd + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 4 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotations; + 11 4 1 value I + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsSubstitute + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + public static int nativeAddThree(int); + descriptor: (I)I + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotations + x: ldc #x // String nativeAddThree + x: ldc #x // String (I)I + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: iload_0 + x: iconst_3 + x: iadd + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 4 0 value I + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsSubstitute + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + public java.lang.String unsupportedMethod(); + descriptor: ()Ljava/lang/String; + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotations + x: ldc #x // String unsupportedMethod + x: ldc #x // String ()Ljava/lang/String; + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onThrowMethodCalled:()V + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Unreachable + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsThrow + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestThrow + + public int toBeIgnored(); + descriptor: ()I + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotations + x: ldc #x // String toBeIgnored + x: ldc #x // String ()I + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: iconst_0 + x: ireturn + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsIgnore + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestIgnore +} +SourceFile: "TinyFrameworkAnnotations.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestKeep + x: #x(#x=s#x) + android.hosttest.annotation.HostSideTestClassLoadHook( + value="com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook.onClassLoaded" + ) +## 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: 65 + 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<*>;>; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + private com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook(); + descriptor: ()V + flags: (0x0002) ACC_PRIVATE + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkClassLoadHook + x: ldc #x // String <init> + x: ldc #x // String ()V + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassLoadHook; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + public static void onClassLoaded(java.lang.Class<?>); + descriptor: (Ljava/lang/Class;)V + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkClassLoadHook + x: ldc #x // String onClassLoaded + x: ldc #x // String (Ljava/lang/Class;)V + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: getstatic #x // Field sLoadedClasses:Ljava/util/Set; + x: aload_0 + x: invokeinterface #x, 2 // InterfaceMethod java/util/Set.add:(Ljava/lang/Object;)Z + x: pop + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 11 0 clazz Ljava/lang/Class; + LocalVariableTypeTable: + Start Length Slot Name Signature + 11 11 0 clazz Ljava/lang/Class<*>; + Signature: #x // (Ljava/lang/Class<*>;)V + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + static {}; + descriptor: ()V + flags: (0x0008) ACC_STATIC + Code: + stack=4, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkClassLoadHook + x: ldc #x // String <clinit> + x: ldc #x // String ()V + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkClassLoadHook + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V + x: new #x // class java/util/HashSet + x: dup + x: invokespecial #x // Method java/util/HashSet."<init>":()V + x: putstatic #x // Field sLoadedClasses:Ljava/util/Set; + x: return + LineNumberTable: + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +} +SourceFile: "TinyFrameworkClassLoadHook.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestWholeClassKeep +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWideAnnotations.class + Compiled from "TinyFrameworkClassWideAnnotations.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassWideAnnotations + minor version: 0 + major version: 65 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWideAnnotations + super_class: #x // java/lang/Object + interfaces: 0, fields: 1, methods: 5, attributes: 3 + public int keep; + descriptor: I + flags: (0x0001) ACC_PUBLIC + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + private static {}; + descriptor: ()V + flags: (0x000a) ACC_PRIVATE, ACC_STATIC + Code: + stack=2, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWideAnnotations + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V + x: return + + public com.android.hoststubgen.test.tinyframework.TinyFrameworkClassWideAnnotations(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWideAnnotations + x: ldc #x // String <init> + x: ldc #x // String ()V + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: aload_0 + x: iconst_1 + x: putfield #x // Field keep:I + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 10 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassWideAnnotations; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + public int addOne(int); + descriptor: (I)I + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=2, args_size=2 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWideAnnotations + x: ldc #x // String addOne + x: ldc #x // String (I)I + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: iload_1 + x: iconst_1 + x: iadd + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 4 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassWideAnnotations; + 11 4 1 value I + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + public int addTwo(int); + descriptor: (I)I + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=2, args_size=2 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWideAnnotations + x: ldc #x // String addTwo + x: ldc #x // String (I)I + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: iload_1 + x: iconst_2 + x: iadd + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 4 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassWideAnnotations; + 11 4 1 value I + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsSubstitute + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + public java.lang.String unsupportedMethod(); + descriptor: ()Ljava/lang/String; + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWideAnnotations + x: ldc #x // String unsupportedMethod + x: ldc #x // String ()Ljava/lang/String; + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onThrowMethodCalled:()V + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Unreachable + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsThrow + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestThrow +} +SourceFile: "TinyFrameworkClassWideAnnotations.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestWholeClassKeep +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializerDefault.class + Compiled from "TinyFrameworkClassWithInitializerDefault.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassWithInitializerDefault + minor version: 0 + major version: 65 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializerDefault + super_class: #x // java/lang/Object + interfaces: 0, fields: 2, methods: 0, attributes: 3 + public static boolean sInitialized; + descriptor: Z + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestKeep + + public static java.lang.Object sObject; + descriptor: Ljava/lang/Object; + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestKeep + +} +SourceFile: "TinyFrameworkClassWithInitializerDefault.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestKeep +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializerStub.class + Compiled from "TinyFrameworkClassWithInitializerStub.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassWithInitializerStub + minor version: 0 + major version: 65 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializerStub + super_class: #x // java/lang/Object + interfaces: 0, fields: 2, methods: 1, attributes: 3 + public static boolean sInitialized; + descriptor: Z + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestKeep + + public static java.lang.Object sObject; + descriptor: Ljava/lang/Object; + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestKeep + + static {}; + descriptor: ()V + flags: (0x0008) ACC_STATIC + Code: + stack=4, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializerStub + x: ldc #x // String <clinit> + x: ldc #x // String ()V + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializerStub + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializerStub + x: ldc #x // String com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook.onClassLoaded + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V + x: iconst_1 + x: putstatic #x // Field sInitialized:Z + x: new #x // class java/lang/Object + x: dup + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: putstatic #x // Field sObject:Ljava/lang/Object; + x: return + LineNumberTable: + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +} +SourceFile: "TinyFrameworkClassWithInitializerStub.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +RuntimeInvisibleAnnotations: + x: #x(#x=s#x) + android.hosttest.annotation.HostSideTestClassLoadHook( + value="com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook.onClassLoaded" + ) + x: #x() + android.hosttest.annotation.HostSideTestKeep + x: #x() + android.hosttest.annotation.HostSideTestStaticInitializerKeep +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex.class + Compiled from "TinyFrameworkEnumComplex.java" +public final class com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex extends java.lang.Enum<com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex> + minor version: 0 + major version: 65 + flags: (0x4031) ACC_PUBLIC, ACC_FINAL, ACC_SUPER, ACC_ENUM + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex + super_class: #x // java/lang/Enum + interfaces: 0, fields: 6, methods: 7, attributes: 4 + public static final com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex RED; + descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + flags: (0x4019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestKeep + + public static final com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex GREEN; + descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + flags: (0x4019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestKeep + + public static final com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex BLUE; + descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + flags: (0x4019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestKeep + + private final java.lang.String mLongName; + descriptor: Ljava/lang/String; + flags: (0x0012) ACC_PRIVATE, ACC_FINAL + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestKeep + + private final java.lang.String mShortName; + descriptor: Ljava/lang/String; + flags: (0x0012) ACC_PRIVATE, ACC_FINAL + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestKeep + + private static final com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex[] $VALUES; + descriptor: [Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + flags: (0x101a) ACC_PRIVATE, ACC_STATIC, ACC_FINAL, ACC_SYNTHETIC + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + public static com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex[] values(); + descriptor: ()[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=4, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex + x: ldc #x // String values + x: ldc #x // String ()[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: getstatic #x // Field $VALUES:[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + x: invokevirtual #x // Method "[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex;".clone:()Ljava/lang/Object; + x: checkcast #x // class "[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex;" + x: areturn + LineNumberTable: + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + public static com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex valueOf(java.lang.String); + descriptor: (Ljava/lang/String;)Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex + x: ldc #x // String valueOf + x: ldc #x // String (Ljava/lang/String;)Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex + x: aload_0 + x: invokestatic #x // Method java/lang/Enum.valueOf:(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum; + x: checkcast #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex + x: areturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 10 0 name Ljava/lang/String; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + MethodParameters: + Name Flags + <no name> mandated + + private com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex(java.lang.String, java.lang.String); + descriptor: (Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;)V + flags: (0x0002) ACC_PRIVATE + Code: + stack=4, locals=5, args_size=5 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex + x: ldc #x // String <init> + x: ldc #x // String (Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;)V + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: aload_0 + x: aload_1 + x: iload_2 + x: invokespecial #x // Method java/lang/Enum."<init>":(Ljava/lang/String;I)V + x: aload_0 + x: aload_3 + x: putfield #x // Field mLongName:Ljava/lang/String; + x: aload_0 + x: aload 4 + x: putfield #x // Field mShortName:Ljava/lang/String; + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 18 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + 11 18 3 longName Ljava/lang/String; + 11 18 4 shortName Ljava/lang/String; + Signature: #x // (Ljava/lang/String;Ljava/lang/String;)V + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestKeep + MethodParameters: + Name Flags + <no name> synthetic + <no name> synthetic + <no name> + <no name> + + public java.lang.String getLongName(); + descriptor: ()Ljava/lang/String; + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex + x: ldc #x // String getLongName + x: ldc #x // String ()Ljava/lang/String; + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: aload_0 + x: getfield #x // Field mLongName:Ljava/lang/String; + x: areturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestKeep + + public java.lang.String getShortName(); + descriptor: ()Ljava/lang/String; + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex + x: ldc #x // String getShortName + x: ldc #x // String ()Ljava/lang/String; + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: aload_0 + x: getfield #x // Field mShortName:Ljava/lang/String; + x: areturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestKeep + + private static com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex[] $values(); + descriptor: ()[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC + Code: + stack=4, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex + x: ldc #x // String $values + x: ldc #x // String ()[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: iconst_3 + x: anewarray #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex + x: dup + x: iconst_0 + x: getstatic #x // Field RED:Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + x: aastore + x: dup + x: iconst_1 + x: getstatic #x // Field GREEN:Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + x: aastore + x: dup + x: iconst_2 + x: getstatic #x // Field BLUE:Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + x: aastore + x: areturn + LineNumberTable: + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + static {}; + descriptor: ()V + flags: (0x0008) ACC_STATIC + Code: + stack=6, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex + x: ldc #x // String <clinit> + x: ldc #x // String ()V + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V + x: new #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex + x: dup + x: ldc #x // String RED + x: iconst_0 + x: ldc #x // String Red + x: ldc #x // String R + x: invokespecial #x // Method "<init>":(Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;)V + x: putstatic #x // Field RED:Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + x: new #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex + x: dup + x: ldc #x // String GREEN + x: iconst_1 + x: ldc #x // String Green + x: ldc #x // String G + x: invokespecial #x // Method "<init>":(Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;)V + x: putstatic #x // Field GREEN:Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + x: new #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex + x: dup + x: ldc #x // String BLUE + x: iconst_2 + x: ldc #x // String Blue + x: ldc #x // String B + x: invokespecial #x // Method "<init>":(Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;)V + x: putstatic #x // Field BLUE:Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + x: invokestatic #x // Method $values:()[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + x: putstatic #x // Field $VALUES:[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex; + x: return + LineNumberTable: + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +} +Signature: #x // Ljava/lang/Enum<Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex;>; +SourceFile: "TinyFrameworkEnumComplex.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestKeep +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple.class + Compiled from "TinyFrameworkEnumSimple.java" +public final class com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple extends java.lang.Enum<com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple> + minor version: 0 + major version: 65 + flags: (0x4031) ACC_PUBLIC, ACC_FINAL, ACC_SUPER, ACC_ENUM + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple + super_class: #x // java/lang/Enum + interfaces: 0, fields: 3, methods: 5, attributes: 4 + public static final com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple CAT; + descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple; + flags: (0x4019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestKeep + + public static final com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple DOG; + descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple; + flags: (0x4019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestKeep + + private static final com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple[] $VALUES; + descriptor: [Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple; + flags: (0x101a) ACC_PRIVATE, ACC_STATIC, ACC_FINAL, ACC_SYNTHETIC + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + public static com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple[] values(); + descriptor: ()[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple; + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=4, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple + x: ldc #x // String values + x: ldc #x // String ()[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple; + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: getstatic #x // Field $VALUES:[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple; + x: invokevirtual #x // Method "[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple;".clone:()Ljava/lang/Object; + x: checkcast #x // class "[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple;" + x: areturn + LineNumberTable: + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + public static com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple valueOf(java.lang.String); + descriptor: (Ljava/lang/String;)Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple; + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple + x: ldc #x // String valueOf + x: ldc #x // String (Ljava/lang/String;)Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple; + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple + x: aload_0 + x: invokestatic #x // Method java/lang/Enum.valueOf:(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum; + x: checkcast #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple + x: areturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 10 0 name Ljava/lang/String; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + MethodParameters: + Name Flags + <no name> mandated + + private com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple(); + descriptor: (Ljava/lang/String;I)V + flags: (0x0002) ACC_PRIVATE + Code: + stack=4, locals=3, args_size=3 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple + x: ldc #x // String <init> + x: ldc #x // String (Ljava/lang/String;I)V + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: aload_0 + x: aload_1 + x: iload_2 + x: invokespecial #x // Method java/lang/Enum."<init>":(Ljava/lang/String;I)V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 7 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple; + Signature: #x // ()V + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + MethodParameters: + Name Flags + <no name> synthetic + <no name> synthetic + + private static com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple[] $values(); + descriptor: ()[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple; + flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC + Code: + stack=4, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple + x: ldc #x // String $values + x: ldc #x // String ()[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple; + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: iconst_2 + x: anewarray #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple + x: dup + x: iconst_0 + x: getstatic #x // Field CAT:Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple; + x: aastore + x: dup + x: iconst_1 + x: getstatic #x // Field DOG:Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple; + x: aastore + x: areturn + LineNumberTable: + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + static {}; + descriptor: ()V + flags: (0x0008) ACC_STATIC + Code: + stack=4, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple + x: ldc #x // String <clinit> + x: ldc #x // String ()V + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V + x: new #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple + x: dup + x: ldc #x // String CAT + x: iconst_0 + x: invokespecial #x // Method "<init>":(Ljava/lang/String;I)V + x: putstatic #x // Field CAT:Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple; + x: new #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple + x: dup + x: ldc #x // String DOG + x: iconst_1 + x: invokespecial #x // Method "<init>":(Ljava/lang/String;I)V + x: putstatic #x // Field DOG:Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple; + x: invokestatic #x // Method $values:()[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple; + x: putstatic #x // Field $VALUES:[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple; + x: return + LineNumberTable: + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +} +Signature: #x // Ljava/lang/Enum<Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple;>; +SourceFile: "TinyFrameworkEnumSimple.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestKeep +## 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: 65 + 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: 3, attributes: 3 + private static {}; + descriptor: ()V + flags: (0x000a) ACC_PRIVATE, ACC_STATIC + Code: + stack=2, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkExceptionTester + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V + x: return + + public com.android.hoststubgen.test.tinyframework.TinyFrameworkExceptionTester(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkExceptionTester + x: ldc #x // String <init> + x: ldc #x // String ()V + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkExceptionTester; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + public static int testException(); + descriptor: ()I + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=4, locals=1, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkExceptionTester + x: ldc #x // String testException + x: ldc #x // String ()I + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: new #x // class java/lang/IllegalStateException + x: dup + x: ldc #x // String Inner exception + x: invokespecial #x // Method java/lang/IllegalStateException."<init>":(Ljava/lang/String;)V + x: athrow + x: astore_0 + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Outer exception + x: aload_0 + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;Ljava/lang/Throwable;)V + x: athrow + Exception table: + from to target type + 11 21 21 Class java/lang/Exception + StackMapTable: number_of_entries = 1 + frame_type = 85 /* same_locals_1_stack_item */ + stack = [ class java/lang/Exception ] + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 22 11 0 e Ljava/lang/Exception; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +} +SourceFile: "TinyFrameworkExceptionTester.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestWholeClassKeep +## 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: 65 + 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: 15, attributes: 2 + public int stub; + descriptor: I + flags: (0x0001) ACC_PUBLIC + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + private static {}; + descriptor: ()V + flags: (0x000a) ACC_PRIVATE, ACC_STATIC + Code: + stack=2, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy + x: ldc #x // String com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook.onClassLoaded + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V + x: return + + public com.android.hoststubgen.test.tinyframework.TinyFrameworkForTextPolicy(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy + x: ldc #x // String <init> + x: ldc #x // String ()V + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: aload_0 + x: iconst_1 + x: putfield #x // Field stub:I + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 10 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + public int addOne(int); + descriptor: (I)I + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=2, args_size=2 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy + x: ldc #x // String addOne + x: ldc #x // String (I)I + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: iload_1 + x: iconst_1 + x: iadd + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 4 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy; + 11 4 1 value I + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + public java.lang.String toBeIgnoredObj(); + descriptor: ()Ljava/lang/String; + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy + x: ldc #x // String toBeIgnoredObj + x: ldc #x // String ()Ljava/lang/String; + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: aconst_null + x: areturn + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsIgnore + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + public void toBeIgnoredV(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy + x: ldc #x // String toBeIgnoredV + x: ldc #x // String ()V + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: return + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsIgnore + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + public boolean toBeIgnoredZ(); + descriptor: ()Z + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy + x: ldc #x // String toBeIgnoredZ + x: ldc #x // String ()Z + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: iconst_0 + x: ireturn + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsIgnore + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + public byte toBeIgnoredB(); + descriptor: ()B + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy + x: ldc #x // String toBeIgnoredB + x: ldc #x // String ()B + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: iconst_0 + x: ireturn + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsIgnore + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + public char toBeIgnoredC(); + descriptor: ()C + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy + x: ldc #x // String toBeIgnoredC + x: ldc #x // String ()C + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: iconst_0 + x: ireturn + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsIgnore + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + public short toBeIgnoredS(); + descriptor: ()S + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy + x: ldc #x // String toBeIgnoredS + x: ldc #x // String ()S + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: iconst_0 + x: ireturn + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsIgnore + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + public int toBeIgnoredI(); + descriptor: ()I + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy + x: ldc #x // String toBeIgnoredI + x: ldc #x // String ()I + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: iconst_0 + x: ireturn + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsIgnore + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + public float toBeIgnoredF(); + descriptor: ()F + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy + x: ldc #x // String toBeIgnoredF + x: ldc #x // String ()F + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: fconst_0 + x: freturn + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsIgnore + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + public double toBeIgnoredD(); + descriptor: ()D + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy + x: ldc #x // String toBeIgnoredD + x: ldc #x // String ()D + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: dconst_0 + x: dreturn + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsIgnore + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + public int addTwo(int); + descriptor: (I)I + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=2, args_size=2 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy + x: ldc #x // String addTwo + x: ldc #x // String (I)I + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: iload_1 + x: iconst_2 + x: iadd + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 4 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy; + 11 4 1 value I + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsSubstitute + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + public static int nativeAddThree(int); + descriptor: (I)I + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy + x: ldc #x // String nativeAddThree + x: ldc #x // String (I)I + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: iload_0 + x: iconst_3 + x: iadd + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 4 0 value I + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsSubstitute + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + public java.lang.String unsupportedMethod(); + descriptor: ()Ljava/lang/String; + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy + x: ldc #x // String unsupportedMethod + x: ldc #x // String ()Ljava/lang/String; + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onThrowMethodCalled:()V + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Unreachable + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsThrow + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +} +SourceFile: "TinyFrameworkForTextPolicy.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested.class + Compiled from "TinyFrameworkLambdas.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkLambdas$Nested + minor version: 0 + major version: 65 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested + super_class: #x // java/lang/Object + interfaces: 0, fields: 2, methods: 8, attributes: 6 + 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;>; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestKeep + + 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;>; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestKeep + + public com.android.hoststubgen.test.tinyframework.TinyFrameworkLambdas$Nested(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested + x: ldc #x // String <init> + x: ldc #x // String ()V + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: aload_0 + x: invokedynamic #x, 0 // InvokeDynamic #x:get:()Ljava/util/function/Supplier; + x: putfield #x // Field mSupplier:Ljava/util/function/Supplier; + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 14 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestKeep + + public java.util.function.Supplier<java.lang.Integer> getSupplier(); + descriptor: ()Ljava/util/function/Supplier; + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested + x: ldc #x // String getSupplier + x: ldc #x // String ()Ljava/util/function/Supplier; + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: invokedynamic #x, 0 // InvokeDynamic #x:get:()Ljava/util/function/Supplier; + x: areturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 6 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested; + Signature: #x // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestKeep + + public static java.util.function.Supplier<java.lang.Integer> getSupplier_static(); + descriptor: ()Ljava/util/function/Supplier; + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=4, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested + x: ldc #x // String getSupplier_static + x: ldc #x // String ()Ljava/util/function/Supplier; + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: invokedynamic #x, 0 // InvokeDynamic #x:get:()Ljava/util/function/Supplier; + x: areturn + LineNumberTable: + Signature: #x // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestKeep + + private static java.lang.Integer lambda$getSupplier_static$3(); + descriptor: ()Ljava/lang/Integer; + flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC + Code: + stack=4, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested + x: ldc #x // String lambda$getSupplier_static$3 + x: ldc #x // String ()Ljava/lang/Integer; + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: bipush 8 + x: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; + x: areturn + LineNumberTable: + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + private static java.lang.Integer lambda$getSupplier$2(); + descriptor: ()Ljava/lang/Integer; + flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC + Code: + stack=4, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested + x: ldc #x // String lambda$getSupplier$2 + x: ldc #x // String ()Ljava/lang/Integer; + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: bipush 7 + x: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; + x: areturn + LineNumberTable: + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + private static java.lang.Integer lambda$static$1(); + descriptor: ()Ljava/lang/Integer; + flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC + Code: + stack=4, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested + x: ldc #x // String lambda$static$1 + x: ldc #x // String ()Ljava/lang/Integer; + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: bipush 6 + x: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; + x: areturn + LineNumberTable: + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + private static java.lang.Integer lambda$new$0(); + descriptor: ()Ljava/lang/Integer; + flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC + Code: + stack=4, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested + x: ldc #x // String lambda$new$0 + x: ldc #x // String ()Ljava/lang/Integer; + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: iconst_5 + x: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; + x: areturn + LineNumberTable: + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + static {}; + descriptor: ()V + flags: (0x0008) ACC_STATIC + Code: + stack=4, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested + x: ldc #x // String <clinit> + x: ldc #x // String ()V + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V + x: invokedynamic #x, 0 // InvokeDynamic #x:get:()Ljava/util/function/Supplier; + x: putstatic #x // Field sSupplier:Ljava/util/function/Supplier; + x: return + LineNumberTable: + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +} +InnerClasses: + public static #x= #x of #x; // Nested=class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested of class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas + public static final #x= #x of #x; // Lookup=class java/lang/invoke/MethodHandles$Lookup of class java/lang/invoke/MethodHandles +SourceFile: "TinyFrameworkLambdas.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestKeep + x: #x() + android.hosttest.annotation.HostSideTestStaticInitializerKeep +BootstrapMethods: + x: #x REF_invokeStatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite; + Method arguments: + #x ()Ljava/lang/Object; + #x REF_invokeStatic com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested.lambda$new$0:()Ljava/lang/Integer; + #x ()Ljava/lang/Integer; + x: #x REF_invokeStatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite; + Method arguments: + #x ()Ljava/lang/Object; + #x REF_invokeStatic com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested.lambda$getSupplier$2:()Ljava/lang/Integer; + #x ()Ljava/lang/Integer; + x: #x REF_invokeStatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite; + Method arguments: + #x ()Ljava/lang/Object; + #x REF_invokeStatic com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested.lambda$getSupplier_static$3:()Ljava/lang/Integer; + #x ()Ljava/lang/Integer; + x: #x REF_invokeStatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite; + Method arguments: + #x ()Ljava/lang/Object; + #x REF_invokeStatic com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested.lambda$static$1:()Ljava/lang/Integer; + #x ()Ljava/lang/Integer; +NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas.class + Compiled from "TinyFrameworkLambdas.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkLambdas + minor version: 0 + major version: 65 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas + super_class: #x // java/lang/Object + interfaces: 0, fields: 2, methods: 8, attributes: 6 + 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;>; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestKeep + + 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;>; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestKeep + + public com.android.hoststubgen.test.tinyframework.TinyFrameworkLambdas(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas + x: ldc #x // String <init> + x: ldc #x // String ()V + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: aload_0 + x: invokedynamic #x, 0 // InvokeDynamic #x:get:()Ljava/util/function/Supplier; + x: putfield #x // Field mSupplier:Ljava/util/function/Supplier; + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 14 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestKeep + + public java.util.function.Supplier<java.lang.Integer> getSupplier(); + descriptor: ()Ljava/util/function/Supplier; + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas + x: ldc #x // String getSupplier + x: ldc #x // String ()Ljava/util/function/Supplier; + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: invokedynamic #x, 0 // InvokeDynamic #x:get:()Ljava/util/function/Supplier; + x: areturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 6 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas; + Signature: #x // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestKeep + + public static java.util.function.Supplier<java.lang.Integer> getSupplier_static(); + descriptor: ()Ljava/util/function/Supplier; + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=4, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas + x: ldc #x // String getSupplier_static + x: ldc #x // String ()Ljava/util/function/Supplier; + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: invokedynamic #x, 0 // InvokeDynamic #x:get:()Ljava/util/function/Supplier; + x: areturn + LineNumberTable: + Signature: #x // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestKeep + + private static java.lang.Integer lambda$getSupplier_static$3(); + descriptor: ()Ljava/lang/Integer; + flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC + Code: + stack=4, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas + x: ldc #x // String lambda$getSupplier_static$3 + x: ldc #x // String ()Ljava/lang/Integer; + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: iconst_4 + x: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; + x: areturn + LineNumberTable: + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + private static java.lang.Integer lambda$getSupplier$2(); + descriptor: ()Ljava/lang/Integer; + flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC + Code: + stack=4, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas + x: ldc #x // String lambda$getSupplier$2 + x: ldc #x // String ()Ljava/lang/Integer; + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: iconst_3 + x: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; + x: areturn + LineNumberTable: + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + private static java.lang.Integer lambda$static$1(); + descriptor: ()Ljava/lang/Integer; + flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC + Code: + stack=4, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas + x: ldc #x // String lambda$static$1 + x: ldc #x // String ()Ljava/lang/Integer; + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: iconst_2 + x: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; + x: areturn + LineNumberTable: + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + private static java.lang.Integer lambda$new$0(); + descriptor: ()Ljava/lang/Integer; + flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC + Code: + stack=4, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas + x: ldc #x // String lambda$new$0 + x: ldc #x // String ()Ljava/lang/Integer; + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: iconst_1 + x: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; + x: areturn + LineNumberTable: + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + static {}; + descriptor: ()V + flags: (0x0008) ACC_STATIC + Code: + stack=4, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas + x: ldc #x // String <clinit> + x: ldc #x // String ()V + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V + x: invokedynamic #x, 0 // InvokeDynamic #x:get:()Ljava/util/function/Supplier; + x: putstatic #x // Field sSupplier:Ljava/util/function/Supplier; + x: return + LineNumberTable: + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +} +InnerClasses: + public static #x= #x of #x; // Nested=class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested of class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas + public static final #x= #x of #x; // Lookup=class java/lang/invoke/MethodHandles$Lookup of class java/lang/invoke/MethodHandles +SourceFile: "TinyFrameworkLambdas.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestKeep + x: #x() + android.hosttest.annotation.HostSideTestStaticInitializerKeep +BootstrapMethods: + x: #x REF_invokeStatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite; + Method arguments: + #x ()Ljava/lang/Object; + #x REF_invokeStatic com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas.lambda$new$0:()Ljava/lang/Integer; + #x ()Ljava/lang/Integer; + x: #x REF_invokeStatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite; + Method arguments: + #x ()Ljava/lang/Object; + #x REF_invokeStatic com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas.lambda$getSupplier$2:()Ljava/lang/Integer; + #x ()Ljava/lang/Integer; + x: #x REF_invokeStatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite; + Method arguments: + #x ()Ljava/lang/Object; + #x REF_invokeStatic com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas.lambda$getSupplier_static$3:()Ljava/lang/Integer; + #x ()Ljava/lang/Integer; + x: #x REF_invokeStatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite; + Method arguments: + #x ()Ljava/lang/Object; + #x REF_invokeStatic com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas.lambda$static$1:()Ljava/lang/Integer; + #x ()Ljava/lang/Integer; +NestMembers: + com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo.class + Compiled from "TinyFrameworkMethodCallReplace.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace$ReplaceTo + minor version: 0 + major version: 65 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo + super_class: #x // java/lang/Object + interfaces: 0, fields: 0, methods: 4, attributes: 4 + private static {}; + descriptor: ()V + flags: (0x000a) ACC_PRIVATE, ACC_STATIC + Code: + stack=2, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V + x: return + + public com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace$ReplaceTo(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo + x: ldc #x // String <init> + x: ldc #x // String ()V + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + public static void startThread(java.lang.Thread); + descriptor: (Ljava/lang/Thread;)V + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo + x: ldc #x // String startThread + x: ldc #x // String (Ljava/lang/Thread;)V + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: aload_0 + x: iconst_1 + x: invokevirtual #x // Method java/lang/Thread.setDaemon:(Z)V + x: aload_0 + x: invokevirtual #x // Method java/lang/Thread.start:()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 10 0 thread Ljava/lang/Thread; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + public static int add(int, int); + descriptor: (II)I + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=4, locals=2, args_size=2 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo + x: ldc #x // String add + x: ldc #x // String (II)I + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: iload_0 + x: iload_1 + x: iadd + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 4 0 a I + 11 4 1 b I + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +} +InnerClasses: + public static #x= #x of #x; // ReplaceTo=class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo of class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace +SourceFile: "TinyFrameworkMethodCallReplace.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace.class + Compiled from "TinyFrameworkMethodCallReplace.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace + minor version: 0 + major version: 65 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace + super_class: #x // java/lang/Object + interfaces: 0, fields: 0, methods: 5, attributes: 6 + private static {}; + descriptor: ()V + flags: (0x000a) ACC_PRIVATE, ACC_STATIC + Code: + stack=2, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V + x: return + + public com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace + x: ldc #x // String <init> + x: ldc #x // String ()V + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + public static boolean nonStaticMethodCallReplaceTester() throws java.lang.Exception; + descriptor: ()Z + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=4, locals=2, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace + x: ldc #x // String nonStaticMethodCallReplaceTester + x: ldc #x // String ()Z + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: new #x // class java/util/concurrent/atomic/AtomicBoolean + x: dup + x: iconst_0 + x: invokespecial #x // Method java/util/concurrent/atomic/AtomicBoolean."<init>":(Z)V + x: astore_0 + x: new #x // class java/lang/Thread + x: dup + x: aload_0 + x: invokedynamic #x, 0 // InvokeDynamic #x:run:(Ljava/util/concurrent/atomic/AtomicBoolean;)Ljava/lang/Runnable; + x: invokespecial #x // Method java/lang/Thread."<init>":(Ljava/lang/Runnable;)V + x: astore_1 + x: aload_1 + x: invokestatic #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo.startThread:(Ljava/lang/Thread;)V + x: aload_1 + x: invokevirtual #x // Method java/lang/Thread.join:()V + x: aload_0 + x: invokevirtual #x // Method java/util/concurrent/atomic/AtomicBoolean.get:()Z + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 20 27 0 ab Ljava/util/concurrent/atomic/AtomicBoolean; + 34 13 1 th Ljava/lang/Thread; + Exceptions: + throws java.lang.Exception + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + public static int staticMethodCallReplaceTester(); + descriptor: ()I + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=4, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace + x: ldc #x // String staticMethodCallReplaceTester + x: ldc #x // String ()I + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: iconst_1 + x: iconst_2 + x: invokestatic #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo.add:(II)I + x: ireturn + LineNumberTable: + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + private static void lambda$nonStaticMethodCallReplaceTester$0(java.util.concurrent.atomic.AtomicBoolean); + descriptor: (Ljava/util/concurrent/atomic/AtomicBoolean;)V + flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace + x: ldc #x // String lambda$nonStaticMethodCallReplaceTester$0 + x: ldc #x // String (Ljava/util/concurrent/atomic/AtomicBoolean;)V + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: aload_0 + x: invokestatic #x // Method java/lang/Thread.currentThread:()Ljava/lang/Thread; + x: invokevirtual #x // Method java/lang/Thread.isDaemon:()Z + x: invokevirtual #x // Method java/util/concurrent/atomic/AtomicBoolean.set:(Z)V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 11 0 ab Ljava/util/concurrent/atomic/AtomicBoolean; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +} +InnerClasses: + public static #x= #x of #x; // ReplaceTo=class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo of class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace + public static final #x= #x of #x; // Lookup=class java/lang/invoke/MethodHandles$Lookup of class java/lang/invoke/MethodHandles +SourceFile: "TinyFrameworkMethodCallReplace.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestWholeClassKeep +BootstrapMethods: + x: #x REF_invokeStatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite; + Method arguments: + #x ()V + #x REF_invokeStatic com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace.lambda$nonStaticMethodCallReplaceTester$0:(Ljava/util/concurrent/atomic/AtomicBoolean;)V + #x ()V +NestMembers: + com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo +## 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: 65 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNative + super_class: #x // java/lang/Object + interfaces: 0, fields: 1, methods: 15, attributes: 3 + int value; + descriptor: I + flags: (0x0000) + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + private static {}; + descriptor: ()V + flags: (0x000a) ACC_PRIVATE, ACC_STATIC + Code: + stack=2, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNative + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V + x: return + + public com.android.hoststubgen.test.tinyframework.TinyFrameworkNative(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNative + x: ldc #x // String <init> + x: ldc #x // String ()V + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + public static int nativeAddTwo(int); + descriptor: (I)I + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNative + x: ldc #x // String nativeAddTwo + x: ldc #x // String (I)I + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: iload_0 + x: invokestatic #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.nativeAddTwo:(I)I + x: ireturn + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsSubstitute + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestRedirect + + public static int nativeAddTwo_should_be_like_this(int); + descriptor: (I)I + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNative + x: ldc #x // String nativeAddTwo_should_be_like_this + x: ldc #x // String (I)I + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: iload_0 + x: invokestatic #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.nativeAddTwo:(I)I + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 5 0 arg I + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + public static long nativeLongPlus(long, long); + descriptor: (JJ)J + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=4, locals=4, args_size=2 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNative + x: ldc #x // String nativeLongPlus + x: ldc #x // String (JJ)J + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: lload_0 + x: lload_2 + x: invokestatic #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.nativeLongPlus:(JJ)J + x: lreturn + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsSubstitute + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestRedirect + + 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 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNative + x: ldc #x // String nativeLongPlus_should_be_like_this + x: ldc #x // String (JJ)J + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: lload_0 + x: lload_2 + x: invokestatic #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.nativeLongPlus:(JJ)J + x: lreturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 6 0 arg1 J + 11 6 2 arg2 J + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + public void setValue(int); + descriptor: (I)V + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=2, args_size=2 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNative + x: ldc #x // String setValue + x: ldc #x // String (I)V + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: aload_0 + x: iload_1 + x: putfield #x // Field value:I + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 6 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative; + 11 6 1 v I + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + public int nativeNonStaticAddToValue(int); + descriptor: (I)I + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=2, args_size=2 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNative + x: ldc #x // String nativeNonStaticAddToValue + x: ldc #x // String (I)I + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: aload_0 + x: iload_1 + x: invokestatic #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.nativeNonStaticAddToValue:(Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative;I)I + x: ireturn + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsSubstitute + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestRedirect + + public int nativeNonStaticAddToValue_should_be_like_this(int); + descriptor: (I)I + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=2, args_size=2 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNative + x: ldc #x // String nativeNonStaticAddToValue_should_be_like_this + x: ldc #x // String (I)I + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: aload_0 + x: iload_1 + x: invokestatic #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.nativeNonStaticAddToValue:(Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative;I)I + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 6 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative; + 11 6 1 arg I + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + public static void nativeStillNotSupported(); + descriptor: ()V + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=4, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNative + x: ldc #x // String nativeStillNotSupported + x: ldc #x // String ()V + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onThrowMethodCalled:()V + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String Unreachable + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsThrow + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestThrow + + public static native void nativeStillKeep(); + descriptor: ()V + flags: (0x0109) ACC_PUBLIC, ACC_STATIC, ACC_NATIVE + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + public static void nativeStillNotSupported_should_be_like_this(); + descriptor: ()V + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=4, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNative + x: ldc #x // String nativeStillNotSupported_should_be_like_this + x: ldc #x // String ()V + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: new #x // class java/lang/RuntimeException + x: dup + x: invokespecial #x // Method java/lang/RuntimeException."<init>":()V + x: athrow + LineNumberTable: + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + public static byte nativeBytePlus(byte, byte); + descriptor: (BB)B + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=4, locals=2, args_size=2 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNative + x: ldc #x // String nativeBytePlus + x: ldc #x // String (BB)B + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: iload_0 + x: iload_1 + x: invokestatic #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.nativeBytePlus:(BB)B + x: ireturn + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsSubstitute + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestRedirect + + public void notNativeRedirected(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNative + x: ldc #x // String notNativeRedirected + x: ldc #x // String ()V + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: aload_0 + x: invokestatic #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.notNativeRedirected:(Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative;)V + x: return + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsSubstitute + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestRedirect + + public static void notNativeStaticRedirected(); + descriptor: ()V + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=4, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNative + x: ldc #x // String notNativeStaticRedirected + x: ldc #x // String ()V + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: invokestatic #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.notNativeStaticRedirected:()V + x: return + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsSubstitute + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestRedirect +} +SourceFile: "TinyFrameworkNative.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestWholeClassKeep + x: #x(#x=s#x) + android.hosttest.annotation.HostSideTestRedirectionClass( + 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: 65 + 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: 8, attributes: 3 + private static {}; + descriptor: ()V + flags: (0x000a) ACC_PRIVATE, ACC_STATIC + Code: + stack=2, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V + x: return + + public com.android.hoststubgen.test.tinyframework.TinyFrameworkNative_host(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host + x: ldc #x // String <init> + x: ldc #x // String ()V + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + public static int nativeAddTwo(int); + descriptor: (I)I + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host + x: ldc #x // String nativeAddTwo + x: ldc #x // String (I)I + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: iload_0 + x: iconst_2 + x: iadd + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 4 0 arg I + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + public static long nativeLongPlus(long, long); + descriptor: (JJ)J + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=4, locals=4, args_size=2 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host + x: ldc #x // String nativeLongPlus + x: ldc #x // String (JJ)J + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: lload_0 + x: lload_2 + x: ladd + x: lreturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 4 0 arg1 J + 11 4 2 arg2 J + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + public static int nativeNonStaticAddToValue(com.android.hoststubgen.test.tinyframework.TinyFrameworkNative, int); + descriptor: (Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative;I)I + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=4, locals=2, args_size=2 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host + x: ldc #x // String nativeNonStaticAddToValue + x: ldc #x // String (Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative;I)I + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: aload_0 + x: getfield #x // Field com/android/hoststubgen/test/tinyframework/TinyFrameworkNative.value:I + x: iload_1 + x: iadd + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 7 0 source Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative; + 11 7 1 arg I + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + public static byte nativeBytePlus(byte, byte); + descriptor: (BB)B + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=4, locals=2, args_size=2 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host + x: ldc #x // String nativeBytePlus + x: ldc #x // String (BB)B + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: iload_0 + x: iload_1 + x: iadd + x: i2b + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 5 0 arg1 B + 11 5 1 arg2 B + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + public static void notNativeRedirected(com.android.hoststubgen.test.tinyframework.TinyFrameworkNative); + descriptor: (Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative;)V + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host + x: ldc #x // String notNativeRedirected + x: ldc #x // String (Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative;)V + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 1 0 source Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + public static void notNativeStaticRedirected(); + descriptor: ()V + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=4, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host + x: ldc #x // String notNativeStaticRedirected + x: ldc #x // String ()V + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: return + LineNumberTable: + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +} +SourceFile: "TinyFrameworkNative_host.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +RuntimeInvisibleAnnotations: + x: #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: 65 + flags: (0x0020) ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1 + super_class: #x // java/lang/Object + interfaces: 1, fields: 0, methods: 4, attributes: 6 + private static {}; + descriptor: ()V + flags: (0x000a) ACC_PRIVATE, ACC_STATIC + Code: + stack=2, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1 + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V + x: return + + 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=4, locals=2, args_size=2 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1 + x: ldc #x // String <init> + x: ldc #x // String (Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;)V + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1; + 11 5 1 this$0 Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + MethodParameters: + Name Flags + <no name> final mandated + + public java.lang.Integer get(); + descriptor: ()Ljava/lang/Integer; + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1 + x: ldc #x // String get + x: ldc #x // String ()Ljava/lang/Integer; + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: iconst_1 + x: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; + x: areturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + 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 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1 + x: ldc #x // String get + x: ldc #x // String ()Ljava/lang/Object; + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: aload_0 + x: invokevirtual #x // Method get:()Ljava/lang/Integer; + x: areturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +} +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: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +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: 65 + 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: 4, attributes: 6 + private static {}; + descriptor: ()V + flags: (0x000a) ACC_PRIVATE, ACC_STATIC + Code: + stack=2, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2 + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V + x: return + + com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$2(); + descriptor: ()V + flags: (0x0000) + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2 + x: ldc #x // String <init> + x: ldc #x // String ()V + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + public java.lang.Integer get(); + descriptor: ()Ljava/lang/Integer; + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2 + x: ldc #x // String get + x: ldc #x // String ()Ljava/lang/Integer; + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: iconst_2 + x: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; + x: areturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + 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 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2 + x: ldc #x // String get + x: ldc #x // String ()Ljava/lang/Object; + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: aload_0 + x: invokevirtual #x // Method get:()Ljava/lang/Integer; + x: areturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +} +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: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +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: 65 + flags: (0x0020) ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3 + super_class: #x // java/lang/Object + interfaces: 1, fields: 0, methods: 4, attributes: 6 + private static {}; + descriptor: ()V + flags: (0x000a) ACC_PRIVATE, ACC_STATIC + Code: + stack=2, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3 + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V + x: return + + 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=4, locals=2, args_size=2 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3 + x: ldc #x // String <init> + x: ldc #x // String (Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;)V + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3; + 11 5 1 this$0 Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + MethodParameters: + Name Flags + <no name> final mandated + + public java.lang.Integer get(); + descriptor: ()Ljava/lang/Integer; + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3 + x: ldc #x // String get + x: ldc #x // String ()Ljava/lang/Integer; + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: iconst_3 + x: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; + x: areturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + 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 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3 + x: ldc #x // String get + x: ldc #x // String ()Ljava/lang/Object; + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: aload_0 + x: invokevirtual #x // Method get:()Ljava/lang/Integer; + x: areturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +} +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: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +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: 65 + 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: 4, attributes: 6 + private static {}; + descriptor: ()V + flags: (0x000a) ACC_PRIVATE, ACC_STATIC + Code: + stack=2, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4 + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V + x: return + + com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$4(); + descriptor: ()V + flags: (0x0000) + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4 + x: ldc #x // String <init> + x: ldc #x // String ()V + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + public java.lang.Integer get(); + descriptor: ()Ljava/lang/Integer; + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4 + x: ldc #x // String get + x: ldc #x // String ()Ljava/lang/Integer; + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: iconst_4 + x: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; + x: areturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + 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 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4 + x: ldc #x // String get + x: ldc #x // String ()Ljava/lang/Object; + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: aload_0 + x: invokevirtual #x // Method get:()Ljava/lang/Integer; + x: areturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +} +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: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +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: 65 + 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: 2, attributes: 4 + public int value; + descriptor: I + flags: (0x0001) ACC_PUBLIC + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + private static {}; + descriptor: ()V + flags: (0x000a) ACC_PRIVATE, ACC_STATIC + Code: + stack=2, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V + x: return + + public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$BaseClass(int); + descriptor: (I)V + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=2, args_size=2 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass + x: ldc #x // String <init> + x: ldc #x // String (I)V + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: aload_0 + x: iload_1 + x: putfield #x // Field value:I + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 10 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass; + 11 10 1 x I + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +} +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: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +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: 65 + 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: 1, methods: 2, attributes: 4 + public int value; + descriptor: I + flags: (0x0001) ACC_PUBLIC + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + private static {}; + descriptor: ()V + flags: (0x000a) ACC_PRIVATE, ACC_STATIC + Code: + stack=2, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V + x: return + + 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=4, locals=2, args_size=2 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass + x: ldc #x // String <init> + x: ldc #x // String (Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;)V + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: aload_0 + x: iconst_5 + x: putfield #x // Field value:I + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 10 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass; + 11 10 1 this$0 Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + MethodParameters: + Name Flags + <no name> final mandated +} +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: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +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: 65 + 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: 4, attributes: 6 + private static {}; + descriptor: ()V + flags: (0x000a) ACC_PRIVATE, ACC_STATIC + Code: + stack=2, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1 + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V + x: return + + com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$StaticNestedClass$1(); + descriptor: ()V + flags: (0x0000) + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1 + x: ldc #x // String <init> + x: ldc #x // String ()V + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + public java.lang.Integer get(); + descriptor: ()Ljava/lang/Integer; + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1 + x: ldc #x // String get + x: ldc #x // String ()Ljava/lang/Integer; + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: bipush 7 + x: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; + x: areturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 6 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + 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 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1 + x: ldc #x // String get + x: ldc #x // String ()Ljava/lang/Object; + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: aload_0 + x: invokevirtual #x // Method get:()Ljava/lang/Integer; + x: areturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +} +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: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$Double$NestedClass.class + Compiled from "TinyFrameworkNestedClasses.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$StaticNestedClass$Double$NestedClass + minor version: 0 + major version: 65 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$Double$NestedClass + super_class: #x // java/lang/Object + interfaces: 0, fields: 1, methods: 2, attributes: 4 + public int value; + descriptor: I + flags: (0x0001) ACC_PUBLIC + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + private static {}; + descriptor: ()V + flags: (0x000a) ACC_PRIVATE, ACC_STATIC + Code: + stack=2, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$Double$NestedClass + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V + x: return + + public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$StaticNestedClass$Double$NestedClass(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$Double$NestedClass + x: ldc #x // String <init> + x: ldc #x // String ()V + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: aload_0 + x: bipush 8 + x: putfield #x // Field value:I + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 11 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$Double$NestedClass; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +} +InnerClasses: + public static #x= #x of #x; // StaticNestedClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses + public static #x= #x of #x; // Double$NestedClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$Double$NestedClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass +SourceFile: "TinyFrameworkNestedClasses.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +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: 65 + 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: 3, attributes: 4 + public int value; + descriptor: I + flags: (0x0001) ACC_PUBLIC + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + private static {}; + descriptor: ()V + flags: (0x000a) ACC_PRIVATE, ACC_STATIC + Code: + stack=2, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V + x: return + + public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$StaticNestedClass(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass + x: ldc #x // String <init> + x: ldc #x // String ()V + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: aload_0 + x: bipush 6 + x: putfield #x // Field value:I + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 11 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + public static java.util.function.Supplier<java.lang.Integer> getSupplier_static(); + descriptor: ()Ljava/util/function/Supplier; + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=4, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass + x: ldc #x // String getSupplier_static + x: ldc #x // String ()Ljava/util/function/Supplier; + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: new #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1 + x: dup + x: invokespecial #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1."<init>":()V + x: areturn + LineNumberTable: + Signature: #x // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +} +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 + public static #x= #x of #x; // Double$NestedClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$Double$NestedClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass +SourceFile: "TinyFrameworkNestedClasses.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +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: 65 + 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: 2, attributes: 4 + private static {}; + descriptor: ()V + flags: (0x000a) ACC_PRIVATE, ACC_STATIC + Code: + stack=2, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V + x: return + + public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$SubClass(int); + descriptor: (I)V + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=2, args_size=2 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass + x: ldc #x // String <init> + x: ldc #x // String (I)V + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: aload_0 + x: iload_1 + x: invokespecial #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass."<init>":(I)V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 6 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass; + 11 6 1 x I + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +} +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: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +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: 65 + 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;>; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + 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;>; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses + x: ldc #x // String <init> + x: ldc #x // String ()V + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: aload_0 + x: new #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1 + x: dup + x: aload_0 + x: invokespecial #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1."<init>":(Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;)V + x: putfield #x // Field mSupplier:Ljava/util/function/Supplier; + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 17 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + public java.util.function.Supplier<java.lang.Integer> getSupplier(); + descriptor: ()Ljava/util/function/Supplier; + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses + x: ldc #x // String getSupplier + x: ldc #x // String ()Ljava/util/function/Supplier; + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: new #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3 + x: dup + x: aload_0 + x: invokespecial #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3."<init>":(Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;)V + x: areturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 9 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses; + Signature: #x // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + public static java.util.function.Supplier<java.lang.Integer> getSupplier_static(); + descriptor: ()Ljava/util/function/Supplier; + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=4, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses + x: ldc #x // String getSupplier_static + x: ldc #x // String ()Ljava/util/function/Supplier; + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: new #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4 + x: dup + x: invokespecial #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4."<init>":()V + x: areturn + LineNumberTable: + Signature: #x // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + static {}; + descriptor: ()V + flags: (0x0008) ACC_STATIC + Code: + stack=4, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses + x: ldc #x // String <clinit> + x: ldc #x // String ()V + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V + x: new #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2 + x: dup + x: invokespecial #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2."<init>":()V + x: putstatic #x // Field sSupplier:Ljava/util/function/Supplier; + x: return + LineNumberTable: + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +} +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 + public static #x= #x of #x; // Double$NestedClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$Double$NestedClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass + #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1 +SourceFile: "TinyFrameworkNestedClasses.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestWholeClassKeep +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$Double$NestedClass + 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 +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkPackageRedirect.class + Compiled from "TinyFrameworkPackageRedirect.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkPackageRedirect + minor version: 0 + major version: 65 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkPackageRedirect + super_class: #x // java/lang/Object + interfaces: 0, fields: 0, methods: 3, attributes: 3 + private static {}; + descriptor: ()V + flags: (0x000a) ACC_PRIVATE, ACC_STATIC + Code: + stack=2, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkPackageRedirect + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V + x: return + + public com.android.hoststubgen.test.tinyframework.TinyFrameworkPackageRedirect(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkPackageRedirect + x: ldc #x // String <init> + x: ldc #x // String ()V + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkPackageRedirect; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + public static int foo(int); + descriptor: (I)I + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkPackageRedirect + x: ldc #x // String foo + x: ldc #x // String (I)I + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: new #x // class com/supported/UnsupportedClass + x: dup + x: iload_0 + x: invokespecial #x // Method com/supported/UnsupportedClass."<init>":(I)V + x: invokevirtual #x // Method com/supported/UnsupportedClass.getValue:()I + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 12 0 value I + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +} +SourceFile: "TinyFrameworkPackageRedirect.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestWholeClassKeep +## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkRenamedClassCaller.class + Compiled from "TinyFrameworkRenamedClassCaller.java" +public class com.android.hoststubgen.test.tinyframework.TinyFrameworkRenamedClassCaller + minor version: 0 + major version: 65 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkRenamedClassCaller + super_class: #x // java/lang/Object + interfaces: 0, fields: 0, methods: 3, attributes: 3 + private static {}; + descriptor: ()V + flags: (0x000a) ACC_PRIVATE, ACC_STATIC + Code: + stack=2, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkRenamedClassCaller + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V + x: return + + public com.android.hoststubgen.test.tinyframework.TinyFrameworkRenamedClassCaller(); + descriptor: ()V + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkRenamedClassCaller + x: ldc #x // String <init> + x: ldc #x // String ()V + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkRenamedClassCaller; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + public static int foo(int); + descriptor: (I)I + flags: (0x0009) ACC_PUBLIC, ACC_STATIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkRenamedClassCaller + x: ldc #x // String foo + x: ldc #x // String (I)I + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: new #x // class rename_prefix/com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed + x: dup + x: iload_0 + x: invokespecial #x // Method rename_prefix/com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed."<init>":(I)V + x: invokevirtual #x // Method rename_prefix/com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed.getValue:()I + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 12 0 value I + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +} +SourceFile: "TinyFrameworkRenamedClassCaller.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestWholeClassKeep +## Class: com/android/hoststubgen/test/tinyframework/packagetest/A.class + Compiled from "A.java" +public class com.android.hoststubgen.test.tinyframework.packagetest.A + minor version: 0 + major version: 65 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/packagetest/A + super_class: #x // java/lang/Object + interfaces: 0, fields: 0, methods: 1, attributes: 2 + private static {}; + descriptor: ()V + flags: (0x000a) ACC_PRIVATE, ACC_STATIC + Code: + stack=2, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/packagetest/A + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V + x: return +} +SourceFile: "A.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +## Class: com/android/hoststubgen/test/tinyframework/packagetest/sub/A.class + Compiled from "A.java" +public class com.android.hoststubgen.test.tinyframework.packagetest.sub.A + minor version: 0 + major version: 65 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/packagetest/sub/A + super_class: #x // java/lang/Object + interfaces: 0, fields: 0, methods: 1, attributes: 2 + private static {}; + descriptor: ()V + flags: (0x000a) ACC_PRIVATE, ACC_STATIC + Code: + stack=2, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/packagetest/sub/A + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V + x: return +} +SourceFile: "A.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +## Class: com/android/hoststubgen/test/tinyframework/subclasstest/C1.class + Compiled from "C1.java" +public class com.android.hoststubgen.test.tinyframework.subclasstest.C1 + minor version: 0 + major version: 65 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/C1 + super_class: #x // java/lang/Object + interfaces: 0, fields: 0, methods: 1, attributes: 2 + private static {}; + descriptor: ()V + flags: (0x000a) ACC_PRIVATE, ACC_STATIC + Code: + stack=2, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/subclasstest/C1 + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V + x: return +} +SourceFile: "C1.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +## Class: com/android/hoststubgen/test/tinyframework/subclasstest/C2.class + Compiled from "C2.java" +public class com.android.hoststubgen.test.tinyframework.subclasstest.C2 extends com.android.hoststubgen.test.tinyframework.subclasstest.C1 + minor version: 0 + major version: 65 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/C2 + super_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/C1 + interfaces: 0, fields: 0, methods: 1, attributes: 2 + private static {}; + descriptor: ()V + flags: (0x000a) ACC_PRIVATE, ACC_STATIC + Code: + stack=2, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/subclasstest/C2 + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V + x: return +} +SourceFile: "C2.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +## Class: com/android/hoststubgen/test/tinyframework/subclasstest/C3.class + Compiled from "C3.java" +public class com.android.hoststubgen.test.tinyframework.subclasstest.C3 extends com.android.hoststubgen.test.tinyframework.subclasstest.C2 + minor version: 0 + major version: 65 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/C3 + super_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/C2 + interfaces: 0, fields: 0, methods: 1, attributes: 2 + private static {}; + descriptor: ()V + flags: (0x000a) ACC_PRIVATE, ACC_STATIC + Code: + stack=2, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/subclasstest/C3 + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V + x: return +} +SourceFile: "C3.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +## Class: com/android/hoststubgen/test/tinyframework/subclasstest/CA.class + Compiled from "CA.java" +public class com.android.hoststubgen.test.tinyframework.subclasstest.CA + minor version: 0 + major version: 65 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/CA + super_class: #x // java/lang/Object + interfaces: 0, fields: 0, methods: 1, attributes: 2 + private static {}; + descriptor: ()V + flags: (0x000a) ACC_PRIVATE, ACC_STATIC + Code: + stack=2, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/subclasstest/CA + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V + x: return +} +SourceFile: "CA.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +## Class: com/android/hoststubgen/test/tinyframework/subclasstest/CB.class + Compiled from "CB.java" +public class com.android.hoststubgen.test.tinyframework.subclasstest.CB + minor version: 0 + major version: 65 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/CB + super_class: #x // java/lang/Object + interfaces: 0, fields: 0, methods: 1, attributes: 2 + private static {}; + descriptor: ()V + flags: (0x000a) ACC_PRIVATE, ACC_STATIC + Code: + stack=2, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/subclasstest/CB + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V + x: return +} +SourceFile: "CB.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +## Class: com/android/hoststubgen/test/tinyframework/subclasstest/Class_C1.class + Compiled from "Class_C1.java" +public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_C1 extends com.android.hoststubgen.test.tinyframework.subclasstest.C1 + minor version: 0 + major version: 65 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/Class_C1 + super_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/C1 + interfaces: 0, fields: 0, methods: 1, attributes: 2 + private static {}; + descriptor: ()V + flags: (0x000a) ACC_PRIVATE, ACC_STATIC + Code: + stack=2, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/subclasstest/Class_C1 + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V + x: return +} +SourceFile: "Class_C1.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +## Class: com/android/hoststubgen/test/tinyframework/subclasstest/Class_C2.class + Compiled from "Class_C2.java" +public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_C2 extends com.android.hoststubgen.test.tinyframework.subclasstest.C2 + minor version: 0 + major version: 65 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/Class_C2 + super_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/C2 + interfaces: 0, fields: 0, methods: 1, attributes: 2 + private static {}; + descriptor: ()V + flags: (0x000a) ACC_PRIVATE, ACC_STATIC + Code: + stack=2, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/subclasstest/Class_C2 + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V + x: return +} +SourceFile: "Class_C2.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +## Class: com/android/hoststubgen/test/tinyframework/subclasstest/Class_C3.class + Compiled from "Class_C3.java" +public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_C3 extends com.android.hoststubgen.test.tinyframework.subclasstest.C3 + minor version: 0 + major version: 65 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/Class_C3 + super_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/C3 + interfaces: 0, fields: 0, methods: 1, attributes: 2 + private static {}; + descriptor: ()V + flags: (0x000a) ACC_PRIVATE, ACC_STATIC + Code: + stack=2, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/subclasstest/Class_C3 + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V + x: return +} +SourceFile: "Class_C3.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +## Class: com/android/hoststubgen/test/tinyframework/subclasstest/Class_I1.class + Compiled from "Class_I1.java" +public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_I1 implements com.android.hoststubgen.test.tinyframework.subclasstest.I1 + minor version: 0 + major version: 65 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/Class_I1 + super_class: #x // java/lang/Object + interfaces: 1, fields: 0, methods: 1, attributes: 2 + private static {}; + descriptor: ()V + flags: (0x000a) ACC_PRIVATE, ACC_STATIC + Code: + stack=2, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/subclasstest/Class_I1 + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V + x: return +} +SourceFile: "Class_I1.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +## Class: com/android/hoststubgen/test/tinyframework/subclasstest/Class_I1_IA.class + Compiled from "Class_I1_IA.java" +public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_I1_IA implements com.android.hoststubgen.test.tinyframework.subclasstest.I1,com.android.hoststubgen.test.tinyframework.subclasstest.IA + minor version: 0 + major version: 65 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/Class_I1_IA + super_class: #x // java/lang/Object + interfaces: 2, fields: 0, methods: 1, attributes: 2 + private static {}; + descriptor: ()V + flags: (0x000a) ACC_PRIVATE, ACC_STATIC + Code: + stack=2, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/subclasstest/Class_I1_IA + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V + x: return +} +SourceFile: "Class_I1_IA.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +## Class: com/android/hoststubgen/test/tinyframework/subclasstest/Class_I2.class + Compiled from "Class_I2.java" +public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_I2 implements com.android.hoststubgen.test.tinyframework.subclasstest.I2 + minor version: 0 + major version: 65 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/Class_I2 + super_class: #x // java/lang/Object + interfaces: 1, fields: 0, methods: 1, attributes: 2 + private static {}; + descriptor: ()V + flags: (0x000a) ACC_PRIVATE, ACC_STATIC + Code: + stack=2, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/subclasstest/Class_I2 + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V + x: return +} +SourceFile: "Class_I2.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +## Class: com/android/hoststubgen/test/tinyframework/subclasstest/Class_I3.class + Compiled from "Class_I3.java" +public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_I3 implements com.android.hoststubgen.test.tinyframework.subclasstest.I3 + minor version: 0 + major version: 65 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/Class_I3 + super_class: #x // java/lang/Object + interfaces: 1, fields: 0, methods: 1, attributes: 2 + private static {}; + descriptor: ()V + flags: (0x000a) ACC_PRIVATE, ACC_STATIC + Code: + stack=2, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/subclasstest/Class_I3 + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V + x: return +} +SourceFile: "Class_I3.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +## Class: com/android/hoststubgen/test/tinyframework/subclasstest/I1.class + Compiled from "I1.java" +public interface com.android.hoststubgen.test.tinyframework.subclasstest.I1 + minor version: 0 + major version: 65 + flags: (0x0601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT + this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/I1 + super_class: #x // java/lang/Object + interfaces: 0, fields: 0, methods: 1, attributes: 2 + private static {}; + descriptor: ()V + flags: (0x000a) ACC_PRIVATE, ACC_STATIC + Code: + stack=2, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/subclasstest/I1 + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V + x: return +} +SourceFile: "I1.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +## Class: com/android/hoststubgen/test/tinyframework/subclasstest/I2.class + Compiled from "I2.java" +public interface com.android.hoststubgen.test.tinyframework.subclasstest.I2 extends com.android.hoststubgen.test.tinyframework.subclasstest.I1 + minor version: 0 + major version: 65 + flags: (0x0601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT + this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/I2 + super_class: #x // java/lang/Object + interfaces: 1, fields: 0, methods: 1, attributes: 2 + private static {}; + descriptor: ()V + flags: (0x000a) ACC_PRIVATE, ACC_STATIC + Code: + stack=2, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/subclasstest/I2 + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V + x: return +} +SourceFile: "I2.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +## Class: com/android/hoststubgen/test/tinyframework/subclasstest/I3.class + Compiled from "I3.java" +public interface com.android.hoststubgen.test.tinyframework.subclasstest.I3 extends com.android.hoststubgen.test.tinyframework.subclasstest.I2 + minor version: 0 + major version: 65 + flags: (0x0601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT + this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/I3 + super_class: #x // java/lang/Object + interfaces: 1, fields: 0, methods: 1, attributes: 2 + private static {}; + descriptor: ()V + flags: (0x000a) ACC_PRIVATE, ACC_STATIC + Code: + stack=2, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/subclasstest/I3 + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V + x: return +} +SourceFile: "I3.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +## Class: com/android/hoststubgen/test/tinyframework/subclasstest/IA.class + Compiled from "IA.java" +public interface com.android.hoststubgen.test.tinyframework.subclasstest.IA + minor version: 0 + major version: 65 + flags: (0x0601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT + this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/IA + super_class: #x // java/lang/Object + interfaces: 0, fields: 0, methods: 1, attributes: 2 + private static {}; + descriptor: ()V + flags: (0x000a) ACC_PRIVATE, ACC_STATIC + Code: + stack=2, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/subclasstest/IA + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V + x: return +} +SourceFile: "IA.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +## Class: com/android/hoststubgen/test/tinyframework/subclasstest/IB.class + Compiled from "IB.java" +public interface com.android.hoststubgen.test.tinyframework.subclasstest.IB + minor version: 0 + major version: 65 + flags: (0x0601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT + this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/IB + super_class: #x // java/lang/Object + interfaces: 0, fields: 0, methods: 1, attributes: 2 + private static {}; + descriptor: ()V + flags: (0x000a) ACC_PRIVATE, ACC_STATIC + Code: + stack=2, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/subclasstest/IB + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V + x: return +} +SourceFile: "IB.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +## Class: com/supported/UnsupportedClass.class + Compiled from "UnsupportedClass.java" +public class com.supported.UnsupportedClass + minor version: 0 + major version: 65 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/supported/UnsupportedClass + super_class: #x // java/lang/Object + interfaces: 0, fields: 1, methods: 3, attributes: 3 + private final int mValue; + descriptor: I + flags: (0x0012) ACC_PRIVATE, ACC_FINAL + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + private static {}; + descriptor: ()V + flags: (0x000a) ACC_PRIVATE, ACC_STATIC + Code: + stack=2, locals=0, args_size=0 + x: ldc #x // class com/supported/UnsupportedClass + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V + x: return + + public com.supported.UnsupportedClass(int); + descriptor: (I)V + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=2, args_size=2 + x: ldc #x // class com/supported/UnsupportedClass + x: ldc #x // String <init> + x: ldc #x // String (I)V + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: aload_0 + x: iload_1 + x: putfield #x // Field mValue:I + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 10 0 this Lcom/supported/UnsupportedClass; + 11 10 1 value I + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + public int getValue(); + descriptor: ()I + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/supported/UnsupportedClass + x: ldc #x // String getValue + x: ldc #x // String ()I + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: aload_0 + x: getfield #x // Field mValue:I + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 5 0 this Lcom/supported/UnsupportedClass; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +} +SourceFile: "UnsupportedClass.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestWholeClassKeep +## Class: com/unsupported/UnsupportedClass.class + Compiled from "UnsupportedClass.java" +public class com.unsupported.UnsupportedClass + minor version: 0 + major version: 65 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // com/unsupported/UnsupportedClass + super_class: #x // java/lang/Object + interfaces: 0, fields: 0, methods: 3, attributes: 3 + private static {}; + descriptor: ()V + flags: (0x000a) ACC_PRIVATE, ACC_STATIC + Code: + stack=2, locals=0, args_size=0 + x: ldc #x // class com/unsupported/UnsupportedClass + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V + x: return + + public com.unsupported.UnsupportedClass(int); + descriptor: (I)V + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=2, args_size=2 + x: ldc #x // class com/unsupported/UnsupportedClass + x: ldc #x // String <init> + x: ldc #x // String (I)V + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String This class is not supported + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 14 0 this Lcom/unsupported/UnsupportedClass; + 11 14 1 value I + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + public int getValue(); + descriptor: ()I + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/unsupported/UnsupportedClass + x: ldc #x // String getValue + x: ldc #x // String ()I + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: new #x // class java/lang/RuntimeException + x: dup + x: ldc #x // String This class is not supported + x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V + x: athrow + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 10 0 this Lcom/unsupported/UnsupportedClass; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +} +SourceFile: "UnsupportedClass.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestWholeClassKeep +## Class: rename_prefix/com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed.class + Compiled from "TinyFrameworkToBeRenamed.java" +public class rename_prefix.com.android.hoststubgen.test.tinyframework.TinyFrameworkToBeRenamed + minor version: 0 + major version: 65 + flags: (0x0021) ACC_PUBLIC, ACC_SUPER + this_class: #x // rename_prefix/com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed + super_class: #x // java/lang/Object + interfaces: 0, fields: 1, methods: 3, attributes: 3 + private final int mValue; + descriptor: I + flags: (0x0012) ACC_PRIVATE, ACC_FINAL + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + private static {}; + descriptor: ()V + flags: (0x000a) ACC_PRIVATE, ACC_STATIC + Code: + stack=2, locals=0, args_size=0 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V + x: return + + public rename_prefix.com.android.hoststubgen.test.tinyframework.TinyFrameworkToBeRenamed(int); + descriptor: (I)V + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=2, args_size=2 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed + x: ldc #x // String <init> + x: ldc #x // String (I)V + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: aload_0 + x: invokespecial #x // Method java/lang/Object."<init>":()V + x: aload_0 + x: iload_1 + x: putfield #x // Field mValue:I + x: return + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 10 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed; + 11 10 1 value I + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep + + public int getValue(); + descriptor: ()I + flags: (0x0001) ACC_PUBLIC + Code: + stack=4, locals=1, args_size=1 + x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed + x: ldc #x // String getValue + x: ldc #x // String ()I + x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall + x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + x: aload_0 + x: getfield #x // Field mValue:I + x: ireturn + LineNumberTable: + LocalVariableTable: + Start Length Slot Name Signature + 11 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed; + RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +} +SourceFile: "TinyFrameworkToBeRenamed.java" +RuntimeVisibleAnnotations: + x: #x() + com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep +RuntimeInvisibleAnnotations: + x: #x() + android.hosttest.annotation.HostSideTestWholeClassKeep diff --git a/ravenwood/tools/hoststubgen/test-tiny-framework/tiny-framework-dump-test.py b/ravenwood/tools/hoststubgen/test-tiny-framework/tiny-framework-dump-test.py index 7a7de3553829..88fa492addb8 100755 --- a/ravenwood/tools/hoststubgen/test-tiny-framework/tiny-framework-dump-test.py +++ b/ravenwood/tools/hoststubgen/test-tiny-framework/tiny-framework-dump-test.py @@ -20,18 +20,23 @@ import os import unittest import subprocess -GOLDEN_DIR = 'golden-output' +GOLDEN_DIRS = [ + 'golden-output', + 'golden-output.RELEASE_TARGET_JAVA_21', +] + # Run diff. def run_diff(file1, file2): - command = ['diff', '-u', '--ignore-blank-lines', '--ignore-space-change', file1, file2] + command = ['diff', '-u', '--ignore-blank-lines', + '--ignore-space-change', file1, file2] print(' '.join(command)) - result = subprocess.run(command, stderr = sys.stdout) + result = subprocess.run(command, stderr=sys.stdout) success = result.returncode == 0 if success: - print(f'No diff found.') + print('No diff found.') else: print(f'Fail: {file1} and {file2} are different.') @@ -39,27 +44,42 @@ def run_diff(file1, file2): # Check one golden file. -def check_one_file(filename): +def check_one_file(golden_dir, filename): print(f'= Checking file: {filename}') - return run_diff(os.path.join(GOLDEN_DIR, filename), 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. + # Depending on build flags, the golden output may differ in expected ways. + # So only expect the files to match one of the possible golden outputs. def test_compare_to_golden(self): - self.skipTest("test cannot handle multiple images (see b/378470825)") - files = os.listdir(GOLDEN_DIR) + success = False + + for golden_dir in GOLDEN_DIRS: + if self.matches_golden(golden_dir): + success = True + print(f"Test passes for dir: {golden_dir}") + break + + if not success: + self.fail('Some files are different. ' + + 'See stdout log for more details.') + + def matches_golden(self, golden_dir): + files = os.listdir(golden_dir) files.sort() - print(f"Golden files: {files}") - success = True + print(f"Golden files for {golden_dir}: {files}") + match_success = True for file in files: - if not check_one_file(file): - success = False + if not check_one_file(golden_dir, file): + match_success = False + + return match_success - 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/services/accessibility/accessibility.aconfig b/services/accessibility/accessibility.aconfig index 2808056f72c9..a0b989b44f4f 100644 --- a/services/accessibility/accessibility.aconfig +++ b/services/accessibility/accessibility.aconfig @@ -55,16 +55,6 @@ flag { } flag { - name: "compute_window_changes_on_a11y_v2" - namespace: "accessibility" - description: "Computes accessibility window changes in accessibility instead of wm package." - bug: "322444245" - metadata { - purpose: PURPOSE_BUGFIX - } -} - -flag { name: "deprecate_package_list_observer" namespace: "accessibility" description: "Stops using the deprecated PackageListObserver." diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityWindowManager.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityWindowManager.java index 9a81aa6cc506..5cbe0c4fe4d2 100644 --- a/services/accessibility/java/com/android/server/accessibility/AccessibilityWindowManager.java +++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityWindowManager.java @@ -433,22 +433,10 @@ public class AccessibilityWindowManager { return Collections.emptyList(); } - /** - * Callbacks from window manager when there's an accessibility change in windows. - * - * @param forceSend Send the windows for accessibility even if they haven't changed. - * @param topFocusedDisplayId The display Id which has the top focused window. - * @param topFocusedWindowToken The window token of top focused window. - * @param windows The windows for accessibility. - */ - @Override - public void onWindowsForAccessibilityChanged(boolean forceSend, int topFocusedDisplayId, + private void onWindowsForAccessibilityChanged(boolean forceSend, int topFocusedDisplayId, IBinder topFocusedWindowToken, @NonNull List<WindowInfo> windows) { + // TODO(b/322444245): no longer need to get a lock. synchronized (mLock) { - if (!Flags.computeWindowChangesOnA11yV2()) { - // If the flag is enabled, it's already done in #createWindowInfoListLocked. - updateWindowsByWindowAttributesLocked(windows); - } if (DEBUG) { Slogf.i(LOG_TAG, "mDisplayId=%d, topFocusedDisplayId=%d, currentUserId=%d, " + "visibleBgUsers=%s", mDisplayId, topFocusedDisplayId, @@ -490,9 +478,7 @@ public class AccessibilityWindowManager { } /** - * Called when the windows for accessibility changed. This is called if - * {@link com.android.server.accessibility.Flags.FLAG_COMPUTE_WINDOW_CHANGES_ON_A11Y_V2} is - * true. + * Called when the windows for accessibility changed. * * @param forceSend Send the windows for accessibility even if they haven't * changed. @@ -655,16 +641,6 @@ public class AccessibilityWindowManager { return true; } - private void updateWindowsByWindowAttributesLocked(List<WindowInfo> windows) { - for (int i = windows.size() - 1; i >= 0; i--) { - final WindowInfo windowInfo = windows.get(i); - final IBinder token = windowInfo.token; - final int windowId = findWindowIdLocked( - mAccessibilityUserManager.getCurrentUserIdLocked(), token); - updateWindowWithWindowAttributes(windowInfo, mWindowAttributes.get(windowId)); - } - } - private void updateWindowWithWindowAttributes(@NonNull WindowInfo windowInfo, @Nullable AccessibilityWindowAttributes attributes) { if (attributes == null) { @@ -990,19 +966,6 @@ public class AccessibilityWindowManager { private AccessibilityWindowInfo populateReportedWindowLocked(int userId, WindowInfo window, SparseArray<AccessibilityWindowInfo> oldWindowsById) { final int windowId = findWindowIdLocked(userId, window.token); - - // With the flag enabled, createWindowInfoListLocked() already removes invalid windows. - if (!Flags.computeWindowChangesOnA11yV2()) { - if (windowId < 0) { - return null; - } - - // Don't need to add the embedded hierarchy windows into the a11y windows list. - if (isEmbeddedHierarchyWindowsLocked(windowId)) { - return null; - } - } - final AccessibilityWindowInfo reportedWindow = AccessibilityWindowInfo.obtain(); reportedWindow.setId(windowId); 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 8b5b93e96494..d4beb019e049 100644 --- a/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java +++ b/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java @@ -44,7 +44,6 @@ import android.app.PendingIntent; import android.app.admin.DevicePolicyManager; import android.app.compat.CompatChanges; import android.companion.AssociationInfo; -import android.companion.AssociationRequest; import android.companion.virtual.ActivityPolicyExemption; import android.companion.virtual.IVirtualDevice; import android.companion.virtual.IVirtualDeviceActivityListener; @@ -156,9 +155,6 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub private static final String PERSISTENT_ID_PREFIX_CDM_ASSOCIATION = "companion:"; - private static final List<String> DEVICE_PROFILES_ALLOWING_MIRROR_DISPLAYS = List.of( - AssociationRequest.DEVICE_PROFILE_APP_STREAMING); - /** * Timeout until {@link #launchPendingIntent} stops waiting for an activity to be launched. */ @@ -1352,11 +1348,6 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub return hasCustomAudioInputSupportInternal(); } - @Override - public boolean canCreateMirrorDisplays() { - return DEVICE_PROFILES_ALLOWING_MIRROR_DISPLAYS.contains(getDeviceProfile()); - } - private boolean hasCustomAudioInputSupportInternal() { if (!Flags.vdmPublicApis()) { return false; diff --git a/services/core/java/com/android/server/BinaryTransparencyService.java b/services/core/java/com/android/server/BinaryTransparencyService.java index 485bf31dfb64..aabbd3bf49ae 100644 --- a/services/core/java/com/android/server/BinaryTransparencyService.java +++ b/services/core/java/com/android/server/BinaryTransparencyService.java @@ -65,6 +65,7 @@ import android.os.Binder; import android.os.Build; import android.os.Bundle; import android.os.IBinder; +import android.os.IRemoteCallback; import android.os.RemoteException; import android.os.ResultReceiver; import android.os.ServiceManager; @@ -347,7 +348,8 @@ public class BinaryTransparencyService extends SystemService { + " packages after considering preloads"); } - if (CompatChanges.isChangeEnabled(LOG_MBA_INFO)) { + if (!android.app.Flags.backgroundInstallControlCallbackApi() + && CompatChanges.isChangeEnabled(LOG_MBA_INFO)) { // lastly measure all newly installed MBAs List<IBinaryTransparencyService.AppInfo> allMbaInfo = collectAllSilentInstalledMbaInfo(packagesMeasured); @@ -1158,6 +1160,49 @@ public class BinaryTransparencyService extends SystemService { } /** + * Receive callbacks from BIC to write silently installed apps to log + * + * TODO: Add a host test for testing registration and callback of BicCallbackHandler + * b/380002484 + */ + static class BicCallbackHandler extends IRemoteCallback.Stub { + private static final String BIC_CALLBACK_HANDLER_TAG = + "BTS.BicCallbackHandler"; + private final BinaryTransparencyServiceImpl mServiceImpl; + static final String FLAGGED_PACKAGE_NAME_KEY = "packageName"; + + BicCallbackHandler(BinaryTransparencyServiceImpl impl) { + mServiceImpl = impl; + } + + @Override + public void sendResult(Bundle data) { + String packageName = data.getString(FLAGGED_PACKAGE_NAME_KEY); + if (packageName == null) return; + if (DEBUG) { + Slog.d(BIC_CALLBACK_HANDLER_TAG, "background install event detected for " + + packageName); + } + + PackageState packageState = LocalServices.getService(PackageManagerInternal.class) + .getPackageStateInternal(packageName); + if (packageState == null) { + Slog.w(TAG, "Package state is unavailable, ignoring the package " + + packageName); + return; + } + if (packageState.isUpdatedSystemApp()) { + return; + } + List<IBinaryTransparencyService.AppInfo> mbaInfo = mServiceImpl.collectAppInfo( + packageState, MBA_STATUS_NEW_INSTALL); + for (IBinaryTransparencyService.AppInfo appInfo : mbaInfo) { + mServiceImpl.writeAppInfoToLog(appInfo); + } + } + }; + + /** * Called when the system service should publish a binder service using * {@link #publishBinderService(String, IBinder).} */ @@ -1534,6 +1579,19 @@ public class BinaryTransparencyService extends SystemService { } } + private void registerBicCallback() { + IBackgroundInstallControlService iBics = + IBackgroundInstallControlService.Stub.asInterface( + ServiceManager.getService( + Context.BACKGROUND_INSTALL_CONTROL_SERVICE)); + try { + iBics.registerBackgroundInstallCallback( + new BicCallbackHandler(mServiceImpl)); + } catch (RemoteException e) { + Slog.e(TAG, "Failed to register BackgroundInstallControl callback."); + } + } + private boolean isPackagePreloaded(String packageName) { PackageManager pm = mContext.getPackageManager(); try { @@ -1596,6 +1654,10 @@ public class BinaryTransparencyService extends SystemService { private void registerAllPackageUpdateObservers() { registerApkAndNonStagedApexUpdateListener(); registerStagedApexUpdateObserver(); + if (android.app.Flags.backgroundInstallControlCallbackApi() + && CompatChanges.isChangeEnabled(LOG_MBA_INFO)) { + registerBicCallback(); + } } private String translateContentDigestAlgorithmIdToString(int algorithmId) { diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java index ab3ab159ba12..71cbc10074d6 100644 --- a/services/core/java/com/android/server/am/ActiveServices.java +++ b/services/core/java/com/android/server/am/ActiveServices.java @@ -9319,6 +9319,46 @@ public final class ActiveServices { Slog.e(TAG, "stopForegroundServiceDelegateLocked delegate does not exist"); } } + /** + * Handles notifications from MediaSessionService about active media service. + * This method evaluates the provided information and transitions corresponding service to + * foreground state. + * + * @param packageName The package name of the app running the service. + * @param userId The user ID associated with the service. + * @param notificationId The ID of the media notification associated with the service. + */ + void notifyActiveMediaForegroundServiceLocked(@NonNull String packageName, + @UserIdInt int userId, int notificationId) { + if (!enableNotifyingActivityManagerWithMediaSessionStatusChange()) { + return; + } + + final ServiceMap smap = mServiceMap.get(userId); + if (smap == null) { + return; + } + final int serviceSize = smap.mServicesByInstanceName.size(); + for (int i = 0; i < serviceSize; i++) { + final ServiceRecord sr = smap.mServicesByInstanceName.valueAt(i); + if (sr.appInfo.packageName.equals(packageName) && !sr.isForeground) { + // foregroundServiceType is cleared when media session is user-disengaged + // and calls notifyInactiveMediaForegroundService->setServiceForegroundInnerLocked. + if (sr.foregroundServiceType + == ServiceInfo.FOREGROUND_SERVICE_TYPE_NONE + && sr.foregroundId == notificationId) { + if (DEBUG_FOREGROUND_SERVICE) { + Slog.d(TAG, "Moving media service to foreground for package " + + packageName); + } + setServiceForegroundInnerLocked(sr, sr.foregroundId, + sr.foregroundNoti, /* flags */ 0, + ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK, + /* callingUidStart */ 0); + } + } + } + } /** * Handles notifications from MediaSessionService about inactive media foreground services. diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 5c5361bacf5a..d79e66db8661 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -17923,6 +17923,15 @@ public class ActivityManagerService extends IActivityManager.Stub } @Override + public void notifyActiveMediaForegroundService(@NonNull String packageName, + @UserIdInt int userId, int notificationId) { + synchronized (ActivityManagerService.this) { + mServices.notifyActiveMediaForegroundServiceLocked(packageName, userId, + notificationId); + } + } + + @Override public void notifyInactiveMediaForegroundService(@NonNull String packageName, @UserIdInt int userId, int notificationId) { synchronized (ActivityManagerService.this) { diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java index d3d3fc968ae6..fa40283d43e1 100644 --- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java +++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java @@ -471,14 +471,14 @@ final class ActivityManagerShellCommand extends ShellCommand { } int userId = UserHandle.USER_CURRENT; final String cmd = getNextArgRequired(); - if ("inactive".equals(cmd)) { + if ("inactive".equals(cmd) || "active".equals(cmd)) { String opt; while ((opt = getNextOption()) != null) { if (opt.equals("--user")) { userId = UserHandle.parseUserArg(getNextArgRequired()); if (userId == UserHandle.USER_ALL) { err.println( - "Error: Can't set media fgs inactive with user 'all'"); + "Error: Can't set media fgs with user 'all'"); return -1; } } else { @@ -492,8 +492,13 @@ final class ActivityManagerShellCommand extends ShellCommand { err.println("Error: notification id cannot be zero"); return -1; } - mInternal.mInternal.notifyInactiveMediaForegroundService(pkgName, - userId, notificationId); + if ("inactive".equals(cmd)) { + mInternal.mInternal.notifyInactiveMediaForegroundService(pkgName, + userId, notificationId); + } else { + mInternal.mInternal.notifyActiveMediaForegroundService(pkgName, + userId, notificationId); + } return 0; } err.println("Error: Unknown set-media-foreground-service command: " + cmd); @@ -4683,9 +4688,9 @@ final class ActivityManagerShellCommand extends ShellCommand { pw.println(" --protobuf: format output using protobuffer"); pw.println(" set-app-zygote-preload-timeout <TIMEOUT_IN_MS>"); pw.println(" Set the timeout for preloading code in the app-zygote"); - pw.println(" set-media-foreground-service inactive [--user USER_ID]" - + " <PACKAGE> <NOTIFICATION_ID>"); - pw.println(" Set an app's media foreground service inactive."); + pw.println(" set-media-foreground-service inactive|active [--user USER_ID] <PACKAGE>" + + " <NOTIFICATION_ID>"); + pw.println(" Set an app's media service inactive or active."); Intent.printIntentArgsHelp(pw, ""); } } diff --git a/services/core/java/com/android/server/am/AppErrors.java b/services/core/java/com/android/server/am/AppErrors.java index 415f78aa3ee5..b7a5f3e4099a 100644 --- a/services/core/java/com/android/server/am/AppErrors.java +++ b/services/core/java/com/android/server/am/AppErrors.java @@ -598,7 +598,7 @@ class AppErrors { } if (r != null) { - mPackageWatchdog.onPackageFailure(r.getPackageListWithVersionCode(), + mPackageWatchdog.notifyPackageFailure(r.getPackageListWithVersionCode(), PackageWatchdog.FAILURE_REASON_APP_CRASH); synchronized (mService) { @@ -1142,7 +1142,7 @@ class AppErrors { } // Notify PackageWatchdog without the lock held if (packageList != null) { - mPackageWatchdog.onPackageFailure(packageList, + mPackageWatchdog.notifyPackageFailure(packageList, PackageWatchdog.FAILURE_REASON_APP_NOT_RESPONDING); } } diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java index 2eb9f3cb600f..d5bd05764f38 100644 --- a/services/core/java/com/android/server/am/BatteryStatsService.java +++ b/services/core/java/com/android/server/am/BatteryStatsService.java @@ -1262,6 +1262,17 @@ public final class BatteryStatsService extends IBatteryStats.Stub mFrameworkStatsLogger = frameworkStatsLogger; } + private static float clampPowerMah(double powerMah, String consumer) { + float resultPowerMah = 0; + if (powerMah <= Float.MAX_VALUE && powerMah >= Float.MIN_VALUE) { + resultPowerMah = (float) powerMah; + } else { + // Handle overflow appropriately + Slog.wtfStack(TAG, consumer + " reported powerMah float overflow: " + powerMah); + } + return resultPowerMah; + } + /** * Generates StatsEvents for the supplied battery usage stats and adds them to * the supplied list. @@ -1282,7 +1293,8 @@ public final class BatteryStatsService extends IBatteryStats.Stub bus.getAggregateBatteryConsumer( BatteryUsageStats.AGGREGATE_BATTERY_CONSUMER_SCOPE_DEVICE); - final float totalDeviceConsumedPowerMah = (float) deviceConsumer.getConsumedPower(); + final float totalDeviceConsumedPowerMah = + clampPowerMah(deviceConsumer.getConsumedPower(), "AggregateBatteryConsumer"); for (@BatteryConsumer.PowerComponentId int powerComponentId : deviceConsumer.getPowerComponentIds()) { @@ -1314,7 +1326,9 @@ public final class BatteryStatsService extends IBatteryStats.Stub // Log single atom for BatteryUsageStats per uid/process_state/component/etc. for (UidBatteryConsumer uidConsumer : uidConsumers) { final int uid = uidConsumer.getUid(); - final float totalConsumedPowerMah = (float) uidConsumer.getConsumedPower(); + + final float totalConsumedPowerMah = + clampPowerMah(uidConsumer.getConsumedPower(), "uidConsumer-" + uid); for (@BatteryConsumer.PowerComponentId int powerComponentId : uidConsumer.getPowerComponentIds()) { @@ -1358,7 +1372,10 @@ public final class BatteryStatsService extends IBatteryStats.Stub } final String powerComponentName = batteryConsumer.getPowerComponentName(componentId); - final float powerMah = (float) batteryConsumer.getConsumedPower(key); + final double consumedPowerMah = batteryConsumer.getConsumedPower(key); + float powerMah = + clampPowerMah( + consumedPowerMah, "uidConsumer-" + uid + "-" + powerComponentName); final long powerComponentDurationMillis = batteryConsumer.getUsageDurationMillis(key); if (powerMah == 0 && powerComponentDurationMillis == 0) { diff --git a/services/core/java/com/android/server/am/OWNERS b/services/core/java/com/android/server/am/OWNERS index ab7cd5f29660..1a6051b6ac9c 100644 --- a/services/core/java/com/android/server/am/OWNERS +++ b/services/core/java/com/android/server/am/OWNERS @@ -66,6 +66,9 @@ per-file CarUserSwitchingDialog.java = file:platform/packages/services/Car:/OWNE # Activity Security per-file ActivityManager* = file:/ACTIVITY_SECURITY_OWNERS +# Aconfig Flags +per-file flags.aconfig = yamasani@google.com, bills@google.com, nalini@google.com + # Londoners michaelwr@google.com #{LAST_RESORT_SUGGESTION} narayan@google.com #{LAST_RESORT_SUGGESTION} diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java index b84bf6b90711..f42641ece09b 100644 --- a/services/core/java/com/android/server/am/OomAdjuster.java +++ b/services/core/java/com/android/server/am/OomAdjuster.java @@ -1376,9 +1376,11 @@ public class OomAdjuster { ProcessRecord app = lruList.get(i); final ProcessStateRecord state = app.mState; if (!app.isKilledByAm() && app.getThread() != null) { - // We don't need to apply the update for the process which didn't get computed - if (state.getCompletedAdjSeq() == mAdjSeq) { - applyOomAdjLSP(app, doingAll, now, nowElapsed, oomAdjReason, true); + if (!Flags.fixApplyOomadjOrder()) { + // We don't need to apply the update for the process which didn't get computed + if (state.getCompletedAdjSeq() == mAdjSeq) { + applyOomAdjLSP(app, doingAll, now, nowElapsed, oomAdjReason, true); + } } if (app.isPendingFinishAttach()) { @@ -1480,6 +1482,19 @@ public class OomAdjuster { } } + if (Flags.fixApplyOomadjOrder()) { + // We need to apply the update starting from the least recently used. + // Otherwise, they won't be in the correct LRU order in LMKD. + for (int i = 0; i < numLru; i++) { + ProcessRecord app = lruList.get(i); + // We don't need to apply the update for the process which didn't get computed + if (!app.isKilledByAm() && app.getThread() != null + && app.mState.getCompletedAdjSeq() == mAdjSeq) { + applyOomAdjLSP(app, doingAll, now, nowElapsed, oomAdjReason, true); + } + } + } + if (!mProcsToOomAdj.isEmpty()) { mInjector.batchSetOomAdj(mProcsToOomAdj); mProcsToOomAdj.clear(); diff --git a/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java b/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java index 78c4f74f3afa..f28f3e1e4fdf 100644 --- a/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java +++ b/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java @@ -140,6 +140,7 @@ public class SettingsToPropertiesMapper { // The list is sorted. @VisibleForTesting static final String[] sDeviceConfigAconfigScopes = new String[] { + "aaos_power_triage", "aaos_sdv", "accessibility", "android_core_networking", diff --git a/services/core/java/com/android/server/am/flags.aconfig b/services/core/java/com/android/server/am/flags.aconfig index 6d247d227774..89e4a8d82676 100644 --- a/services/core/java/com/android/server/am/flags.aconfig +++ b/services/core/java/com/android/server/am/flags.aconfig @@ -245,6 +245,14 @@ flag { } flag { + name: "fix_apply_oomadj_order" + namespace: "backstage_power" + is_fixed_read_only: true + description: "Fix the iteration direction of process LRU list when applying oom adj" + bug: "378580264" +} + +flag { name: "phantom_processes_fix" namespace: "backstage_power" description: "Make sure setProcessGroupForPhantomProcessOfApp deals with phantom processes properly" diff --git a/services/core/java/com/android/server/app/GameManagerService.java b/services/core/java/com/android/server/app/GameManagerService.java index 8c5152fdb0d6..6f8dc105850d 100644 --- a/services/core/java/com/android/server/app/GameManagerService.java +++ b/services/core/java/com/android/server/app/GameManagerService.java @@ -100,6 +100,7 @@ import com.android.server.LocalServices; import com.android.server.ServiceThread; import com.android.server.SystemService; import com.android.server.SystemService.TargetUser; +import com.android.server.utils.LazyJniRegistrar; import com.android.server.wm.ActivityTaskManagerInternal; import com.android.server.wm.CompatScaleProvider; @@ -158,6 +159,10 @@ public final class GameManagerService extends IGameManagerService.Stub { private static final String GAME_MODE_INTERVENTION_LIST_FILE_NAME = "game_mode_intervention.list"; + static { + LazyJniRegistrar.registerGameManagerService(); + } + private final Context mContext; private final Object mLock = new Object(); private final Object mDeviceConfigLock = new Object(); diff --git a/services/core/java/com/android/server/appop/AppOpsUidStateTrackerImpl.java b/services/core/java/com/android/server/appop/AppOpsUidStateTrackerImpl.java index ed41f2e881f8..fa2e674d37c7 100644 --- a/services/core/java/com/android/server/appop/AppOpsUidStateTrackerImpl.java +++ b/services/core/java/com/android/server/appop/AppOpsUidStateTrackerImpl.java @@ -31,7 +31,6 @@ import static android.app.AppOpsManager.OP_CAMERA; import static android.app.AppOpsManager.OP_NONE; import static android.app.AppOpsManager.OP_RECEIVE_EXPLICIT_USER_INTERACTION_AUDIO; import static android.app.AppOpsManager.OP_RECORD_AUDIO; -import static android.app.AppOpsManager.OP_TAKE_AUDIO_FOCUS; import static android.app.AppOpsManager.UID_STATE_FOREGROUND_SERVICE; import static android.app.AppOpsManager.UID_STATE_MAX_LAST_NON_RESTRICTED; import static android.app.AppOpsManager.UID_STATE_NONEXISTENT; @@ -177,8 +176,6 @@ class AppOpsUidStateTrackerImpl implements AppOpsUidStateTracker { case OP_RECORD_AUDIO: case OP_RECEIVE_EXPLICIT_USER_INTERACTION_AUDIO: return PROCESS_CAPABILITY_FOREGROUND_MICROPHONE; - case OP_TAKE_AUDIO_FOCUS: - return PROCESS_CAPABILITY_FOREGROUND_AUDIO_CONTROL; default: return PROCESS_CAPABILITY_NONE; } diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java index 40d5f86f8094..5c2eb5cf1086 100644 --- a/services/core/java/com/android/server/audio/AudioService.java +++ b/services/core/java/com/android/server/audio/AudioService.java @@ -4954,6 +4954,15 @@ public class AudioService extends IAudioService.Stub } final Set<Integer> deviceTypes = getDeviceSetForStreamDirect(streamType); + + final Set<Integer> a2dpDevices = AudioSystem.intersectionAudioDeviceTypes( + AudioSystem.DEVICE_OUT_ALL_A2DP_SET, deviceTypes); + if (!a2dpDevices.isEmpty()) { + int index = getStreamVolume(streamType, + a2dpDevices.toArray(new Integer[0])[0].intValue()); + mDeviceBroker.postSetAvrcpAbsoluteVolumeIndex(index); + } + final Set<Integer> absVolumeMultiModeCaseDevices = AudioSystem.intersectionAudioDeviceTypes( mAbsVolumeMultiModeCaseDevices, deviceTypes); @@ -11425,6 +11434,10 @@ public class AudioService extends IAudioService.Stub return mSpatializerHelper.canBeSpatialized(attributes, format); } + public @NonNull List<Integer> getSpatializedChannelMasks() { + return mSpatializerHelper.getSpatializedChannelMasks(); + } + /** @see Spatializer.SpatializerInfoDispatcherStub */ public void registerSpatializerCallback( @NonNull ISpatializerCallback cb) { diff --git a/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java b/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java index a62ac82f27eb..a2200c9f8bf5 100644 --- a/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java +++ b/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java @@ -24,6 +24,7 @@ import static android.media.AudioPlaybackConfiguration.MUTED_BY_PORT_VOLUME; import static android.media.AudioPlaybackConfiguration.MUTED_BY_STREAM_MUTED; import static android.media.AudioPlaybackConfiguration.MUTED_BY_STREAM_VOLUME; import static android.media.AudioPlaybackConfiguration.MUTED_BY_VOLUME_SHAPER; +import static android.media.AudioPlaybackConfiguration.MUTED_BY_OP_CONTROL_AUDIO; import static android.media.AudioPlaybackConfiguration.PLAYER_PIID_INVALID; import static android.media.AudioPlaybackConfiguration.PLAYER_UPDATE_MUTED; @@ -1388,6 +1389,10 @@ public final class PlaybackActivityMonitor if ((eventValue & MUTED_BY_PORT_VOLUME) != 0) { builder.append("portVolume "); } + if ((eventValue & MUTED_BY_OP_CONTROL_AUDIO) != 0) { + builder.append("opControlAudio "); + } + } return builder.toString(); default: diff --git a/services/core/java/com/android/server/audio/SpatializerHelper.java b/services/core/java/com/android/server/audio/SpatializerHelper.java index 9265ff2d9b2d..afa90d5869e3 100644 --- a/services/core/java/com/android/server/audio/SpatializerHelper.java +++ b/services/core/java/com/android/server/audio/SpatializerHelper.java @@ -59,6 +59,8 @@ import com.android.server.utils.EventLogger; import java.io.PrintWriter; import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; import java.util.List; import java.util.Locale; import java.util.UUID; @@ -1100,6 +1102,23 @@ public class SpatializerHelper { return able; } + synchronized @NonNull List<Integer> getSpatializedChannelMasks() { + if (!checkSpatializer("getSpatializedChannelMasks")) { + return Collections.emptyList(); + } + try { + final int[] nativeMasks = new int[0]; // FIXME mSpat query goes here + for (int i = 0; i < nativeMasks.length; i++) { + nativeMasks[i] = AudioFormat.convertNativeChannelMaskToOutMask(nativeMasks[i]); + } + final List<Integer> masks = Arrays.stream(nativeMasks).boxed().toList(); + return masks; + } catch (Exception e) { // just catch Exception in case nativeMasks is null + Log.e(TAG, "Error calling getSpatializedChannelMasks", e); + return Collections.emptyList(); + } + } + //------------------------------------------------------ // head tracking final RemoteCallbackList<ISpatializerHeadTrackingModeCallback> mHeadTrackingModeCallbacks = diff --git a/services/core/java/com/android/server/biometrics/BiometricService.java b/services/core/java/com/android/server/biometrics/BiometricService.java index 97a88542f0a4..b365ef7ff61c 100644 --- a/services/core/java/com/android/server/biometrics/BiometricService.java +++ b/services/core/java/com/android/server/biometrics/BiometricService.java @@ -434,21 +434,12 @@ public class BiometricService extends SystemService { public boolean getMandatoryBiometricsEnabledAndRequirementsSatisfiedForUser(int userId) { if (!mMandatoryBiometricsEnabled.containsKey(userId)) { - Slog.d(TAG, "update mb toggle for user " + userId); updateMandatoryBiometricsForAllProfiles(userId); } if (!mMandatoryBiometricsRequirementsSatisfied.containsKey(userId)) { - Slog.d(TAG, "update mb reqs for user " + userId); updateMandatoryBiometricsRequirementsForAllProfiles(userId); } - Slog.d(TAG, mMandatoryBiometricsEnabled.getOrDefault(userId, - DEFAULT_MANDATORY_BIOMETRICS_STATUS) - + " " + mMandatoryBiometricsRequirementsSatisfied.getOrDefault(userId, - DEFAULT_MANDATORY_BIOMETRICS_REQUIREMENTS_SATISFIED_STATUS) - + " " + getEnabledForApps(userId) - + " " + (mFingerprintEnrolledForUser.getOrDefault(userId, false /* default */) - || mFaceEnrolledForUser.getOrDefault(userId, false /* default */))); return mMandatoryBiometricsEnabled.getOrDefault(userId, DEFAULT_MANDATORY_BIOMETRICS_STATUS) && mMandatoryBiometricsRequirementsSatisfied.getOrDefault(userId, diff --git a/services/core/java/com/android/server/biometrics/sensors/PerformanceTracker.java b/services/core/java/com/android/server/biometrics/sensors/PerformanceTracker.java index eed2bddb0312..958ab8ee0b6a 100644 --- a/services/core/java/com/android/server/biometrics/sensors/PerformanceTracker.java +++ b/services/core/java/com/android/server/biometrics/sensors/PerformanceTracker.java @@ -18,6 +18,8 @@ package com.android.server.biometrics.sensors; import android.util.SparseArray; +import java.util.concurrent.ConcurrentHashMap; + /** * Tracks biometric performance across sensors and users. */ @@ -25,17 +27,12 @@ public class PerformanceTracker { private static final String TAG = "PerformanceTracker"; // Keyed by SensorId - private static SparseArray<PerformanceTracker> sTrackers; + private static final ConcurrentHashMap<Integer, PerformanceTracker> sTrackers = + new ConcurrentHashMap<>(); public static PerformanceTracker getInstanceForSensorId(int sensorId) { - if (sTrackers == null) { - sTrackers = new SparseArray<>(); - } - - if (!sTrackers.contains(sensorId)) { - sTrackers.put(sensorId, new PerformanceTracker()); - } - return sTrackers.get(sensorId); + PerformanceTracker tracker = sTrackers.putIfAbsent(sensorId, new PerformanceTracker()); + return tracker != null ? tracker : sTrackers.get(sensorId); } private static class Info { diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java index 36e4a7e6a7ef..944e85cc970e 100644 --- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java +++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java @@ -851,13 +851,8 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider { for (int i = 0; i < mFaceSensors.size(); i++) { final Sensor sensor = mFaceSensors.valueAt(i); final int sensorId = mFaceSensors.keyAt(i); - final PerformanceTracker performanceTracker = PerformanceTracker.getInstanceForSensorId( - sensorId); - if (performanceTracker != null) { - performanceTracker.incrementHALDeathCount(); - } else { - Slog.w(getTag(), "Performance tracker is null. Not counting HAL death."); - } + PerformanceTracker.getInstanceForSensorId(sensorId) + .incrementHALDeathCount(); sensor.onBinderDied(); } }); diff --git a/services/core/java/com/android/server/crashrecovery/CrashRecoveryHelper.java b/services/core/java/com/android/server/crashrecovery/CrashRecoveryHelper.java index 8e725465ddd6..eef2b15c3387 100644 --- a/services/core/java/com/android/server/crashrecovery/CrashRecoveryHelper.java +++ b/services/core/java/com/android/server/crashrecovery/CrashRecoveryHelper.java @@ -93,7 +93,8 @@ public final class CrashRecoveryHelper { return; } final List<VersionedPackage> pkgList = Collections.singletonList(pkg); - PackageWatchdog.getInstance(mContext).onPackageFailure(pkgList, PackageWatchdog.FAILURE_REASON_EXPLICIT_HEALTH_CHECK); + PackageWatchdog.getInstance(mContext).notifyPackageFailure(pkgList, + PackageWatchdog.FAILURE_REASON_EXPLICIT_HEALTH_CHECK); }); } diff --git a/services/core/java/com/android/server/display/DisplayDeviceInfo.java b/services/core/java/com/android/server/display/DisplayDeviceInfo.java index d2c044fdbb5e..1c1bdad01034 100644 --- a/services/core/java/com/android/server/display/DisplayDeviceInfo.java +++ b/services/core/java/com/android/server/display/DisplayDeviceInfo.java @@ -311,6 +311,11 @@ final class DisplayDeviceInfo { */ public FrameRateCategoryRate frameRateCategoryRate; /** + * All the refresh rates supported for the default display mode. + */ + public float[] supportedRefreshRates = new float[0]; + + /** * The default mode of the display. */ public int defaultModeId; @@ -562,7 +567,8 @@ final class DisplayDeviceInfo { || installOrientation != other.installOrientation || !Objects.equals(displayShape, other.displayShape) || hasArrSupport != other.hasArrSupport - || !Objects.equals(frameRateCategoryRate, other.frameRateCategoryRate)) { + || !Objects.equals(frameRateCategoryRate, other.frameRateCategoryRate) + || !Arrays.equals(supportedRefreshRates, other.supportedRefreshRates)) { diff |= DIFF_OTHER; } return diff; @@ -582,6 +588,7 @@ final class DisplayDeviceInfo { renderFrameRate = other.renderFrameRate; hasArrSupport = other.hasArrSupport; frameRateCategoryRate = other.frameRateCategoryRate; + supportedRefreshRates = other.supportedRefreshRates; defaultModeId = other.defaultModeId; userPreferredModeId = other.userPreferredModeId; supportedModes = other.supportedModes; @@ -628,6 +635,7 @@ final class DisplayDeviceInfo { sb.append(", renderFrameRate ").append(renderFrameRate); sb.append(", hasArrSupport ").append(hasArrSupport); sb.append(", frameRateCategoryRate ").append(frameRateCategoryRate); + sb.append(", supportedRefreshRates ").append(Arrays.toString(supportedRefreshRates)); sb.append(", defaultModeId ").append(defaultModeId); sb.append(", userPreferredModeId ").append(userPreferredModeId); sb.append(", supportedModes ").append(Arrays.toString(supportedModes)); diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java index ae74dbecc5f8..3871f2a57f76 100644 --- a/services/core/java/com/android/server/display/DisplayManagerService.java +++ b/services/core/java/com/android/server/display/DisplayManagerService.java @@ -17,6 +17,7 @@ package com.android.server.display; import static android.Manifest.permission.ADD_ALWAYS_UNLOCKED_DISPLAY; +import static android.Manifest.permission.ADD_MIRROR_DISPLAY; import static android.Manifest.permission.ADD_TRUSTED_DISPLAY; import static android.Manifest.permission.CAPTURE_SECURE_VIDEO_OUTPUT; import static android.Manifest.permission.CAPTURE_VIDEO_OUTPUT; @@ -1677,15 +1678,10 @@ public final class DisplayManagerService extends SystemService { } private boolean canCreateMirrorDisplays(IVirtualDevice virtualDevice) { - if (virtualDevice == null) { - return false; - } - try { - return virtualDevice.canCreateMirrorDisplays(); - } catch (RemoteException e) { - Slog.e(TAG, "Unable to query virtual device for permissions", e); - return false; + if (android.companion.virtualdevice.flags.Flags.enableLimitedVdmRole()) { + return checkCallingPermission(ADD_MIRROR_DISPLAY, "canCreateMirrorDisplays"); } + return virtualDevice != null; } private boolean canProjectVideo(IMediaProjection projection) { @@ -1818,7 +1814,7 @@ public final class DisplayManagerService extends SystemService { // display. if (!canProjectVideo(projection) && !canCreateMirrorDisplays(virtualDevice) && !hasVideoOutputPermission("createVirtualDisplayInternal")) { - throw new SecurityException("Requires CAPTURE_VIDEO_OUTPUT or " + throw new SecurityException("Requires ADD_MIRROR_DISPLAY, CAPTURE_VIDEO_OUTPUT or " + "CAPTURE_SECURE_VIDEO_OUTPUT permission, or an appropriate " + "MediaProjection token in order to create a screen sharing virtual " + "display. In order to create a virtual display that does not perform " diff --git a/services/core/java/com/android/server/display/LocalDisplayAdapter.java b/services/core/java/com/android/server/display/LocalDisplayAdapter.java index a4bb8c348d3f..0b8f7d5ef2cf 100644 --- a/services/core/java/com/android/server/display/LocalDisplayAdapter.java +++ b/services/core/java/com/android/server/display/LocalDisplayAdapter.java @@ -249,6 +249,7 @@ final class LocalDisplayAdapter extends DisplayAdapter { private int mActiveColorMode; private boolean mHasArrSupport; private FrameRateCategoryRate mFrameRateCategoryRate; + private float[] mSupportedRefreshRates = new float[0]; private Display.HdrCapabilities mHdrCapabilities; private boolean mAllmSupported; private boolean mGameContentTypeSupported; @@ -316,6 +317,7 @@ final class LocalDisplayAdapter extends DisplayAdapter { changed |= updateGameContentTypeSupport(dynamicInfo.gameContentTypeSupported); changed |= updateHasArrSupportLocked(dynamicInfo.hasArrSupport); changed |= updateFrameRateCategoryRatesLocked(dynamicInfo.frameRateCategoryRate); + changed |= updateSupportedRefreshatesLocked(dynamicInfo.supportedRefreshRates); if (changed) { mHavePendingChanges = true; @@ -624,6 +626,20 @@ final class LocalDisplayAdapter extends DisplayAdapter { return true; } + private boolean updateSupportedRefreshatesLocked(float[] supportedRefreshRates) { + if (!getFeatureFlags().enableGetSupportedRefreshRates()) { + return false; + } + if (supportedRefreshRates == null) { + return false; + } + if (Arrays.equals(mSupportedRefreshRates, supportedRefreshRates)) { + return false; + } + mSupportedRefreshRates = supportedRefreshRates; + return true; + } + private boolean updateAllmSupport(boolean supported) { if (mAllmSupported == supported) { return false; @@ -708,6 +724,7 @@ final class LocalDisplayAdapter extends DisplayAdapter { mInfo.hdrCapabilities = mHdrCapabilities; mInfo.hasArrSupport = mHasArrSupport; mInfo.frameRateCategoryRate = mFrameRateCategoryRate; + mInfo.supportedRefreshRates = mSupportedRefreshRates; mInfo.appVsyncOffsetNanos = mActiveSfDisplayMode.appVsyncOffsetNanos; mInfo.presentationDeadlineNanos = mActiveSfDisplayMode.presentationDeadlineNanos; mInfo.state = mState; @@ -1299,6 +1316,7 @@ final class LocalDisplayAdapter extends DisplayAdapter { pw.println("mDefaultModeId=" + mDefaultModeId); pw.println("mUserPreferredModeId=" + mUserPreferredModeId); pw.println("mHasArrSupport=" + mHasArrSupport); + pw.println("mSupportedRefreshRates=" + Arrays.toString(mSupportedRefreshRates)); pw.println("mState=" + Display.stateToString(mState)); pw.println("mCommittedState=" + Display.stateToString(mCommittedState)); pw.println("mBrightnessState=" + mBrightnessState); diff --git a/services/core/java/com/android/server/display/LogicalDisplay.java b/services/core/java/com/android/server/display/LogicalDisplay.java index 7cfdcafcb610..85465981c473 100644 --- a/services/core/java/com/android/server/display/LogicalDisplay.java +++ b/services/core/java/com/android/server/display/LogicalDisplay.java @@ -508,6 +508,8 @@ final class LogicalDisplay { mBaseDisplayInfo.renderFrameRate = deviceInfo.renderFrameRate; mBaseDisplayInfo.hasArrSupport = deviceInfo.hasArrSupport; mBaseDisplayInfo.frameRateCategoryRate = deviceInfo.frameRateCategoryRate; + mBaseDisplayInfo.supportedRefreshRates = Arrays.copyOf( + deviceInfo.supportedRefreshRates, deviceInfo.supportedRefreshRates.length); mBaseDisplayInfo.defaultModeId = deviceInfo.defaultModeId; mBaseDisplayInfo.userPreferredModeId = deviceInfo.userPreferredModeId; mBaseDisplayInfo.supportedModes = Arrays.copyOf( diff --git a/services/core/java/com/android/server/display/feature/DisplayManagerFlags.java b/services/core/java/com/android/server/display/feature/DisplayManagerFlags.java index 7f46bbbf0507..e273c6862fe0 100644 --- a/services/core/java/com/android/server/display/feature/DisplayManagerFlags.java +++ b/services/core/java/com/android/server/display/feature/DisplayManagerFlags.java @@ -243,6 +243,11 @@ public class DisplayManagerFlags { Flags::autoBrightnessModeBedtimeWear ); + private final FlagState mGetSupportedRefreshRatesFlagState = new FlagState( + Flags.FLAG_ENABLE_GET_SUPPORTED_REFRESH_RATES, + Flags::enableGetSupportedRefreshRates + ); + private final FlagState mEnablePluginManagerFlagState = new FlagState( Flags.FLAG_ENABLE_PLUGIN_MANAGER, Flags::enablePluginManager @@ -528,6 +533,13 @@ public class DisplayManagerFlags { return mAutoBrightnessModeBedtimeWearFlagState.isEnabled(); } + /** + * @return {@code true} if supported refresh rate api is enabled. + */ + public boolean enableGetSupportedRefreshRates() { + return mGetSupportedRefreshRatesFlagState.isEnabled(); + } + public boolean isPluginManagerEnabled() { return mEnablePluginManagerFlagState.isEnabled(); } @@ -590,6 +602,7 @@ public class DisplayManagerFlags { pw.println(" " + mIsUserRefreshRateForExternalDisplayEnabled); pw.println(" " + mHasArrSupport); pw.println(" " + mAutoBrightnessModeBedtimeWearFlagState); + pw.println(" " + mGetSupportedRefreshRatesFlagState); pw.println(" " + mEnablePluginManagerFlagState); pw.println(" " + mDisplayListenerPerformanceImprovementsFlagState); } diff --git a/services/core/java/com/android/server/hdmi/Constants.java b/services/core/java/com/android/server/hdmi/Constants.java index 0e7d2b631833..a06f9ef634d1 100644 --- a/services/core/java/com/android/server/hdmi/Constants.java +++ b/services/core/java/com/android/server/hdmi/Constants.java @@ -524,6 +524,13 @@ final class Constants { static final String PROPERTY_DISABLE_CEC_ON_STANDBY_IN_LOW_ENERGY_MODE = "persist.sys.hdmi.property_disable_cec_on_standby_in_low_energy_mode"; + /** + * Property that checks if CEC was manually enabled by the user in offline mode. With the help + * of this property we avoid turning off CEC when the device goes to sleep and if the device + * is in low energy mode. + */ + static final String PROPERTY_USER_ACTION_KEEP_CEC_ENABLED_IN_OFFLINE_MODE = + "persist.sys.hdmi.property_user_action_keep_cec_enabled_in_offline_mode"; static final int RECORDING_TYPE_DIGITAL_RF = 1; static final int RECORDING_TYPE_ANALOGUE_RF = 2; static final int RECORDING_TYPE_EXTERNAL_PHYSICAL_ADDRESS = 3; diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java index 0c5069f81774..6e98bff8dda5 100644 --- a/services/core/java/com/android/server/hdmi/HdmiControlService.java +++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java @@ -4027,7 +4027,8 @@ public class HdmiControlService extends SystemService { return; } if (isTvDevice() && getDisableCecOnStandbyByLowEnergyMode() - && mPowerManager.isLowPowerStandbyEnabled()) { + && mPowerManager.isLowPowerStandbyEnabled() + && !userEnabledCecInOfflineMode()) { Slog.w(TAG, "Disable CEC on standby due to low power energy mode."); setWasCecDisabledOnStandbyByLowEnergyMode(true); getHdmiCecConfig().setIntValue( @@ -5225,4 +5226,14 @@ public class HdmiControlService extends SystemService { Constants.PROPERTY_WAS_CEC_DISABLED_ON_STANDBY_BY_LOW_ENERGY_MODE, String.valueOf(value)); } + + /** + * Reads the property that checks if CEC was enabled by the user while in offline mode such that + * it won't be disabled when going to sleep by low energy mode. + */ + @VisibleForTesting + protected boolean userEnabledCecInOfflineMode() { + return SystemProperties.getBoolean( + Constants.PROPERTY_USER_ACTION_KEEP_CEC_ENABLED_IN_OFFLINE_MODE, false); + } } diff --git a/services/core/java/com/android/server/inputmethod/HandwritingEventReceiverSurface.java b/services/core/java/com/android/server/inputmethod/HandwritingEventReceiverSurface.java index d13244905633..da2089131b9f 100644 --- a/services/core/java/com/android/server/inputmethod/HandwritingEventReceiverSurface.java +++ b/services/core/java/com/android/server/inputmethod/HandwritingEventReceiverSurface.java @@ -19,13 +19,19 @@ package com.android.server.inputmethod; import static android.os.InputConstants.DEFAULT_DISPATCHING_TIMEOUT_MILLIS; import android.annotation.NonNull; +import android.content.Context; +import android.graphics.Rect; +import android.graphics.Region; import android.os.InputConfig; import android.os.Process; +import android.util.Slog; import android.view.InputApplicationHandle; import android.view.InputChannel; import android.view.InputWindowHandle; import android.view.SurfaceControl; import android.view.WindowManager; +import android.view.WindowMetrics; +import android.view.inputmethod.Flags; import com.android.server.input.InputManagerService; @@ -39,8 +45,8 @@ final class HandwritingEventReceiverSurface { private final SurfaceControl mInputSurface; private boolean mIsIntercepting; - HandwritingEventReceiverSurface(String name, int displayId, @NonNull SurfaceControl sc, - @NonNull InputChannel inputChannel) { + HandwritingEventReceiverSurface(Context context, String name, int displayId, + @NonNull SurfaceControl sc, @NonNull InputChannel inputChannel) { mClientChannel = inputChannel; mInputSurface = sc; @@ -59,15 +65,31 @@ final class HandwritingEventReceiverSurface { | InputConfig.SPY | InputConfig.INTERCEPTS_STYLUS; - // Configure the surface to receive stylus events across the entire display. - mWindowHandle.replaceTouchableRegionWithCrop(null /* use this surface's bounds */); + Rect bounds = null; + if (Flags.adaptiveHandwritingBounds()) { + mWindowHandle.setTouchableRegionCrop(mInputSurface); + // Default touchable area to getMaximumWindowMetrics() + WindowMetrics windowMetrics = context.getSystemService(WindowManager.class) + .getMaximumWindowMetrics(); + bounds = windowMetrics.getBounds(); + if (DEBUG) Slog.d(TAG, "initial handwriting touchable bounds: " + bounds); + mWindowHandle.setTouchableRegion(windowMetrics.getBounds()); + } else { + // Configure the surface to receive stylus events across the entire display. + mWindowHandle.replaceTouchableRegionWithCrop(null /* use this surface's bounds */); + } final SurfaceControl.Transaction t = new SurfaceControl.Transaction(); mWindowHandle.setTrustedOverlay(t, mInputSurface, true); t.setInputWindowInfo(mInputSurface, mWindowHandle); t.setLayer(mInputSurface, InputManagerService.INPUT_OVERLAY_LAYER_HANDWRITING_SURFACE); t.setPosition(mInputSurface, 0, 0); - t.setCrop(mInputSurface, null /* crop to parent surface */); + if (Flags.adaptiveHandwritingBounds()) { + // crop to parent surface if null, else bounds. + t.setCrop(mInputSurface, bounds); + } else { + t.setCrop(mInputSurface, null /* crop to parent surface */); + } t.show(mInputSurface); t.apply(); @@ -79,12 +101,23 @@ final class HandwritingEventReceiverSurface { mWindowHandle.ownerUid = imeUid; mWindowHandle.inputConfig &= ~InputConfig.SPY; + if (Flags.adaptiveHandwritingBounds()) { + // watch outside touch to finish handwriting. + mWindowHandle.inputConfig |= InputConfig.WATCH_OUTSIDE_TOUCH; + } new SurfaceControl.Transaction() .setInputWindowInfo(mInputSurface, mWindowHandle) .apply(); mIsIntercepting = true; } + void setTouchableRegion(Region touchableRegion) { + mWindowHandle.touchableRegion.set(touchableRegion); + new SurfaceControl.Transaction() + .setInputWindowInfo(mInputSurface, mWindowHandle) + .apply(); + } + void setNotTouchable(boolean notTouchable) { if (notTouchable) { mWindowHandle.inputConfig |= InputConfig.NOT_TOUCHABLE; diff --git a/services/core/java/com/android/server/inputmethod/HandwritingModeController.java b/services/core/java/com/android/server/inputmethod/HandwritingModeController.java index c19cb030ef37..45d7d0464fe1 100644 --- a/services/core/java/com/android/server/inputmethod/HandwritingModeController.java +++ b/services/core/java/com/android/server/inputmethod/HandwritingModeController.java @@ -27,6 +27,7 @@ import android.annotation.UiThread; import android.content.ComponentName; import android.content.Context; import android.content.pm.PackageManagerInternal; +import android.graphics.Region; import android.hardware.input.InputManager; import android.hardware.input.InputManagerGlobal; import android.os.Handler; @@ -139,7 +140,7 @@ final class HandwritingModeController { } mHandwritingSurface = new HandwritingEventReceiverSurface( - name, displayId, surface, channel); + mContext, name, displayId, surface, channel); // Use a dup of the input channel so that event processing can be paused by disposing the // event receiver without causing a fd hangup. @@ -163,6 +164,13 @@ final class HandwritingModeController { mHandwritingSurface.setNotTouchable(notTouchable); } + void setHandwritingTouchableRegion(Region region) { + if (!getCurrentRequestId().isPresent()) { + return; + } + mHandwritingSurface.setTouchableRegion(region); + } + boolean isStylusGestureOngoing() { if (mRecordingGestureAfterStylusUp && !mHandwritingBuffer.isEmpty()) { // If it is less than AFTER_STYLUS_UP_ALLOW_PERIOD_MS after the stylus up event, return diff --git a/services/core/java/com/android/server/location/contexthub/ContextHubService.java b/services/core/java/com/android/server/location/contexthub/ContextHubService.java index 76049ca824c2..d177d0e5f2eb 100644 --- a/services/core/java/com/android/server/location/contexthub/ContextHubService.java +++ b/services/core/java/com/android/server/location/contexthub/ContextHubService.java @@ -34,6 +34,7 @@ import android.hardware.contexthub.ErrorCode; import android.hardware.contexthub.HubEndpointInfo; import android.hardware.contexthub.IContextHubEndpoint; import android.hardware.contexthub.IContextHubEndpointCallback; +import android.hardware.contexthub.IContextHubEndpointDiscoveryCallback; import android.hardware.contexthub.MessageDeliveryStatus; import android.hardware.location.ContextHubInfo; import android.hardware.location.ContextHubMessage; @@ -793,6 +794,31 @@ public class ContextHubService extends IContextHubService.Stub { return null; } + @android.annotation.EnforcePermission(android.Manifest.permission.ACCESS_CONTEXT_HUB) + @Override + public void registerEndpointDiscoveryCallbackId( + long endpointId, IContextHubEndpointDiscoveryCallback callback) throws RemoteException { + super.registerEndpointDiscoveryCallbackId_enforcePermission(); + // TODO(b/375487784): Implement this + } + + @android.annotation.EnforcePermission(android.Manifest.permission.ACCESS_CONTEXT_HUB) + @Override + public void registerEndpointDiscoveryCallbackDescriptor( + String serviceDescriptor, IContextHubEndpointDiscoveryCallback callback) + throws RemoteException { + super.registerEndpointDiscoveryCallbackDescriptor_enforcePermission(); + // TODO(b/375487784): Implement this + } + + @android.annotation.EnforcePermission(android.Manifest.permission.ACCESS_CONTEXT_HUB) + @Override + public void unregisterEndpointDiscoveryCallback(IContextHubEndpointDiscoveryCallback callback) + throws RemoteException { + super.unregisterEndpointDiscoveryCallback_enforcePermission(); + // TODO(b/375487784): Implement this + } + /** * Creates an internal load transaction callback to be used for old API clients * diff --git a/services/core/java/com/android/server/media/projection/FrameworkStatsLogWrapper.java b/services/core/java/com/android/server/media/projection/FrameworkStatsLogWrapper.java index 6c74cba99bcb..05fe78114eca 100644 --- a/services/core/java/com/android/server/media/projection/FrameworkStatsLogWrapper.java +++ b/services/core/java/com/android/server/media/projection/FrameworkStatsLogWrapper.java @@ -30,7 +30,8 @@ public class FrameworkStatsLogWrapper { int hostUid, int targetUid, int timeSinceLastActive, - int creationSource) { + int creationSource, + int stopSource) { FrameworkStatsLog.write( code, sessionId, @@ -39,7 +40,8 @@ public class FrameworkStatsLogWrapper { hostUid, targetUid, timeSinceLastActive, - creationSource); + creationSource, + stopSource); } /** Wrapper around {@link FrameworkStatsLog#write} for MediaProjectionTargetChanged atom. */ @@ -49,13 +51,23 @@ public class FrameworkStatsLogWrapper { int targetType, int hostUid, int targetUid, - int windowingMode) { + int windowingMode, + int width, + int height, + int centerX, + int centerY, + int targetChangeType) { FrameworkStatsLog.write( code, sessionId, targetType, hostUid, targetUid, - windowingMode); + windowingMode, + width, + height, + centerX, + centerY, + targetChangeType); } } diff --git a/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java b/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java index df5ecf872df4..c428f39fd9d0 100644 --- a/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java +++ b/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java @@ -51,6 +51,7 @@ import android.content.pm.PackageManager; import android.content.pm.PackageManager.ApplicationInfoFlags; import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.ServiceInfo; +import android.graphics.Rect; import android.hardware.display.DisplayManager; import android.media.MediaRouter; import android.media.projection.IMediaProjection; @@ -60,6 +61,7 @@ import android.media.projection.IMediaProjectionWatcherCallback; import android.media.projection.MediaProjectionInfo; import android.media.projection.MediaProjectionManager; import android.media.projection.ReviewGrantedConsentResult; +import android.media.projection.StopReason; import android.os.Binder; import android.os.Build; import android.os.Handler; @@ -178,7 +180,7 @@ public final class MediaProjectionManagerService extends SystemService if (!mMediaProjectionStopController.isExemptFromStopping(mProjectionGrant, reason)) { Slog.d(TAG, "Content Recording: Stopping MediaProjection due to " + MediaProjectionStopController.stopReasonToString(reason)); - mProjectionGrant.stop(); + mProjectionGrant.stop(StopReason.STOP_DEVICE_LOCKED); } } } @@ -257,7 +259,7 @@ public final class MediaProjectionManagerService extends SystemService synchronized (mLock) { if (mProjectionGrant != null) { Slog.d(TAG, "Content Recording: Stopped MediaProjection due to user switching"); - mProjectionGrant.stop(); + mProjectionGrant.stop(StopReason.STOP_USER_SWITCH); } } } @@ -295,7 +297,7 @@ public final class MediaProjectionManagerService extends SystemService Slog.d(TAG, "Content Recording: Stopped MediaProjection due to foreground service change"); if (mProjectionGrant != null) { - mProjectionGrant.stop(); + mProjectionGrant.stop(StopReason.STOP_FOREGROUND_SERVICE_CHANGE); } } } @@ -304,7 +306,7 @@ public final class MediaProjectionManagerService extends SystemService if (mProjectionGrant != null) { Slog.d(TAG, "Content Recording: Stopped MediaProjection to start new " + "incoming projection"); - mProjectionGrant.stop(); + mProjectionGrant.stop(StopReason.STOP_NEW_PROJECTION); } if (mMediaRouteInfo != null) { mMediaRouter.getFallbackRoute().select(); @@ -314,7 +316,10 @@ public final class MediaProjectionManagerService extends SystemService dispatchStart(projection); } - private void stopProjectionLocked(final MediaProjection projection) { + private void stopProjectionLocked( + final MediaProjection projection, + @StopReason int stopReason + ) { Slog.d(TAG, "Content Recording: Stopped active MediaProjection and " + "dispatching stop to callbacks"); ContentRecordingSession session = projection.mSession; @@ -322,7 +327,7 @@ public final class MediaProjectionManagerService extends SystemService session != null ? session.getTargetUid() : ContentRecordingSession.TARGET_UID_UNKNOWN; - mMediaProjectionMetricsLogger.logStopped(projection.uid, targetUid); + mMediaProjectionMetricsLogger.logStopped(projection.uid, targetUid, stopReason); mProjectionToken = null; mProjectionGrant = null; dispatchStop(projection); @@ -403,7 +408,7 @@ public final class MediaProjectionManagerService extends SystemService + "ContentRecordingSession - id= " + mProjectionGrant.getVirtualDisplayId() + "type=" + projectionType); - mProjectionGrant.stop(); + mProjectionGrant.stop(StopReason.STOP_ERROR); } return false; } @@ -517,6 +522,18 @@ public final class MediaProjectionManagerService extends SystemService } } + @VisibleForTesting + void notifyCaptureBoundsChanged(int contentToRecord, int targetUid, Rect captureBounds) { + synchronized (mLock) { + if (mProjectionGrant == null) { + Slog.i(TAG, "Cannot log MediaProjectionTargetChanged atom due to null projection"); + } else { + mMediaProjectionMetricsLogger.logChangedCaptureBounds( + contentToRecord, mProjectionGrant.uid, targetUid, captureBounds); + } + } + } + /** * Handles result of dialog shown from * {@link BinderService#buildReviewGrantedConsentIntentLocked()}. @@ -557,7 +574,7 @@ public final class MediaProjectionManagerService extends SystemService Slog.w(TAG, "Content Recording: Stopped MediaProjection due to user " + "consent result of CANCEL - " + "id= " + mProjectionGrant.getVirtualDisplayId()); - mProjectionGrant.stop(); + mProjectionGrant.stop(StopReason.STOP_ERROR); } break; case RECORD_CONTENT_DISPLAY: @@ -773,14 +790,14 @@ public final class MediaProjectionManagerService extends SystemService @android.annotation.EnforcePermission(android.Manifest.permission.MANAGE_MEDIA_PROJECTION) @Override // Binder call - public void stopActiveProjection() { + public void stopActiveProjection(@StopReason int stopReason) { stopActiveProjection_enforcePermission(); final long token = Binder.clearCallingIdentity(); try { synchronized (mLock) { if (mProjectionGrant != null) { Slog.d(TAG, "Content Recording: Stopping active projection"); - mProjectionGrant.stop(); + mProjectionGrant.stop(stopReason); } } } finally { @@ -790,8 +807,9 @@ public final class MediaProjectionManagerService extends SystemService @android.annotation.EnforcePermission(android.Manifest.permission.MANAGE_MEDIA_PROJECTION) @Override // Binder call - public void notifyActiveProjectionCapturedContentResized(int width, int height) { - notifyActiveProjectionCapturedContentResized_enforcePermission(); + public void notifyCaptureBoundsChanged( + int contentToRecord, int targetProcessUid, Rect newBounds) { + notifyCaptureBoundsChanged_enforcePermission(); synchronized (mLock) { if (!isCurrentProjection(mProjectionGrant)) { return; @@ -801,7 +819,13 @@ public final class MediaProjectionManagerService extends SystemService try { synchronized (mLock) { if (mProjectionGrant != null && mCallbackDelegate != null) { - mCallbackDelegate.dispatchResize(mProjectionGrant, width, height); + // log metrics for the new bounds + MediaProjectionManagerService.this.notifyCaptureBoundsChanged( + contentToRecord, targetProcessUid, newBounds); + + // update clients of the new update bounds + mCallbackDelegate.dispatchResize( + mProjectionGrant, newBounds.width(), newBounds.height()); } } } finally { @@ -1133,7 +1157,7 @@ public final class MediaProjectionManagerService extends SystemService Slog.d(TAG, "Content Recording: MediaProjection stopped by Binder death - " + "id= " + mVirtualDisplayId); mCallbackDelegate.remove(callback); - stop(); + stop(StopReason.STOP_TARGET_REMOVED); }; mToken.linkToDeath(mDeathEater, 0); } catch (RemoteException e) { @@ -1182,7 +1206,7 @@ public final class MediaProjectionManagerService extends SystemService } @Override // Binder call - public void stop() { + public void stop(@StopReason int stopReason) { synchronized (mLock) { if (!isCurrentProjection(asBinder())) { Slog.w(TAG, "Attempted to stop inactive MediaProjection " @@ -1211,7 +1235,7 @@ public final class MediaProjectionManagerService extends SystemService Slog.d(TAG, "Content Recording: handling stopping this projection token" + " createTime= " + mCreateTimeMillis + " countStarts= " + mCountStarts); - stopProjectionLocked(this); + stopProjectionLocked(this, stopReason); mToken.unlinkToDeath(mDeathEater, 0); mToken = null; unregisterCallback(mCallback); @@ -1295,7 +1319,7 @@ public final class MediaProjectionManagerService extends SystemService Slog.v(TAG, "Reusing token: Throw exception due to invalid projection."); // Tear down projection here; necessary to ensure (among other reasons) that // stop is dispatched to client and cast icon disappears from status bar. - mProjectionGrant.stop(); + mProjectionGrant.stop(StopReason.STOP_ERROR); throw new SecurityException("Don't re-use the resultData to retrieve " + "the same projection instance, and don't use a token that has " + "timed out. Don't take multiple captures by invoking " @@ -1315,10 +1339,9 @@ public final class MediaProjectionManagerService extends SystemService Slog.w(TAG, "Content Recording: MediaProjection start disallowed, aborting " + "MediaProjection"); - stop(); + stop(StopReason.STOP_DEVICE_LOCKED); return; } - mVirtualDisplayId = displayId; // If prior session was does not have a valid display id, then update the display @@ -1357,7 +1380,7 @@ public final class MediaProjectionManagerService extends SystemService if (mProjectionGrant != null) { Slog.d(TAG, "Content Recording: Stopped MediaProjection due to " + "route type of REMOTE_DISPLAY not selected"); - mProjectionGrant.stop(); + mProjectionGrant.stop(StopReason.STOP_NEW_MEDIA_ROUTE); } } } diff --git a/services/core/java/com/android/server/media/projection/MediaProjectionMetricsLogger.java b/services/core/java/com/android/server/media/projection/MediaProjectionMetricsLogger.java index be2a25a755a5..8e5c01685275 100644 --- a/services/core/java/com/android/server/media/projection/MediaProjectionMetricsLogger.java +++ b/services/core/java/com/android/server/media/projection/MediaProjectionMetricsLogger.java @@ -19,15 +19,34 @@ package com.android.server.media.projection; import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM; import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW; +import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; import static android.view.ContentRecordingSession.RECORD_CONTENT_DISPLAY; import static android.view.ContentRecordingSession.RECORD_CONTENT_TASK; +import static com.android.internal.util.FrameworkStatsLog.MEDIA_PROJECTION_STATE_CHANGED; +import static com.android.internal.util.FrameworkStatsLog.MEDIA_PROJECTION_STATE_CHANGED__STATE__MEDIA_PROJECTION_STATE_CANCELLED; +import static com.android.internal.util.FrameworkStatsLog.MEDIA_PROJECTION_STATE_CHANGED__STATE__MEDIA_PROJECTION_STATE_UNKNOWN; +import static com.android.internal.util.FrameworkStatsLog.MEDIA_PROJECTION_STATE_CHANGED__STOP_SOURCE__STOP_SOURCE_DEVICE_LOCK; +import static com.android.internal.util.FrameworkStatsLog.MEDIA_PROJECTION_STATE_CHANGED__STOP_SOURCE__STOP_SOURCE_ERROR; +import static com.android.internal.util.FrameworkStatsLog.MEDIA_PROJECTION_STATE_CHANGED__STOP_SOURCE__STOP_SOURCE_FOREGROUND_SERVICE_CHANGE; +import static com.android.internal.util.FrameworkStatsLog.MEDIA_PROJECTION_STATE_CHANGED__STOP_SOURCE__STOP_SOURCE_HOST_APP_STOP; +import static com.android.internal.util.FrameworkStatsLog.MEDIA_PROJECTION_STATE_CHANGED__STOP_SOURCE__STOP_SOURCE_NEW_MEDIA_ROUTE; +import static com.android.internal.util.FrameworkStatsLog.MEDIA_PROJECTION_STATE_CHANGED__STOP_SOURCE__STOP_SOURCE_NEW_PROJECTION; +import static com.android.internal.util.FrameworkStatsLog.MEDIA_PROJECTION_STATE_CHANGED__STOP_SOURCE__STOP_SOURCE_QS_TILE; +import static com.android.internal.util.FrameworkStatsLog.MEDIA_PROJECTION_STATE_CHANGED__STOP_SOURCE__STOP_SOURCE_STATUS_BAR_CHIP_STOP; +import static com.android.internal.util.FrameworkStatsLog.MEDIA_PROJECTION_STATE_CHANGED__STOP_SOURCE__STOP_SOURCE_TASK_APP_CLOSE; +import static com.android.internal.util.FrameworkStatsLog.MEDIA_PROJECTION_STATE_CHANGED__STOP_SOURCE__STOP_SOURCE_UNKNOWN; import static com.android.internal.util.FrameworkStatsLog.MEDIA_PROJECTION_STATE_CHANGED__CREATION_SOURCE__CREATION_SOURCE_UNKNOWN; import static com.android.internal.util.FrameworkStatsLog.MEDIA_PROJECTION_STATE_CHANGED__STATE__MEDIA_PROJECTION_STATE_APP_SELECTOR_DISPLAYED; import static com.android.internal.util.FrameworkStatsLog.MEDIA_PROJECTION_STATE_CHANGED__STATE__MEDIA_PROJECTION_STATE_CAPTURING_IN_PROGRESS; import static com.android.internal.util.FrameworkStatsLog.MEDIA_PROJECTION_STATE_CHANGED__STATE__MEDIA_PROJECTION_STATE_INITIATED; import static com.android.internal.util.FrameworkStatsLog.MEDIA_PROJECTION_STATE_CHANGED__STATE__MEDIA_PROJECTION_STATE_PERMISSION_REQUEST_DISPLAYED; import static com.android.internal.util.FrameworkStatsLog.MEDIA_PROJECTION_STATE_CHANGED__STATE__MEDIA_PROJECTION_STATE_STOPPED; +import static com.android.internal.util.FrameworkStatsLog.MEDIA_PROJECTION_STATE_CHANGED__STOP_SOURCE__STOP_SOURCE_USER_SWITCH; +import static com.android.internal.util.FrameworkStatsLog.MEDIA_PROJECTION_TARGET_CHANGED; +import static com.android.internal.util.FrameworkStatsLog.MEDIA_PROJECTION_TARGET_CHANGED__TARGET_CHANGE_TYPE__TARGET_CHANGE_BOUNDS; +import static com.android.internal.util.FrameworkStatsLog.MEDIA_PROJECTION_TARGET_CHANGED__TARGET_CHANGE_TYPE__TARGET_CHANGE_POSITION; +import static com.android.internal.util.FrameworkStatsLog.MEDIA_PROJECTION_TARGET_CHANGED__TARGET_CHANGE_TYPE__TARGET_CHANGE_WINDOWING_MODE; import static com.android.internal.util.FrameworkStatsLog.MEDIA_PROJECTION_TARGET_CHANGED__TARGET_TYPE__TARGET_TYPE_APP_TASK; import static com.android.internal.util.FrameworkStatsLog.MEDIA_PROJECTION_TARGET_CHANGED__TARGET_TYPE__TARGET_TYPE_DISPLAY; import static com.android.internal.util.FrameworkStatsLog.MEDIA_PROJECTION_TARGET_CHANGED__TARGET_TYPE__TARGET_TYPE_UNKNOWN; @@ -36,8 +55,12 @@ import static com.android.internal.util.FrameworkStatsLog.MEDIA_PROJECTION_TARGE import static com.android.internal.util.FrameworkStatsLog.MEDIA_PROJECTION_TARGET_CHANGED__TARGET_WINDOWING_MODE__WINDOWING_MODE_SPLIT_SCREEN; import static com.android.internal.util.FrameworkStatsLog.MEDIA_PROJECTION_TARGET_CHANGED__TARGET_WINDOWING_MODE__WINDOWING_MODE_UNKNOWN; +import android.app.WindowConfiguration; import android.app.WindowConfiguration.WindowingMode; import android.content.Context; +import android.graphics.Point; +import android.graphics.Rect; +import android.media.projection.StopReason; import android.util.Log; import android.view.ContentRecordingSession.RecordContent; @@ -59,8 +82,10 @@ public class MediaProjectionMetricsLogger { private final MediaProjectionSessionIdGenerator mSessionIdGenerator; private final MediaProjectionTimestampStore mTimestampStore; - private int mPreviousState = - FrameworkStatsLog.MEDIA_PROJECTION_STATE_CHANGED__STATE__MEDIA_PROJECTION_STATE_UNKNOWN; + private final Rect mPreviousTargetBounds = new Rect(); + private int mPreviousTargetWindowingMode = WINDOWING_MODE_UNDEFINED; + private int mPreviousProjectionState = + MEDIA_PROJECTION_STATE_CHANGED__STATE__MEDIA_PROJECTION_STATE_UNKNOWN; MediaProjectionMetricsLogger( FrameworkStatsLogWrapper frameworkStatsLogWrapper, @@ -113,7 +138,8 @@ public class MediaProjectionMetricsLogger { hostUid, TARGET_UID_UNKNOWN, timeSinceLastActiveInSeconds, - sessionCreationSource); + sessionCreationSource, + MEDIA_PROJECTION_STATE_CHANGED__STOP_SOURCE__STOP_SOURCE_UNKNOWN); } /** @@ -130,7 +156,8 @@ public class MediaProjectionMetricsLogger { hostUid, TARGET_UID_UNKNOWN, TIME_SINCE_LAST_ACTIVE_UNKNOWN, - MEDIA_PROJECTION_STATE_CHANGED__CREATION_SOURCE__CREATION_SOURCE_UNKNOWN); + MEDIA_PROJECTION_STATE_CHANGED__CREATION_SOURCE__CREATION_SOURCE_UNKNOWN, + MEDIA_PROJECTION_STATE_CHANGED__STOP_SOURCE__STOP_SOURCE_UNKNOWN); } /** @@ -141,13 +168,12 @@ public class MediaProjectionMetricsLogger { public void logProjectionPermissionRequestCancelled(int hostUid) { writeStateChanged( mSessionIdGenerator.getCurrentSessionId(), - FrameworkStatsLog - .MEDIA_PROJECTION_STATE_CHANGED__STATE__MEDIA_PROJECTION_STATE_CANCELLED, + MEDIA_PROJECTION_STATE_CHANGED__STATE__MEDIA_PROJECTION_STATE_CANCELLED, hostUid, TARGET_UID_UNKNOWN, TIME_SINCE_LAST_ACTIVE_UNKNOWN, - FrameworkStatsLog - .MEDIA_PROJECTION_STATE_CHANGED__CREATION_SOURCE__CREATION_SOURCE_UNKNOWN); + MEDIA_PROJECTION_STATE_CHANGED__CREATION_SOURCE__CREATION_SOURCE_UNKNOWN, + MEDIA_PROJECTION_STATE_CHANGED__STOP_SOURCE__STOP_SOURCE_UNKNOWN); } /** @@ -163,7 +189,8 @@ public class MediaProjectionMetricsLogger { hostUid, TARGET_UID_UNKNOWN, TIME_SINCE_LAST_ACTIVE_UNKNOWN, - MEDIA_PROJECTION_STATE_CHANGED__CREATION_SOURCE__CREATION_SOURCE_UNKNOWN); + MEDIA_PROJECTION_STATE_CHANGED__CREATION_SOURCE__CREATION_SOURCE_UNKNOWN, + MEDIA_PROJECTION_STATE_CHANGED__STOP_SOURCE__STOP_SOURCE_UNKNOWN); } /** @@ -180,7 +207,8 @@ public class MediaProjectionMetricsLogger { hostUid, targetUid, TIME_SINCE_LAST_ACTIVE_UNKNOWN, - MEDIA_PROJECTION_STATE_CHANGED__CREATION_SOURCE__CREATION_SOURCE_UNKNOWN); + MEDIA_PROJECTION_STATE_CHANGED__CREATION_SOURCE__CREATION_SOURCE_UNKNOWN, + MEDIA_PROJECTION_STATE_CHANGED__STOP_SOURCE__STOP_SOURCE_UNKNOWN); } /** @@ -196,14 +224,63 @@ public class MediaProjectionMetricsLogger { */ public void logChangedWindowingMode( int contentToRecord, int hostUid, int targetUid, int windowingMode) { - Log.d(TAG, "logChangedWindowingMode"); + Log.d(TAG, "logChangedWindowingMode: windowingMode= " + + WindowConfiguration.windowingModeToString(windowingMode)); + Log.d(TAG, "targetChangeType= changeWindowingMode"); writeTargetChanged( mSessionIdGenerator.getCurrentSessionId(), contentToRecordToTargetType(contentToRecord), hostUid, targetUid, - windowingModeToTargetWindowingMode(windowingMode)); + windowingModeToTargetWindowingMode(windowingMode), + mPreviousTargetBounds.width(), + mPreviousTargetBounds.height(), + mPreviousTargetBounds.centerX(), + mPreviousTargetBounds.centerY(), + MEDIA_PROJECTION_TARGET_CHANGED__TARGET_CHANGE_TYPE__TARGET_CHANGE_WINDOWING_MODE); + mPreviousTargetWindowingMode = windowingMode; + } + /** + * Logs that the bounds of projection's capture target has changed. + * + * @param contentToRecord ContentRecordingSession.RecordContent indicating whether it is a + * task capture or display capture - gets converted to the corresponding + * TargetType before being logged. + * @param hostUid UID of the package that initiates MediaProjection. + * @param targetUid UID of the package that is captured if selected. + * @param captureBounds Updated bounds of the captured region. + */ + public void logChangedCaptureBounds( + int contentToRecord, int hostUid, int targetUid, Rect captureBounds) { + final Point capturePosition = new Point(captureBounds.centerX(), captureBounds.centerY()); + Log.d(TAG, "logChangedCaptureBounds: captureBounds= " + captureBounds + " position= " + + capturePosition); + + writeTargetChanged( + mSessionIdGenerator.getCurrentSessionId(), + contentToRecordToTargetType(contentToRecord), + hostUid, + targetUid, + mPreviousTargetWindowingMode, + captureBounds.width(), + captureBounds.height(), + captureBounds.centerX(), + captureBounds.centerY(), + captureBoundsToTargetChangeType(captureBounds)); + mPreviousTargetBounds.set(captureBounds); + } + + private int captureBoundsToTargetChangeType(Rect captureBounds) { + final boolean hasChangedSize = captureBounds.width() != mPreviousTargetBounds.width() + && captureBounds.height() != mPreviousTargetBounds.height(); + + if (hasChangedSize) { + Log.d(TAG, "targetChangeType= changeBounds"); + return MEDIA_PROJECTION_TARGET_CHANGED__TARGET_CHANGE_TYPE__TARGET_CHANGE_BOUNDS; + } + Log.d(TAG, "targetChangeType= changePosition"); + return MEDIA_PROJECTION_TARGET_CHANGED__TARGET_CHANGE_TYPE__TARGET_CHANGE_POSITION; } @VisibleForTesting @@ -231,45 +308,85 @@ public class MediaProjectionMetricsLogger { }; } + @VisibleForTesting + public int stopReasonToSessionStopSource(@StopReason int stopReason) { + return switch (stopReason) { + case StopReason.STOP_HOST_APP -> + MEDIA_PROJECTION_STATE_CHANGED__STOP_SOURCE__STOP_SOURCE_HOST_APP_STOP; + case StopReason.STOP_TARGET_REMOVED -> + MEDIA_PROJECTION_STATE_CHANGED__STOP_SOURCE__STOP_SOURCE_TASK_APP_CLOSE; + case StopReason.STOP_DEVICE_LOCKED-> + MEDIA_PROJECTION_STATE_CHANGED__STOP_SOURCE__STOP_SOURCE_DEVICE_LOCK; + case StopReason.STOP_PRIVACY_CHIP -> + MEDIA_PROJECTION_STATE_CHANGED__STOP_SOURCE__STOP_SOURCE_STATUS_BAR_CHIP_STOP; + case StopReason.STOP_QS_TILE -> + MEDIA_PROJECTION_STATE_CHANGED__STOP_SOURCE__STOP_SOURCE_QS_TILE; + case StopReason.STOP_USER_SWITCH -> + MEDIA_PROJECTION_STATE_CHANGED__STOP_SOURCE__STOP_SOURCE_USER_SWITCH; + case StopReason.STOP_FOREGROUND_SERVICE_CHANGE -> + MEDIA_PROJECTION_STATE_CHANGED__STOP_SOURCE__STOP_SOURCE_FOREGROUND_SERVICE_CHANGE; + case StopReason.STOP_NEW_PROJECTION -> + MEDIA_PROJECTION_STATE_CHANGED__STOP_SOURCE__STOP_SOURCE_NEW_PROJECTION; + case StopReason.STOP_NEW_MEDIA_ROUTE -> + MEDIA_PROJECTION_STATE_CHANGED__STOP_SOURCE__STOP_SOURCE_NEW_MEDIA_ROUTE; + case StopReason.STOP_ERROR -> + MEDIA_PROJECTION_STATE_CHANGED__STOP_SOURCE__STOP_SOURCE_ERROR; + default -> + MEDIA_PROJECTION_STATE_CHANGED__STOP_SOURCE__STOP_SOURCE_UNKNOWN; + }; + } + /** * Logs that the capturing stopped, either normally or because of error. * * @param hostUid UID of the package that initiates MediaProjection. * @param targetUid UID of the package that is captured if selected. */ - public void logStopped(int hostUid, int targetUid) { + public void logStopped(int hostUid, int targetUid, int stopReason) { boolean wasCaptureInProgress = - mPreviousState + mPreviousProjectionState == MEDIA_PROJECTION_STATE_CHANGED__STATE__MEDIA_PROJECTION_STATE_CAPTURING_IN_PROGRESS; - Log.d(TAG, "logStopped: wasCaptureInProgress=" + wasCaptureInProgress); + Log.d(TAG, "logStopped: wasCaptureInProgress=" + wasCaptureInProgress + + " stopReason=" + stopReason); writeStateChanged( mSessionIdGenerator.getCurrentSessionId(), MEDIA_PROJECTION_STATE_CHANGED__STATE__MEDIA_PROJECTION_STATE_STOPPED, hostUid, targetUid, TIME_SINCE_LAST_ACTIVE_UNKNOWN, - MEDIA_PROJECTION_STATE_CHANGED__CREATION_SOURCE__CREATION_SOURCE_UNKNOWN); + MEDIA_PROJECTION_STATE_CHANGED__CREATION_SOURCE__CREATION_SOURCE_UNKNOWN, + stopReasonToSessionStopSource(stopReason)); if (wasCaptureInProgress) { mTimestampStore.registerActiveSessionEnded(); } } - public void notifyProjectionStateChange(int hostUid, int state, int sessionCreationSource) { - writeStateChanged(hostUid, state, sessionCreationSource); + public void notifyProjectionStateChange( + int hostUid, + int state, + int sessionCreationSource, + int sessionStopSource + ) { + writeStateChanged(hostUid, state, sessionCreationSource, sessionStopSource); } - private void writeStateChanged(int hostUid, int state, int sessionCreationSource) { + private void writeStateChanged( + int hostUid, + int state, + int sessionCreationSource, + int sessionStopSource + ) { mFrameworkStatsLogWrapper.writeStateChanged( - /* code */ FrameworkStatsLog.MEDIA_PROJECTION_STATE_CHANGED, + /* code */ MEDIA_PROJECTION_STATE_CHANGED, /* session_id */ 123, /* state */ state, - /* previous_state */ FrameworkStatsLog - .MEDIA_PROJECTION_STATE_CHANGED__STATE__MEDIA_PROJECTION_STATE_UNKNOWN, + /* previous_state */ MEDIA_PROJECTION_STATE_CHANGED__STATE__MEDIA_PROJECTION_STATE_UNKNOWN, /* host_uid */ hostUid, /* target_uid */ -1, /* time_since_last_active */ 0, - /* creation_source */ sessionCreationSource); + /* creation_source */ sessionCreationSource, + /* stop_source */ sessionStopSource); } private void writeStateChanged( @@ -278,17 +395,19 @@ public class MediaProjectionMetricsLogger { int hostUid, int targetUid, int timeSinceLastActive, - int creationSource) { + int creationSource, + int stopSource) { mFrameworkStatsLogWrapper.writeStateChanged( - /* code */ FrameworkStatsLog.MEDIA_PROJECTION_STATE_CHANGED, + /* code */ MEDIA_PROJECTION_STATE_CHANGED, sessionId, state, - mPreviousState, + mPreviousProjectionState, hostUid, targetUid, timeSinceLastActive, - creationSource); - mPreviousState = state; + creationSource, + stopSource); + mPreviousProjectionState = state; } private void writeTargetChanged( @@ -296,13 +415,23 @@ public class MediaProjectionMetricsLogger { int targetType, int hostUid, int targetUid, - int targetWindowingMode) { + int targetWindowingMode, + int width, + int height, + int centerX, + int centerY, + int targetChangeType) { mFrameworkStatsLogWrapper.writeTargetChanged( - /* code */ FrameworkStatsLog.MEDIA_PROJECTION_TARGET_CHANGED, + /* code */ MEDIA_PROJECTION_TARGET_CHANGED, sessionId, targetType, hostUid, targetUid, - targetWindowingMode); + targetWindowingMode, + width, + height, + centerX, + centerY, + targetChangeType); } } diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index e019267f21cd..15af36ba66af 100644 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -6597,6 +6597,14 @@ public class NotificationManagerService extends SystemService { android.Manifest.permission.INTERACT_ACROSS_USERS, "setNotificationListenerAccessGrantedForUser for user " + userId); } + if (mUmInternal.isVisibleBackgroundFullUser(userId)) { + // The main use case for visible background users is the Automotive multi-display + // configuration where a passenger can use a secondary display while the driver is + // using the main display. NotificationListeners is designed only for the current + // user and work profile. We added a condition to prevent visible background users + // from updating the data managed within the NotificationListeners object. + return; + } checkNotificationListenerAccess(); if (granted && listener.flattenToString().length() > NotificationManager.MAX_SERVICE_COMPONENT_NAME_LENGTH) { @@ -12746,6 +12754,20 @@ public class NotificationManagerService extends SystemService { } @Override + public void onUserUnlocked(int user) { + if (mUmInternal.isVisibleBackgroundFullUser(user)) { + // The main use case for visible background users is the Automotive + // multi-display configuration where a passenger can use a secondary + // display while the driver is using the main display. + // NotificationListeners is designed only for the current user and work + // profile. We added a condition to prevent visible background users from + // updating the data managed within the NotificationListeners object. + return; + } + super.onUserUnlocked(user); + } + + @Override protected boolean allowRebindForParentUser() { return true; } diff --git a/services/core/java/com/android/server/pm/InstallDependencyHelper.java b/services/core/java/com/android/server/pm/InstallDependencyHelper.java index 527d68049537..5bd2c994160c 100644 --- a/services/core/java/com/android/server/pm/InstallDependencyHelper.java +++ b/services/core/java/com/android/server/pm/InstallDependencyHelper.java @@ -16,6 +16,7 @@ package com.android.server.pm; +import static android.content.pm.PackageInstaller.ACTION_INSTALL_DEPENDENCY; import static android.content.pm.PackageManager.INSTALL_FAILED_MISSING_SHARED_LIBRARY; import static android.os.Process.SYSTEM_UID; @@ -23,6 +24,7 @@ import android.annotation.NonNull; import android.content.ComponentName; import android.content.Context; import android.content.Intent; +import android.content.pm.PackageInstaller.SessionInfo; import android.content.pm.ResolveInfo; import android.content.pm.SharedLibraryInfo; import android.content.pm.dependencyinstaller.DependencyInstallerCallback; @@ -33,12 +35,14 @@ import android.os.Handler; import android.os.OutcomeReceiver; import android.os.Process; import android.os.RemoteException; +import android.util.ArraySet; import android.util.Slog; import com.android.internal.annotations.GuardedBy; import com.android.internal.infra.AndroidFuture; import com.android.internal.infra.ServiceConnector; +import java.util.ArrayList; import java.util.List; import java.util.concurrent.TimeUnit; @@ -48,22 +52,25 @@ import java.util.concurrent.TimeUnit; public class InstallDependencyHelper { private static final String TAG = InstallDependencyHelper.class.getSimpleName(); private static final boolean DEBUG = true; - private static final String ACTION_INSTALL_DEPENDENCY = - "android.intent.action.INSTALL_DEPENDENCY"; // The maximum amount of time to wait before the system unbinds from the verifier. private static final long UNBIND_TIMEOUT_MILLIS = TimeUnit.HOURS.toMillis(6); private static final long REQUEST_TIMEOUT_MILLIS = TimeUnit.MINUTES.toMillis(1); - private final SharedLibrariesImpl mSharedLibraries; private final Context mContext; + private final SharedLibrariesImpl mSharedLibraries; + private final PackageInstallerService mPackageInstallerService; private final Object mRemoteServiceLock = new Object(); + @GuardedBy("mTrackers") + private final List<DependencyInstallTracker> mTrackers = new ArrayList<>(); @GuardedBy("mRemoteServiceLock") private ServiceConnector<IDependencyInstallerService> mRemoteService = null; - InstallDependencyHelper(Context context, SharedLibrariesImpl sharedLibraries) { + InstallDependencyHelper(Context context, SharedLibrariesImpl sharedLibraries, + PackageInstallerService packageInstallerService) { mContext = context; mSharedLibraries = sharedLibraries; + mPackageInstallerService = packageInstallerService; } void resolveLibraryDependenciesIfNeeded(PackageLite pkg, Computer snapshot, int userId, @@ -98,19 +105,8 @@ public class InstallDependencyHelper { return; } - IDependencyInstallerCallback serviceCallback = new IDependencyInstallerCallback.Stub() { - @Override - public void onAllDependenciesResolved(int[] sessionIds) throws RemoteException { - // TODO(b/372862145): Implement waiting for sessions to finish installation - callback.onResult(null); - } - - @Override - public void onFailureToResolveAllDependencies() throws RemoteException { - onError(callback, "Failed to resolve all dependencies automatically"); - } - }; - + IDependencyInstallerCallback serviceCallback = + new DependencyInstallerCallbackCallOnce(handler, callback); boolean scheduleSuccess; synchronized (mRemoteServiceLock) { scheduleSuccess = mRemoteService.run(service -> { @@ -123,10 +119,28 @@ public class InstallDependencyHelper { } } - private void onError(CallOnceProxy callback, String msg) { + void notifySessionComplete(int sessionId, boolean success) { + if (DEBUG) { + Slog.i(TAG, "Session complete for " + sessionId + " result: " + success); + } + synchronized (mTrackers) { + List<DependencyInstallTracker> completedTrackers = new ArrayList<>(); + for (DependencyInstallTracker tracker: mTrackers) { + if (!tracker.onSessionComplete(sessionId, success)) { + completedTrackers.add(tracker); + } + } + mTrackers.removeAll(completedTrackers); + } + } + + private static void onError(CallOnceProxy callback, String msg) { PackageManagerException pe = new PackageManagerException( INSTALL_FAILED_MISSING_SHARED_LIBRARY, msg); callback.onError(pe); + if (DEBUG) { + Slog.i(TAG, "Orig session error: " + msg); + } } private boolean bindToDependencyInstallerIfNeeded(int userId, Handler handler, @@ -253,4 +267,135 @@ public class InstallDependencyHelper { } } } + + /** + * Ensure we call one of the outcomes only once, on the right handler. + * + * Repeated calls will be no-op. + */ + private class DependencyInstallerCallbackCallOnce extends IDependencyInstallerCallback.Stub { + + private final Handler mHandler; + private final CallOnceProxy mCallback; + + @GuardedBy("this") + private boolean mCalled = false; + + DependencyInstallerCallbackCallOnce(Handler handler, CallOnceProxy callback) { + mHandler = handler; + mCallback = callback; + } + + // TODO(b/372862145): Consider turning the binder call to two-way so that we can + // throw IllegalArgumentException + @Override + public void onAllDependenciesResolved(int[] sessionIds) throws RemoteException { + synchronized (this) { + if (mCalled) { + return; + } + mCalled = true; + } + + ArraySet<Integer> set = new ArraySet<>(); + for (int i = 0; i < sessionIds.length; i++) { + if (DEBUG) { + Slog.i(TAG, "onAllDependenciesResolved called with " + sessionIds[i]); + } + set.add(sessionIds[i]); + } + + DependencyInstallTracker tracker = new DependencyInstallTracker(mCallback, set); + synchronized (mTrackers) { + mTrackers.add(tracker); + } + + // In case any of the session ids have already been installed, check if they + // are valid. + mHandler.post(() -> { + if (DEBUG) { + Slog.i(TAG, "onAllDependenciesResolved cleaning up invalid sessions"); + } + + for (int i = 0; i < sessionIds.length; i++) { + int sessionId = sessionIds[i]; + SessionInfo sessionInfo = mPackageInstallerService.getSessionInfo(sessionId); + + // Continue waiting if session exists and hasn't passed or failed yet. + if (sessionInfo != null && !sessionInfo.isSessionApplied + && !sessionInfo.isSessionFailed) { + continue; + } + + if (DEBUG) { + Slog.i(TAG, "onAllDependenciesResolved cleaning up finished" + + " session: " + sessionId); + } + + // If session info is null, we assume it to be success. + // TODO(b/372862145): Check historical sessions to be more precise. + boolean success = sessionInfo == null || sessionInfo.isSessionApplied; + + notifySessionComplete(sessionId, /*success=*/success); + } + }); + } + + @Override + public void onFailureToResolveAllDependencies() throws RemoteException { + synchronized (this) { + if (mCalled) { + return; + } + onError(mCallback, "Failed to resolve all dependencies automatically"); + mCalled = true; + } + } + } + + /** + * Tracks a list of session ids against a particular callback. + * + * If all the sessions completes successfully, it invokes the positive flow. If any of the + * sessions fails, it invokes the failure flow immediately. + */ + // TODO(b/372862145): Determine and add support for rebooting while dependency is being resolved + private static class DependencyInstallTracker { + private final CallOnceProxy mCallback; + private final ArraySet<Integer> mPendingSessionIds; + + DependencyInstallTracker(CallOnceProxy callback, ArraySet<Integer> pendingSessionIds) { + mCallback = callback; + mPendingSessionIds = pendingSessionIds; + } + + /** + * Process a session complete event. + * + * Returns true if we still need to continue tracking. + */ + public boolean onSessionComplete(int sessionId, boolean success) { + synchronized (this) { + if (!mPendingSessionIds.contains(sessionId)) { + // This had no impact on tracker, so continue tracking + return true; + } + + if (!success) { + // If one of the dependency fails, the orig session would fail too. + onError(mCallback, "Failed to install all dependencies"); + // TODO(b/372862145): Abandon the rest of the pending sessions. + return false; // No point in tracking anymore + } + + mPendingSessionIds.remove(sessionId); + if (mPendingSessionIds.isEmpty()) { + mCallback.onResult(null); + return false; // Nothing to track anymore + } + return true; // Keep on tracking + } + } + + } } diff --git a/services/core/java/com/android/server/pm/InstallPackageHelper.java b/services/core/java/com/android/server/pm/InstallPackageHelper.java index 8168c5493304..e5e274450655 100644 --- a/services/core/java/com/android/server/pm/InstallPackageHelper.java +++ b/services/core/java/com/android/server/pm/InstallPackageHelper.java @@ -229,6 +229,7 @@ final class InstallPackageHelper { private final SharedLibrariesImpl mSharedLibraries; private final PackageManagerServiceInjector mInjector; private final UpdateOwnershipHelper mUpdateOwnershipHelper; + private final InstallDependencyHelper mInstallDependencyHelper; private final Object mInternalLock = new Object(); @GuardedBy("mInternalLock") @@ -239,7 +240,8 @@ final class InstallPackageHelper { AppDataHelper appDataHelper, RemovePackageHelper removePackageHelper, DeletePackageHelper deletePackageHelper, - BroadcastHelper broadcastHelper) { + BroadcastHelper broadcastHelper, + InstallDependencyHelper installDependencyHelper) { mPm = pm; mInjector = pm.mInjector; mAppDataHelper = appDataHelper; @@ -253,6 +255,7 @@ final class InstallPackageHelper { mPackageAbiHelper = pm.mInjector.getAbiHelper(); mSharedLibraries = pm.mInjector.getSharedLibrariesImpl(); mUpdateOwnershipHelper = pm.mInjector.getUpdateOwnershipHelper(); + mInstallDependencyHelper = installDependencyHelper; } /** @@ -1364,6 +1367,10 @@ final class InstallPackageHelper { } } } + + for (InstallRequest request : requests) { + mInstallDependencyHelper.notifySessionComplete(request.getSessionId(), success); + } } @GuardedBy("mPm.mInstallLock") diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java index a4152a724d64..47b785040d44 100644 --- a/services/core/java/com/android/server/pm/PackageInstallerService.java +++ b/services/core/java/com/android/server/pm/PackageInstallerService.java @@ -327,7 +327,7 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements context, mInstallThread.getLooper(), new AppStateHelper(context)); mPackageArchiver = new PackageArchiver(mContext, mPm); mInstallDependencyHelper = new InstallDependencyHelper(mContext, - mPm.mInjector.getSharedLibrariesImpl()); + mPm.mInjector.getSharedLibrariesImpl(), this); LocalServices.getService(SystemServiceManager.class).startService( new Lifecycle(context, this)); @@ -337,6 +337,10 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements return mStagingManager; } + InstallDependencyHelper getInstallDependencyHelper() { + return mInstallDependencyHelper; + } + boolean okToSendBroadcasts() { return mOkToSendBroadcasts; } diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 807445ef062d..715633410575 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -2118,7 +2118,8 @@ public class PackageManagerService implements PackageSender, TestUtilityService mDeletePackageHelper = new DeletePackageHelper(this, mRemovePackageHelper, mBroadcastHelper); mInstallPackageHelper = new InstallPackageHelper(this, mAppDataHelper, mRemovePackageHelper, - mDeletePackageHelper, mBroadcastHelper); + mDeletePackageHelper, mBroadcastHelper, + injector.getPackageInstallerService().getInstallDependencyHelper()); mInstantAppRegistry = new InstantAppRegistry(mContext, mPermissionManager, mInjector.getUserManagerInternal(), mDeletePackageHelper); diff --git a/services/core/java/com/android/server/security/intrusiondetection/IntrusionDetectionEventTransportConnection.java b/services/core/java/com/android/server/security/intrusiondetection/IntrusionDetectionEventTransportConnection.java index 82f39b327cea..b25656ebf47f 100644 --- a/services/core/java/com/android/server/security/intrusiondetection/IntrusionDetectionEventTransportConnection.java +++ b/services/core/java/com/android/server/security/intrusiondetection/IntrusionDetectionEventTransportConnection.java @@ -60,7 +60,7 @@ public class IntrusionDetectionEventTransportConnection implements ServiceConnec if (!bindService()) { return false; } - AndroidFuture<Integer> resultFuture = new AndroidFuture<>(); + AndroidFuture<Boolean> resultFuture = new AndroidFuture<>(); try { mService.initialize(resultFuture); } catch (RemoteException e) { @@ -68,8 +68,8 @@ public class IntrusionDetectionEventTransportConnection implements ServiceConnec unbindService(); return false; } - Integer result = getFutureResult(resultFuture); - if (result != null && result == 0) { + Boolean result = getFutureResult(resultFuture); + if (result != null && result == true) { return true; } else { unbindService(); @@ -83,22 +83,22 @@ public class IntrusionDetectionEventTransportConnection implements ServiceConnec * @return Whether the data is added to the binder service. */ public boolean addData(List<IntrusionDetectionEvent> data) { - AndroidFuture<Integer> resultFuture = new AndroidFuture<>(); + AndroidFuture<Boolean> resultFuture = new AndroidFuture<>(); try { mService.addData(data, resultFuture); } catch (RemoteException e) { Slog.e(TAG, "Remote Exception", e); return false; } - Integer result = getFutureResult(resultFuture); - return result != null && result == 0; + Boolean result = getFutureResult(resultFuture); + return result != null && result == true; } /** * Release the BackupTransport binder service. */ public void release() { - AndroidFuture<Integer> resultFuture = new AndroidFuture<>(); + AndroidFuture<Boolean> resultFuture = new AndroidFuture<>(); try { mService.release(resultFuture); } catch (RemoteException e) { diff --git a/services/core/java/com/android/server/trust/TrustManagerService.java b/services/core/java/com/android/server/trust/TrustManagerService.java index 887e1861f789..708bca71eced 100644 --- a/services/core/java/com/android/server/trust/TrustManagerService.java +++ b/services/core/java/com/android/server/trust/TrustManagerService.java @@ -2528,22 +2528,24 @@ public class TrustManagerService extends SystemService { } private void notifyDeviceLockedListenersForUser(int userId, boolean locked) { - int numListeners = mDeviceLockedStateListeners.beginBroadcast(); - try { - IntStream.range(0, numListeners).forEach(i -> { - try { - Integer uid = (Integer) mDeviceLockedStateListeners.getBroadcastCookie(i); - if (userId == uid.intValue()) { - mDeviceLockedStateListeners.getBroadcastItem(i) - .onDeviceLockedStateChanged(locked); + synchronized (mDeviceLockedStateListeners) { + int numListeners = mDeviceLockedStateListeners.beginBroadcast(); + try { + IntStream.range(0, numListeners).forEach(i -> { + try { + Integer uid = (Integer) mDeviceLockedStateListeners.getBroadcastCookie(i); + if (userId == uid.intValue()) { + mDeviceLockedStateListeners.getBroadcastItem(i) + .onDeviceLockedStateChanged(locked); + } + } catch (RemoteException re) { + Log.i(TAG, "Service died", re); } - } catch (RemoteException re) { - Log.i(TAG, "Service died", re); - } - }); + }); - } finally { - mDeviceLockedStateListeners.finishBroadcast(); + } finally { + mDeviceLockedStateListeners.finishBroadcast(); + } } } } diff --git a/services/core/java/com/android/server/utils/LazyJniRegistrar.java b/services/core/java/com/android/server/utils/LazyJniRegistrar.java index ac4a92e12909..6d29e9e58a98 100644 --- a/services/core/java/com/android/server/utils/LazyJniRegistrar.java +++ b/services/core/java/com/android/server/utils/LazyJniRegistrar.java @@ -42,6 +42,9 @@ public final class LazyJniRegistrar { /** Registers native methods for ConsumerIrService. */ public static native void registerConsumerIrService(); + /** Registers native methods for GameManagerService. */ + public static native void registerGameManagerService(); + /** Registers native methods for VrManagerService. */ public static native void registerVrManagerService(); } diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java index d019516cd069..bbef5785dfcb 100644 --- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java +++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java @@ -1513,11 +1513,15 @@ public class WallpaperManagerService extends IWallpaperManager.Stub } if (wallpaper.getComponent() != null && isPackageModified(wallpaper.getComponent().getPackageName())) { + ServiceInfo serviceInfo = null; try { - mContext.getPackageManager().getServiceInfo(wallpaper.getComponent(), - PackageManager.MATCH_DIRECT_BOOT_AWARE - | PackageManager.MATCH_DIRECT_BOOT_UNAWARE); - } catch (NameNotFoundException e) { + serviceInfo = mIPackageManager.getServiceInfo( + wallpaper.getComponent(), PackageManager.MATCH_DIRECT_BOOT_AWARE + | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, wallpaper.userId); + } catch (RemoteException e) { + Slog.w(TAG, "Failed to call IPackageManager.getServiceInfo", e); + } + if (serviceInfo == null) { Slog.e(TAG, "Wallpaper component gone, removing: " + wallpaper.getComponent()); clearWallpaperLocked(wallpaper.mWhich, wallpaper.userId, false, null); @@ -3177,7 +3181,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub throw new IllegalArgumentException("Invalid crop rect supplied: " + crop); } int orientation = screenOrientations[i]; - if (orientation == ORIENTATION_UNKNOWN && cropMap.size() > 1) { + if (orientation == ORIENTATION_UNKNOWN && crops.size() > 1) { throw new IllegalArgumentException("Invalid crops supplied: the UNKNOWN" + "screen orientation should only be used in a singleton map"); } diff --git a/services/core/java/com/android/server/wm/AccessibilityController.java b/services/core/java/com/android/server/wm/AccessibilityController.java index 7cbacd6b0b82..4b7e74af474c 100644 --- a/services/core/java/com/android/server/wm/AccessibilityController.java +++ b/services/core/java/com/android/server/wm/AccessibilityController.java @@ -22,7 +22,6 @@ import static android.os.Build.IS_USER; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_EXCLUDE_FROM_SCREEN_MAGNIFICATION; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY; import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY; -import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER; import static android.view.WindowManager.LayoutParams.TYPE_MAGNIFICATION_OVERLAY; import static android.view.WindowManager.TRANSIT_FLAG_IS_RECENTS; @@ -1784,22 +1783,13 @@ final class AccessibilityController { mA11yWindowsPopulator.populateVisibleWindowsOnScreenLocked( mDisplayId, visibleWindows); - if (!com.android.server.accessibility.Flags.computeWindowChangesOnA11yV2()) { - windows = buildWindowInfoListLocked(visibleWindows, screenSize); - } - // Gets the top focused display Id and window token for supporting multi-display. topFocusedDisplayId = mService.mRoot.getTopFocusedDisplayContent().getDisplayId(); topFocusedWindowToken = topFocusedWindowState.mClient.asBinder(); } - if (com.android.server.accessibility.Flags.computeWindowChangesOnA11yV2()) { - mCallback.onAccessibilityWindowsChanged(forceSend, topFocusedDisplayId, - topFocusedWindowToken, screenSize, visibleWindows); - } else { - mCallback.onWindowsForAccessibilityChanged(forceSend, topFocusedDisplayId, - topFocusedWindowToken, windows); - } + mCallback.onAccessibilityWindowsChanged(forceSend, topFocusedDisplayId, + topFocusedWindowToken, screenSize, visibleWindows); // Recycle the windows as we do not need them. for (final AccessibilityWindowsPopulator.AccessibilityWindow window : visibleWindows) { @@ -1808,166 +1798,6 @@ final class AccessibilityController { mInitialized = true; } - // Here are old code paths, called when computeWindowChangesOnA11yV2 flag is disabled. - // LINT.IfChange - - /** - * From a list of windows, decides windows to be exposed to accessibility based on touchable - * region in the screen. - */ - private List<WindowInfo> buildWindowInfoListLocked(List<AccessibilityWindow> visibleWindows, - Point screenSize) { - final List<WindowInfo> windows = new ArrayList<>(); - final Set<IBinder> addedWindows = mTempBinderSet; - addedWindows.clear(); - - boolean focusedWindowAdded = false; - - final int visibleWindowCount = visibleWindows.size(); - - Region unaccountedSpace = mTempRegion; - unaccountedSpace.set(0, 0, screenSize.x, screenSize.y); - - // Iterate until we figure out what is touchable for the entire screen. - for (int i = 0; i < visibleWindowCount; i++) { - final AccessibilityWindow a11yWindow = visibleWindows.get(i); - final Region regionInWindow = new Region(); - a11yWindow.getTouchableRegionInWindow(regionInWindow); - if (windowMattersToAccessibility(a11yWindow, regionInWindow, unaccountedSpace)) { - addPopulatedWindowInfo(a11yWindow, regionInWindow, windows, addedWindows); - if (windowMattersToUnaccountedSpaceComputation(a11yWindow)) { - updateUnaccountedSpace(a11yWindow, unaccountedSpace); - } - focusedWindowAdded |= a11yWindow.isFocused(); - } else if (a11yWindow.isUntouchableNavigationBar()) { - // If this widow is navigation bar without touchable region, accounting the - // region of navigation bar inset because all touch events from this region - // would be received by launcher, i.e. this region is a un-touchable one - // for the application. - unaccountedSpace.op( - getSystemBarInsetsFrame( - mService.mWindowMap.get(a11yWindow.getWindowInfo().token)), - unaccountedSpace, - Region.Op.REVERSE_DIFFERENCE); - } - - if (unaccountedSpace.isEmpty() && focusedWindowAdded) { - break; - } - } - - // Remove child/parent references to windows that were not added. - final int windowCount = windows.size(); - for (int i = 0; i < windowCount; i++) { - WindowInfo window = windows.get(i); - if (!addedWindows.contains(window.parentToken)) { - window.parentToken = null; - } - if (window.childTokens != null) { - final int childTokenCount = window.childTokens.size(); - for (int j = childTokenCount - 1; j >= 0; j--) { - if (!addedWindows.contains(window.childTokens.get(j))) { - window.childTokens.remove(j); - } - } - // Leave the child token list if empty. - } - } - - addedWindows.clear(); - - return windows; - } - - // Some windows should be excluded from unaccounted space computation, though they still - // should be reported - private boolean windowMattersToUnaccountedSpaceComputation(AccessibilityWindow a11yWindow) { - // Do not account space of trusted non-touchable windows, except the split-screen - // divider. - // If it's not trusted, touch events are not sent to the windows behind it. - if (!a11yWindow.isTouchable() - && (a11yWindow.getType() != TYPE_DOCK_DIVIDER) - && a11yWindow.isTrustedOverlay()) { - return false; - } - - if (a11yWindow.getType() == WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY) { - return false; - } - return true; - } - - private boolean windowMattersToAccessibility(AccessibilityWindow a11yWindow, - Region regionInScreen, Region unaccountedSpace) { - if (a11yWindow.isFocused()) { - return true; - } - - // Ignore non-touchable windows, except the split-screen divider, which is - // occasionally non-touchable but still useful for identifying split-screen - // mode and the PIP menu. - if (!a11yWindow.isTouchable() - && (a11yWindow.getType() != TYPE_DOCK_DIVIDER - && !a11yWindow.isPIPMenu())) { - return false; - } - - // If the window is completely covered by other windows - ignore. - if (unaccountedSpace.quickReject(regionInScreen)) { - return false; - } - - // Add windows of certain types not covered by modal windows. - if (isReportedWindowType(a11yWindow.getType())) { - return true; - } - - return false; - } - - private void updateUnaccountedSpace(AccessibilityWindow a11yWindow, - Region unaccountedSpace) { - if (a11yWindow.getType() - != WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY) { - // Account for the space this window takes if the window - // is not an accessibility overlay which does not change - // the reported windows. - final Region touchableRegion = mTempRegion2; - a11yWindow.getTouchableRegionInScreen(touchableRegion); - unaccountedSpace.op(touchableRegion, unaccountedSpace, - Region.Op.REVERSE_DIFFERENCE); - } - } - - private static void addPopulatedWindowInfo(AccessibilityWindow a11yWindow, - Region regionInScreen, List<WindowInfo> out, Set<IBinder> tokenOut) { - final WindowInfo window = a11yWindow.getWindowInfo(); - if (window.token == null) { - // The window was used in calculating visible windows but does not have an - // associated IWindow token, so exclude it from the list returned to accessibility. - return; - } - window.regionInScreen.set(regionInScreen); - window.layer = tokenOut.size(); - out.add(window); - tokenOut.add(window.token); - } - - private static boolean isReportedWindowType(int windowType) { - return (windowType != WindowManager.LayoutParams.TYPE_WALLPAPER - && windowType != WindowManager.LayoutParams.TYPE_BOOT_PROGRESS - && windowType != WindowManager.LayoutParams.TYPE_DISPLAY_OVERLAY - && windowType != WindowManager.LayoutParams.TYPE_DRAG - && windowType != WindowManager.LayoutParams.TYPE_INPUT_CONSUMER - && windowType != WindowManager.LayoutParams.TYPE_POINTER - && windowType != TYPE_MAGNIFICATION_OVERLAY - && windowType != WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA_OVERLAY - && windowType != WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY - && windowType != WindowManager.LayoutParams.TYPE_PRIVATE_PRESENTATION); - } - - // LINT.ThenChange(/services/accessibility/java/com/android/server/accessibility/AccessibilityWindowManager.java) - private WindowState getTopFocusWindow() { return mService.mRoot.getTopFocusedDisplayContent().mCurrentFocus; } diff --git a/services/core/java/com/android/server/wm/AccessibilityWindowsPopulator.java b/services/core/java/com/android/server/wm/AccessibilityWindowsPopulator.java index fd2a909f8b05..7fc11e6c3ac9 100644 --- a/services/core/java/com/android/server/wm/AccessibilityWindowsPopulator.java +++ b/services/core/java/com/android/server/wm/AccessibilityWindowsPopulator.java @@ -724,8 +724,7 @@ public final class AccessibilityWindowsPopulator extends WindowInfosListener { } // Compute system bar insets frame if needed. - if (com.android.server.accessibility.Flags.computeWindowChangesOnA11yV2() - && windowState != null && instance.isUntouchableNavigationBar()) { + if (windowState != null && instance.isUntouchableNavigationBar()) { final InsetsSourceProvider provider = windowState.getControllableInsetProvider(); if (provider != null) { diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index f70dec175c06..ae55a1a77873 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -4575,10 +4575,22 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A // at #postWindowRemoveCleanupLocked return false; } + + // Link the fixed rotation transform to this activity since we are transferring the + // starting window. + if (fromActivity.hasFixedRotationTransform()) { + mDisplayContent.handleTopActivityLaunchingInDifferentOrientation(this, + false /* checkOpening */); + } // Do not transfer if the orientation doesn't match, redraw starting window while it is // on top will cause flicker. - if (fromActivity.getRequestedConfigurationOrientation() - != getRequestedConfigurationOrientation()) { + final int fromOrientation = fromActivity.getConfiguration().orientation; + final int requestedOrientation = getRequestedConfigurationOrientation(); + if (requestedOrientation == ORIENTATION_UNDEFINED) { + if (fromOrientation != getConfiguration().orientation) { + return false; + } + } else if (fromOrientation != requestedOrientation) { return false; } // In this case, the starting icon has already been displayed, so start @@ -4592,13 +4604,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A final long origId = Binder.clearCallingIdentity(); try { - // Link the fixed rotation transform to this activity since we are transferring the - // starting window. - if (fromActivity.hasFixedRotationTransform()) { - mDisplayContent.handleTopActivityLaunchingInDifferentOrientation(this, - false /* checkOpening */); - } - // Transfer the starting window over to the new token. mStartingData = fromActivity.mStartingData; mStartingSurface = fromActivity.mStartingSurface; diff --git a/services/core/java/com/android/server/wm/AppCompatController.java b/services/core/java/com/android/server/wm/AppCompatController.java index 145a3767c149..203932d4df58 100644 --- a/services/core/java/com/android/server/wm/AppCompatController.java +++ b/services/core/java/com/android/server/wm/AppCompatController.java @@ -76,6 +76,16 @@ class AppCompatController { mAppCompatSizeCompatModePolicy = new AppCompatSizeCompatModePolicy(mActivityRecord, mAppCompatOverrides); mAllowRestrictedResizability = AppCompatUtils.asLazy(() -> { + // Application level. + try { + if (packageManager.getProperty(PROPERTY_COMPAT_ALLOW_RESTRICTED_RESIZABILITY, + mActivityRecord.packageName).getBoolean()) { + return true; + } + } catch (PackageManager.NameNotFoundException e) { + // Fall through. + } + // Activity level. try { return packageManager.getPropertyAsUser( PROPERTY_COMPAT_ALLOW_RESTRICTED_RESIZABILITY, diff --git a/services/core/java/com/android/server/wm/ContentRecorder.java b/services/core/java/com/android/server/wm/ContentRecorder.java index 0b5872b3e601..93ccd74c6b23 100644 --- a/services/core/java/com/android/server/wm/ContentRecorder.java +++ b/services/core/java/com/android/server/wm/ContentRecorder.java @@ -32,6 +32,7 @@ import android.graphics.Point; import android.graphics.PointF; import android.graphics.Rect; import android.media.projection.IMediaProjectionManager; +import android.media.projection.StopReason; import android.os.IBinder; import android.os.RemoteException; import android.os.ServiceManager; @@ -226,6 +227,7 @@ final class ContentRecorder implements WindowContainerListener { + "size %s", mDisplayContent.getDisplayId(), recordedContentBounds, recordedContentOrientation, surfaceSize); + updateMirroredSurface(mRecordedWindowContainer.getSyncTransaction(), recordedContentBounds, surfaceSize); } else { @@ -295,12 +297,12 @@ final class ContentRecorder implements WindowContainerListener { * Ensure recording does not fall back to the display stack; ensure the recording is stopped * and the client notified by tearing down the virtual display. */ - private void stopMediaProjection() { + private void stopMediaProjection(@StopReason int stopReason) { ProtoLog.v(WM_DEBUG_CONTENT_RECORDING, "Content Recording: Stop MediaProjection on virtual display %d", mDisplayContent.getDisplayId()); if (mMediaProjectionManager != null) { - mMediaProjectionManager.stopActiveProjection(); + mMediaProjectionManager.stopActiveProjection(stopReason); } } @@ -507,7 +509,7 @@ final class ContentRecorder implements WindowContainerListener { if (shouldExitTaskRecording) { // Clean up the cached session first to ensure recording doesn't re-start, since // tearing down the display will generate display events which will trickle back here. - stopMediaProjection(); + stopMediaProjection(StopReason.STOP_ERROR); } } @@ -599,9 +601,13 @@ final class ContentRecorder implements WindowContainerListener { mLastRecordedBounds = new Rect(recordedContentBounds); mLastConsumingSurfaceSize.x = surfaceSize.x; mLastConsumingSurfaceSize.y = surfaceSize.y; - // Request to notify the client about the resize. - mMediaProjectionManager.notifyActiveProjectionCapturedContentResized( - mLastRecordedBounds.width(), mLastRecordedBounds.height()); + + // Request to notify the client about the updated bounds. + mMediaProjectionManager.notifyCaptureBoundsChanged( + mContentRecordingSession.getContentToRecord(), + mContentRecordingSession.getTargetUid(), + mLastRecordedBounds + ); } /** @@ -641,7 +647,7 @@ final class ContentRecorder implements WindowContainerListener { clearContentRecordingSession(); // Clean up the cached session first to ensure recording doesn't re-start, since // tearing down the display will generate display events which will trickle back here. - stopMediaProjection(); + stopMediaProjection(StopReason.STOP_TARGET_REMOVED); } // WindowContainerListener @@ -674,10 +680,10 @@ final class ContentRecorder implements WindowContainerListener { } @VisibleForTesting interface MediaProjectionManagerWrapper { - void stopActiveProjection(); - void notifyActiveProjectionCapturedContentResized(int width, int height); + void stopActiveProjection(@StopReason int stopReason); void notifyActiveProjectionCapturedContentVisibilityChanged(boolean isVisible); void notifyWindowingModeChanged(int contentToRecord, int targetUid, int windowingMode); + void notifyCaptureBoundsChanged(int contentToRecord, int targetUid, Rect captureBounds); } private static final class RemoteMediaProjectionManagerWrapper implements @@ -691,7 +697,7 @@ final class ContentRecorder implements WindowContainerListener { } @Override - public void stopActiveProjection() { + public void stopActiveProjection(@StopReason int stopReason) { fetchMediaProjectionManager(); if (mIMediaProjectionManager == null) { return; @@ -700,7 +706,7 @@ final class ContentRecorder implements WindowContainerListener { ProtoLog.e(WM_DEBUG_CONTENT_RECORDING, "Content Recording: stopping active projection for display %d", mDisplayId); - mIMediaProjectionManager.stopActiveProjection(); + mIMediaProjectionManager.stopActiveProjection(stopReason); } catch (RemoteException e) { ProtoLog.e(WM_DEBUG_CONTENT_RECORDING, "Content Recording: Unable to tell MediaProjectionManagerService to stop " @@ -710,52 +716,51 @@ final class ContentRecorder implements WindowContainerListener { } @Override - public void notifyActiveProjectionCapturedContentResized(int width, int height) { + public void notifyActiveProjectionCapturedContentVisibilityChanged(boolean isVisible) { fetchMediaProjectionManager(); if (mIMediaProjectionManager == null) { return; } try { - mIMediaProjectionManager.notifyActiveProjectionCapturedContentResized(width, - height); + mIMediaProjectionManager.notifyActiveProjectionCapturedContentVisibilityChanged( + isVisible); } catch (RemoteException e) { ProtoLog.e(WM_DEBUG_CONTENT_RECORDING, "Content Recording: Unable to tell MediaProjectionManagerService about " - + "resizing the active projection: %s", + + "visibility change on the active projection: %s", e); } } @Override - public void notifyActiveProjectionCapturedContentVisibilityChanged(boolean isVisible) { + public void notifyWindowingModeChanged(int contentToRecord, int targetUid, + int windowingMode) { fetchMediaProjectionManager(); if (mIMediaProjectionManager == null) { return; } try { - mIMediaProjectionManager.notifyActiveProjectionCapturedContentVisibilityChanged( - isVisible); + mIMediaProjectionManager.notifyWindowingModeChanged( + contentToRecord, targetUid, windowingMode); } catch (RemoteException e) { ProtoLog.e(WM_DEBUG_CONTENT_RECORDING, - "Content Recording: Unable to tell MediaProjectionManagerService about " - + "visibility change on the active projection: %s", - e); + "Content Recording: Unable to tell log windowing mode change: %s", e); } } @Override - public void notifyWindowingModeChanged(int contentToRecord, int targetUid, - int windowingMode) { + public void notifyCaptureBoundsChanged(int contentToRecord, int targetUid, + Rect captureBounds) { fetchMediaProjectionManager(); if (mIMediaProjectionManager == null) { return; } try { - mIMediaProjectionManager.notifyWindowingModeChanged( - contentToRecord, targetUid, windowingMode); + mIMediaProjectionManager.notifyCaptureBoundsChanged( + contentToRecord, targetUid, captureBounds); } catch (RemoteException e) { ProtoLog.e(WM_DEBUG_CONTENT_RECORDING, - "Content Recording: Unable to tell log windowing mode change: %s", e); + "Content Recording: Unable to tell log bounds change: %s", e); } } diff --git a/services/core/java/com/android/server/wm/DeferredDisplayUpdater.java b/services/core/java/com/android/server/wm/DeferredDisplayUpdater.java index 6f8c17a9ac75..4e79e377a2a3 100644 --- a/services/core/java/com/android/server/wm/DeferredDisplayUpdater.java +++ b/services/core/java/com/android/server/wm/DeferredDisplayUpdater.java @@ -403,6 +403,7 @@ class DeferredDisplayUpdater { || first.renderFrameRate != second.renderFrameRate || first.hasArrSupport != second.hasArrSupport || !Objects.equals(first.frameRateCategoryRate, second.frameRateCategoryRate) + || !Arrays.equals(first.supportedRefreshRates, second.supportedRefreshRates) || first.defaultModeId != second.defaultModeId || first.userPreferredModeId != second.userPreferredModeId || !Arrays.equals(first.supportedModes, second.supportedModes) diff --git a/services/core/java/com/android/server/wm/DesktopAppCompatAspectRatioPolicy.java b/services/core/java/com/android/server/wm/DesktopAppCompatAspectRatioPolicy.java index c8cb62132b4c..43855aa3d247 100644 --- a/services/core/java/com/android/server/wm/DesktopAppCompatAspectRatioPolicy.java +++ b/services/core/java/com/android/server/wm/DesktopAppCompatAspectRatioPolicy.java @@ -196,10 +196,11 @@ public class DesktopAppCompatAspectRatioPolicy { if (!aspectRatioOverrides.shouldOverrideMinAspectRatio() && !AppCompatCameraPolicy.shouldOverrideMinAspectRatioForCamera(mActivityRecord)) { - if (mActivityRecord.isUniversalResizeable()) { + final float minAspectRatio = info.getMinAspectRatio(); + if (minAspectRatio == 0 || mActivityRecord.isUniversalResizeable()) { return 0; } - return info.getMinAspectRatio(); + return minAspectRatio; } if (info.isChangeEnabled(OVERRIDE_MIN_ASPECT_RATIO_PORTRAIT_ONLY) @@ -242,10 +243,11 @@ public class DesktopAppCompatAspectRatioPolicy { if (mTransparentPolicy.isRunning()) { return mTransparentPolicy.getInheritedMaxAspectRatio(); } - if (mActivityRecord.isUniversalResizeable()) { + final float maxAspectRatio = mActivityRecord.info.getMaxAspectRatio(); + if (maxAspectRatio == 0 || mActivityRecord.isUniversalResizeable()) { return 0; } - return mActivityRecord.info.getMaxAspectRatio(); + return maxAspectRatio; } /** diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index e9e550e72a00..9a33df13bb6a 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -5502,14 +5502,18 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp // Attach the SystemUiContext to this DisplayContent the get latest configuration. // Note that the SystemUiContext will be removed automatically if this DisplayContent // is detached. - final WindowProcessController wpc = mAtmService.getProcessController( - getDisplayUiContext().getIApplicationThread()); - mWmService.mWindowContextListenerController.registerWindowContainerListener( - wpc, getDisplayUiContext().getWindowContextToken(), this, - INVALID_WINDOW_TYPE, null /* options */); + registerSystemUiContext(); } } + private void registerSystemUiContext() { + final WindowProcessController wpc = mAtmService.getProcessController( + getDisplayUiContext().getIApplicationThread()); + mWmService.mWindowContextListenerController.registerWindowContainerListener( + wpc, getDisplayUiContext().getWindowContextToken(), this, + INVALID_WINDOW_TYPE, null /* options */); + } + @Override void assignChildLayers(SurfaceControl.Transaction t) { assignRelativeLayerForIme(t, false /* forceUpdate */); diff --git a/services/core/java/com/android/server/wm/DisplayRotation.java b/services/core/java/com/android/server/wm/DisplayRotation.java index 4cf1fb400fe7..df209ff4cf50 100644 --- a/services/core/java/com/android/server/wm/DisplayRotation.java +++ b/services/core/java/com/android/server/wm/DisplayRotation.java @@ -485,6 +485,9 @@ public class DisplayRotation { if (isDefaultDisplay) { updateOrientationListenerLw(); } + } else if (mCompatPolicyForImmersiveApps != null + && mCompatPolicyForImmersiveApps.deferOrientationUpdate()) { + return false; } return updateRotationUnchecked(forceUpdate); } diff --git a/services/core/java/com/android/server/wm/DisplayRotationImmersiveAppCompatPolicy.java b/services/core/java/com/android/server/wm/DisplayRotationImmersiveAppCompatPolicy.java index 094434d07cfe..046ed614dc19 100644 --- a/services/core/java/com/android/server/wm/DisplayRotationImmersiveAppCompatPolicy.java +++ b/services/core/java/com/android/server/wm/DisplayRotationImmersiveAppCompatPolicy.java @@ -17,10 +17,13 @@ package com.android.server.wm; import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; +import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; import static android.content.res.Configuration.ORIENTATION_LANDSCAPE; import static android.content.res.Configuration.ORIENTATION_PORTRAIT; import static android.content.res.Configuration.ORIENTATION_UNDEFINED; +import static com.android.server.policy.WindowManagerPolicy.USER_ROTATION_FREE; + import android.annotation.NonNull; import android.annotation.Nullable; import android.content.res.Configuration.Orientation; @@ -66,6 +69,37 @@ final class DisplayRotationImmersiveAppCompatPolicy { } /** + * Returns {@code true} if the orientation update should be skipped and it will update when + * transition is done. This is to keep the orientation which was preserved by + * {@link #isRotationLockEnforced} from being changed by a transient launch (i.e. recents). + */ + boolean deferOrientationUpdate() { + if (mDisplayRotation.getUserRotation() != USER_ROTATION_FREE + || mDisplayRotation.getLastOrientation() != SCREEN_ORIENTATION_UNSPECIFIED) { + return false; + } + final WindowOrientationListener orientationListener = + mDisplayRotation.getOrientationListener(); + if (orientationListener == null + || orientationListener.getProposedRotation() == mDisplayRotation.getRotation()) { + return false; + } + // The above conditions mean that isRotationLockEnforced might have taken effect: + // Auto-rotation is enabled and the proposed rotation is not applied. + // Then the update should defer until the transition idle to avoid disturbing animation. + if (!mDisplayContent.mTransitionController.hasTransientLaunch(mDisplayContent)) { + return false; + } + mDisplayContent.mTransitionController.mStateValidators.add(() -> { + if (!isRotationLockEnforcedLocked(orientationListener.getProposedRotation())) { + mDisplayContent.mWmService.updateRotation(false /* alwaysSendConfiguration */, + false /* forceRelayout */); + } + }); + return true; + } + + /** * Decides whether it is necessary to lock screen rotation, preventing auto rotation, based on * the top activity configuration and proposed screen rotation. * diff --git a/services/core/java/com/android/server/wm/RecentTasks.java b/services/core/java/com/android/server/wm/RecentTasks.java index f0e12fec3107..27f82d90fdac 100644 --- a/services/core/java/com/android/server/wm/RecentTasks.java +++ b/services/core/java/com/android/server/wm/RecentTasks.java @@ -495,11 +495,18 @@ class RecentTasks { mTaskNotificationController.notifyTaskListUpdated(); } - private void notifyTaskRemoved(Task task, boolean wasTrimmed, boolean killProcess) { + private void notifyTaskRemoved(Task task, boolean wasTrimmed, boolean killProcess, + boolean removedForAddTask) { for (int i = 0; i < mCallbacks.size(); i++) { mCallbacks.get(i).onRecentTaskRemoved(task, wasTrimmed, killProcess); } mTaskNotificationController.notifyTaskListUpdated(); + if (removedForAddTask) { + mTaskNotificationController.notifyRecentTaskRemovedForAddTask(task.mTaskId); + } + } + private void notifyTaskRemoved(Task task, boolean wasTrimmed, boolean killProcess) { + notifyTaskRemoved(task, wasTrimmed, killProcess, false /* removedForAddTask */); } /** @@ -1635,7 +1642,8 @@ class RecentTasks { // from becoming dangling. mHiddenTasks.add(0, removedTask); } - notifyTaskRemoved(removedTask, false /* wasTrimmed */, false /* killProcess */); + notifyTaskRemoved(removedTask, false /* wasTrimmed */, false /* killProcess */, + true /* removedForAddTask */); if (DEBUG_RECENTS_TRIM_TASKS) { Slog.d(TAG, "Trimming task=" + removedTask + " for addition of task=" + task); diff --git a/services/core/java/com/android/server/wm/SafeActivityOptions.java b/services/core/java/com/android/server/wm/SafeActivityOptions.java index 70b214cc71b5..88e534351e2e 100644 --- a/services/core/java/com/android/server/wm/SafeActivityOptions.java +++ b/services/core/java/com/android/server/wm/SafeActivityOptions.java @@ -361,10 +361,13 @@ public class SafeActivityOptions { } // If launched from bubble is specified, then ensure that the caller is system or sysui. - if (options.getLaunchedFromBubble() && !isSystemOrSystemUI(callingPid, callingUid)) { + if ((options.getLaunchedFromBubble() || options.getTaskAlwaysOnTop()) + && !isSystemOrSystemUI(callingPid, callingUid)) { final String msg = "Permission Denial: starting " + getIntentString(intent) + " from " + callerApp + " (pid=" + callingPid - + ", uid=" + callingUid + ") with launchedFromBubble=true"; + + ", uid=" + callingUid + ") with" + + (options.getLaunchedFromBubble() ? " launchedFromBubble=true" : "") + + (options.getTaskAlwaysOnTop() ? " taskAlwaysOnTop=true" : ""); Slog.w(TAG, msg); throw new SecurityException(msg); } diff --git a/services/core/java/com/android/server/wm/TaskChangeNotificationController.java b/services/core/java/com/android/server/wm/TaskChangeNotificationController.java index 586f3c35c0c4..c3649fe98056 100644 --- a/services/core/java/com/android/server/wm/TaskChangeNotificationController.java +++ b/services/core/java/com/android/server/wm/TaskChangeNotificationController.java @@ -62,6 +62,8 @@ class TaskChangeNotificationController { private static final int NOTIFY_TASK_MOVED_TO_BACK_LISTENERS_MSG = 27; private static final int NOTIFY_LOCK_TASK_MODE_CHANGED_MSG = 28; private static final int NOTIFY_TASK_SNAPSHOT_INVALIDATED_LISTENERS_MSG = 29; + private static final int NOTIFY_RECENT_TASK_REMOVED_FOR_ADD_TASK_LISTENERS_MSG = 30; + // Delay in notifying task stack change listeners (in millis) private static final int NOTIFY_TASK_STACK_CHANGE_LISTENERS_DELAY = 100; @@ -167,6 +169,10 @@ class TaskChangeNotificationController { l.onRecentTaskListFrozenChanged(m.arg1 != 0); }; + private final TaskStackConsumer mNotifyRecentTaskRemovedForAddTask = (l, m) -> { + l.onRecentTaskRemovedForAddTask(m.arg1); + }; + private final TaskStackConsumer mNotifyTaskFocusChanged = (l, m) -> { l.onTaskFocusChanged(m.arg1, m.arg2 != 0); }; @@ -261,6 +267,9 @@ class TaskChangeNotificationController { case NOTIFY_TASK_LIST_FROZEN_UNFROZEN_MSG: forAllRemoteListeners(mNotifyTaskListFrozen, msg); break; + case NOTIFY_RECENT_TASK_REMOVED_FOR_ADD_TASK_LISTENERS_MSG: + forAllRemoteListeners(mNotifyRecentTaskRemovedForAddTask, msg); + break; case NOTIFY_TASK_FOCUS_CHANGED_MSG: forAllRemoteListeners(mNotifyTaskFocusChanged, msg); break; @@ -541,6 +550,15 @@ class TaskChangeNotificationController { msg.sendToTarget(); } + /** Called when a task is removed from the recent tasks list. */ + void notifyRecentTaskRemovedForAddTask(int taskId) { + final Message msg = mHandler.obtainMessage( + NOTIFY_RECENT_TASK_REMOVED_FOR_ADD_TASK_LISTENERS_MSG, taskId, + 0 /* unused */); + forAllLocalListeners(mNotifyRecentTaskRemovedForAddTask, msg); + msg.sendToTarget(); + } + /** @see ITaskStackListener#onTaskFocusChanged(int, boolean) */ void notifyTaskFocusChanged(int taskId, boolean focused) { final Message msg = mHandler.obtainMessage(NOTIFY_TASK_FOCUS_CHANGED_MSG, diff --git a/services/core/java/com/android/server/wm/WindowManagerInternal.java b/services/core/java/com/android/server/wm/WindowManagerInternal.java index ce032b4f7f9a..c77b1d9a7bcf 100644 --- a/services/core/java/com/android/server/wm/WindowManagerInternal.java +++ b/services/core/java/com/android/server/wm/WindowManagerInternal.java @@ -46,7 +46,6 @@ import android.view.RemoteAnimationTarget; import android.view.Surface; import android.view.SurfaceControl; import android.view.SurfaceControlViewHost; -import android.view.WindowInfo; import android.view.WindowManager.DisplayImePolicy; import android.view.inputmethod.ImeTracker; import android.window.ScreenCapture; @@ -158,26 +157,8 @@ public abstract class WindowManagerInternal { * accessibility changed. */ public interface WindowsForAccessibilityCallback { - - /** - * Called when the windows for accessibility changed. This is called if - * {@link com.android.server.accessibility.Flags.FLAG_COMPUTE_WINDOW_CHANGES_ON_A11Y_V2} is - * false. - * - * @param forceSend Send the windows for accessibility even if they haven't changed. - * @param topFocusedDisplayId The display Id which has the top focused window. - * @param topFocusedWindowToken The window token of top focused window. - * @param windows The windows for accessibility. - */ - void onWindowsForAccessibilityChanged(boolean forceSend, int topFocusedDisplayId, - IBinder topFocusedWindowToken, @NonNull List<WindowInfo> windows); - /** - * Called when the windows for accessibility changed. This is called if - * {@link com.android.server.accessibility.Flags.FLAG_COMPUTE_WINDOW_CHANGES_ON_A11Y_V2} is - * true. - * TODO(b/322444245): Remove screenSize parameter by getting it from - * DisplayManager#getDisplay(int).getRealSize() on the a11y side. + * Called when the windows for accessibility changed. * * @param forceSend Send the windows for accessibility even if they haven't changed. * @param topFocusedDisplayId The display Id which has the top focused window. diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 8268cae12e3d..a0c0b9836507 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -3030,8 +3030,8 @@ public class WindowManagerService extends IWindowManager.Stub mWindowContextListenerController.unregisterWindowContainerListener(clientToken); - final WindowToken token = wc.asWindowToken(); - if (token != null && token.isFromClient()) { + final WindowToken token = wc != null ? wc.asWindowToken() : null; + if (token != null && token.isFromClient() && token.getDisplayContent() != null) { removeWindowToken(token.token, token.getDisplayContent().getDisplayId()); } } @@ -10314,7 +10314,7 @@ public class WindowManagerService extends IWindowManager.Stub mH.post(() -> { Toast.makeText(mContext, Looper.getMainLooper(), mContext.getString(R.string.screen_not_shared_sensitive_content), - Toast.LENGTH_SHORT) + Toast.LENGTH_LONG) .show(); }); // If blocked due to notification protection (null window token) log protection applied diff --git a/services/core/jni/Android.bp b/services/core/jni/Android.bp index eaa3a37d5bf3..4c0cee404b68 100644 --- a/services/core/jni/Android.bp +++ b/services/core/jni/Android.bp @@ -38,7 +38,6 @@ cc_library_static { "com_android_server_adb_AdbDebuggingManager.cpp", "com_android_server_am_BatteryStatsService.cpp", "com_android_server_biometrics_SurfaceToNativeHandleConverter.cpp", - "com_android_server_ConsumerIrService.cpp", "com_android_server_companion_virtual_InputController.cpp", "com_android_server_companion_virtual_VirtualDeviceImpl.cpp", "com_android_server_devicepolicy_CryptoTestHelper.cpp", @@ -63,7 +62,6 @@ cc_library_static { "com_android_server_SystemServer.cpp", "com_android_server_tv_TvUinputBridge.cpp", "com_android_server_tv_TvInputHal.cpp", - "com_android_server_vr_VrManagerService.cpp", "com_android_server_UsbAlsaJackDetector.cpp", "com_android_server_UsbAlsaMidiDevice.cpp", "com_android_server_UsbDeviceManager.cpp", @@ -75,14 +73,13 @@ cc_library_static { "com_android_server_am_LowMemDetector.cpp", "com_android_server_pm_PackageManagerShellCommandDataLoader.cpp", "com_android_server_sensor_SensorService.cpp", - "com_android_server_utils_LazyJniRegistrar.cpp", "com_android_server_wm_TaskFpsCallbackController.cpp", "onload.cpp", ":lib_cachedAppOptimizer_native", ":lib_freezer_native", - ":lib_gameManagerService_native", ":lib_oomConnection_native", ":lib_anrTimer_native", + ":lib_lazilyRegisteredServices_native", ], include_dirs: [ @@ -248,13 +245,6 @@ filegroup { } filegroup { - name: "lib_gameManagerService_native", - srcs: [ - "com_android_server_app_GameManagerService.cpp", - ], -} - -filegroup { name: "lib_oomConnection_native", srcs: ["com_android_server_am_OomConnection.cpp"], } @@ -265,3 +255,13 @@ filegroup { "com_android_server_utils_AnrTimer.cpp", ], } + +filegroup { + name: "lib_lazilyRegisteredServices_native", + srcs: [ + "com_android_server_ConsumerIrService.cpp", + "com_android_server_app_GameManagerService.cpp", + "com_android_server_utils_LazyJniRegistrar.cpp", + "com_android_server_vr_VrManagerService.cpp", + ], +} diff --git a/services/core/jni/com_android_server_utils_LazyJniRegistrar.cpp b/services/core/jni/com_android_server_utils_LazyJniRegistrar.cpp index ad7781e3b8b5..0c0f8b02279b 100644 --- a/services/core/jni/com_android_server_utils_LazyJniRegistrar.cpp +++ b/services/core/jni/com_android_server_utils_LazyJniRegistrar.cpp @@ -22,6 +22,7 @@ namespace android { // Forward declared per-class registration methods. int register_android_server_ConsumerIrService(JNIEnv* env); +int register_android_server_app_GameManagerService(JNIEnv* env); int register_android_server_vr_VrManagerService(JNIEnv* env); namespace { @@ -33,12 +34,17 @@ void registerConsumerIrService(JNIEnv* env, jclass) { register_android_server_ConsumerIrService(env); } +void registerGameManagerService(JNIEnv* env, jclass) { + register_android_server_app_GameManagerService(env); +} + void registerVrManagerService(JNIEnv* env, jclass) { register_android_server_vr_VrManagerService(env); } static const JNINativeMethod sJniRegistrarMethods[] = { {"registerConsumerIrService", "()V", (void*)registerConsumerIrService}, + {"registerGameManagerService", "()V", (void*)registerGameManagerService}, {"registerVrManagerService", "()V", (void*)registerVrManagerService}, }; diff --git a/services/core/jni/onload.cpp b/services/core/jni/onload.cpp index c170ae99da04..df37ec3ef037 100644 --- a/services/core/jni/onload.cpp +++ b/services/core/jni/onload.cpp @@ -65,7 +65,6 @@ int register_android_server_stats_pull_StatsPullAtomService(JNIEnv* env); int register_android_server_sensor_SensorService(JavaVM* vm, JNIEnv* env); int register_android_server_companion_virtual_InputController(JNIEnv* env); int register_android_server_companion_virtual_VirtualDeviceImpl(JNIEnv* env); -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); @@ -131,7 +130,6 @@ extern "C" jint JNI_OnLoad(JavaVM* vm, void* /* reserved */) register_android_server_sensor_SensorService(vm, env); register_android_server_companion_virtual_InputController(env); register_android_server_companion_virtual_VirtualDeviceImpl(env); - register_android_server_app_GameManagerService(env); register_com_android_server_wm_TaskFpsCallbackController(env); register_com_android_server_display_DisplayControl(env); register_com_android_server_SystemClockTime(env); diff --git a/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java b/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java index e307e529a40b..228e32e98cc7 100644 --- a/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java +++ b/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java @@ -70,6 +70,7 @@ public final class ProfcollectForwardingService extends SystemService { private int mUsageSetting; private boolean mUploadEnabled; + private static boolean sVerityEnforced; private boolean mAdbActive; private IProfCollectd mIProfcollect; @@ -117,6 +118,13 @@ public final class ProfcollectForwardingService extends SystemService { mUsageSetting = -1; } + // Check verity, disable profile upload if not enforced. + final String verityMode = SystemProperties.get("ro.boot.veritymode"); + sVerityEnforced = verityMode.equals("enforcing"); + if (!sVerityEnforced) { + Log.d(LOG_TAG, "verity is not enforced: " + verityMode); + } + mUploadEnabled = context.getResources().getBoolean(R.bool.config_profcollectReportUploaderEnabled); @@ -373,6 +381,10 @@ public final class ProfcollectForwardingService extends SystemService { Log.i(LOG_TAG, "Upload is not enabled."); return; } + if (!sVerityEnforced) { + Log.i(LOG_TAG, "Verity is not enforced."); + return; + } Intent intent = new Intent() .setPackage("com.android.shell") .setAction("com.android.shell.action.PROFCOLLECT_UPLOAD") 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 759976f79371..47e96d378149 100644 --- a/services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java +++ b/services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java @@ -17,6 +17,7 @@ package com.android.server.display; import static android.Manifest.permission.ADD_ALWAYS_UNLOCKED_DISPLAY; +import static android.Manifest.permission.ADD_MIRROR_DISPLAY; import static android.Manifest.permission.ADD_TRUSTED_DISPLAY; import static android.Manifest.permission.CAPTURE_VIDEO_OUTPUT; import static android.Manifest.permission.CONTROL_DISPLAY_BRIGHTNESS; @@ -122,6 +123,7 @@ import android.os.RemoteException; import android.os.SystemProperties; import android.os.UserManager; import android.os.test.FakePermissionEnforcer; +import android.platform.test.annotations.EnableFlags; import android.platform.test.flag.junit.SetFlagsRule; import android.provider.Settings; import android.provider.Settings.SettingNotFoundException; @@ -1388,6 +1390,7 @@ public class DisplayManagerServiceTest { * Tests that it's not allowed to create an auto-mirror virtual display without * CAPTURE_VIDEO_OUTPUT permission or a virtual device that can mirror displays */ + @EnableFlags(android.companion.virtualdevice.flags.Flags.FLAG_ENABLE_LIMITED_VDM_ROLE) @Test public void createAutoMirrorDisplay_withoutPermissionOrAllowedVirtualDevice_throwsException() throws Exception { @@ -1397,7 +1400,8 @@ public class DisplayManagerServiceTest { when(mMockAppToken.asBinder()).thenReturn(mMockAppToken); IVirtualDevice virtualDevice = mock(IVirtualDevice.class); when(virtualDevice.getDeviceId()).thenReturn(1); - when(virtualDevice.canCreateMirrorDisplays()).thenReturn(false); + when(mContext.checkCallingPermission(ADD_MIRROR_DISPLAY)) + .thenReturn(PackageManager.PERMISSION_DENIED); when(mIVirtualDeviceManager.isValidVirtualDeviceId(1)).thenReturn(true); when(mContext.checkCallingPermission(CAPTURE_VIDEO_OUTPUT)).thenReturn( PackageManager.PERMISSION_DENIED); @@ -1428,7 +1432,8 @@ public class DisplayManagerServiceTest { when(mMockAppToken.asBinder()).thenReturn(mMockAppToken); IVirtualDevice virtualDevice = mock(IVirtualDevice.class); when(virtualDevice.getDeviceId()).thenReturn(1); - when(virtualDevice.canCreateMirrorDisplays()).thenReturn(true); + when(mContext.checkCallingPermission(ADD_MIRROR_DISPLAY)) + .thenReturn(PackageManager.PERMISSION_GRANTED); when(mIVirtualDeviceManager.isValidVirtualDeviceId(1)).thenReturn(true); // Create an auto-mirror virtual display using a virtual device. @@ -1461,7 +1466,8 @@ public class DisplayManagerServiceTest { when(mMockAppToken.asBinder()).thenReturn(mMockAppToken); IVirtualDevice virtualDevice = mock(IVirtualDevice.class); when(virtualDevice.getDeviceId()).thenReturn(1); - when(virtualDevice.canCreateMirrorDisplays()).thenReturn(true); + when(mContext.checkCallingPermission(ADD_MIRROR_DISPLAY)) + .thenReturn(PackageManager.PERMISSION_GRANTED); when(mIVirtualDeviceManager.isValidVirtualDeviceId(1)).thenReturn(true); // Create an auto-mirror virtual display using a virtual device. @@ -1528,7 +1534,8 @@ public class DisplayManagerServiceTest { when(mMockAppToken.asBinder()).thenReturn(mMockAppToken); IVirtualDevice virtualDevice = mock(IVirtualDevice.class); when(virtualDevice.getDeviceId()).thenReturn(1); - when(virtualDevice.canCreateMirrorDisplays()).thenReturn(true); + when(mContext.checkCallingPermission(ADD_MIRROR_DISPLAY)) + .thenReturn(PackageManager.PERMISSION_GRANTED); when(mIVirtualDeviceManager.isValidVirtualDeviceId(1)).thenReturn(true); when(mContext.checkCallingPermission(ADD_ALWAYS_UNLOCKED_DISPLAY)) .thenReturn(PackageManager.PERMISSION_GRANTED); @@ -1564,7 +1571,8 @@ public class DisplayManagerServiceTest { when(mMockAppToken.asBinder()).thenReturn(mMockAppToken); IVirtualDevice virtualDevice = mock(IVirtualDevice.class); when(virtualDevice.getDeviceId()).thenReturn(1); - when(virtualDevice.canCreateMirrorDisplays()).thenReturn(true); + when(mContext.checkCallingPermission(ADD_MIRROR_DISPLAY)) + .thenReturn(PackageManager.PERMISSION_GRANTED); when(mIVirtualDeviceManager.isValidVirtualDeviceId(1)).thenReturn(true); // Create an auto-mirror virtual display using a virtual device. diff --git a/services/tests/mockingservicestests/jni/Android.bp b/services/tests/mockingservicestests/jni/Android.bp index 00543a8a9871..94d4b9522d60 100644 --- a/services/tests/mockingservicestests/jni/Android.bp +++ b/services/tests/mockingservicestests/jni/Android.bp @@ -22,8 +22,8 @@ cc_library_shared { srcs: [ ":lib_cachedAppOptimizer_native", ":lib_freezer_native", - ":lib_gameManagerService_native", ":lib_oomConnection_native", + ":lib_lazilyRegisteredServices_native", "onload.cpp", ], @@ -54,6 +54,8 @@ cc_library_shared { "android.hardware.graphics.bufferqueue@2.0", "android.hardware.graphics.common@1.2", "android.hardware.graphics.mapper@4.0", + "android.hardware.ir@1.0", + "android.hardware.vr@1.0", "android.hidl.token@1.0-utils", ], } diff --git a/services/tests/mockingservicestests/jni/onload.cpp b/services/tests/mockingservicestests/jni/onload.cpp index cb246d15fce8..9b4c8178b092 100644 --- a/services/tests/mockingservicestests/jni/onload.cpp +++ b/services/tests/mockingservicestests/jni/onload.cpp @@ -26,8 +26,8 @@ namespace android { int register_android_server_am_CachedAppOptimizer(JNIEnv* env); int register_android_server_am_Freezer(JNIEnv* env); -int register_android_server_app_GameManagerService(JNIEnv* env); int register_android_server_am_OomConnection(JNIEnv* env); +int register_android_server_utils_LazyJniRegistrar(JNIEnv* env); }; using namespace android; @@ -44,7 +44,7 @@ extern "C" jint JNI_OnLoad(JavaVM* vm, void* /* reserved */) ALOG_ASSERT(env, "Could not retrieve the env!"); register_android_server_am_CachedAppOptimizer(env); register_android_server_am_Freezer(env); - register_android_server_app_GameManagerService(env); register_android_server_am_OomConnection(env); + register_android_server_utils_LazyJniRegistrar(env); return JNI_VERSION_1_4; } diff --git a/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java b/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java index a9569b4096ff..1efe4707fc11 100644 --- a/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java +++ b/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java @@ -105,6 +105,7 @@ import android.os.PowerManagerInternal; import android.os.Process; import android.os.SystemClock; import android.os.UserHandle; +import android.platform.test.annotations.EnableFlags; import android.platform.test.annotations.Presubmit; import android.platform.test.flag.junit.SetFlagsRule; import android.util.ArrayMap; @@ -3260,6 +3261,24 @@ public class MockingOomAdjusterTests { "cch-empty"); } + @SuppressWarnings("GuardedBy") + @Test + @EnableFlags(Flags.FLAG_FIX_APPLY_OOMADJ_ORDER) + public void testUpdateOomAdj_ApplyOomAdjInCorrectOrder() { + final int numberOfApps = 5; + final ProcessRecord[] apps = new ProcessRecord[numberOfApps]; + for (int i = 0; i < numberOfApps; i++) { + apps[i] = spy(makeDefaultProcessRecord(MOCKAPP_PID + i, MOCKAPP_UID + i, + MOCKAPP_PROCESSNAME + i, MOCKAPP_PACKAGENAME + i, true)); + } + updateOomAdj(apps); + for (int i = 1; i < numberOfApps; i++) { + final int pre = mInjector.mSetOomAdjAppliedAt.get(apps[i - 1].mPid); + final int cur = mInjector.mSetOomAdjAppliedAt.get(apps[i].mPid); + assertTrue("setOomAdj is called in wrong order", pre < cur); + } + } + private ProcessRecord makeDefaultProcessRecord(int pid, int uid, String processName, String packageName, boolean hasShownUi) { return new ProcessRecordBuilder(pid, uid, processName, packageName).setHasShownUi( @@ -3589,9 +3608,16 @@ public class MockingOomAdjusterTests { long mTimeOffsetMillis = 0; private SparseIntArray mLastSetOomAdj = new SparseIntArray(); + // A sequence number that increases every time setOomAdj is called + int mLastAppliedAt = 0; + // Holds the last sequence number setOomAdj is called for a pid + private SparseIntArray mSetOomAdjAppliedAt = new SparseIntArray(); + void reset() { mTimeOffsetMillis = 0; mLastSetOomAdj.clear(); + mLastAppliedAt = 0; + mSetOomAdjAppliedAt.clear(); } void jumpUptimeAheadTo(long uptimeMillis) { @@ -3616,6 +3642,7 @@ public class MockingOomAdjusterTests { final int pid = proc.getPid(); if (pid <= 0) continue; mLastSetOomAdj.put(pid, proc.mState.getCurAdj()); + mSetOomAdjAppliedAt.put(pid, mLastAppliedAt++); } } @@ -3623,6 +3650,7 @@ public class MockingOomAdjusterTests { void setOomAdj(int pid, int uid, int adj) { if (pid <= 0) return; mLastSetOomAdj.put(pid, adj); + mSetOomAdjAppliedAt.put(pid, mLastAppliedAt++); } @Override diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/ApexManagerTest.java b/services/tests/mockingservicestests/src/com/android/server/pm/ApexManagerTest.java index 769f071e3ddc..405024cc0e34 100644 --- a/services/tests/mockingservicestests/src/com/android/server/pm/ApexManagerTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/pm/ApexManagerTest.java @@ -134,7 +134,7 @@ public class ApexManagerTest { mMockSystem.system().validateFinalState(); mInstallPackageHelper = new InstallPackageHelper(mPmService, mock(AppDataHelper.class), mock(RemovePackageHelper.class), mock(DeletePackageHelper.class), - mock(BroadcastHelper.class)); + mock(BroadcastHelper.class), mock(InstallDependencyHelper.class)); } @NonNull diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/InstallDependencyHelperTest.java b/services/tests/mockingservicestests/src/com/android/server/pm/InstallDependencyHelperTest.java index 20ac0781e2ed..0304a74f7654 100644 --- a/services/tests/mockingservicestests/src/com/android/server/pm/InstallDependencyHelperTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/pm/InstallDependencyHelperTest.java @@ -79,12 +79,14 @@ public class InstallDependencyHelperTest { @Mock private SharedLibrariesImpl mSharedLibraries; @Mock private Context mContext; @Mock private Computer mComputer; + @Mock private PackageInstallerService mPackageInstallerService; private InstallDependencyHelper mInstallDependencyHelper; @Before public void setUp() { MockitoAnnotations.initMocks(this); - mInstallDependencyHelper = new InstallDependencyHelper(mContext, mSharedLibraries); + mInstallDependencyHelper = new InstallDependencyHelper(mContext, mSharedLibraries, + mPackageInstallerService); } @Test diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/MockSystem.kt b/services/tests/mockingservicestests/src/com/android/server/pm/MockSystem.kt index 0a6edf1b9831..b53dbc834351 100644 --- a/services/tests/mockingservicestests/src/com/android/server/pm/MockSystem.kt +++ b/services/tests/mockingservicestests/src/com/android/server/pm/MockSystem.kt @@ -218,6 +218,8 @@ class MockSystem(withSession: (StaticMockitoSessionBuilder) -> Unit = {}) { val handler = TestHandler(null) val defaultAppProvider: DefaultAppProvider = mock() val backgroundHandler = TestHandler(null) + val packageInstallerService: PackageInstallerService = mock() + val installDependencyHelper: InstallDependencyHelper = mock() val updateOwnershipHelper: UpdateOwnershipHelper = mock() } @@ -306,6 +308,7 @@ class MockSystem(withSession: (StaticMockitoSessionBuilder) -> Unit = {}) { whenever(mocks.injector.handler) { mocks.handler } whenever(mocks.injector.defaultAppProvider) { mocks.defaultAppProvider } whenever(mocks.injector.backgroundHandler) { mocks.backgroundHandler } + whenever(mocks.injector.packageInstallerService) { mocks.packageInstallerService } whenever(mocks.injector.updateOwnershipHelper) { mocks.updateOwnershipHelper } whenever(mocks.injector.getSystemService(AppOpsManager::class.java)) { mocks.appOpsManager } wheneverStatic { SystemConfig.getInstance() }.thenReturn(mocks.systemConfig) @@ -332,6 +335,8 @@ class MockSystem(withSession: (StaticMockitoSessionBuilder) -> Unit = {}) { DEVICE_PROVISIONING_PACKAGE_NAME } whenever(mocks.apexManager.activeApexInfos).thenReturn(DEFAULT_ACTIVE_APEX_INFO_LIST) + whenever(mocks.packageInstallerService.installDependencyHelper).thenReturn( + mocks.installDependencyHelper) whenever(mocks.settings.packagesLocked).thenReturn(mSettingsMap) whenever(mocks.settings.internalVersion).thenReturn(DEFAULT_VERSION_INFO) whenever(mocks.settings.keySetManagerService).thenReturn(mocks.keySetManagerService) diff --git a/services/tests/servicestests/jni/Android.bp b/services/tests/servicestests/jni/Android.bp index 0a3103722796..e738c19cc545 100644 --- a/services/tests/servicestests/jni/Android.bp +++ b/services/tests/servicestests/jni/Android.bp @@ -22,9 +22,9 @@ cc_library_shared { srcs: [ ":lib_cachedAppOptimizer_native", ":lib_freezer_native", - ":lib_gameManagerService_native", ":lib_oomConnection_native", ":lib_anrTimer_native", + ":lib_lazilyRegisteredServices_native", "onload.cpp", ], @@ -55,6 +55,8 @@ cc_library_shared { "android.hardware.graphics.bufferqueue@2.0", "android.hardware.graphics.common@1.2", "android.hardware.graphics.mapper@4.0", + "android.hardware.ir@1.0", + "android.hardware.vr@1.0", "android.hidl.token@1.0-utils", ], } diff --git a/services/tests/servicestests/jni/onload.cpp b/services/tests/servicestests/jni/onload.cpp index 25487c5aabbe..ad979c62f40e 100644 --- a/services/tests/servicestests/jni/onload.cpp +++ b/services/tests/servicestests/jni/onload.cpp @@ -25,9 +25,9 @@ namespace android { int register_android_server_am_CachedAppOptimizer(JNIEnv* env); -int register_android_server_app_GameManagerService(JNIEnv* env); int register_android_server_am_OomConnection(JNIEnv* env); int register_android_server_utils_AnrTimer(JNIEnv *env); +int register_android_server_utils_LazyJniRegistrar(JNIEnv* env); }; using namespace android; @@ -43,8 +43,8 @@ extern "C" jint JNI_OnLoad(JavaVM* vm, void* /* reserved */) } ALOG_ASSERT(env, "Could not retrieve the env!"); register_android_server_am_CachedAppOptimizer(env); - register_android_server_app_GameManagerService(env); register_android_server_am_OomConnection(env); register_android_server_utils_AnrTimer(env); + register_android_server_utils_LazyJniRegistrar(env); return JNI_VERSION_1_4; } diff --git a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityWindowManagerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityWindowManagerTest.java index 403930d96a12..2ae31ad618d6 100644 --- a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityWindowManagerTest.java +++ b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityWindowManagerTest.java @@ -18,20 +18,24 @@ package com.android.server.accessibility; import static com.android.server.accessibility.AbstractAccessibilityServiceConnection.DISPLAY_TYPE_DEFAULT; import static com.android.server.accessibility.AccessibilityWindowManagerTest.DisplayIdMatcher.displayId; +import static com.android.server.accessibility.AccessibilityWindowManagerTest.EventWindowIdMatcher.eventWindowId; import static com.android.server.accessibility.AccessibilityWindowManagerTest.WindowChangesMatcher.a11yWindowChanges; -import static com.android.server.accessibility.AccessibilityWindowManagerTest.WindowIdMatcher.a11yWindowId; +import static com.android.server.accessibility.AccessibilityWindowManagerTest.WindowIdMatcher.windowId; import static junit.framework.Assert.assertFalse; import static junit.framework.Assert.assertNotNull; import static junit.framework.Assert.assertNull; import static junit.framework.Assert.assertTrue; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.allOf; +import static org.hamcrest.Matchers.hasItem; +import static org.hamcrest.Matchers.hasSize; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.not; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotEquals; -import static org.junit.Assert.assertThat; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; @@ -42,14 +46,13 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.annotation.Nullable; +import android.graphics.Point; +import android.graphics.Rect; import android.graphics.Region; import android.os.IBinder; import android.os.LocaleList; import android.os.RemoteException; import android.os.UserHandle; -import android.platform.test.annotations.RequiresFlagsDisabled; -import android.platform.test.flag.junit.CheckFlagsRule; -import android.platform.test.flag.junit.DeviceFlagsValueProvider; import android.util.SparseArray; import android.view.Display; import android.view.IWindow; @@ -63,6 +66,7 @@ import android.view.accessibility.IAccessibilityInteractionConnection; import com.android.server.accessibility.AccessibilityWindowManager.RemoteAccessibilityConnection; import com.android.server.accessibility.test.MessageCapturingHandler; +import com.android.server.wm.AccessibilityWindowsPopulator.AccessibilityWindow; import com.android.server.wm.WindowManagerInternal; import com.android.server.wm.WindowManagerInternal.WindowsForAccessibilityCallback; @@ -70,7 +74,6 @@ import org.hamcrest.Description; import org.hamcrest.TypeSafeMatcher; import org.junit.After; import org.junit.Before; -import org.junit.Rule; import org.junit.Test; import org.mockito.ArgumentCaptor; import org.mockito.Mock; @@ -81,17 +84,9 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; -// This test verifies deprecated codepath. Probably changing this file means -// AccessibilityWindowManagerWithAccessibilityWindowTest also needs to be updated. -// LINT.IfChange - /** - * Tests for the AccessibilityWindowManager with Flags.FLAG_COMPUTE_WINDOW_CHANGES_ON_A11Y_V2 - * enabled. - * TODO(b/322444245): Merge with AccessibilityWindowManagerWithAccessibilityWindowTest - * after completing the flag migration. + * Tests for the AccessibilityWindowManager. */ -@RequiresFlagsDisabled(Flags.FLAG_COMPUTE_WINDOW_CHANGES_ON_A11Y_V2) public class AccessibilityWindowManagerTest { private static final String PACKAGE_NAME = "com.android.server.accessibility"; private static final boolean FORCE_SEND = true; @@ -122,9 +117,8 @@ public class AccessibilityWindowManagerTest { // List of window token, mapping from windowId -> window token. private final SparseArray<IWindow> mA11yWindowTokens = new SparseArray<>(); - // List of window info lists, mapping from displayId -> window info lists. - private final SparseArray<ArrayList<WindowInfo>> mWindowInfos = - new SparseArray<>(); + // List of window info lists, mapping from displayId -> a11y window lists. + private final SparseArray<ArrayList<AccessibilityWindow>> mWindows = new SparseArray<>(); // List of callback, mapping from displayId -> callback. private final SparseArray<WindowsForAccessibilityCallback> mCallbackOfWindows = new SparseArray<>(); @@ -134,6 +128,13 @@ public class AccessibilityWindowManagerTest { private final MessageCapturingHandler mHandler = new MessageCapturingHandler(null); + // This maps displayId -> next region offset. + // Touchable region must have un-occluded area so that it's exposed to a11y services. + // This offset can be used as left and top of new region so that top-left of each region are + // kept visible. + // It's expected to be incremented by some amount everytime the value is used. + private final SparseArray<Integer> mNextRegionOffsets = new SparseArray<>(); + @Mock private WindowManagerInternal mMockWindowManagerInternal; @Mock private AccessibilityWindowManager.AccessibilityEventSender mMockA11yEventSender; @Mock private AccessibilitySecurityPolicy mMockA11ySecurityPolicy; @@ -144,9 +145,6 @@ public class AccessibilityWindowManagerTest { @Mock private IBinder mMockEmbeddedToken; @Mock private IBinder mMockInvalidToken; - @Rule - public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule(); - @Before public void setUp() throws RemoteException { MockitoAnnotations.initMocks(this); @@ -159,7 +157,7 @@ public class AccessibilityWindowManagerTest { anyString(), anyInt(), anyInt(), anyInt())).thenReturn(PACKAGE_NAME); doAnswer((invocation) -> { - onWindowsForAccessibilityChanged(invocation.getArgument(0), false); + onAccessibilityWindowsChanged(invocation.getArgument(0), false); return null; }).when(mMockWindowManagerInternal).computeWindowsForAccessibility(anyInt()); @@ -173,7 +171,7 @@ public class AccessibilityWindowManagerTest { // as top focused display before each testing starts. startTrackingPerDisplay(Display.DEFAULT_DISPLAY); - // AccessibilityEventSender is invoked during onWindowsForAccessibilityChanged. + // AccessibilityEventSender is invoked during onAccessibilityWindowsChanged. // Resets it for mockito verify of further test case. Mockito.reset(mMockA11yEventSender); @@ -237,19 +235,18 @@ public class AccessibilityWindowManagerTest { @Test public void onWindowsChanged_duringTouchInteractAndFocusChange_shouldChangeActiveWindow() { final int activeWindowId = mA11yWindowManager.getActiveWindowId(USER_SYSTEM_ID); - WindowInfo focusedWindowInfo = - mWindowInfos.get(Display.DEFAULT_DISPLAY).get(DEFAULT_FOCUSED_INDEX); + final WindowInfo focusedWindowInfo = + mWindows.get(Display.DEFAULT_DISPLAY).get(DEFAULT_FOCUSED_INDEX).getWindowInfo(); assertEquals(activeWindowId, mA11yWindowManager.findWindowIdLocked( USER_SYSTEM_ID, focusedWindowInfo.token)); focusedWindowInfo.focused = false; - focusedWindowInfo = - mWindowInfos.get(Display.DEFAULT_DISPLAY).get(DEFAULT_FOCUSED_INDEX + 1); - focusedWindowInfo.focused = true; + mWindows.get(Display.DEFAULT_DISPLAY).get( + DEFAULT_FOCUSED_INDEX + 1).getWindowInfo().focused = true; mA11yWindowManager.onTouchInteractionStart(); setTopFocusedWindowAndDisplay(Display.DEFAULT_DISPLAY, DEFAULT_FOCUSED_INDEX + 1); - onWindowsForAccessibilityChanged(Display.DEFAULT_DISPLAY, SEND_ON_WINDOW_CHANGES); + onAccessibilityWindowsChanged(Display.DEFAULT_DISPLAY, SEND_ON_WINDOW_CHANGES); assertNotEquals(activeWindowId, mA11yWindowManager.getActiveWindowId(USER_SYSTEM_ID)); } @@ -273,7 +270,7 @@ public class AccessibilityWindowManagerTest { changeFocusedWindowOnDisplayPerDisplayFocusConfig(SECONDARY_DISPLAY_ID, DEFAULT_FOCUSED_INDEX + 1, Display.DEFAULT_DISPLAY, DEFAULT_FOCUSED_INDEX); - onWindowsForAccessibilityChanged(SECONDARY_DISPLAY_ID, SEND_ON_WINDOW_CHANGES); + onAccessibilityWindowsChanged(SECONDARY_DISPLAY_ID, SEND_ON_WINDOW_CHANGES); // The active window should not be changed. assertEquals(activeWindowId, mA11yWindowManager.getActiveWindowId(USER_SYSTEM_ID)); // The top focused window should not be changed. @@ -301,8 +298,8 @@ public class AccessibilityWindowManagerTest { changeFocusedWindowOnDisplayPerDisplayFocusConfig(SECONDARY_DISPLAY_ID, DEFAULT_FOCUSED_INDEX, Display.DEFAULT_DISPLAY, DEFAULT_FOCUSED_INDEX); - onWindowsForAccessibilityChanged(Display.DEFAULT_DISPLAY, SEND_ON_WINDOW_CHANGES); - onWindowsForAccessibilityChanged(SECONDARY_DISPLAY_ID, SEND_ON_WINDOW_CHANGES); + onAccessibilityWindowsChanged(Display.DEFAULT_DISPLAY, SEND_ON_WINDOW_CHANGES); + onAccessibilityWindowsChanged(SECONDARY_DISPLAY_ID, SEND_ON_WINDOW_CHANGES); // The active window should be changed. assertNotEquals(activeWindowId, mA11yWindowManager.getActiveWindowId(USER_SYSTEM_ID)); // The top focused window should be changed. @@ -312,53 +309,181 @@ public class AccessibilityWindowManagerTest { @Test public void onWindowsChanged_shouldReportCorrectLayer() { - // AccessibilityWindowManager#onWindowsForAccessibilityChanged already invoked in setup. + // AccessibilityWindowManager#onAccessibilityWindowsChanged already invoked in setup. List<AccessibilityWindowInfo> a11yWindows = mA11yWindowManager.getWindowListLocked(Display.DEFAULT_DISPLAY); for (int i = 0; i < a11yWindows.size(); i++) { final AccessibilityWindowInfo a11yWindow = a11yWindows.get(i); - final WindowInfo windowInfo = mWindowInfos.get(Display.DEFAULT_DISPLAY).get(i); - assertThat(mWindowInfos.get(Display.DEFAULT_DISPLAY).size() - windowInfo.layer - 1, + assertThat(mWindows.get(Display.DEFAULT_DISPLAY).size() - i - 1, is(a11yWindow.getLayer())); } } @Test public void onWindowsChanged_shouldReportCorrectOrder() { - // AccessibilityWindowManager#onWindowsForAccessibilityChanged already invoked in setup. + // AccessibilityWindowManager#onAccessibilityWindowsChanged already invoked in setup. List<AccessibilityWindowInfo> a11yWindows = mA11yWindowManager.getWindowListLocked(Display.DEFAULT_DISPLAY); for (int i = 0; i < a11yWindows.size(); i++) { final AccessibilityWindowInfo a11yWindow = a11yWindows.get(i); final IBinder windowToken = mA11yWindowManager .getWindowTokenForUserAndWindowIdLocked(USER_SYSTEM_ID, a11yWindow.getId()); - final WindowInfo windowInfo = mWindowInfos.get(Display.DEFAULT_DISPLAY).get(i); + final WindowInfo windowInfo = mWindows.get(Display.DEFAULT_DISPLAY) + .get(i).getWindowInfo(); assertThat(windowToken, is(windowInfo.token)); } } @Test - public void onWindowsChangedAndForceSend_shouldUpdateWindows() { - final WindowInfo windowInfo = mWindowInfos.get(Display.DEFAULT_DISPLAY).get(0); - final int correctLayer = - mA11yWindowManager.getWindowListLocked(Display.DEFAULT_DISPLAY).get(0).getLayer(); - windowInfo.layer += 1; + public void onWindowsChanged_shouldNotReportNonTouchableWindow() { + final AccessibilityWindow window = mWindows.get(Display.DEFAULT_DISPLAY).get(0); + when(window.isTouchable()).thenReturn(false); + final int windowId = mA11yWindowManager.findWindowIdLocked( + USER_SYSTEM_ID, window.getWindowInfo().token); + + onAccessibilityWindowsChanged(Display.DEFAULT_DISPLAY, SEND_ON_WINDOW_CHANGES); + + final List<AccessibilityWindowInfo> a11yWindows = + mA11yWindowManager.getWindowListLocked(Display.DEFAULT_DISPLAY); + assertThat(a11yWindows, not(hasItem(windowId(windowId)))); + } + + @Test + public void onWindowsChanged_shouldReportFocusedNonTouchableWindow() { + final AccessibilityWindow window = mWindows.get(Display.DEFAULT_DISPLAY).get( + DEFAULT_FOCUSED_INDEX); + when(window.isTouchable()).thenReturn(false); + final int windowId = mA11yWindowManager.findWindowIdLocked( + USER_SYSTEM_ID, window.getWindowInfo().token); + + onAccessibilityWindowsChanged(Display.DEFAULT_DISPLAY, SEND_ON_WINDOW_CHANGES); + + final List<AccessibilityWindowInfo> a11yWindows = + mA11yWindowManager.getWindowListLocked(Display.DEFAULT_DISPLAY); + assertThat(a11yWindows, hasItem(windowId(windowId))); + } + + @Test + public void onWindowsChanged_trustedFocusedNonTouchableWindow_shouldNotHideWindowsBelow() { + // Make the focused trusted un-touchable window fullscreen. + final AccessibilityWindow window = mWindows.get(Display.DEFAULT_DISPLAY).get( + DEFAULT_FOCUSED_INDEX); + setRegionForMockAccessibilityWindow(window, new Region(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT)); + when(window.isTouchable()).thenReturn(false); + when(window.isTrustedOverlay()).thenReturn(true); + + onAccessibilityWindowsChanged(Display.DEFAULT_DISPLAY, SEND_ON_WINDOW_CHANGES); + + final List<AccessibilityWindowInfo> a11yWindows = + mA11yWindowManager.getWindowListLocked(Display.DEFAULT_DISPLAY); + assertThat(a11yWindows, hasSize(NUM_OF_WINDOWS)); + } + + @Test + public void onWindowsChanged_accessibilityOverlay_shouldNotHideWindowsBelow() { + // Make the a11y overlay window fullscreen. + final AccessibilityWindow window = mWindows.get(Display.DEFAULT_DISPLAY).get(0); + setRegionForMockAccessibilityWindow(window, new Region(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT)); + when(window.getType()).thenReturn(WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY); + + onAccessibilityWindowsChanged(Display.DEFAULT_DISPLAY, SEND_ON_WINDOW_CHANGES); + + final List<AccessibilityWindowInfo> a11yWindows = + mA11yWindowManager.getWindowListLocked(Display.DEFAULT_DISPLAY); + assertThat(a11yWindows, hasSize(NUM_OF_WINDOWS)); + } + + @Test + public void onWindowsChanged_shouldReportFocusedWindowEvenIfOccluded() { + // Make the front window fullscreen. + final AccessibilityWindow frontWindow = mWindows.get(Display.DEFAULT_DISPLAY).get(0); + setRegionForMockAccessibilityWindow(frontWindow, + new Region(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT)); + final int frontWindowId = mA11yWindowManager.findWindowIdLocked( + USER_SYSTEM_ID, frontWindow.getWindowInfo().token); + + final AccessibilityWindow focusedWindow = mWindows.get(Display.DEFAULT_DISPLAY).get( + DEFAULT_FOCUSED_INDEX); + final int focusedWindowId = mA11yWindowManager.findWindowIdLocked( + USER_SYSTEM_ID, focusedWindow.getWindowInfo().token); + + onAccessibilityWindowsChanged(Display.DEFAULT_DISPLAY, SEND_ON_WINDOW_CHANGES); + + final List<AccessibilityWindowInfo> a11yWindows = + mA11yWindowManager.getWindowListLocked(Display.DEFAULT_DISPLAY); + assertThat(a11yWindows, hasSize(2)); + assertThat(a11yWindows.get(0), windowId(frontWindowId)); + assertThat(a11yWindows.get(1), windowId(focusedWindowId)); + } + + @Test + public void onWindowsChanged_embeddedWindows_shouldOnlyReportHost() throws RemoteException { + final Rect embeddingBounds = new Rect(0, 0, 200, 100); + + // The embedded window comes front of the host window. + final IBinder embeddedWindowLeashToken = Mockito.mock(IBinder.class); + final int embeddedWindowId = addAccessibilityInteractionConnection(Display.DEFAULT_DISPLAY, + false, embeddedWindowLeashToken, USER_SYSTEM_ID); + final AccessibilityWindow embeddedWindow = createMockAccessibilityWindow( + mA11yWindowTokens.get(embeddedWindowId), Display.DEFAULT_DISPLAY); + setRegionForMockAccessibilityWindow(embeddedWindow, new Region(embeddingBounds)); + mWindows.get(Display.DEFAULT_DISPLAY).set(0, embeddedWindow); + + final IBinder hostWindowLeashToken = Mockito.mock(IBinder.class); + final int hostWindowId = addAccessibilityInteractionConnection(Display.DEFAULT_DISPLAY, + false, hostWindowLeashToken, USER_SYSTEM_ID); + final AccessibilityWindow hostWindow = createMockAccessibilityWindow( + mA11yWindowTokens.get(hostWindowId), Display.DEFAULT_DISPLAY); + setRegionForMockAccessibilityWindow(hostWindow, new Region(embeddingBounds)); + mWindows.get(Display.DEFAULT_DISPLAY).set(1, hostWindow); + + mA11yWindowManager.associateEmbeddedHierarchyLocked( + hostWindowLeashToken, embeddedWindowLeashToken); + + onAccessibilityWindowsChanged(Display.DEFAULT_DISPLAY, SEND_ON_WINDOW_CHANGES); + + final List<AccessibilityWindowInfo> a11yWindows = + mA11yWindowManager.getWindowListLocked(Display.DEFAULT_DISPLAY); + assertThat(a11yWindows, not(hasItem(windowId(embeddedWindowId)))); + assertThat(a11yWindows.get(0), windowId(hostWindowId)); + final Rect bounds = new Rect(); + a11yWindows.get(0).getBoundsInScreen(bounds); + assertEquals(bounds, embeddingBounds); + } - onWindowsForAccessibilityChanged(Display.DEFAULT_DISPLAY, FORCE_SEND); - assertNotEquals(correctLayer, - mA11yWindowManager.getWindowListLocked(Display.DEFAULT_DISPLAY).get(0).getLayer()); + @Test + public void onWindowsChanged_shouldNotReportfullyOccludedWindow() { + final AccessibilityWindow frontWindow = mWindows.get(Display.DEFAULT_DISPLAY).get(0); + setRegionForMockAccessibilityWindow(frontWindow, new Region(100, 100, 300, 300)); + final int frontWindowId = mA11yWindowManager.findWindowIdLocked( + USER_SYSTEM_ID, frontWindow.getWindowInfo().token); + + // index 1 is focused. Let's use the next one for this test. + final AccessibilityWindow occludedWindow = mWindows.get(Display.DEFAULT_DISPLAY).get(2); + setRegionForMockAccessibilityWindow(occludedWindow, new Region(150, 150, 250, 250)); + final int occludedWindowId = mA11yWindowManager.findWindowIdLocked( + USER_SYSTEM_ID, occludedWindow.getWindowInfo().token); + + onAccessibilityWindowsChanged(Display.DEFAULT_DISPLAY, SEND_ON_WINDOW_CHANGES); + + final List<AccessibilityWindowInfo> a11yWindows = + mA11yWindowManager.getWindowListLocked(Display.DEFAULT_DISPLAY); + assertThat(a11yWindows, hasItem(windowId(frontWindowId))); + assertThat(a11yWindows, not(hasItem(windowId(occludedWindowId)))); } @Test - public void onWindowsChangedNoForceSend_layerChanged_shouldNotUpdateWindows() { - final WindowInfo windowInfo = mWindowInfos.get(Display.DEFAULT_DISPLAY).get(0); - final int correctLayer = - mA11yWindowManager.getWindowListLocked(Display.DEFAULT_DISPLAY).get(0).getLayer(); - windowInfo.layer += 1; + public void onWindowsChangedAndForceSend_shouldUpdateWindows() { + assertNotEquals("new title", + toString(mA11yWindowManager.getWindowListLocked(Display.DEFAULT_DISPLAY) + .get(0).getTitle())); - onWindowsForAccessibilityChanged(Display.DEFAULT_DISPLAY, SEND_ON_WINDOW_CHANGES); - assertEquals(correctLayer, - mA11yWindowManager.getWindowListLocked(Display.DEFAULT_DISPLAY).get(0).getLayer()); + mWindows.get(Display.DEFAULT_DISPLAY).get(0).getWindowInfo().title = "new title"; + + onAccessibilityWindowsChanged(Display.DEFAULT_DISPLAY, FORCE_SEND); + assertEquals("new title", + toString(mA11yWindowManager.getWindowListLocked(Display.DEFAULT_DISPLAY) + .get(0).getTitle())); } @Test @@ -368,14 +493,10 @@ public class AccessibilityWindowManagerTest { mA11yWindowManager.getWindowListLocked(Display.DEFAULT_DISPLAY).get(0); final IWindow token = addAccessibilityInteractionConnection(Display.DEFAULT_DISPLAY, true, USER_SYSTEM_ID); - final WindowInfo windowInfo = WindowInfo.obtain(); - windowInfo.type = AccessibilityWindowInfo.TYPE_APPLICATION; - windowInfo.token = token.asBinder(); - windowInfo.layer = 0; - windowInfo.regionInScreen.set(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); - mWindowInfos.get(Display.DEFAULT_DISPLAY).set(0, windowInfo); + mWindows.get(Display.DEFAULT_DISPLAY).set(0, + createMockAccessibilityWindow(token, Display.DEFAULT_DISPLAY)); - onWindowsForAccessibilityChanged(Display.DEFAULT_DISPLAY, SEND_ON_WINDOW_CHANGES); + onAccessibilityWindowsChanged(Display.DEFAULT_DISPLAY, SEND_ON_WINDOW_CHANGES); assertNotEquals(oldWindow, mA11yWindowManager.getWindowListLocked(Display.DEFAULT_DISPLAY).get(0)); } @@ -383,12 +504,12 @@ public class AccessibilityWindowManagerTest { @Test public void onWindowsChangedNoForceSend_focusChanged_shouldUpdateWindows() { final WindowInfo focusedWindowInfo = - mWindowInfos.get(Display.DEFAULT_DISPLAY).get(DEFAULT_FOCUSED_INDEX); - final WindowInfo windowInfo = mWindowInfos.get(Display.DEFAULT_DISPLAY).get(0); + mWindows.get(Display.DEFAULT_DISPLAY).get(DEFAULT_FOCUSED_INDEX).getWindowInfo(); + final WindowInfo windowInfo = mWindows.get(Display.DEFAULT_DISPLAY).get(0).getWindowInfo(); focusedWindowInfo.focused = false; windowInfo.focused = true; - onWindowsForAccessibilityChanged(Display.DEFAULT_DISPLAY, SEND_ON_WINDOW_CHANGES); + onAccessibilityWindowsChanged(Display.DEFAULT_DISPLAY, SEND_ON_WINDOW_CHANGES); assertTrue(mA11yWindowManager.getWindowListLocked(Display.DEFAULT_DISPLAY).get(0) .isFocused()); } @@ -497,15 +618,18 @@ public class AccessibilityWindowManagerTest { @Test public void computePartialInteractiveRegionForWindow_wholeVisible_returnWholeRegion() { // Updates top 2 z-order WindowInfo are whole visible. - WindowInfo windowInfo = mWindowInfos.get(Display.DEFAULT_DISPLAY).get(0); - windowInfo.regionInScreen.set(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT / 2); - windowInfo = mWindowInfos.get(Display.DEFAULT_DISPLAY).get(1); - windowInfo.regionInScreen.set(0, SCREEN_HEIGHT / 2, - SCREEN_WIDTH, SCREEN_HEIGHT); - onWindowsForAccessibilityChanged(Display.DEFAULT_DISPLAY, SEND_ON_WINDOW_CHANGES); + final AccessibilityWindow firstWindow = mWindows.get(Display.DEFAULT_DISPLAY).get(0); + setRegionForMockAccessibilityWindow(firstWindow, + new Region(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT / 2)); + final AccessibilityWindow secondWindow = mWindows.get(Display.DEFAULT_DISPLAY).get(1); + setRegionForMockAccessibilityWindow(secondWindow, + new Region(0, SCREEN_HEIGHT / 2, SCREEN_WIDTH, SCREEN_HEIGHT)); + + onAccessibilityWindowsChanged(Display.DEFAULT_DISPLAY, SEND_ON_WINDOW_CHANGES); final List<AccessibilityWindowInfo> a11yWindows = mA11yWindowManager.getWindowListLocked(Display.DEFAULT_DISPLAY); + assertThat(a11yWindows, hasSize(2)); final Region outBounds = new Region(); int windowId = a11yWindows.get(0).getId(); @@ -523,12 +647,17 @@ public class AccessibilityWindowManagerTest { @Test public void computePartialInteractiveRegionForWindow_halfVisible_returnHalfRegion() { // Updates z-order #1 WindowInfo is half visible. - WindowInfo windowInfo = mWindowInfos.get(Display.DEFAULT_DISPLAY).get(0); - windowInfo.regionInScreen.set(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT / 2); - - onWindowsForAccessibilityChanged(Display.DEFAULT_DISPLAY, SEND_ON_WINDOW_CHANGES); + final AccessibilityWindow firstWindow = mWindows.get(Display.DEFAULT_DISPLAY).get(0); + setRegionForMockAccessibilityWindow(firstWindow, + new Region(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT / 2)); + final AccessibilityWindow secondWindow = mWindows.get(Display.DEFAULT_DISPLAY).get(1); + setRegionForMockAccessibilityWindow(secondWindow, + new Region(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT)); + + onAccessibilityWindowsChanged(Display.DEFAULT_DISPLAY, SEND_ON_WINDOW_CHANGES); final List<AccessibilityWindowInfo> a11yWindows = mA11yWindowManager.getWindowListLocked(Display.DEFAULT_DISPLAY); + assertThat(a11yWindows, hasSize(2)); final Region outBounds = new Region(); int windowId = a11yWindows.get(1).getId(); @@ -539,9 +668,17 @@ public class AccessibilityWindowManagerTest { @Test public void computePartialInteractiveRegionForWindow_notVisible_returnEmptyRegion() { - // Since z-order #0 WindowInfo is full screen, z-order #1 WindowInfo should be invisible. + // z-order #0 WindowInfo is full screen, z-order #1 WindowInfo should be invisible. + final AccessibilityWindow firstWindow = mWindows.get(Display.DEFAULT_DISPLAY).get(0); + setRegionForMockAccessibilityWindow(firstWindow, + new Region(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT)); + + onAccessibilityWindowsChanged(Display.DEFAULT_DISPLAY, SEND_ON_WINDOW_CHANGES); + final List<AccessibilityWindowInfo> a11yWindows = mA11yWindowManager.getWindowListLocked(Display.DEFAULT_DISPLAY); + // Note that the second window is also exposed even if region is empty because it's focused. + assertThat(a11yWindows, hasSize(2)); final Region outBounds = new Region(); int windowId = a11yWindows.get(1).getId(); @@ -552,16 +689,21 @@ public class AccessibilityWindowManagerTest { @Test public void computePartialInteractiveRegionForWindow_partialVisible_returnVisibleRegion() { // Updates z-order #0 WindowInfo to have two interact-able areas. - Region region = new Region(0, 0, SCREEN_WIDTH, 200); + final Region region = new Region(0, 0, SCREEN_WIDTH, 200); region.op(0, SCREEN_HEIGHT - 200, SCREEN_WIDTH, SCREEN_HEIGHT, Region.Op.UNION); - WindowInfo windowInfo = mWindowInfos.get(Display.DEFAULT_DISPLAY).get(0); - windowInfo.regionInScreen.set(region); - onWindowsForAccessibilityChanged(Display.DEFAULT_DISPLAY, SEND_ON_WINDOW_CHANGES); + final AccessibilityWindow firstWindow = mWindows.get(Display.DEFAULT_DISPLAY).get(0); + setRegionForMockAccessibilityWindow(firstWindow, region); + final AccessibilityWindow secondWindow = mWindows.get(Display.DEFAULT_DISPLAY).get(1); + setRegionForMockAccessibilityWindow(secondWindow, + new Region(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT)); + + onAccessibilityWindowsChanged(Display.DEFAULT_DISPLAY, SEND_ON_WINDOW_CHANGES); final List<AccessibilityWindowInfo> a11yWindows = mA11yWindowManager.getWindowListLocked(Display.DEFAULT_DISPLAY); + assertThat(a11yWindows, hasSize(2)); final Region outBounds = new Region(); - int windowId = a11yWindows.get(1).getId(); + final int windowId = a11yWindows.get(1).getId(); mA11yWindowManager.computePartialInteractiveRegionForWindowLocked(windowId, outBounds); assertFalse(outBounds.getBounds().isEmpty()); @@ -572,7 +714,8 @@ public class AccessibilityWindowManagerTest { @Test public void updateActiveAndA11yFocusedWindow_windowStateChangedEvent_noTracking_shouldUpdate() { final IBinder eventWindowToken = - mWindowInfos.get(Display.DEFAULT_DISPLAY).get(DEFAULT_FOCUSED_INDEX + 1).token; + mWindows.get(Display.DEFAULT_DISPLAY) + .get(DEFAULT_FOCUSED_INDEX + 1).getWindowInfo().token; final int eventWindowId = mA11yWindowManager.findWindowIdLocked( USER_SYSTEM_ID, eventWindowToken); when(mMockWindowManagerInternal.getFocusedWindowTokenFromWindowStates()) @@ -611,11 +754,11 @@ public class AccessibilityWindowManagerTest { .sendAccessibilityEventForCurrentUserLocked(captor.capture()); assertThat(captor.getAllValues().get(0), allOf(displayId(Display.DEFAULT_DISPLAY), - a11yWindowId(currentActiveWindowId), + eventWindowId(currentActiveWindowId), a11yWindowChanges(AccessibilityEvent.WINDOWS_CHANGE_ACTIVE))); assertThat(captor.getAllValues().get(1), allOf(displayId(Display.DEFAULT_DISPLAY), - a11yWindowId(eventWindowId), + eventWindowId(eventWindowId), a11yWindowChanges(AccessibilityEvent.WINDOWS_CHANGE_ACTIVE))); } @@ -641,7 +784,7 @@ public class AccessibilityWindowManagerTest { .sendAccessibilityEventForCurrentUserLocked(captor.capture()); assertThat(captor.getAllValues().get(0), allOf(displayId(Display.DEFAULT_DISPLAY), - a11yWindowId(eventWindowId), + eventWindowId(eventWindowId), a11yWindowChanges( AccessibilityEvent.WINDOWS_CHANGE_ACCESSIBILITY_FOCUSED))); } @@ -690,12 +833,12 @@ public class AccessibilityWindowManagerTest { .sendAccessibilityEventForCurrentUserLocked(captor.capture()); assertThat(captor.getAllValues().get(0), allOf(displayId(initialDisplayId), - a11yWindowId(initialWindowId), + eventWindowId(initialWindowId), a11yWindowChanges( AccessibilityEvent.WINDOWS_CHANGE_ACCESSIBILITY_FOCUSED))); assertThat(captor.getAllValues().get(1), allOf(displayId(eventDisplayId), - a11yWindowId(eventWindowId), + eventWindowId(eventWindowId), a11yWindowChanges( AccessibilityEvent.WINDOWS_CHANGE_ACCESSIBILITY_FOCUSED))); } @@ -722,7 +865,7 @@ public class AccessibilityWindowManagerTest { AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED, noUse); assertThat(mA11yWindowManager.getFocusedWindowId( - AccessibilityNodeInfo.FOCUS_ACCESSIBILITY), + AccessibilityNodeInfo.FOCUS_ACCESSIBILITY), is(AccessibilityWindowInfo.UNDEFINED_WINDOW_ID)); } @@ -751,11 +894,11 @@ public class AccessibilityWindowManagerTest { .sendAccessibilityEventForCurrentUserLocked(captor.capture()); assertThat(captor.getAllValues().get(0), allOf(displayId(Display.DEFAULT_DISPLAY), - a11yWindowId(eventWindowId), + eventWindowId(eventWindowId), a11yWindowChanges(AccessibilityEvent.WINDOWS_CHANGE_ACTIVE))); assertThat(captor.getAllValues().get(1), allOf(displayId(Display.DEFAULT_DISPLAY), - a11yWindowId(currentActiveWindowId), + eventWindowId(currentActiveWindowId), a11yWindowChanges(AccessibilityEvent.WINDOWS_CHANGE_ACTIVE))); } @@ -763,7 +906,8 @@ public class AccessibilityWindowManagerTest { public void onTouchInteractionEnd_noServiceInteractiveWindow_shouldClearA11yFocus() throws RemoteException { final IBinder defaultFocusWinToken = - mWindowInfos.get(Display.DEFAULT_DISPLAY).get(DEFAULT_FOCUSED_INDEX).token; + mWindows.get(Display.DEFAULT_DISPLAY).get( + DEFAULT_FOCUSED_INDEX).getWindowInfo().token; final int defaultFocusWindowId = mA11yWindowManager.findWindowIdLocked( USER_SYSTEM_ID, defaultFocusWinToken); when(mMockWindowManagerInternal.getFocusedWindowTokenFromWindowStates()) @@ -808,8 +952,8 @@ public class AccessibilityWindowManagerTest { @Test public void getPictureInPictureWindow_shouldNotNull() { assertNull(mA11yWindowManager.getPictureInPictureWindowLocked()); - mWindowInfos.get(Display.DEFAULT_DISPLAY).get(1).inPictureInPicture = true; - onWindowsForAccessibilityChanged(Display.DEFAULT_DISPLAY, SEND_ON_WINDOW_CHANGES); + mWindows.get(Display.DEFAULT_DISPLAY).get(1).getWindowInfo().inPictureInPicture = true; + onAccessibilityWindowsChanged(Display.DEFAULT_DISPLAY, SEND_ON_WINDOW_CHANGES); assertNotNull(mA11yWindowManager.getPictureInPictureWindowLocked()); } @@ -823,8 +967,9 @@ public class AccessibilityWindowManagerTest { final IAccessibilityInteractionConnection mockRemoteConnection = mA11yWindowManager.getConnectionLocked( USER_SYSTEM_ID, outsideWindowId).getRemote(); - mWindowInfos.get(Display.DEFAULT_DISPLAY).get(0).hasFlagWatchOutsideTouch = true; - onWindowsForAccessibilityChanged(Display.DEFAULT_DISPLAY, SEND_ON_WINDOW_CHANGES); + mWindows.get(Display.DEFAULT_DISPLAY).get(0).getWindowInfo().hasFlagWatchOutsideTouch = + true; + onAccessibilityWindowsChanged(Display.DEFAULT_DISPLAY, SEND_ON_WINDOW_CHANGES); mA11yWindowManager.notifyOutsideTouch(USER_SYSTEM_ID, targetWindowId); verify(mockRemoteConnection).notifyOutsideTouch(); @@ -942,18 +1087,14 @@ public class AccessibilityWindowManagerTest { @Test public void sendAccessibilityEventOnWindowRemoval() { - final ArrayList<WindowInfo> infos = mWindowInfos.get(Display.DEFAULT_DISPLAY); + final ArrayList<AccessibilityWindow> windows = mWindows.get(Display.DEFAULT_DISPLAY); // Removing index 0 because it's not focused, and avoids unnecessary layer change. final int windowId = getWindowIdFromWindowInfosForDisplay(Display.DEFAULT_DISPLAY, 0); - infos.remove(0); - for (WindowInfo info : infos) { - // Adjust layer number because it should start from 0. - info.layer--; - } + windows.remove(0); - onWindowsForAccessibilityChanged(Display.DEFAULT_DISPLAY, FORCE_SEND); + onAccessibilityWindowsChanged(Display.DEFAULT_DISPLAY, FORCE_SEND); final ArgumentCaptor<AccessibilityEvent> captor = ArgumentCaptor.forClass(AccessibilityEvent.class); @@ -961,27 +1102,21 @@ public class AccessibilityWindowManagerTest { .sendAccessibilityEventForCurrentUserLocked(captor.capture()); assertThat(captor.getAllValues().get(0), allOf(displayId(Display.DEFAULT_DISPLAY), - a11yWindowId(windowId), + eventWindowId(windowId), a11yWindowChanges(AccessibilityEvent.WINDOWS_CHANGE_REMOVED))); } @Test public void sendAccessibilityEventOnWindowAddition() throws RemoteException { - final ArrayList<WindowInfo> infos = mWindowInfos.get(Display.DEFAULT_DISPLAY); - - for (WindowInfo info : infos) { - // Adjust layer number because new window will have 0 so that layer number in - // A11yWindowInfo in window won't be changed. - info.layer++; - } + final ArrayList<AccessibilityWindow> windows = mWindows.get(Display.DEFAULT_DISPLAY); final IWindow token = addAccessibilityInteractionConnection(Display.DEFAULT_DISPLAY, false, USER_SYSTEM_ID); - addWindowInfo(infos, token, 0); - final int windowId = - getWindowIdFromWindowInfosForDisplay(Display.DEFAULT_DISPLAY, infos.size() - 1); + // Adding window to the front so that other windows' layer won't change. + windows.add(0, createMockAccessibilityWindow(token, Display.DEFAULT_DISPLAY)); + final int windowId = getWindowIdFromWindowInfosForDisplay(Display.DEFAULT_DISPLAY, 0); - onWindowsForAccessibilityChanged(Display.DEFAULT_DISPLAY, FORCE_SEND); + onAccessibilityWindowsChanged(Display.DEFAULT_DISPLAY, FORCE_SEND); final ArgumentCaptor<AccessibilityEvent> captor = ArgumentCaptor.forClass(AccessibilityEvent.class); @@ -989,17 +1124,17 @@ public class AccessibilityWindowManagerTest { .sendAccessibilityEventForCurrentUserLocked(captor.capture()); assertThat(captor.getAllValues().get(0), allOf(displayId(Display.DEFAULT_DISPLAY), - a11yWindowId(windowId), + eventWindowId(windowId), a11yWindowChanges(AccessibilityEvent.WINDOWS_CHANGE_ADDED))); } @Test public void sendAccessibilityEventOnWindowChange() { - final ArrayList<WindowInfo> infos = mWindowInfos.get(Display.DEFAULT_DISPLAY); - infos.get(0).title = "new title"; + final ArrayList<AccessibilityWindow> windows = mWindows.get(Display.DEFAULT_DISPLAY); + windows.get(0).getWindowInfo().title = "new title"; final int windowId = getWindowIdFromWindowInfosForDisplay(Display.DEFAULT_DISPLAY, 0); - onWindowsForAccessibilityChanged(Display.DEFAULT_DISPLAY, FORCE_SEND); + onAccessibilityWindowsChanged(Display.DEFAULT_DISPLAY, FORCE_SEND); final ArgumentCaptor<AccessibilityEvent> captor = ArgumentCaptor.forClass(AccessibilityEvent.class); @@ -1007,7 +1142,7 @@ public class AccessibilityWindowManagerTest { .sendAccessibilityEventForCurrentUserLocked(captor.capture()); assertThat(captor.getAllValues().get(0), allOf(displayId(Display.DEFAULT_DISPLAY), - a11yWindowId(windowId), + eventWindowId(windowId), a11yWindowChanges(AccessibilityEvent.WINDOWS_CHANGE_TITLE))); } @@ -1017,48 +1152,47 @@ public class AccessibilityWindowManagerTest { } private void startTrackingPerDisplay(int displayId) throws RemoteException { - ArrayList<WindowInfo> windowInfosForDisplay = new ArrayList<>(); + ArrayList<AccessibilityWindow> windowsForDisplay = new ArrayList<>(); // Adds RemoteAccessibilityConnection into AccessibilityWindowManager, and copy // mock window token into mA11yWindowTokens. Also, preparing WindowInfo mWindowInfos // for the test. - int layer = 0; for (int i = 0; i < NUM_GLOBAL_WINDOWS; i++) { final IWindow token = addAccessibilityInteractionConnection(displayId, true, USER_SYSTEM_ID); - addWindowInfo(windowInfosForDisplay, token, layer++); + windowsForDisplay.add(createMockAccessibilityWindow(token, displayId)); } for (int i = 0; i < NUM_APP_WINDOWS; i++) { final IWindow token = addAccessibilityInteractionConnection(displayId, false, USER_SYSTEM_ID); - addWindowInfo(windowInfosForDisplay, token, layer++); + windowsForDisplay.add(createMockAccessibilityWindow(token, displayId)); } // Sets up current focused window of display. // Each display has its own current focused window if config_perDisplayFocusEnabled is true. // Otherwise only default display needs to current focused window. if (mSupportPerDisplayFocus || displayId == Display.DEFAULT_DISPLAY) { - windowInfosForDisplay.get(DEFAULT_FOCUSED_INDEX).focused = true; + windowsForDisplay.get(DEFAULT_FOCUSED_INDEX).getWindowInfo().focused = true; } // Turns on windows tracking, and update window info. mA11yWindowManager.startTrackingWindows(displayId, false); // Puts window lists into array. - mWindowInfos.put(displayId, windowInfosForDisplay); + mWindows.put(displayId, windowsForDisplay); // Sets the default display is the top focused display and // its current focused window is the top focused window. if (displayId == Display.DEFAULT_DISPLAY) { setTopFocusedWindowAndDisplay(displayId, DEFAULT_FOCUSED_INDEX); } // Invokes callback for sending window lists to A11y framework. - onWindowsForAccessibilityChanged(displayId, FORCE_SEND); + onAccessibilityWindowsChanged(displayId, FORCE_SEND); assertEquals(mA11yWindowManager.getWindowListLocked(displayId).size(), - windowInfosForDisplay.size()); + windowsForDisplay.size()); } private WindowsForAccessibilityCallback getWindowsForAccessibilityCallbacks(int displayId) { ArgumentCaptor<WindowsForAccessibilityCallback> windowsForAccessibilityCallbacksCaptor = ArgumentCaptor.forClass( - WindowManagerInternal.WindowsForAccessibilityCallback.class); + WindowsForAccessibilityCallback.class); verify(mMockWindowManagerInternal) .setWindowsForAccessibilityCallback(eq(displayId), windowsForAccessibilityCallbacksCaptor.capture()); @@ -1106,36 +1240,28 @@ public class AccessibilityWindowManagerTest { return windowId; } - private void addWindowInfo(ArrayList<WindowInfo> windowInfos, IWindow windowToken, int layer) { - final WindowInfo windowInfo = WindowInfo.obtain(); - windowInfo.type = AccessibilityWindowInfo.TYPE_APPLICATION; - windowInfo.token = windowToken.asBinder(); - windowInfo.layer = layer; - windowInfo.regionInScreen.set(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); - windowInfos.add(windowInfo); - } - private int getWindowIdFromWindowInfosForDisplay(int displayId, int index) { - final IBinder windowToken = mWindowInfos.get(displayId).get(index).token; + final IBinder windowToken = mWindows.get(displayId).get(index).getWindowInfo().token; return mA11yWindowManager.findWindowIdLocked( USER_SYSTEM_ID, windowToken); } private void setTopFocusedWindowAndDisplay(int displayId, int index) { // Sets the top focus window. - mTopFocusedWindowToken = mWindowInfos.get(displayId).get(index).token; + mTopFocusedWindowToken = mWindows.get(displayId).get(index).getWindowInfo().token; // Sets the top focused display. mTopFocusedDisplayId = displayId; } - private void onWindowsForAccessibilityChanged(int displayId, boolean forceSend) { + private void onAccessibilityWindowsChanged(int displayId, boolean forceSend) { WindowsForAccessibilityCallback callbacks = mCallbackOfWindows.get(displayId); if (callbacks == null) { callbacks = getWindowsForAccessibilityCallbacks(displayId); mCallbackOfWindows.put(displayId, callbacks); } - callbacks.onWindowsForAccessibilityChanged(forceSend, mTopFocusedDisplayId, - mTopFocusedWindowToken, mWindowInfos.get(displayId)); + callbacks.onAccessibilityWindowsChanged(forceSend, mTopFocusedDisplayId, + mTopFocusedWindowToken, new Point(SCREEN_WIDTH, SCREEN_HEIGHT), + mWindows.get(displayId)); } private void changeFocusedWindowOnDisplayPerDisplayFocusConfig( @@ -1144,23 +1270,23 @@ public class AccessibilityWindowManagerTest { if (mSupportPerDisplayFocus) { // Gets the old focused window of display which wants to change focused window. WindowInfo focusedWindowInfo = - mWindowInfos.get(changeFocusedDisplayId).get(oldFocusedWindowIndex); + mWindows.get(changeFocusedDisplayId).get(oldFocusedWindowIndex).getWindowInfo(); // Resets the focus of old focused window. focusedWindowInfo.focused = false; // Gets the new window of display which wants to change focused window. focusedWindowInfo = - mWindowInfos.get(changeFocusedDisplayId).get(newFocusedWindowIndex); + mWindows.get(changeFocusedDisplayId).get(newFocusedWindowIndex).getWindowInfo(); // Sets the focus of new focused window. focusedWindowInfo.focused = true; } else { // Gets the window of display which wants to change focused window. WindowInfo focusedWindowInfo = - mWindowInfos.get(changeFocusedDisplayId).get(newFocusedWindowIndex); + mWindows.get(changeFocusedDisplayId).get(newFocusedWindowIndex).getWindowInfo(); // Sets the focus of new focused window. focusedWindowInfo.focused = true; // Gets the old focused window of old top focused display. focusedWindowInfo = - mWindowInfos.get(oldTopFocusedDisplayId).get(oldFocusedWindowIndex); + mWindows.get(oldTopFocusedDisplayId).get(oldFocusedWindowIndex).getWindowInfo(); // Resets the focus of old focused window. focusedWindowInfo.focused = false; // Changes the top focused display and window. @@ -1168,6 +1294,39 @@ public class AccessibilityWindowManagerTest { } } + private AccessibilityWindow createMockAccessibilityWindow(IWindow windowToken, int displayId) { + final WindowInfo windowInfo = WindowInfo.obtain(); + windowInfo.type = WindowManager.LayoutParams.TYPE_APPLICATION; + windowInfo.token = windowToken.asBinder(); + + final AccessibilityWindow window = Mockito.mock(AccessibilityWindow.class); + when(window.getWindowInfo()).thenReturn(windowInfo); + when(window.isFocused()).thenAnswer(invocation -> windowInfo.focused); + when(window.isTouchable()).thenReturn(true); + when(window.getType()).thenReturn(windowInfo.type); + + setRegionForMockAccessibilityWindow(window, nextToucableRegion(displayId)); + return window; + } + + private void setRegionForMockAccessibilityWindow(AccessibilityWindow window, Region region) { + doAnswer(invocation -> { + ((Region) invocation.getArgument(0)).set(region); + return null; + }).when(window).getTouchableRegionInScreen(any(Region.class)); + doAnswer(invocation -> { + ((Region) invocation.getArgument(0)).set(region); + return null; + }).when(window).getTouchableRegionInWindow(any(Region.class)); + } + + private Region nextToucableRegion(int displayId) { + final int topLeft = mNextRegionOffsets.get(displayId, 0); + final int bottomRight = topLeft + 100; + mNextRegionOffsets.put(displayId, topLeft + 10); + return new Region(topLeft, topLeft, bottomRight, bottomRight); + } + @Nullable private static String toString(@Nullable CharSequence cs) { return cs == null ? null : cs.toString(); @@ -1196,16 +1355,16 @@ public class AccessibilityWindowManagerTest { } } - static class WindowIdMatcher extends TypeSafeMatcher<AccessibilityEvent> { + static class EventWindowIdMatcher extends TypeSafeMatcher<AccessibilityEvent> { private int mWindowId; - WindowIdMatcher(int windowId) { + EventWindowIdMatcher(int windowId) { super(); mWindowId = windowId; } - static WindowIdMatcher a11yWindowId(int windowId) { - return new WindowIdMatcher(windowId); + static EventWindowIdMatcher eventWindowId(int windowId) { + return new EventWindowIdMatcher(windowId); } @Override @@ -1241,5 +1400,27 @@ public class AccessibilityWindowManagerTest { description.appendText("Matching to window changes " + mWindowChanges); } } + + static class WindowIdMatcher extends TypeSafeMatcher<AccessibilityWindowInfo> { + private final int mWindowId; + + WindowIdMatcher(int windowId) { + super(); + mWindowId = windowId; + } + + static WindowIdMatcher windowId(int windowId) { + return new WindowIdMatcher(windowId); + } + + @Override + protected boolean matchesSafely(AccessibilityWindowInfo window) { + return window.getId() == mWindowId; + } + + @Override + public void describeTo(Description description) { + description.appendText("Matching to windowId " + mWindowId); + } + } } -// LINT.ThenChange(/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityWindowManagerWithAccessibilityWindowTest.java) diff --git a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityWindowManagerWithAccessibilityWindowTest.java b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityWindowManagerWithAccessibilityWindowTest.java deleted file mode 100644 index 19041451c8eb..000000000000 --- a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityWindowManagerWithAccessibilityWindowTest.java +++ /dev/null @@ -1,1444 +0,0 @@ -/* - * Copyright (C) 2019 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.accessibility; - -import static com.android.server.accessibility.AbstractAccessibilityServiceConnection.DISPLAY_TYPE_DEFAULT; -import static com.android.server.accessibility.AccessibilityWindowManagerWithAccessibilityWindowTest.DisplayIdMatcher.displayId; -import static com.android.server.accessibility.AccessibilityWindowManagerWithAccessibilityWindowTest.WindowIdMatcher.windowId; -import static com.android.server.accessibility.AccessibilityWindowManagerWithAccessibilityWindowTest.WindowChangesMatcher.a11yWindowChanges; -import static com.android.server.accessibility.AccessibilityWindowManagerWithAccessibilityWindowTest.EventWindowIdMatcher.eventWindowId; - -import static junit.framework.Assert.assertFalse; -import static junit.framework.Assert.assertNotNull; -import static junit.framework.Assert.assertNull; -import static junit.framework.Assert.assertTrue; - -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.allOf; -import static org.hamcrest.Matchers.hasItem; -import static org.hamcrest.Matchers.hasSize; -import static org.hamcrest.Matchers.is; -import static org.hamcrest.Matchers.not; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotEquals; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.ArgumentMatchers.isNull; -import static org.mockito.Mockito.doAnswer; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import android.annotation.Nullable; -import android.graphics.Point; -import android.graphics.Rect; -import android.graphics.Region; -import android.os.IBinder; -import android.os.LocaleList; -import android.os.RemoteException; -import android.os.UserHandle; -import android.platform.test.annotations.RequiresFlagsEnabled; -import android.platform.test.flag.junit.CheckFlagsRule; -import android.platform.test.flag.junit.DeviceFlagsValueProvider; -import android.util.SparseArray; -import android.view.Display; -import android.view.IWindow; -import android.view.WindowInfo; -import android.view.WindowManager; -import android.view.accessibility.AccessibilityEvent; -import android.view.accessibility.AccessibilityNodeInfo; -import android.view.accessibility.AccessibilityWindowAttributes; -import android.view.accessibility.AccessibilityWindowInfo; -import android.view.accessibility.IAccessibilityInteractionConnection; - -import com.android.server.accessibility.AccessibilityWindowManager.RemoteAccessibilityConnection; -import com.android.server.accessibility.test.MessageCapturingHandler; -import com.android.server.wm.AccessibilityWindowsPopulator.AccessibilityWindow; -import com.android.server.wm.WindowManagerInternal; -import com.android.server.wm.WindowManagerInternal.WindowsForAccessibilityCallback; - -import org.hamcrest.Description; -import org.hamcrest.TypeSafeMatcher; -import org.junit.After; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.mockito.ArgumentCaptor; -import org.mockito.Mock; -import org.mockito.Mockito; -import org.mockito.MockitoAnnotations; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -/** - * Tests for the AccessibilityWindowManager with Flags.FLAG_COMPUTE_WINDOW_CHANGES_ON_A11Y_V2 - * TODO(b/322444245): Merge with AccessibilityWindowManagerTest - * after completing the flag migration. - */ -@RequiresFlagsEnabled(Flags.FLAG_COMPUTE_WINDOW_CHANGES_ON_A11Y_V2) -public class AccessibilityWindowManagerWithAccessibilityWindowTest { - private static final String PACKAGE_NAME = "com.android.server.accessibility"; - private static final boolean FORCE_SEND = true; - private static final boolean SEND_ON_WINDOW_CHANGES = false; - private static final int USER_SYSTEM_ID = UserHandle.USER_SYSTEM; - private static final int USER_PROFILE = 11; - private static final int USER_PROFILE_PARENT = 1; - private static final int SECONDARY_DISPLAY_ID = Display.DEFAULT_DISPLAY + 1; - private static final int NUM_GLOBAL_WINDOWS = 4; - private static final int NUM_APP_WINDOWS = 4; - private static final int NUM_OF_WINDOWS = (NUM_GLOBAL_WINDOWS + NUM_APP_WINDOWS); - private static final int DEFAULT_FOCUSED_INDEX = 1; - private static final int SCREEN_WIDTH = 1080; - private static final int SCREEN_HEIGHT = 1920; - private static final int INVALID_ID = AccessibilityWindowInfo.UNDEFINED_WINDOW_ID; - private static final int HOST_WINDOW_ID = 10; - private static final int EMBEDDED_WINDOW_ID = 11; - private static final int OTHER_WINDOW_ID = 12; - - private AccessibilityWindowManager mA11yWindowManager; - // Window manager will support multiple focused window if config_perDisplayFocusEnabled is true, - // i.e., each display would have its current focused window, and one of all focused windows - // would be top focused window. Otherwise, window manager only supports one focused window - // at all displays, and that focused window would be top focused window. - private boolean mSupportPerDisplayFocus = false; - private int mTopFocusedDisplayId = Display.INVALID_DISPLAY; - private IBinder mTopFocusedWindowToken = null; - - // List of window token, mapping from windowId -> window token. - private final SparseArray<IWindow> mA11yWindowTokens = new SparseArray<>(); - // List of window info lists, mapping from displayId -> a11y window lists. - private final SparseArray<ArrayList<AccessibilityWindow>> mWindows = new SparseArray<>(); - // List of callback, mapping from displayId -> callback. - private final SparseArray<WindowsForAccessibilityCallback> mCallbackOfWindows = - new SparseArray<>(); - // List of display ID. - private final ArrayList<Integer> mExpectedDisplayList = new ArrayList<>(Arrays.asList( - Display.DEFAULT_DISPLAY, SECONDARY_DISPLAY_ID)); - - private final MessageCapturingHandler mHandler = new MessageCapturingHandler(null); - - // This maps displayId -> next region offset. - // Touchable region must have un-occluded area so that it's exposed to a11y services. - // This offset can be used as left and top of new region so that top-left of each region are - // kept visible. - // It's expected to be incremented by some amount everytime the value is used. - private final SparseArray<Integer> mNextRegionOffsets = new SparseArray<>(); - - @Mock - private WindowManagerInternal mMockWindowManagerInternal; - @Mock - private AccessibilityWindowManager.AccessibilityEventSender mMockA11yEventSender; - @Mock - private AccessibilitySecurityPolicy mMockA11ySecurityPolicy; - @Mock - private AccessibilitySecurityPolicy.AccessibilityUserManager mMockA11yUserManager; - @Mock - private AccessibilityTraceManager mMockA11yTraceManager; - - @Mock - private IBinder mMockHostToken; - @Mock - private IBinder mMockEmbeddedToken; - @Mock - private IBinder mMockInvalidToken; - - @Rule - public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule(); - - @Before - public void setUp() throws RemoteException { - MockitoAnnotations.initMocks(this); - when(mMockA11yUserManager.getCurrentUserIdLocked()).thenReturn(USER_SYSTEM_ID); - when(mMockA11ySecurityPolicy.resolveCallingUserIdEnforcingPermissionsLocked( - USER_PROFILE)).thenReturn(USER_PROFILE_PARENT); - when(mMockA11ySecurityPolicy.resolveCallingUserIdEnforcingPermissionsLocked( - USER_SYSTEM_ID)).thenReturn(USER_SYSTEM_ID); - when(mMockA11ySecurityPolicy.resolveValidReportedPackageLocked( - anyString(), anyInt(), anyInt(), anyInt())).thenReturn(PACKAGE_NAME); - - doAnswer((invocation) -> { - onAccessibilityWindowsChanged(invocation.getArgument(0), false); - return null; - }).when(mMockWindowManagerInternal).computeWindowsForAccessibility(anyInt()); - - mA11yWindowManager = new AccessibilityWindowManager(new Object(), mHandler, - mMockWindowManagerInternal, - mMockA11yEventSender, - mMockA11ySecurityPolicy, - mMockA11yUserManager, - mMockA11yTraceManager); - // Starts tracking window of default display and sets the default display - // as top focused display before each testing starts. - startTrackingPerDisplay(Display.DEFAULT_DISPLAY); - - // AccessibilityEventSender is invoked during onAccessibilityWindowsChanged. - // Resets it for mockito verify of further test case. - Mockito.reset(mMockA11yEventSender); - - registerLeashedTokenAndWindowId(); - } - - @After - public void tearDown() { - mHandler.removeAllMessages(); - } - - @Test - public void startTrackingWindows_shouldEnableWindowManagerCallback() { - // AccessibilityWindowManager#startTrackingWindows already invoked in setup. - assertTrue(mA11yWindowManager.isTrackingWindowsLocked(Display.DEFAULT_DISPLAY)); - final WindowsForAccessibilityCallback callbacks = - mCallbackOfWindows.get(Display.DEFAULT_DISPLAY); - verify(mMockWindowManagerInternal).setWindowsForAccessibilityCallback( - eq(Display.DEFAULT_DISPLAY), eq(callbacks)); - } - - @Test - public void stopTrackingWindows_shouldDisableWindowManagerCallback() { - assertTrue(mA11yWindowManager.isTrackingWindowsLocked(Display.DEFAULT_DISPLAY)); - Mockito.reset(mMockWindowManagerInternal); - - mA11yWindowManager.stopTrackingWindows(Display.DEFAULT_DISPLAY); - assertFalse(mA11yWindowManager.isTrackingWindowsLocked(Display.DEFAULT_DISPLAY)); - verify(mMockWindowManagerInternal).setWindowsForAccessibilityCallback( - eq(Display.DEFAULT_DISPLAY), isNull()); - - } - - @Test - public void stopTrackingWindows_shouldClearWindows() { - assertTrue(mA11yWindowManager.isTrackingWindowsLocked(Display.DEFAULT_DISPLAY)); - final int activeWindowId = mA11yWindowManager.getActiveWindowId(USER_SYSTEM_ID); - - mA11yWindowManager.stopTrackingWindows(Display.DEFAULT_DISPLAY); - assertNull(mA11yWindowManager.getWindowListLocked(Display.DEFAULT_DISPLAY)); - assertEquals(mA11yWindowManager.getFocusedWindowId(AccessibilityNodeInfo.FOCUS_INPUT), - AccessibilityWindowInfo.UNDEFINED_WINDOW_ID); - assertEquals(mA11yWindowManager.getActiveWindowId(USER_SYSTEM_ID), - activeWindowId); - } - - @Test - public void stopTrackingWindows_onNonTopFocusedDisplay_shouldNotResetTopFocusWindow() - throws RemoteException { - // At setup, the default display sets be the top focused display and - // its current focused window sets be the top focused window. - // Starts tracking window of second display. - startTrackingPerDisplay(SECONDARY_DISPLAY_ID); - assertTrue(mA11yWindowManager.isTrackingWindowsLocked(SECONDARY_DISPLAY_ID)); - // Stops tracking windows of second display. - mA11yWindowManager.stopTrackingWindows(SECONDARY_DISPLAY_ID); - assertNotEquals(mA11yWindowManager.getFocusedWindowId(AccessibilityNodeInfo.FOCUS_INPUT), - AccessibilityWindowInfo.UNDEFINED_WINDOW_ID); - } - - @Test - public void onWindowsChanged_duringTouchInteractAndFocusChange_shouldChangeActiveWindow() { - final int activeWindowId = mA11yWindowManager.getActiveWindowId(USER_SYSTEM_ID); - final WindowInfo focusedWindowInfo = - mWindows.get(Display.DEFAULT_DISPLAY).get(DEFAULT_FOCUSED_INDEX).getWindowInfo(); - assertEquals(activeWindowId, mA11yWindowManager.findWindowIdLocked( - USER_SYSTEM_ID, focusedWindowInfo.token)); - - focusedWindowInfo.focused = false; - mWindows.get(Display.DEFAULT_DISPLAY).get( - DEFAULT_FOCUSED_INDEX + 1).getWindowInfo().focused = true; - - mA11yWindowManager.onTouchInteractionStart(); - setTopFocusedWindowAndDisplay(Display.DEFAULT_DISPLAY, DEFAULT_FOCUSED_INDEX + 1); - onAccessibilityWindowsChanged(Display.DEFAULT_DISPLAY, SEND_ON_WINDOW_CHANGES); - - assertNotEquals(activeWindowId, mA11yWindowManager.getActiveWindowId(USER_SYSTEM_ID)); - } - - @Test - public void - onWindowsChanged_focusChangeOnNonTopFocusedDisplay_perDisplayFocusOn_notChangeWindow() - throws RemoteException { - // At setup, the default display sets be the top focused display and - // its current focused window sets be the top focused window. - // Sets supporting multiple focused window, i.e., config_perDisplayFocusEnabled is true. - mSupportPerDisplayFocus = true; - // Starts tracking window of second display. - startTrackingPerDisplay(SECONDARY_DISPLAY_ID); - // Gets the active window. - final int activeWindowId = mA11yWindowManager.getActiveWindowId(USER_SYSTEM_ID); - // Gets the top focused window. - final int topFocusedWindowId = - mA11yWindowManager.getFocusedWindowId(AccessibilityNodeInfo.FOCUS_INPUT); - // Changes the current focused window at second display. - changeFocusedWindowOnDisplayPerDisplayFocusConfig(SECONDARY_DISPLAY_ID, - DEFAULT_FOCUSED_INDEX + 1, Display.DEFAULT_DISPLAY, DEFAULT_FOCUSED_INDEX); - - onAccessibilityWindowsChanged(SECONDARY_DISPLAY_ID, SEND_ON_WINDOW_CHANGES); - // The active window should not be changed. - assertEquals(activeWindowId, mA11yWindowManager.getActiveWindowId(USER_SYSTEM_ID)); - // The top focused window should not be changed. - assertEquals(topFocusedWindowId, - mA11yWindowManager.getFocusedWindowId(AccessibilityNodeInfo.FOCUS_INPUT)); - } - - @Test - public void - onWindowChange_focusChangeToNonTopFocusedDisplay_perDisplayFocusOff_shouldChangeWindow() - throws RemoteException { - // At setup, the default display sets be the top focused display and - // its current focused window sets be the top focused window. - // Sets not supporting multiple focused window, i.e., config_perDisplayFocusEnabled is - // false. - mSupportPerDisplayFocus = false; - // Starts tracking window of second display. - startTrackingPerDisplay(SECONDARY_DISPLAY_ID); - // Gets the active window. - final int activeWindowId = mA11yWindowManager.getActiveWindowId(USER_SYSTEM_ID); - // Gets the top focused window. - final int topFocusedWindowId = - mA11yWindowManager.getFocusedWindowId(AccessibilityNodeInfo.FOCUS_INPUT); - // Changes the current focused window from default display to second display. - changeFocusedWindowOnDisplayPerDisplayFocusConfig(SECONDARY_DISPLAY_ID, - DEFAULT_FOCUSED_INDEX, Display.DEFAULT_DISPLAY, DEFAULT_FOCUSED_INDEX); - - onAccessibilityWindowsChanged(Display.DEFAULT_DISPLAY, SEND_ON_WINDOW_CHANGES); - onAccessibilityWindowsChanged(SECONDARY_DISPLAY_ID, SEND_ON_WINDOW_CHANGES); - // The active window should be changed. - assertNotEquals(activeWindowId, mA11yWindowManager.getActiveWindowId(USER_SYSTEM_ID)); - // The top focused window should be changed. - assertNotEquals(topFocusedWindowId, - mA11yWindowManager.getFocusedWindowId(AccessibilityNodeInfo.FOCUS_INPUT)); - } - - @Test - public void onWindowsChanged_shouldReportCorrectLayer() { - // AccessibilityWindowManager#onAccessibilityWindowsChanged already invoked in setup. - List<AccessibilityWindowInfo> a11yWindows = - mA11yWindowManager.getWindowListLocked(Display.DEFAULT_DISPLAY); - for (int i = 0; i < a11yWindows.size(); i++) { - final AccessibilityWindowInfo a11yWindow = a11yWindows.get(i); - assertThat(mWindows.get(Display.DEFAULT_DISPLAY).size() - i - 1, - is(a11yWindow.getLayer())); - } - } - - @Test - public void onWindowsChanged_shouldReportCorrectOrder() { - // AccessibilityWindowManager#onAccessibilityWindowsChanged already invoked in setup. - List<AccessibilityWindowInfo> a11yWindows = - mA11yWindowManager.getWindowListLocked(Display.DEFAULT_DISPLAY); - for (int i = 0; i < a11yWindows.size(); i++) { - final AccessibilityWindowInfo a11yWindow = a11yWindows.get(i); - final IBinder windowToken = mA11yWindowManager - .getWindowTokenForUserAndWindowIdLocked(USER_SYSTEM_ID, a11yWindow.getId()); - final WindowInfo windowInfo = mWindows.get(Display.DEFAULT_DISPLAY) - .get(i).getWindowInfo(); - assertThat(windowToken, is(windowInfo.token)); - } - } - - @Test - public void onWindowsChanged_shouldNotReportNonTouchableWindow() { - final AccessibilityWindow window = mWindows.get(Display.DEFAULT_DISPLAY).get(0); - when(window.isTouchable()).thenReturn(false); - final int windowId = mA11yWindowManager.findWindowIdLocked( - USER_SYSTEM_ID, window.getWindowInfo().token); - - onAccessibilityWindowsChanged(Display.DEFAULT_DISPLAY, SEND_ON_WINDOW_CHANGES); - - final List<AccessibilityWindowInfo> a11yWindows = - mA11yWindowManager.getWindowListLocked(Display.DEFAULT_DISPLAY); - assertThat(a11yWindows, not(hasItem(windowId(windowId)))); - } - - @Test - public void onWindowsChanged_shouldReportFocusedNonTouchableWindow() { - final AccessibilityWindow window = mWindows.get(Display.DEFAULT_DISPLAY).get( - DEFAULT_FOCUSED_INDEX); - when(window.isTouchable()).thenReturn(false); - final int windowId = mA11yWindowManager.findWindowIdLocked( - USER_SYSTEM_ID, window.getWindowInfo().token); - - onAccessibilityWindowsChanged(Display.DEFAULT_DISPLAY, SEND_ON_WINDOW_CHANGES); - - final List<AccessibilityWindowInfo> a11yWindows = - mA11yWindowManager.getWindowListLocked(Display.DEFAULT_DISPLAY); - assertThat(a11yWindows, hasItem(windowId(windowId))); - } - - @Test - public void onWindowsChanged_trustedFocusedNonTouchableWindow_shouldNotHideWindowsBelow() { - // Make the focused trusted un-touchable window fullscreen. - final AccessibilityWindow window = mWindows.get(Display.DEFAULT_DISPLAY).get( - DEFAULT_FOCUSED_INDEX); - setRegionForMockAccessibilityWindow(window, new Region(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT)); - when(window.isTouchable()).thenReturn(false); - when(window.isTrustedOverlay()).thenReturn(true); - - onAccessibilityWindowsChanged(Display.DEFAULT_DISPLAY, SEND_ON_WINDOW_CHANGES); - - final List<AccessibilityWindowInfo> a11yWindows = - mA11yWindowManager.getWindowListLocked(Display.DEFAULT_DISPLAY); - assertThat(a11yWindows, hasSize(NUM_OF_WINDOWS)); - } - - @Test - public void onWindowsChanged_accessibilityOverlay_shouldNotHideWindowsBelow() { - // Make the a11y overlay window fullscreen. - final AccessibilityWindow window = mWindows.get(Display.DEFAULT_DISPLAY).get(0); - setRegionForMockAccessibilityWindow(window, new Region(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT)); - when(window.getType()).thenReturn(WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY); - - onAccessibilityWindowsChanged(Display.DEFAULT_DISPLAY, SEND_ON_WINDOW_CHANGES); - - final List<AccessibilityWindowInfo> a11yWindows = - mA11yWindowManager.getWindowListLocked(Display.DEFAULT_DISPLAY); - assertThat(a11yWindows, hasSize(NUM_OF_WINDOWS)); - } - - @Test - public void onWindowsChanged_shouldReportFocusedWindowEvenIfOccluded() { - // Make the front window fullscreen. - final AccessibilityWindow frontWindow = mWindows.get(Display.DEFAULT_DISPLAY).get(0); - setRegionForMockAccessibilityWindow(frontWindow, - new Region(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT)); - final int frontWindowId = mA11yWindowManager.findWindowIdLocked( - USER_SYSTEM_ID, frontWindow.getWindowInfo().token); - - final AccessibilityWindow focusedWindow = mWindows.get(Display.DEFAULT_DISPLAY).get( - DEFAULT_FOCUSED_INDEX); - final int focusedWindowId = mA11yWindowManager.findWindowIdLocked( - USER_SYSTEM_ID, focusedWindow.getWindowInfo().token); - - onAccessibilityWindowsChanged(Display.DEFAULT_DISPLAY, SEND_ON_WINDOW_CHANGES); - - final List<AccessibilityWindowInfo> a11yWindows = - mA11yWindowManager.getWindowListLocked(Display.DEFAULT_DISPLAY); - assertThat(a11yWindows, hasSize(2)); - assertThat(a11yWindows.get(0), windowId(frontWindowId)); - assertThat(a11yWindows.get(1), windowId(focusedWindowId)); - } - - @Test - public void onWindowsChanged_embeddedWindows_shouldOnlyReportHost() throws RemoteException { - final Rect embeddingBounds = new Rect(0, 0, 200, 100); - - // The embedded window comes front of the host window. - final IBinder embeddedWindowLeashToken = Mockito.mock(IBinder.class); - final int embeddedWindowId = addAccessibilityInteractionConnection(Display.DEFAULT_DISPLAY, - false, embeddedWindowLeashToken, USER_SYSTEM_ID); - final AccessibilityWindow embeddedWindow = createMockAccessibilityWindow( - mA11yWindowTokens.get(embeddedWindowId), Display.DEFAULT_DISPLAY); - setRegionForMockAccessibilityWindow(embeddedWindow, new Region(embeddingBounds)); - mWindows.get(Display.DEFAULT_DISPLAY).set(0, embeddedWindow); - - final IBinder hostWindowLeashToken = Mockito.mock(IBinder.class); - final int hostWindowId = addAccessibilityInteractionConnection(Display.DEFAULT_DISPLAY, - false, hostWindowLeashToken, USER_SYSTEM_ID); - final AccessibilityWindow hostWindow = createMockAccessibilityWindow( - mA11yWindowTokens.get(hostWindowId), Display.DEFAULT_DISPLAY); - setRegionForMockAccessibilityWindow(hostWindow, new Region(embeddingBounds)); - mWindows.get(Display.DEFAULT_DISPLAY).set(1, hostWindow); - - mA11yWindowManager.associateEmbeddedHierarchyLocked( - hostWindowLeashToken, embeddedWindowLeashToken); - - onAccessibilityWindowsChanged(Display.DEFAULT_DISPLAY, SEND_ON_WINDOW_CHANGES); - - final List<AccessibilityWindowInfo> a11yWindows = - mA11yWindowManager.getWindowListLocked(Display.DEFAULT_DISPLAY); - assertThat(a11yWindows, not(hasItem(windowId(embeddedWindowId)))); - assertThat(a11yWindows.get(0), windowId(hostWindowId)); - final Rect bounds = new Rect(); - a11yWindows.get(0).getBoundsInScreen(bounds); - assertEquals(bounds, embeddingBounds); - } - - @Test - public void onWindowsChanged_shouldNotReportfullyOccludedWindow() { - final AccessibilityWindow frontWindow = mWindows.get(Display.DEFAULT_DISPLAY).get(0); - setRegionForMockAccessibilityWindow(frontWindow, new Region(100, 100, 300, 300)); - final int frontWindowId = mA11yWindowManager.findWindowIdLocked( - USER_SYSTEM_ID, frontWindow.getWindowInfo().token); - - // index 1 is focused. Let's use the next one for this test. - final AccessibilityWindow occludedWindow = mWindows.get(Display.DEFAULT_DISPLAY).get(2); - setRegionForMockAccessibilityWindow(occludedWindow, new Region(150, 150, 250, 250)); - final int occludedWindowId = mA11yWindowManager.findWindowIdLocked( - USER_SYSTEM_ID, occludedWindow.getWindowInfo().token); - - onAccessibilityWindowsChanged(Display.DEFAULT_DISPLAY, SEND_ON_WINDOW_CHANGES); - - final List<AccessibilityWindowInfo> a11yWindows = - mA11yWindowManager.getWindowListLocked(Display.DEFAULT_DISPLAY); - assertThat(a11yWindows, hasItem(windowId(frontWindowId))); - assertThat(a11yWindows, not(hasItem(windowId(occludedWindowId)))); - } - - @Test - public void onWindowsChangedAndForceSend_shouldUpdateWindows() { - assertNotEquals("new title", - toString(mA11yWindowManager.getWindowListLocked(Display.DEFAULT_DISPLAY) - .get(0).getTitle())); - - mWindows.get(Display.DEFAULT_DISPLAY).get(0).getWindowInfo().title = "new title"; - - onAccessibilityWindowsChanged(Display.DEFAULT_DISPLAY, FORCE_SEND); - assertEquals("new title", - toString(mA11yWindowManager.getWindowListLocked(Display.DEFAULT_DISPLAY) - .get(0).getTitle())); - } - - @Test - public void onWindowsChangedNoForceSend_windowChanged_shouldUpdateWindows() - throws RemoteException { - final AccessibilityWindowInfo oldWindow = - mA11yWindowManager.getWindowListLocked(Display.DEFAULT_DISPLAY).get(0); - final IWindow token = addAccessibilityInteractionConnection(Display.DEFAULT_DISPLAY, - true, USER_SYSTEM_ID); - mWindows.get(Display.DEFAULT_DISPLAY).set(0, - createMockAccessibilityWindow(token, Display.DEFAULT_DISPLAY)); - - onAccessibilityWindowsChanged(Display.DEFAULT_DISPLAY, SEND_ON_WINDOW_CHANGES); - assertNotEquals(oldWindow, - mA11yWindowManager.getWindowListLocked(Display.DEFAULT_DISPLAY).get(0)); - } - - @Test - public void onWindowsChangedNoForceSend_focusChanged_shouldUpdateWindows() { - final WindowInfo focusedWindowInfo = - mWindows.get(Display.DEFAULT_DISPLAY).get(DEFAULT_FOCUSED_INDEX).getWindowInfo(); - final WindowInfo windowInfo = mWindows.get(Display.DEFAULT_DISPLAY).get(0).getWindowInfo(); - focusedWindowInfo.focused = false; - windowInfo.focused = true; - - onAccessibilityWindowsChanged(Display.DEFAULT_DISPLAY, SEND_ON_WINDOW_CHANGES); - assertTrue(mA11yWindowManager.getWindowListLocked(Display.DEFAULT_DISPLAY).get(0) - .isFocused()); - } - - @Test - public void removeAccessibilityInteractionConnection_byWindowToken_shouldRemoved() { - for (int i = 0; i < NUM_OF_WINDOWS; i++) { - final int windowId = mA11yWindowTokens.keyAt(i); - final IWindow windowToken = mA11yWindowTokens.valueAt(i); - assertNotNull(mA11yWindowManager.getConnectionLocked(USER_SYSTEM_ID, windowId)); - - mA11yWindowManager.removeAccessibilityInteractionConnection(windowToken); - assertNull(mA11yWindowManager.getConnectionLocked(USER_SYSTEM_ID, windowId)); - } - } - - @Test - public void remoteAccessibilityConnection_binderDied_shouldRemoveConnection() { - for (int i = 0; i < NUM_OF_WINDOWS; i++) { - final int windowId = mA11yWindowTokens.keyAt(i); - final RemoteAccessibilityConnection remoteA11yConnection = - mA11yWindowManager.getConnectionLocked(USER_SYSTEM_ID, windowId); - assertNotNull(remoteA11yConnection); - - remoteA11yConnection.binderDied(); - assertNull(mA11yWindowManager.getConnectionLocked(USER_SYSTEM_ID, windowId)); - } - } - - @Test - public void getWindowTokenForUserAndWindowId_shouldNotNull() { - final List<AccessibilityWindowInfo> windows = - mA11yWindowManager.getWindowListLocked(Display.DEFAULT_DISPLAY); - for (int i = 0; i < windows.size(); i++) { - final int windowId = windows.get(i).getId(); - - assertNotNull(mA11yWindowManager.getWindowTokenForUserAndWindowIdLocked( - USER_SYSTEM_ID, windowId)); - } - } - - @Test - public void findWindowId() { - final List<AccessibilityWindowInfo> windows = - mA11yWindowManager.getWindowListLocked(Display.DEFAULT_DISPLAY); - for (int i = 0; i < windows.size(); i++) { - final int windowId = windows.get(i).getId(); - final IBinder windowToken = mA11yWindowManager.getWindowTokenForUserAndWindowIdLocked( - USER_SYSTEM_ID, windowId); - - assertEquals(mA11yWindowManager.findWindowIdLocked( - USER_SYSTEM_ID, windowToken), windowId); - } - } - - @Test - public void resolveParentWindowId_windowIsNotEmbedded_shouldReturnGivenId() - throws RemoteException { - final int windowId = addAccessibilityInteractionConnection(Display.DEFAULT_DISPLAY, false, - Mockito.mock(IBinder.class), USER_SYSTEM_ID); - assertEquals(windowId, mA11yWindowManager.resolveParentWindowIdLocked(windowId)); - } - - @Test - public void resolveParentWindowId_windowIsNotRegistered_shouldReturnGivenId() { - final int windowId = -1; - assertEquals(windowId, mA11yWindowManager.resolveParentWindowIdLocked(windowId)); - } - - @Test - public void resolveParentWindowId_windowIsAssociated_shouldReturnParentWindowId() - throws RemoteException { - final IBinder mockHostToken = Mockito.mock(IBinder.class); - final IBinder mockEmbeddedToken = Mockito.mock(IBinder.class); - final int hostWindowId = addAccessibilityInteractionConnection(Display.DEFAULT_DISPLAY, - false, mockHostToken, USER_SYSTEM_ID); - final int embeddedWindowId = addAccessibilityInteractionConnection(Display.DEFAULT_DISPLAY, - false, mockEmbeddedToken, USER_SYSTEM_ID); - - mA11yWindowManager.associateEmbeddedHierarchyLocked(mockHostToken, mockEmbeddedToken); - - final int resolvedWindowId = mA11yWindowManager.resolveParentWindowIdLocked( - embeddedWindowId); - assertEquals(hostWindowId, resolvedWindowId); - } - - @Test - public void resolveParentWindowId_windowIsDisassociated_shouldReturnGivenId() - throws RemoteException { - final IBinder mockHostToken = Mockito.mock(IBinder.class); - final IBinder mockEmbeddedToken = Mockito.mock(IBinder.class); - final int hostWindowId = addAccessibilityInteractionConnection(Display.DEFAULT_DISPLAY, - false, mockHostToken, USER_SYSTEM_ID); - final int embeddedWindowId = addAccessibilityInteractionConnection(Display.DEFAULT_DISPLAY, - false, mockEmbeddedToken, USER_SYSTEM_ID); - - mA11yWindowManager.associateEmbeddedHierarchyLocked(mockHostToken, mockEmbeddedToken); - mA11yWindowManager.disassociateEmbeddedHierarchyLocked(mockEmbeddedToken); - - final int resolvedWindowId = mA11yWindowManager.resolveParentWindowIdLocked( - embeddedWindowId); - assertNotEquals(hostWindowId, resolvedWindowId); - assertEquals(embeddedWindowId, resolvedWindowId); - } - - @Test - public void computePartialInteractiveRegionForWindow_wholeVisible_returnWholeRegion() { - // Updates top 2 z-order WindowInfo are whole visible. - final AccessibilityWindow firstWindow = mWindows.get(Display.DEFAULT_DISPLAY).get(0); - setRegionForMockAccessibilityWindow(firstWindow, - new Region(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT / 2)); - final AccessibilityWindow secondWindow = mWindows.get(Display.DEFAULT_DISPLAY).get(1); - setRegionForMockAccessibilityWindow(secondWindow, - new Region(0, SCREEN_HEIGHT / 2, SCREEN_WIDTH, SCREEN_HEIGHT)); - - onAccessibilityWindowsChanged(Display.DEFAULT_DISPLAY, SEND_ON_WINDOW_CHANGES); - - final List<AccessibilityWindowInfo> a11yWindows = - mA11yWindowManager.getWindowListLocked(Display.DEFAULT_DISPLAY); - assertThat(a11yWindows, hasSize(2)); - final Region outBounds = new Region(); - int windowId = a11yWindows.get(0).getId(); - - mA11yWindowManager.computePartialInteractiveRegionForWindowLocked(windowId, outBounds); - assertThat(outBounds.getBounds().width(), is(SCREEN_WIDTH)); - assertThat(outBounds.getBounds().height(), is(SCREEN_HEIGHT / 2)); - - windowId = a11yWindows.get(1).getId(); - - mA11yWindowManager.computePartialInteractiveRegionForWindowLocked(windowId, outBounds); - assertThat(outBounds.getBounds().width(), is(SCREEN_WIDTH)); - assertThat(outBounds.getBounds().height(), is(SCREEN_HEIGHT / 2)); - } - - @Test - public void computePartialInteractiveRegionForWindow_halfVisible_returnHalfRegion() { - // Updates z-order #1 WindowInfo is half visible. - final AccessibilityWindow firstWindow = mWindows.get(Display.DEFAULT_DISPLAY).get(0); - setRegionForMockAccessibilityWindow(firstWindow, - new Region(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT / 2)); - final AccessibilityWindow secondWindow = mWindows.get(Display.DEFAULT_DISPLAY).get(1); - setRegionForMockAccessibilityWindow(secondWindow, - new Region(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT)); - - onAccessibilityWindowsChanged(Display.DEFAULT_DISPLAY, SEND_ON_WINDOW_CHANGES); - final List<AccessibilityWindowInfo> a11yWindows = - mA11yWindowManager.getWindowListLocked(Display.DEFAULT_DISPLAY); - assertThat(a11yWindows, hasSize(2)); - final Region outBounds = new Region(); - int windowId = a11yWindows.get(1).getId(); - - mA11yWindowManager.computePartialInteractiveRegionForWindowLocked(windowId, outBounds); - assertThat(outBounds.getBounds().width(), is(SCREEN_WIDTH)); - assertThat(outBounds.getBounds().height(), is(SCREEN_HEIGHT / 2)); - } - - @Test - public void computePartialInteractiveRegionForWindow_notVisible_returnEmptyRegion() { - // z-order #0 WindowInfo is full screen, z-order #1 WindowInfo should be invisible. - final AccessibilityWindow firstWindow = mWindows.get(Display.DEFAULT_DISPLAY).get(0); - setRegionForMockAccessibilityWindow(firstWindow, - new Region(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT)); - - onAccessibilityWindowsChanged(Display.DEFAULT_DISPLAY, SEND_ON_WINDOW_CHANGES); - - final List<AccessibilityWindowInfo> a11yWindows = - mA11yWindowManager.getWindowListLocked(Display.DEFAULT_DISPLAY); - // Note that the second window is also exposed even if region is empty because it's focused. - assertThat(a11yWindows, hasSize(2)); - final Region outBounds = new Region(); - int windowId = a11yWindows.get(1).getId(); - - mA11yWindowManager.computePartialInteractiveRegionForWindowLocked(windowId, outBounds); - assertTrue(outBounds.getBounds().isEmpty()); - } - - @Test - public void computePartialInteractiveRegionForWindow_partialVisible_returnVisibleRegion() { - // Updates z-order #0 WindowInfo to have two interact-able areas. - final Region region = new Region(0, 0, SCREEN_WIDTH, 200); - region.op(0, SCREEN_HEIGHT - 200, SCREEN_WIDTH, SCREEN_HEIGHT, Region.Op.UNION); - final AccessibilityWindow firstWindow = mWindows.get(Display.DEFAULT_DISPLAY).get(0); - setRegionForMockAccessibilityWindow(firstWindow, region); - final AccessibilityWindow secondWindow = mWindows.get(Display.DEFAULT_DISPLAY).get(1); - setRegionForMockAccessibilityWindow(secondWindow, - new Region(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT)); - - onAccessibilityWindowsChanged(Display.DEFAULT_DISPLAY, SEND_ON_WINDOW_CHANGES); - - final List<AccessibilityWindowInfo> a11yWindows = - mA11yWindowManager.getWindowListLocked(Display.DEFAULT_DISPLAY); - assertThat(a11yWindows, hasSize(2)); - final Region outBounds = new Region(); - final int windowId = a11yWindows.get(1).getId(); - - mA11yWindowManager.computePartialInteractiveRegionForWindowLocked(windowId, outBounds); - assertFalse(outBounds.getBounds().isEmpty()); - assertThat(outBounds.getBounds().width(), is(SCREEN_WIDTH)); - assertThat(outBounds.getBounds().height(), is(SCREEN_HEIGHT - 400)); - } - - @Test - public void updateActiveAndA11yFocusedWindow_windowStateChangedEvent_noTracking_shouldUpdate() { - final IBinder eventWindowToken = - mWindows.get(Display.DEFAULT_DISPLAY) - .get(DEFAULT_FOCUSED_INDEX + 1).getWindowInfo().token; - final int eventWindowId = mA11yWindowManager.findWindowIdLocked( - USER_SYSTEM_ID, eventWindowToken); - when(mMockWindowManagerInternal.getFocusedWindowTokenFromWindowStates()) - .thenReturn(eventWindowToken); - - final int noUse = 0; - mA11yWindowManager.stopTrackingWindows(Display.DEFAULT_DISPLAY); - mA11yWindowManager.updateActiveAndAccessibilityFocusedWindowLocked(USER_SYSTEM_ID, - eventWindowId, - noUse, - AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED, - noUse); - assertThat(mA11yWindowManager.getActiveWindowId(USER_SYSTEM_ID), is(eventWindowId)); - assertThat(mA11yWindowManager.getFocusedWindowId(AccessibilityNodeInfo.FOCUS_INPUT), - is(eventWindowId)); - } - - @Test - public void updateActiveAndA11yFocusedWindow_hoverEvent_touchInteract_shouldSetActiveWindow() { - final int eventWindowId = getWindowIdFromWindowInfosForDisplay(Display.DEFAULT_DISPLAY, - DEFAULT_FOCUSED_INDEX + 1); - final int currentActiveWindowId = mA11yWindowManager.getActiveWindowId(USER_SYSTEM_ID); - assertThat(currentActiveWindowId, is(not(eventWindowId))); - - final int noUse = 0; - mA11yWindowManager.onTouchInteractionStart(); - mA11yWindowManager.updateActiveAndAccessibilityFocusedWindowLocked(USER_SYSTEM_ID, - eventWindowId, - noUse, - AccessibilityEvent.TYPE_VIEW_HOVER_ENTER, - noUse); - assertThat(mA11yWindowManager.getActiveWindowId(USER_SYSTEM_ID), is(eventWindowId)); - final ArgumentCaptor<AccessibilityEvent> captor = - ArgumentCaptor.forClass(AccessibilityEvent.class); - verify(mMockA11yEventSender, times(2)) - .sendAccessibilityEventForCurrentUserLocked(captor.capture()); - assertThat(captor.getAllValues().get(0), - allOf(displayId(Display.DEFAULT_DISPLAY), - eventWindowId(currentActiveWindowId), - a11yWindowChanges(AccessibilityEvent.WINDOWS_CHANGE_ACTIVE))); - assertThat(captor.getAllValues().get(1), - allOf(displayId(Display.DEFAULT_DISPLAY), - eventWindowId(eventWindowId), - a11yWindowChanges(AccessibilityEvent.WINDOWS_CHANGE_ACTIVE))); - } - - @Test - public void updateActiveAndA11yFocusedWindow_a11yFocusEvent_shouldUpdateA11yFocus() { - final int eventWindowId = getWindowIdFromWindowInfosForDisplay(Display.DEFAULT_DISPLAY, - DEFAULT_FOCUSED_INDEX); - final int currentA11yFocusedWindowId = mA11yWindowManager.getFocusedWindowId( - AccessibilityNodeInfo.FOCUS_ACCESSIBILITY); - assertThat(currentA11yFocusedWindowId, is(AccessibilityWindowInfo.UNDEFINED_WINDOW_ID)); - - final int noUse = 0; - mA11yWindowManager.updateActiveAndAccessibilityFocusedWindowLocked(USER_SYSTEM_ID, - eventWindowId, - AccessibilityNodeInfo.ROOT_NODE_ID, - AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED, - noUse); - assertThat(mA11yWindowManager.getFocusedWindowId( - AccessibilityNodeInfo.FOCUS_ACCESSIBILITY), is(eventWindowId)); - final ArgumentCaptor<AccessibilityEvent> captor = - ArgumentCaptor.forClass(AccessibilityEvent.class); - verify(mMockA11yEventSender, times(1)) - .sendAccessibilityEventForCurrentUserLocked(captor.capture()); - assertThat(captor.getAllValues().get(0), - allOf(displayId(Display.DEFAULT_DISPLAY), - eventWindowId(eventWindowId), - a11yWindowChanges( - AccessibilityEvent.WINDOWS_CHANGE_ACCESSIBILITY_FOCUSED))); - } - - @Test - public void updateActiveAndA11yFocusedWindow_a11yFocusEvent_multiDisplay_defaultToSecondary() - throws RemoteException { - runUpdateActiveAndA11yFocusedWindow_MultiDisplayTest( - Display.DEFAULT_DISPLAY, SECONDARY_DISPLAY_ID); - } - - @Test - public void updateActiveAndA11yFocusedWindow_a11yFocusEvent_multiDisplay_SecondaryToDefault() - throws RemoteException { - runUpdateActiveAndA11yFocusedWindow_MultiDisplayTest( - SECONDARY_DISPLAY_ID, Display.DEFAULT_DISPLAY); - } - - private void runUpdateActiveAndA11yFocusedWindow_MultiDisplayTest( - int initialDisplayId, int eventDisplayId) throws RemoteException { - startTrackingPerDisplay(SECONDARY_DISPLAY_ID); - final int initialWindowId = getWindowIdFromWindowInfosForDisplay( - initialDisplayId, DEFAULT_FOCUSED_INDEX); - final int noUse = 0; - mA11yWindowManager.updateActiveAndAccessibilityFocusedWindowLocked(USER_SYSTEM_ID, - initialWindowId, - AccessibilityNodeInfo.ROOT_NODE_ID, - AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED, - noUse); - assertThat(mA11yWindowManager.getFocusedWindowId( - AccessibilityNodeInfo.FOCUS_ACCESSIBILITY), is(initialWindowId)); - Mockito.reset(mMockA11yEventSender); - - final int eventWindowId = getWindowIdFromWindowInfosForDisplay( - eventDisplayId, DEFAULT_FOCUSED_INDEX); - mA11yWindowManager.updateActiveAndAccessibilityFocusedWindowLocked(USER_SYSTEM_ID, - eventWindowId, - AccessibilityNodeInfo.ROOT_NODE_ID, - AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED, - noUse); - assertThat(mA11yWindowManager.getFocusedWindowId( - AccessibilityNodeInfo.FOCUS_ACCESSIBILITY), is(eventWindowId)); - final ArgumentCaptor<AccessibilityEvent> captor = - ArgumentCaptor.forClass(AccessibilityEvent.class); - verify(mMockA11yEventSender, times(2)) - .sendAccessibilityEventForCurrentUserLocked(captor.capture()); - assertThat(captor.getAllValues().get(0), - allOf(displayId(initialDisplayId), - eventWindowId(initialWindowId), - a11yWindowChanges( - AccessibilityEvent.WINDOWS_CHANGE_ACCESSIBILITY_FOCUSED))); - assertThat(captor.getAllValues().get(1), - allOf(displayId(eventDisplayId), - eventWindowId(eventWindowId), - a11yWindowChanges( - AccessibilityEvent.WINDOWS_CHANGE_ACCESSIBILITY_FOCUSED))); - } - - @Test - public void updateActiveAndA11yFocusedWindow_clearA11yFocusEvent_shouldClearA11yFocus() { - final int eventWindowId = getWindowIdFromWindowInfosForDisplay(Display.DEFAULT_DISPLAY, - DEFAULT_FOCUSED_INDEX); - final int currentA11yFocusedWindowId = mA11yWindowManager.getFocusedWindowId( - AccessibilityNodeInfo.FOCUS_ACCESSIBILITY); - assertThat(currentA11yFocusedWindowId, is(not(eventWindowId))); - - final int noUse = 0; - mA11yWindowManager.updateActiveAndAccessibilityFocusedWindowLocked(USER_SYSTEM_ID, - eventWindowId, - AccessibilityNodeInfo.ROOT_NODE_ID, - AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED, - noUse); - assertThat(mA11yWindowManager.getFocusedWindowId( - AccessibilityNodeInfo.FOCUS_ACCESSIBILITY), is(eventWindowId)); - mA11yWindowManager.updateActiveAndAccessibilityFocusedWindowLocked(USER_SYSTEM_ID, - eventWindowId, - AccessibilityNodeInfo.ROOT_NODE_ID, - AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED, - noUse); - assertThat(mA11yWindowManager.getFocusedWindowId( - AccessibilityNodeInfo.FOCUS_ACCESSIBILITY), - is(AccessibilityWindowInfo.UNDEFINED_WINDOW_ID)); - } - - @Test - public void onTouchInteractionEnd_shouldRollbackActiveWindow() { - final int eventWindowId = getWindowIdFromWindowInfosForDisplay(Display.DEFAULT_DISPLAY, - DEFAULT_FOCUSED_INDEX + 1); - final int currentActiveWindowId = mA11yWindowManager.getActiveWindowId(USER_SYSTEM_ID); - assertThat(currentActiveWindowId, is(not(eventWindowId))); - - final int noUse = 0; - mA11yWindowManager.onTouchInteractionStart(); - mA11yWindowManager.updateActiveAndAccessibilityFocusedWindowLocked(USER_SYSTEM_ID, - eventWindowId, - noUse, - AccessibilityEvent.TYPE_VIEW_HOVER_ENTER, - noUse); - assertThat(mA11yWindowManager.getActiveWindowId(USER_SYSTEM_ID), is(eventWindowId)); - // AccessibilityEventSender is invoked after active window changed. Reset it. - Mockito.reset(mMockA11yEventSender); - - mA11yWindowManager.onTouchInteractionEnd(); - final ArgumentCaptor<AccessibilityEvent> captor = - ArgumentCaptor.forClass(AccessibilityEvent.class); - verify(mMockA11yEventSender, times(2)) - .sendAccessibilityEventForCurrentUserLocked(captor.capture()); - assertThat(captor.getAllValues().get(0), - allOf(displayId(Display.DEFAULT_DISPLAY), - eventWindowId(eventWindowId), - a11yWindowChanges(AccessibilityEvent.WINDOWS_CHANGE_ACTIVE))); - assertThat(captor.getAllValues().get(1), - allOf(displayId(Display.DEFAULT_DISPLAY), - eventWindowId(currentActiveWindowId), - a11yWindowChanges(AccessibilityEvent.WINDOWS_CHANGE_ACTIVE))); - } - - @Test - public void onTouchInteractionEnd_noServiceInteractiveWindow_shouldClearA11yFocus() - throws RemoteException { - final IBinder defaultFocusWinToken = - mWindows.get(Display.DEFAULT_DISPLAY).get( - DEFAULT_FOCUSED_INDEX).getWindowInfo().token; - final int defaultFocusWindowId = mA11yWindowManager.findWindowIdLocked( - USER_SYSTEM_ID, defaultFocusWinToken); - when(mMockWindowManagerInternal.getFocusedWindowTokenFromWindowStates()) - .thenReturn(defaultFocusWinToken); - final int newFocusWindowId = getWindowIdFromWindowInfosForDisplay(Display.DEFAULT_DISPLAY, - DEFAULT_FOCUSED_INDEX + 1); - final IAccessibilityInteractionConnection mockNewFocusConnection = - mA11yWindowManager.getConnectionLocked( - USER_SYSTEM_ID, newFocusWindowId).getRemote(); - - mA11yWindowManager.stopTrackingWindows(Display.DEFAULT_DISPLAY); - final int noUse = 0; - mA11yWindowManager.updateActiveAndAccessibilityFocusedWindowLocked(USER_SYSTEM_ID, - defaultFocusWindowId, - noUse, - AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED, - noUse); - assertThat(mA11yWindowManager.getActiveWindowId(USER_SYSTEM_ID), is(defaultFocusWindowId)); - assertThat(mA11yWindowManager.getFocusedWindowId(AccessibilityNodeInfo.FOCUS_INPUT), - is(defaultFocusWindowId)); - - mA11yWindowManager.onTouchInteractionStart(); - mA11yWindowManager.updateActiveAndAccessibilityFocusedWindowLocked(USER_SYSTEM_ID, - newFocusWindowId, - noUse, - AccessibilityEvent.TYPE_VIEW_HOVER_ENTER, - noUse); - mA11yWindowManager.updateActiveAndAccessibilityFocusedWindowLocked(USER_SYSTEM_ID, - newFocusWindowId, - AccessibilityNodeInfo.ROOT_NODE_ID, - AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED, - noUse); - assertThat(mA11yWindowManager.getActiveWindowId(USER_SYSTEM_ID), is(newFocusWindowId)); - assertThat(mA11yWindowManager.getFocusedWindowId( - AccessibilityNodeInfo.FOCUS_ACCESSIBILITY), is(newFocusWindowId)); - - mA11yWindowManager.onTouchInteractionEnd(); - mHandler.sendLastMessage(); - verify(mockNewFocusConnection).clearAccessibilityFocus(); - } - - @Test - public void getPictureInPictureWindow_shouldNotNull() { - assertNull(mA11yWindowManager.getPictureInPictureWindowLocked()); - mWindows.get(Display.DEFAULT_DISPLAY).get(1).getWindowInfo().inPictureInPicture = true; - onAccessibilityWindowsChanged(Display.DEFAULT_DISPLAY, SEND_ON_WINDOW_CHANGES); - - assertNotNull(mA11yWindowManager.getPictureInPictureWindowLocked()); - } - - @Test - public void notifyOutsideTouch() throws RemoteException { - final int targetWindowId = - getWindowIdFromWindowInfosForDisplay(Display.DEFAULT_DISPLAY, 1); - final int outsideWindowId = - getWindowIdFromWindowInfosForDisplay(Display.DEFAULT_DISPLAY, 0); - final IAccessibilityInteractionConnection mockRemoteConnection = - mA11yWindowManager.getConnectionLocked( - USER_SYSTEM_ID, outsideWindowId).getRemote(); - mWindows.get(Display.DEFAULT_DISPLAY).get(0).getWindowInfo().hasFlagWatchOutsideTouch = - true; - onAccessibilityWindowsChanged(Display.DEFAULT_DISPLAY, SEND_ON_WINDOW_CHANGES); - - mA11yWindowManager.notifyOutsideTouch(USER_SYSTEM_ID, targetWindowId); - verify(mockRemoteConnection).notifyOutsideTouch(); - } - - @Test - public void addAccessibilityInteractionConnection_profileUser_findInParentUser() - throws RemoteException { - final IWindow token = addAccessibilityInteractionConnection(Display.DEFAULT_DISPLAY, - false, USER_PROFILE); - final int windowId = mA11yWindowManager.findWindowIdLocked( - USER_PROFILE_PARENT, token.asBinder()); - assertTrue(windowId >= 0); - } - - @Test - public void getDisplayList() throws RemoteException { - // Starts tracking window of second display. - startTrackingPerDisplay(SECONDARY_DISPLAY_ID); - - final ArrayList<Integer> displayList = mA11yWindowManager.getDisplayListLocked( - DISPLAY_TYPE_DEFAULT); - assertTrue(displayList.equals(mExpectedDisplayList)); - } - - @Test - public void setAccessibilityWindowIdToSurfaceMetadata() - throws RemoteException { - final IWindow token = addAccessibilityInteractionConnection(Display.DEFAULT_DISPLAY, - true, USER_SYSTEM_ID); - int windowId = -1; - for (int i = 0; i < mA11yWindowTokens.size(); i++) { - if (mA11yWindowTokens.valueAt(i).equals(token)) { - windowId = mA11yWindowTokens.keyAt(i); - } - } - assertNotEquals("Returned token is not found in mA11yWindowTokens", -1, windowId); - verify(mMockWindowManagerInternal, times(1)).setAccessibilityIdToSurfaceMetadata( - token.asBinder(), windowId); - - mA11yWindowManager.removeAccessibilityInteractionConnection(token); - verify(mMockWindowManagerInternal, times(1)).setAccessibilityIdToSurfaceMetadata( - token.asBinder(), -1); - } - - @Test - public void getHostTokenLocked_hierarchiesAreAssociated_shouldReturnHostToken() { - mA11yWindowManager.associateLocked(mMockEmbeddedToken, mMockHostToken); - final IBinder hostToken = mA11yWindowManager.getHostTokenLocked(mMockEmbeddedToken); - assertEquals(hostToken, mMockHostToken); - } - - @Test - public void getHostTokenLocked_hierarchiesAreNotAssociated_shouldReturnNull() { - final IBinder hostToken = mA11yWindowManager.getHostTokenLocked(mMockEmbeddedToken); - assertNull(hostToken); - } - - @Test - public void getHostTokenLocked_embeddedHierarchiesAreDisassociated_shouldReturnNull() { - mA11yWindowManager.associateLocked(mMockEmbeddedToken, mMockHostToken); - mA11yWindowManager.disassociateLocked(mMockEmbeddedToken); - final IBinder hostToken = mA11yWindowManager.getHostTokenLocked(mMockEmbeddedToken); - assertNull(hostToken); - } - - @Test - public void getHostTokenLocked_hostHierarchiesAreDisassociated_shouldReturnNull() { - mA11yWindowManager.associateLocked(mMockEmbeddedToken, mMockHostToken); - mA11yWindowManager.disassociateLocked(mMockHostToken); - final IBinder hostToken = mA11yWindowManager.getHostTokenLocked(mMockHostToken); - assertNull(hostToken); - } - - @Test - public void getWindowIdLocked_windowIsRegistered_shouldReturnWindowId() { - final int windowId = mA11yWindowManager.getWindowIdLocked(mMockHostToken); - assertEquals(windowId, HOST_WINDOW_ID); - } - - @Test - public void getWindowIdLocked_windowIsNotRegistered_shouldReturnInvalidWindowId() { - final int windowId = mA11yWindowManager.getWindowIdLocked(mMockInvalidToken); - assertEquals(windowId, INVALID_ID); - } - - @Test - public void getTokenLocked_windowIsRegistered_shouldReturnToken() { - final IBinder token = mA11yWindowManager.getLeashTokenLocked(HOST_WINDOW_ID); - assertEquals(token, mMockHostToken); - } - - @Test - public void getTokenLocked_windowIsNotRegistered_shouldReturnNull() { - final IBinder token = mA11yWindowManager.getLeashTokenLocked(OTHER_WINDOW_ID); - assertNull(token); - } - - @Test - public void setAccessibilityWindowAttributes_windowIsNotRegistered_titleIsChanged() { - final int windowId = - getWindowIdFromWindowInfosForDisplay(Display.DEFAULT_DISPLAY, 0); - final WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams(); - layoutParams.accessibilityTitle = "accessibility window title"; - final AccessibilityWindowAttributes attributes = new AccessibilityWindowAttributes( - layoutParams, new LocaleList()); - - mA11yWindowManager.setAccessibilityWindowAttributes(Display.DEFAULT_DISPLAY, windowId, - USER_SYSTEM_ID, attributes); - - final AccessibilityWindowInfo a11yWindow = mA11yWindowManager.findA11yWindowInfoByIdLocked( - windowId); - assertEquals(toString(layoutParams.accessibilityTitle), toString(a11yWindow.getTitle())); - } - - @Test - public void sendAccessibilityEventOnWindowRemoval() { - final ArrayList<AccessibilityWindow> windows = mWindows.get(Display.DEFAULT_DISPLAY); - - // Removing index 0 because it's not focused, and avoids unnecessary layer change. - final int windowId = - getWindowIdFromWindowInfosForDisplay(Display.DEFAULT_DISPLAY, 0); - windows.remove(0); - - onAccessibilityWindowsChanged(Display.DEFAULT_DISPLAY, FORCE_SEND); - - final ArgumentCaptor<AccessibilityEvent> captor = - ArgumentCaptor.forClass(AccessibilityEvent.class); - verify(mMockA11yEventSender, times(1)) - .sendAccessibilityEventForCurrentUserLocked(captor.capture()); - assertThat(captor.getAllValues().get(0), - allOf(displayId(Display.DEFAULT_DISPLAY), - eventWindowId(windowId), - a11yWindowChanges(AccessibilityEvent.WINDOWS_CHANGE_REMOVED))); - } - - @Test - public void sendAccessibilityEventOnWindowAddition() throws RemoteException { - final ArrayList<AccessibilityWindow> windows = mWindows.get(Display.DEFAULT_DISPLAY); - - final IWindow token = addAccessibilityInteractionConnection(Display.DEFAULT_DISPLAY, - false, USER_SYSTEM_ID); - // Adding window to the front so that other windows' layer won't change. - windows.add(0, createMockAccessibilityWindow(token, Display.DEFAULT_DISPLAY)); - final int windowId = getWindowIdFromWindowInfosForDisplay(Display.DEFAULT_DISPLAY, 0); - - onAccessibilityWindowsChanged(Display.DEFAULT_DISPLAY, FORCE_SEND); - - final ArgumentCaptor<AccessibilityEvent> captor = - ArgumentCaptor.forClass(AccessibilityEvent.class); - verify(mMockA11yEventSender, times(1)) - .sendAccessibilityEventForCurrentUserLocked(captor.capture()); - assertThat(captor.getAllValues().get(0), - allOf(displayId(Display.DEFAULT_DISPLAY), - eventWindowId(windowId), - a11yWindowChanges(AccessibilityEvent.WINDOWS_CHANGE_ADDED))); - } - - @Test - public void sendAccessibilityEventOnWindowChange() { - final ArrayList<AccessibilityWindow> windows = mWindows.get(Display.DEFAULT_DISPLAY); - windows.get(0).getWindowInfo().title = "new title"; - final int windowId = getWindowIdFromWindowInfosForDisplay(Display.DEFAULT_DISPLAY, 0); - - onAccessibilityWindowsChanged(Display.DEFAULT_DISPLAY, FORCE_SEND); - - final ArgumentCaptor<AccessibilityEvent> captor = - ArgumentCaptor.forClass(AccessibilityEvent.class); - verify(mMockA11yEventSender, times(1)) - .sendAccessibilityEventForCurrentUserLocked(captor.capture()); - assertThat(captor.getAllValues().get(0), - allOf(displayId(Display.DEFAULT_DISPLAY), - eventWindowId(windowId), - a11yWindowChanges(AccessibilityEvent.WINDOWS_CHANGE_TITLE))); - } - - private void registerLeashedTokenAndWindowId() { - mA11yWindowManager.registerIdLocked(mMockHostToken, HOST_WINDOW_ID); - mA11yWindowManager.registerIdLocked(mMockEmbeddedToken, EMBEDDED_WINDOW_ID); - } - - private void startTrackingPerDisplay(int displayId) throws RemoteException { - ArrayList<AccessibilityWindow> windowsForDisplay = new ArrayList<>(); - // Adds RemoteAccessibilityConnection into AccessibilityWindowManager, and copy - // mock window token into mA11yWindowTokens. Also, preparing WindowInfo mWindowInfos - // for the test. - for (int i = 0; i < NUM_GLOBAL_WINDOWS; i++) { - final IWindow token = addAccessibilityInteractionConnection(displayId, - true, USER_SYSTEM_ID); - windowsForDisplay.add(createMockAccessibilityWindow(token, displayId)); - - } - for (int i = 0; i < NUM_APP_WINDOWS; i++) { - final IWindow token = addAccessibilityInteractionConnection(displayId, - false, USER_SYSTEM_ID); - windowsForDisplay.add(createMockAccessibilityWindow(token, displayId)); - } - // Sets up current focused window of display. - // Each display has its own current focused window if config_perDisplayFocusEnabled is true. - // Otherwise only default display needs to current focused window. - if (mSupportPerDisplayFocus || displayId == Display.DEFAULT_DISPLAY) { - windowsForDisplay.get(DEFAULT_FOCUSED_INDEX).getWindowInfo().focused = true; - } - // Turns on windows tracking, and update window info. - mA11yWindowManager.startTrackingWindows(displayId, false); - // Puts window lists into array. - mWindows.put(displayId, windowsForDisplay); - // Sets the default display is the top focused display and - // its current focused window is the top focused window. - if (displayId == Display.DEFAULT_DISPLAY) { - setTopFocusedWindowAndDisplay(displayId, DEFAULT_FOCUSED_INDEX); - } - // Invokes callback for sending window lists to A11y framework. - onAccessibilityWindowsChanged(displayId, FORCE_SEND); - - assertEquals(mA11yWindowManager.getWindowListLocked(displayId).size(), - windowsForDisplay.size()); - } - - private WindowsForAccessibilityCallback getWindowsForAccessibilityCallbacks(int displayId) { - ArgumentCaptor<WindowsForAccessibilityCallback> windowsForAccessibilityCallbacksCaptor = - ArgumentCaptor.forClass( - WindowsForAccessibilityCallback.class); - verify(mMockWindowManagerInternal) - .setWindowsForAccessibilityCallback(eq(displayId), - windowsForAccessibilityCallbacksCaptor.capture()); - return windowsForAccessibilityCallbacksCaptor.getValue(); - } - - private IWindow addAccessibilityInteractionConnection(int displayId, boolean bGlobal, - int userId) throws RemoteException { - final IWindow mockWindowToken = Mockito.mock(IWindow.class); - final IAccessibilityInteractionConnection mockA11yConnection = Mockito.mock( - IAccessibilityInteractionConnection.class); - final IBinder mockConnectionBinder = Mockito.mock(IBinder.class); - final IBinder mockWindowBinder = Mockito.mock(IBinder.class); - final IBinder mockLeashToken = Mockito.mock(IBinder.class); - when(mockA11yConnection.asBinder()).thenReturn(mockConnectionBinder); - when(mockWindowToken.asBinder()).thenReturn(mockWindowBinder); - when(mMockA11ySecurityPolicy.isCallerInteractingAcrossUsers(userId)) - .thenReturn(bGlobal); - when(mMockWindowManagerInternal.getDisplayIdForWindow(mockWindowBinder)) - .thenReturn(displayId); - - int windowId = mA11yWindowManager.addAccessibilityInteractionConnection( - mockWindowToken, mockLeashToken, mockA11yConnection, PACKAGE_NAME, userId); - mA11yWindowTokens.put(windowId, mockWindowToken); - return mockWindowToken; - } - - private int addAccessibilityInteractionConnection(int displayId, boolean bGlobal, - IBinder leashToken, int userId) throws RemoteException { - final IWindow mockWindowToken = Mockito.mock(IWindow.class); - final IAccessibilityInteractionConnection mockA11yConnection = Mockito.mock( - IAccessibilityInteractionConnection.class); - final IBinder mockConnectionBinder = Mockito.mock(IBinder.class); - final IBinder mockWindowBinder = Mockito.mock(IBinder.class); - when(mockA11yConnection.asBinder()).thenReturn(mockConnectionBinder); - when(mockWindowToken.asBinder()).thenReturn(mockWindowBinder); - when(mMockA11ySecurityPolicy.isCallerInteractingAcrossUsers(userId)) - .thenReturn(bGlobal); - when(mMockWindowManagerInternal.getDisplayIdForWindow(mockWindowBinder)) - .thenReturn(displayId); - - int windowId = mA11yWindowManager.addAccessibilityInteractionConnection( - mockWindowToken, leashToken, mockA11yConnection, PACKAGE_NAME, userId); - mA11yWindowTokens.put(windowId, mockWindowToken); - return windowId; - } - - private int getWindowIdFromWindowInfosForDisplay(int displayId, int index) { - final IBinder windowToken = mWindows.get(displayId).get(index).getWindowInfo().token; - return mA11yWindowManager.findWindowIdLocked( - USER_SYSTEM_ID, windowToken); - } - - private void setTopFocusedWindowAndDisplay(int displayId, int index) { - // Sets the top focus window. - mTopFocusedWindowToken = mWindows.get(displayId).get(index).getWindowInfo().token; - // Sets the top focused display. - mTopFocusedDisplayId = displayId; - } - - private void onAccessibilityWindowsChanged(int displayId, boolean forceSend) { - WindowsForAccessibilityCallback callbacks = mCallbackOfWindows.get(displayId); - if (callbacks == null) { - callbacks = getWindowsForAccessibilityCallbacks(displayId); - mCallbackOfWindows.put(displayId, callbacks); - } - callbacks.onAccessibilityWindowsChanged(forceSend, mTopFocusedDisplayId, - mTopFocusedWindowToken, new Point(SCREEN_WIDTH, SCREEN_HEIGHT), - mWindows.get(displayId)); - } - - private void changeFocusedWindowOnDisplayPerDisplayFocusConfig( - int changeFocusedDisplayId, int newFocusedWindowIndex, int oldTopFocusedDisplayId, - int oldFocusedWindowIndex) { - if (mSupportPerDisplayFocus) { - // Gets the old focused window of display which wants to change focused window. - WindowInfo focusedWindowInfo = - mWindows.get(changeFocusedDisplayId).get(oldFocusedWindowIndex).getWindowInfo(); - // Resets the focus of old focused window. - focusedWindowInfo.focused = false; - // Gets the new window of display which wants to change focused window. - focusedWindowInfo = - mWindows.get(changeFocusedDisplayId).get(newFocusedWindowIndex).getWindowInfo(); - // Sets the focus of new focused window. - focusedWindowInfo.focused = true; - } else { - // Gets the window of display which wants to change focused window. - WindowInfo focusedWindowInfo = - mWindows.get(changeFocusedDisplayId).get(newFocusedWindowIndex).getWindowInfo(); - // Sets the focus of new focused window. - focusedWindowInfo.focused = true; - // Gets the old focused window of old top focused display. - focusedWindowInfo = - mWindows.get(oldTopFocusedDisplayId).get(oldFocusedWindowIndex).getWindowInfo(); - // Resets the focus of old focused window. - focusedWindowInfo.focused = false; - // Changes the top focused display and window. - setTopFocusedWindowAndDisplay(changeFocusedDisplayId, newFocusedWindowIndex); - } - } - - private AccessibilityWindow createMockAccessibilityWindow(IWindow windowToken, int displayId) { - final WindowInfo windowInfo = WindowInfo.obtain(); - windowInfo.type = WindowManager.LayoutParams.TYPE_APPLICATION; - windowInfo.token = windowToken.asBinder(); - - final AccessibilityWindow window = Mockito.mock(AccessibilityWindow.class); - when(window.getWindowInfo()).thenReturn(windowInfo); - when(window.isFocused()).thenAnswer(invocation -> windowInfo.focused); - when(window.isTouchable()).thenReturn(true); - when(window.getType()).thenReturn(windowInfo.type); - - setRegionForMockAccessibilityWindow(window, nextToucableRegion(displayId)); - return window; - } - - private void setRegionForMockAccessibilityWindow(AccessibilityWindow window, Region region) { - doAnswer(invocation -> { - ((Region) invocation.getArgument(0)).set(region); - return null; - }).when(window).getTouchableRegionInScreen(any(Region.class)); - doAnswer(invocation -> { - ((Region) invocation.getArgument(0)).set(region); - return null; - }).when(window).getTouchableRegionInWindow(any(Region.class)); - } - - private Region nextToucableRegion(int displayId) { - final int topLeft = mNextRegionOffsets.get(displayId, 0); - final int bottomRight = topLeft + 100; - mNextRegionOffsets.put(displayId, topLeft + 10); - return new Region(topLeft, topLeft, bottomRight, bottomRight); - } - - @Nullable - private static String toString(@Nullable CharSequence cs) { - return cs == null ? null : cs.toString(); - } - - static class DisplayIdMatcher extends TypeSafeMatcher<AccessibilityEvent> { - private final int mDisplayId; - - DisplayIdMatcher(int displayId) { - super(); - mDisplayId = displayId; - } - - static DisplayIdMatcher displayId(int displayId) { - return new DisplayIdMatcher(displayId); - } - - @Override - protected boolean matchesSafely(AccessibilityEvent event) { - return event.getDisplayId() == mDisplayId; - } - - @Override - public void describeTo(Description description) { - description.appendText("Matching to displayId " + mDisplayId); - } - } - - static class EventWindowIdMatcher extends TypeSafeMatcher<AccessibilityEvent> { - private int mWindowId; - - EventWindowIdMatcher(int windowId) { - super(); - mWindowId = windowId; - } - - static EventWindowIdMatcher eventWindowId(int windowId) { - return new EventWindowIdMatcher(windowId); - } - - @Override - protected boolean matchesSafely(AccessibilityEvent event) { - return event.getWindowId() == mWindowId; - } - - @Override - public void describeTo(Description description) { - description.appendText("Matching to windowId " + mWindowId); - } - } - - static class WindowChangesMatcher extends TypeSafeMatcher<AccessibilityEvent> { - private int mWindowChanges; - - WindowChangesMatcher(int windowChanges) { - super(); - mWindowChanges = windowChanges; - } - - static WindowChangesMatcher a11yWindowChanges(int windowChanges) { - return new WindowChangesMatcher(windowChanges); - } - - @Override - protected boolean matchesSafely(AccessibilityEvent event) { - return event.getWindowChanges() == mWindowChanges; - } - - @Override - public void describeTo(Description description) { - description.appendText("Matching to window changes " + mWindowChanges); - } - } - - static class WindowIdMatcher extends TypeSafeMatcher<AccessibilityWindowInfo> { - private final int mWindowId; - - WindowIdMatcher(int windowId) { - super(); - mWindowId = windowId; - } - - static WindowIdMatcher windowId(int windowId) { - return new WindowIdMatcher(windowId); - } - - @Override - protected boolean matchesSafely(AccessibilityWindowInfo window) { - return window.getId() == mWindowId; - } - - @Override - public void describeTo(Description description) { - description.appendText("Matching to windowId " + mWindowId); - } - } -} diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java index cf5dc4bec71c..a7bf3e194dd9 100644 --- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java +++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java @@ -4404,6 +4404,7 @@ public class DevicePolicyManagerTest extends DpmTestBase { } @Test + @Ignore("b/277916462") public void testSetAutoTimeEnabledModifiesSetting() throws Exception { mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID; setupDeviceOwner(); @@ -4415,6 +4416,7 @@ public class DevicePolicyManagerTest extends DpmTestBase { } @Test + @Ignore("b/277916462") public void testSetAutoTimeEnabledWithPOOnUser0() throws Exception { mContext.binder.callingUid = DpmMockContext.SYSTEM_UID; setupProfileOwnerOnUser0(); @@ -4434,7 +4436,7 @@ public class DevicePolicyManagerTest extends DpmTestBase { } @Test - @Ignore("b/359188869") + @Ignore("b/277916462") public void testSetAutoTimeEnabledWithPOOfOrganizationOwnedDevice() throws Exception { setupProfileOwner(); configureProfileOwnerOfOrgOwnedDevice(admin1, CALLER_USER_HANDLE); diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTvTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTvTest.java index 0816e7b61165..5be4490e67ef 100644 --- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTvTest.java +++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTvTest.java @@ -118,6 +118,7 @@ public class HdmiCecLocalDeviceTvTest { private boolean mDisableCecOnStandbyByLowEnergyMode; private boolean mWasCecDisabledOnStandbyByLowEnergyMode; private boolean mUseHdmiCecPowerStatusController; + private boolean mUserEnabledCecInOfflineMode; private class DeviceEventListener { private HdmiDeviceInfo mDevice; @@ -250,6 +251,11 @@ public class HdmiCecLocalDeviceTvTest { protected void setWasCecDisabledOnStandbyByLowEnergyMode(boolean value) { mWasCecDisabledOnStandbyByLowEnergyMode = value; } + + @Override + protected boolean userEnabledCecInOfflineMode() { + return mUserEnabledCecInOfflineMode; + } }; mHdmiControlService.setIoLooper(mMyLooper); @@ -298,6 +304,7 @@ public class HdmiCecLocalDeviceTvTest { mWasCecDisabledOnStandbyByLowEnergyMode = false; mDisableCecOnStandbyByLowEnergyMode = false; mUseHdmiCecPowerStatusController = false; + mUserEnabledCecInOfflineMode = false; mNativeWrapper.clearResultMessages(); } @@ -2400,6 +2407,32 @@ public class HdmiCecLocalDeviceTvTest { assertTrue(mVendorCommandListeners.contains(vendorCommandListenerInvocationSettingChange)); } + @Test + public void lowEnergyMode_userEnabledCecInOfflineMode_onStandby_cecStaysEnabled() { + mDisableCecOnStandbyByLowEnergyMode = true; + mUseHdmiCecPowerStatusController = true; + mUserEnabledCecInOfflineMode = true; + mPowerManager.setIsLowPowerStandbyEnabled(true); + + assertEquals(mHdmiCecLocalDeviceTv.mService.getHdmiCecConfig().getIntValue( + HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_ENABLED), + HdmiControlManager.HDMI_CEC_CONTROL_ENABLED); + mHdmiControlService.onStandby(STANDBY_SCREEN_OFF); + mTestLooper.dispatchAll(); + + assertEquals(mHdmiCecLocalDeviceTv.mService.getHdmiCecConfig().getIntValue( + HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_ENABLED), + HdmiControlManager.HDMI_CEC_CONTROL_ENABLED); + assertFalse(mWasCecDisabledOnStandbyByLowEnergyMode); + mHdmiControlService.onWakeUp(WAKE_UP_SCREEN_ON); + mTestLooper.dispatchAll(); + + assertEquals(mHdmiCecLocalDeviceTv.mService.getHdmiCecConfig().getIntValue( + HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_ENABLED), + HdmiControlManager.HDMI_CEC_CONTROL_ENABLED); + assertFalse(mWasCecDisabledOnStandbyByLowEnergyMode); + } + protected static class MockTvDevice extends HdmiCecLocalDeviceTv { MockTvDevice(HdmiControlService service) { super(service); diff --git a/services/tests/servicestests/src/com/android/server/media/projection/MediaProjectionManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/media/projection/MediaProjectionManagerServiceTest.java index b2a7d20fb948..3ced56a04138 100644 --- a/services/tests/servicestests/src/com/android/server/media/projection/MediaProjectionManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/media/projection/MediaProjectionManagerServiceTest.java @@ -67,10 +67,12 @@ import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.ApplicationInfoFlags; import android.content.pm.PackageManager.NameNotFoundException; +import android.graphics.Rect; import android.media.projection.IMediaProjection; import android.media.projection.IMediaProjectionCallback; import android.media.projection.IMediaProjectionWatcherCallback; import android.media.projection.ReviewGrantedConsentResult; +import android.media.projection.StopReason; import android.os.Binder; import android.os.IBinder; import android.os.Looper; @@ -549,7 +551,7 @@ public class MediaProjectionManagerServiceTest { MediaProjectionManagerService.MediaProjection projection = startProjectionPreconditions(service); - projection.stop(); + projection.stop(StopReason.STOP_UNKNOWN); verifyZeroInteractions(mMediaProjectionMetricsLogger); } @@ -562,10 +564,10 @@ public class MediaProjectionManagerServiceTest { startProjectionPreconditions(service); projection.start(mIMediaProjectionCallback); - projection.stop(); + final @StopReason int stopReason = StopReason.STOP_UNKNOWN; + projection.stop(stopReason); - verify(mMediaProjectionMetricsLogger) - .logStopped(UID, TARGET_UID_UNKNOWN); + verify(mMediaProjectionMetricsLogger).logStopped(UID, TARGET_UID_UNKNOWN, stopReason); } @Test @@ -580,15 +582,16 @@ public class MediaProjectionManagerServiceTest { .setContentRecordingSession(any(ContentRecordingSession.class)); service.setContentRecordingSession(DISPLAY_SESSION); - projection.stop(); + final @StopReason int stopReason = StopReason.STOP_UNKNOWN; + projection.stop(stopReason); - verify(mMediaProjectionMetricsLogger) - .logStopped(UID, TARGET_UID_FULL_SCREEN); + verify(mMediaProjectionMetricsLogger).logStopped(UID, TARGET_UID_FULL_SCREEN, stopReason); } @Test public void stop_taskSession_logsHostUidAndTargetUid() throws Exception { int targetUid = 1234; + int stopReason = StopReason.STOP_UNKNOWN; MediaProjectionManagerService service = new MediaProjectionManagerService(mContext, mMediaProjectionMetricsLoggerInjector); MediaProjectionManagerService.MediaProjection projection = @@ -601,9 +604,9 @@ public class MediaProjectionManagerServiceTest { taskSession.setTargetUid(targetUid); service.setContentRecordingSession(taskSession); - projection.stop(); + projection.stop(stopReason); - verify(mMediaProjectionMetricsLogger).logStopped(UID, targetUid); + verify(mMediaProjectionMetricsLogger).logStopped(UID, targetUid, stopReason); } @Test @@ -638,7 +641,7 @@ public class MediaProjectionManagerServiceTest { projection.start(mIMediaProjectionCallback); assertThat(projection.isValid()).isTrue(); - projection.stop(); + projection.stop(StopReason.STOP_UNKNOWN); // Second start - so not valid. projection.start(mIMediaProjectionCallback); @@ -692,7 +695,7 @@ public class MediaProjectionManagerServiceTest { MediaProjectionManagerService.MediaProjection projection = startProjectionPreconditions( service); projection.start(mIMediaProjectionCallback); - projection.stop(); + projection.stop(StopReason.STOP_UNKNOWN); // Second start - so not valid. projection.start(mIMediaProjectionCallback); @@ -708,7 +711,7 @@ public class MediaProjectionManagerServiceTest { MediaProjectionManagerService.MediaProjection projection = startProjectionPreconditions( service); projection.start(mIMediaProjectionCallback); - projection.stop(); + projection.stop(StopReason.STOP_UNKNOWN); // Second start - so not valid. projection.start(mIMediaProjectionCallback); @@ -947,6 +950,26 @@ public class MediaProjectionManagerServiceTest { projection.uid, targetUid, WINDOWING_MODE_MULTI_WINDOW); } + @Test + public void notifyCaptureBoundsChanged_forwardsToLoggerAndResizeCallbacks() throws Exception { + int targetUid = 123; + mService = + new MediaProjectionManagerService(mContext, mMediaProjectionMetricsLoggerInjector); + + ContentRecordingSession taskSession = createTaskSession(mock(IBinder.class)); + taskSession.setTargetUid(targetUid); + mService.setContentRecordingSession(taskSession); + + MediaProjectionManagerService.MediaProjection projection = startProjectionPreconditions(); + projection.start(mIMediaProjectionCallback); + + Rect newBounds = new Rect(0, 0, 1000, 2000); + mService.notifyCaptureBoundsChanged(RECORD_CONTENT_TASK, targetUid, newBounds); + + verify(mMediaProjectionMetricsLogger) + .logChangedCaptureBounds(RECORD_CONTENT_TASK, projection.uid, targetUid, newBounds); + } + /** * Executes and validates scenario where the consent result indicates the projection ends. */ diff --git a/services/tests/servicestests/src/com/android/server/media/projection/MediaProjectionMetricsLoggerTest.java b/services/tests/servicestests/src/com/android/server/media/projection/MediaProjectionMetricsLoggerTest.java index 72ce9fe9a23f..c727bb6bbf7d 100644 --- a/services/tests/servicestests/src/com/android/server/media/projection/MediaProjectionMetricsLoggerTest.java +++ b/services/tests/servicestests/src/com/android/server/media/projection/MediaProjectionMetricsLoggerTest.java @@ -32,6 +32,17 @@ import static com.android.internal.util.FrameworkStatsLog.MEDIA_PROJECTION_STATE import static com.android.internal.util.FrameworkStatsLog.MEDIA_PROJECTION_STATE_CHANGED__STATE__MEDIA_PROJECTION_STATE_PERMISSION_REQUEST_DISPLAYED; import static com.android.internal.util.FrameworkStatsLog.MEDIA_PROJECTION_STATE_CHANGED__STATE__MEDIA_PROJECTION_STATE_STOPPED; import static com.android.internal.util.FrameworkStatsLog.MEDIA_PROJECTION_STATE_CHANGED__STATE__MEDIA_PROJECTION_STATE_UNKNOWN; +import static com.android.internal.util.FrameworkStatsLog.MEDIA_PROJECTION_STATE_CHANGED__STOP_SOURCE__STOP_SOURCE_DEVICE_LOCK; +import static com.android.internal.util.FrameworkStatsLog.MEDIA_PROJECTION_STATE_CHANGED__STOP_SOURCE__STOP_SOURCE_ERROR; +import static com.android.internal.util.FrameworkStatsLog.MEDIA_PROJECTION_STATE_CHANGED__STOP_SOURCE__STOP_SOURCE_FOREGROUND_SERVICE_CHANGE; +import static com.android.internal.util.FrameworkStatsLog.MEDIA_PROJECTION_STATE_CHANGED__STOP_SOURCE__STOP_SOURCE_HOST_APP_STOP; +import static com.android.internal.util.FrameworkStatsLog.MEDIA_PROJECTION_STATE_CHANGED__STOP_SOURCE__STOP_SOURCE_NEW_MEDIA_ROUTE; +import static com.android.internal.util.FrameworkStatsLog.MEDIA_PROJECTION_STATE_CHANGED__STOP_SOURCE__STOP_SOURCE_NEW_PROJECTION; +import static com.android.internal.util.FrameworkStatsLog.MEDIA_PROJECTION_STATE_CHANGED__STOP_SOURCE__STOP_SOURCE_QS_TILE; +import static com.android.internal.util.FrameworkStatsLog.MEDIA_PROJECTION_STATE_CHANGED__STOP_SOURCE__STOP_SOURCE_STATUS_BAR_CHIP_STOP; +import static com.android.internal.util.FrameworkStatsLog.MEDIA_PROJECTION_STATE_CHANGED__STOP_SOURCE__STOP_SOURCE_TASK_APP_CLOSE; +import static com.android.internal.util.FrameworkStatsLog.MEDIA_PROJECTION_STATE_CHANGED__STOP_SOURCE__STOP_SOURCE_UNKNOWN; +import static com.android.internal.util.FrameworkStatsLog.MEDIA_PROJECTION_STATE_CHANGED__STOP_SOURCE__STOP_SOURCE_USER_SWITCH; import static com.android.internal.util.FrameworkStatsLog.MEDIA_PROJECTION_TARGET_CHANGED__TARGET_TYPE__TARGET_TYPE_APP_TASK; import static com.android.internal.util.FrameworkStatsLog.MEDIA_PROJECTION_TARGET_CHANGED__TARGET_TYPE__TARGET_TYPE_DISPLAY; import static com.android.internal.util.FrameworkStatsLog.MEDIA_PROJECTION_TARGET_CHANGED__TARGET_TYPE__TARGET_TYPE_UNKNOWN; @@ -46,6 +57,7 @@ import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import android.media.projection.StopReason; import android.platform.test.annotations.Presubmit; import androidx.test.ext.junit.runners.AndroidJUnit4; @@ -81,6 +93,7 @@ public class MediaProjectionMetricsLoggerTest { private static final int TEST_WINDOWING_MODE = 987; private static final int TEST_CONTENT_TO_RECORD = 654; + private static final int TEST_STOP_SOURCE = 321; @Mock private FrameworkStatsLogWrapper mFrameworkStatsLogWrapper; @Mock private MediaProjectionSessionIdGenerator mSessionIdGenerator; @@ -136,6 +149,14 @@ public class MediaProjectionMetricsLoggerTest { } @Test + public void logInitiated_logsUnknownStopSource() { + mLogger.logInitiated(TEST_HOST_UID, TEST_CREATION_SOURCE); + + verifyStopSourceLogged( + MEDIA_PROJECTION_STATE_CHANGED__STOP_SOURCE__STOP_SOURCE_UNKNOWN); + } + + @Test public void logInitiated_noPreviousSession_logsUnknownTimeSinceLastActive() { when(mTimestampStore.timeSinceLastActiveSession()).thenReturn(null); @@ -177,7 +198,7 @@ public class MediaProjectionMetricsLoggerTest { @Test public void logStopped_logsStateChangedAtomId() { - mLogger.logStopped(TEST_HOST_UID, TEST_TARGET_UID); + mLogger.logStopped(TEST_HOST_UID, TEST_TARGET_UID, TEST_STOP_SOURCE); verifyStateChangedAtomIdLogged(); } @@ -187,42 +208,49 @@ public class MediaProjectionMetricsLoggerTest { int currentSessionId = 987; when(mSessionIdGenerator.getCurrentSessionId()).thenReturn(currentSessionId); - mLogger.logStopped(TEST_HOST_UID, TEST_TARGET_UID); + mLogger.logStopped(TEST_HOST_UID, TEST_TARGET_UID, TEST_STOP_SOURCE); verifySessionIdLogged(currentSessionId); } @Test public void logStopped_logsStateStopped() { - mLogger.logStopped(TEST_HOST_UID, TEST_TARGET_UID); + mLogger.logStopped(TEST_HOST_UID, TEST_TARGET_UID, TEST_STOP_SOURCE); verifyStateLogged(MEDIA_PROJECTION_STATE_CHANGED__STATE__MEDIA_PROJECTION_STATE_STOPPED); } @Test public void logStopped_logsHostUid() { - mLogger.logStopped(TEST_HOST_UID, TEST_TARGET_UID); + mLogger.logStopped(TEST_HOST_UID, TEST_TARGET_UID, TEST_STOP_SOURCE); verifyStateChangedHostUidLogged(TEST_HOST_UID); } @Test public void logStopped_logsTargetUid() { - mLogger.logStopped(TEST_HOST_UID, TEST_TARGET_UID); + mLogger.logStopped(TEST_HOST_UID, TEST_TARGET_UID, TEST_STOP_SOURCE); verifyStageChangedTargetUidLogged(TEST_TARGET_UID); } @Test + public void logStopped_logsStopSource() { + mLogger.logStopped(TEST_HOST_UID, TEST_TARGET_UID, StopReason.STOP_UNKNOWN); + + verifyStopSourceLogged(MEDIA_PROJECTION_STATE_CHANGED__STOP_SOURCE__STOP_SOURCE_UNKNOWN); + } + + @Test public void logStopped_logsUnknownTimeSinceLastActive() { - mLogger.logStopped(TEST_HOST_UID, TEST_TARGET_UID); + mLogger.logStopped(TEST_HOST_UID, TEST_TARGET_UID, TEST_STOP_SOURCE); verifyTimeSinceLastActiveSessionLogged(-1); } @Test public void logStopped_logsUnknownSessionCreationSource() { - mLogger.logStopped(TEST_HOST_UID, TEST_TARGET_UID); + mLogger.logStopped(TEST_HOST_UID, TEST_TARGET_UID, TEST_STOP_SOURCE); verifyCreationSourceLogged( MEDIA_PROJECTION_STATE_CHANGED__CREATION_SOURCE__CREATION_SOURCE_UNKNOWN); @@ -230,7 +258,7 @@ public class MediaProjectionMetricsLoggerTest { @Test public void logStopped_logsPreviousState() { - mLogger.logStopped(TEST_HOST_UID, TEST_TARGET_UID); + mLogger.logStopped(TEST_HOST_UID, TEST_TARGET_UID, TEST_STOP_SOURCE); verifyPreviousStateLogged( MEDIA_PROJECTION_STATE_CHANGED__STATE__MEDIA_PROJECTION_STATE_UNKNOWN); @@ -238,7 +266,7 @@ public class MediaProjectionMetricsLoggerTest { verifyPreviousStateLogged( MEDIA_PROJECTION_STATE_CHANGED__STATE__MEDIA_PROJECTION_STATE_STOPPED); - mLogger.logStopped(TEST_HOST_UID, TEST_CREATION_SOURCE); + mLogger.logStopped(TEST_HOST_UID, TEST_CREATION_SOURCE, TEST_STOP_SOURCE); verifyPreviousStateLogged( MEDIA_PROJECTION_STATE_CHANGED__STATE__MEDIA_PROJECTION_STATE_INITIATED); } @@ -247,14 +275,14 @@ public class MediaProjectionMetricsLoggerTest { public void logStopped_capturingWasInProgress_registersActiveSessionEnded() { mLogger.logInProgress(TEST_HOST_UID, TEST_TARGET_UID); - mLogger.logStopped(TEST_HOST_UID, TEST_TARGET_UID); + mLogger.logStopped(TEST_HOST_UID, TEST_TARGET_UID, TEST_STOP_SOURCE); verify(mTimestampStore).registerActiveSessionEnded(); } @Test public void logStopped_capturingWasNotInProgress_doesNotRegistersActiveSessionEnded() { - mLogger.logStopped(TEST_HOST_UID, TEST_TARGET_UID); + mLogger.logStopped(TEST_HOST_UID, TEST_TARGET_UID, TEST_STOP_SOURCE); verify(mTimestampStore, never()).registerActiveSessionEnded(); } @@ -314,6 +342,14 @@ public class MediaProjectionMetricsLoggerTest { } @Test + public void logInProgress_logsUnknownSessionStopSource() { + mLogger.logInProgress(TEST_HOST_UID, TEST_TARGET_UID); + + verifyStopSourceLogged( + MEDIA_PROJECTION_STATE_CHANGED__STOP_SOURCE__STOP_SOURCE_UNKNOWN); + } + + @Test public void logInProgress_logsPreviousState() { mLogger.logInitiated(TEST_HOST_UID, TEST_CREATION_SOURCE); verifyPreviousStateLogged( @@ -323,7 +359,7 @@ public class MediaProjectionMetricsLoggerTest { verifyPreviousStateLogged( MEDIA_PROJECTION_STATE_CHANGED__STATE__MEDIA_PROJECTION_STATE_INITIATED); - mLogger.logStopped(TEST_HOST_UID, TEST_CREATION_SOURCE); + mLogger.logStopped(TEST_HOST_UID, TEST_CREATION_SOURCE, TEST_STOP_SOURCE); verifyPreviousStateLogged( MEDIA_PROJECTION_STATE_CHANGED__STATE__MEDIA_PROJECTION_STATE_CAPTURING_IN_PROGRESS); @@ -387,6 +423,14 @@ public class MediaProjectionMetricsLoggerTest { } @Test + public void logPermissionRequestDisplayed_logsUnknownSessionStopSource() { + mLogger.logPermissionRequestDisplayed(TEST_HOST_UID); + + verifyStopSourceLogged( + MEDIA_PROJECTION_STATE_CHANGED__STOP_SOURCE__STOP_SOURCE_UNKNOWN); + } + + @Test public void logPermissionRequestDisplayed_logsPreviousState() { mLogger.logInitiated(TEST_HOST_UID, TEST_CREATION_SOURCE); verifyPreviousStateLogged( @@ -396,7 +440,7 @@ public class MediaProjectionMetricsLoggerTest { verifyPreviousStateLogged( MEDIA_PROJECTION_STATE_CHANGED__STATE__MEDIA_PROJECTION_STATE_INITIATED); - mLogger.logStopped(TEST_HOST_UID, TEST_CREATION_SOURCE); + mLogger.logStopped(TEST_HOST_UID, TEST_CREATION_SOURCE, TEST_STOP_SOURCE); verifyPreviousStateLogged( MEDIA_PROJECTION_STATE_CHANGED__STATE__MEDIA_PROJECTION_STATE_PERMISSION_REQUEST_DISPLAYED); @@ -460,6 +504,14 @@ public class MediaProjectionMetricsLoggerTest { } @Test + public void logAppSelectorDisplayed_logsUnknownSessionStopSource() { + mLogger.logAppSelectorDisplayed(TEST_HOST_UID); + + verifyStopSourceLogged( + MEDIA_PROJECTION_STATE_CHANGED__STOP_SOURCE__STOP_SOURCE_UNKNOWN); + } + + @Test public void logAppSelectorDisplayed_logsPreviousState() { mLogger.logInitiated(TEST_HOST_UID, TEST_CREATION_SOURCE); verifyPreviousStateLogged( @@ -469,7 +521,7 @@ public class MediaProjectionMetricsLoggerTest { verifyPreviousStateLogged( MEDIA_PROJECTION_STATE_CHANGED__STATE__MEDIA_PROJECTION_STATE_INITIATED); - mLogger.logStopped(TEST_HOST_UID, TEST_CREATION_SOURCE); + mLogger.logStopped(TEST_HOST_UID, TEST_CREATION_SOURCE, TEST_STOP_SOURCE); verifyPreviousStateLogged( MEDIA_PROJECTION_STATE_CHANGED__STATE__MEDIA_PROJECTION_STATE_APP_SELECTOR_DISPLAYED); @@ -536,6 +588,14 @@ public class MediaProjectionMetricsLoggerTest { } @Test + public void logProjectionPermissionRequestCancelled_logsUnknownStopSource() { + mLogger.logProjectionPermissionRequestCancelled(TEST_HOST_UID); + + verifyStopSourceLogged( + MEDIA_PROJECTION_STATE_CHANGED__STOP_SOURCE__STOP_SOURCE_UNKNOWN); + } + + @Test public void logWindowingModeChanged_logsTargetChangedAtomId() { mLogger.logChangedWindowingMode( TEST_CONTENT_TO_RECORD, TEST_HOST_UID, TEST_TARGET_UID, TEST_WINDOWING_MODE); @@ -614,6 +674,42 @@ public class MediaProjectionMetricsLoggerTest { .isEqualTo(MEDIA_PROJECTION_TARGET_CHANGED__TARGET_WINDOWING_MODE__WINDOWING_MODE_UNKNOWN); } + @Test + public void testStopReasonToSessionStopSource() { + mExpect.that(mLogger.stopReasonToSessionStopSource(StopReason.STOP_HOST_APP)) + .isEqualTo(MEDIA_PROJECTION_STATE_CHANGED__STOP_SOURCE__STOP_SOURCE_HOST_APP_STOP); + + mExpect.that(mLogger.stopReasonToSessionStopSource(StopReason.STOP_TARGET_REMOVED)) + .isEqualTo(MEDIA_PROJECTION_STATE_CHANGED__STOP_SOURCE__STOP_SOURCE_TASK_APP_CLOSE); + + mExpect.that(mLogger.stopReasonToSessionStopSource(StopReason.STOP_DEVICE_LOCKED)) + .isEqualTo(MEDIA_PROJECTION_STATE_CHANGED__STOP_SOURCE__STOP_SOURCE_DEVICE_LOCK); + + mExpect.that(mLogger.stopReasonToSessionStopSource(StopReason.STOP_PRIVACY_CHIP)) + .isEqualTo(MEDIA_PROJECTION_STATE_CHANGED__STOP_SOURCE__STOP_SOURCE_STATUS_BAR_CHIP_STOP); + + mExpect.that(mLogger.stopReasonToSessionStopSource(StopReason.STOP_QS_TILE)) + .isEqualTo(MEDIA_PROJECTION_STATE_CHANGED__STOP_SOURCE__STOP_SOURCE_QS_TILE); + + mExpect.that(mLogger.stopReasonToSessionStopSource(StopReason.STOP_USER_SWITCH)) + .isEqualTo(MEDIA_PROJECTION_STATE_CHANGED__STOP_SOURCE__STOP_SOURCE_USER_SWITCH); + + mExpect.that(mLogger.stopReasonToSessionStopSource(StopReason.STOP_FOREGROUND_SERVICE_CHANGE)) + .isEqualTo(MEDIA_PROJECTION_STATE_CHANGED__STOP_SOURCE__STOP_SOURCE_FOREGROUND_SERVICE_CHANGE); + + mExpect.that(mLogger.stopReasonToSessionStopSource(StopReason.STOP_NEW_PROJECTION)) + .isEqualTo(MEDIA_PROJECTION_STATE_CHANGED__STOP_SOURCE__STOP_SOURCE_NEW_PROJECTION); + + mExpect.that(mLogger.stopReasonToSessionStopSource(StopReason.STOP_NEW_MEDIA_ROUTE)) + .isEqualTo(MEDIA_PROJECTION_STATE_CHANGED__STOP_SOURCE__STOP_SOURCE_NEW_MEDIA_ROUTE); + + mExpect.that(mLogger.stopReasonToSessionStopSource(StopReason.STOP_ERROR)) + .isEqualTo(MEDIA_PROJECTION_STATE_CHANGED__STOP_SOURCE__STOP_SOURCE_ERROR); + + mExpect.that(mLogger.stopReasonToSessionStopSource(StopReason.STOP_UNKNOWN)) + .isEqualTo(MEDIA_PROJECTION_STATE_CHANGED__STOP_SOURCE__STOP_SOURCE_UNKNOWN); + } + private void verifyStateChangedAtomIdLogged() { verify(mFrameworkStatsLogWrapper) .writeStateChanged( @@ -624,7 +720,8 @@ public class MediaProjectionMetricsLoggerTest { /* hostUid= */ anyInt(), /* targetUid= */ anyInt(), /* timeSinceLastActive= */ anyInt(), - /* creationSource= */ anyInt()); + /* creationSource= */ anyInt(), + /* stopSource= */ anyInt()); } private void verifyStateLogged(int state) { @@ -637,7 +734,8 @@ public class MediaProjectionMetricsLoggerTest { /* hostUid= */ anyInt(), /* targetUid= */ anyInt(), /* timeSinceLastActive= */ anyInt(), - /* creationSource= */ anyInt()); + /* creationSource= */ anyInt(), + /* stopSource= */ anyInt()); } private void verifyStateChangedHostUidLogged(int hostUid) { @@ -650,7 +748,8 @@ public class MediaProjectionMetricsLoggerTest { eq(hostUid), /* targetUid= */ anyInt(), /* timeSinceLastActive= */ anyInt(), - /* creationSource= */ anyInt()); + /* creationSource= */ anyInt(), + /* stopSource= */ anyInt()); } private void verifyCreationSourceLogged(int creationSource) { @@ -663,7 +762,22 @@ public class MediaProjectionMetricsLoggerTest { /* hostUid= */ anyInt(), /* targetUid= */ anyInt(), /* timeSinceLastActive= */ anyInt(), - eq(creationSource)); + eq(creationSource), + /* stopSource= */ anyInt()); + } + + private void verifyStopSourceLogged(int stopSource) { + verify(mFrameworkStatsLogWrapper) + .writeStateChanged( + /* code= */ anyInt(), + /* sessionId= */ anyInt(), + /* state= */ anyInt(), + /* previousState= */ anyInt(), + /* hostUid= */ anyInt(), + /* targetUid= */ anyInt(), + /* timeSinceLastActive= */ anyInt(), + /* stopSource= */ anyInt(), + eq(stopSource)); } private void verifyStageChangedTargetUidLogged(int targetUid) { @@ -676,7 +790,8 @@ public class MediaProjectionMetricsLoggerTest { /* hostUid= */ anyInt(), eq(targetUid), /* timeSinceLastActive= */ anyInt(), - /* creationSource= */ anyInt()); + /* creationSource= */ anyInt(), + /* stopSource= */ anyInt()); } private void verifyTimeSinceLastActiveSessionLogged(int timeSinceLastActiveSession) { @@ -689,7 +804,8 @@ public class MediaProjectionMetricsLoggerTest { /* hostUid= */ anyInt(), /* targetUid= */ anyInt(), /* timeSinceLastActive= */ eq(timeSinceLastActiveSession), - /* creationSource= */ anyInt()); + /* creationSource= */ anyInt(), + /* stopSource= */ anyInt()); } private void verifySessionIdLogged(int newSessionId) { @@ -702,7 +818,8 @@ public class MediaProjectionMetricsLoggerTest { /* hostUid= */ anyInt(), /* targetUid= */ anyInt(), /* timeSinceLastActive= */ anyInt(), - /* creationSource= */ anyInt()); + /* creationSource= */ anyInt(), + /* stopSource= */ anyInt()); } private void verifyPreviousStateLogged(int previousState) { @@ -715,7 +832,8 @@ public class MediaProjectionMetricsLoggerTest { /* hostUid= */ anyInt(), /* targetUid= */ anyInt(), /* timeSinceLastActive= */ anyInt(), - /* creationSource= */ anyInt()); + /* creationSource= */ anyInt(), + /* stopSource= */ anyInt()); } private void verifyTargetChangedAtomIdLogged() { @@ -726,7 +844,12 @@ public class MediaProjectionMetricsLoggerTest { /* targetType= */ anyInt(), /* hostUid= */ anyInt(), /* targetUid= */ anyInt(), - /* targetWindowingMode= */ anyInt()); + /* targetWindowingMode= */ anyInt(), + /* width= */ anyInt(), + /* height= */ anyInt(), + /* centerX= */ anyInt(), + /* centerY= */ anyInt(), + /* targetChangeType= */ anyInt()); } private void verifyTargetTypeLogged(int targetType) { @@ -737,7 +860,12 @@ public class MediaProjectionMetricsLoggerTest { eq(targetType), /* hostUid= */ anyInt(), /* targetUid= */ anyInt(), - /* targetWindowingMode= */ anyInt()); + /* targetWindowingMode= */ anyInt(), + /* width= */ anyInt(), + /* height= */ anyInt(), + /* centerX= */ anyInt(), + /* centerY= */ anyInt(), + /* targetChangeType= */ anyInt()); } private void verifyTargetChangedHostUidLogged(int hostUid) { @@ -748,7 +876,12 @@ public class MediaProjectionMetricsLoggerTest { /* targetType= */ anyInt(), eq(hostUid), /* targetUid= */ anyInt(), - /* targetWindowingMode= */ anyInt()); + /* targetWindowingMode= */ anyInt(), + /* width= */ anyInt(), + /* height= */ anyInt(), + /* centerX= */ anyInt(), + /* centerY= */ anyInt(), + /* targetChangeType= */ anyInt()); } private void verifyTargetChangedTargetUidLogged(int targetUid) { @@ -759,7 +892,12 @@ public class MediaProjectionMetricsLoggerTest { /* targetType= */ anyInt(), /* hostUid= */ anyInt(), eq(targetUid), - /* targetWindowingMode= */ anyInt()); + /* targetWindowingMode= */ anyInt(), + /* width= */ anyInt(), + /* height= */ anyInt(), + /* centerX= */ anyInt(), + /* centerY= */ anyInt(), + /* targetChangeType= */ anyInt()); } private void verifyWindowingModeLogged(int targetWindowingMode) { @@ -770,6 +908,11 @@ public class MediaProjectionMetricsLoggerTest { /* targetType= */ anyInt(), /* hostUid= */ anyInt(), /* targetUid= */ anyInt(), - eq(targetWindowingMode)); + eq(targetWindowingMode), + /* width= */ anyInt(), + /* height= */ anyInt(), + /* centerX= */ anyInt(), + /* centerY= */ anyInt(), + /* targetChangeType= */ anyInt()); } } diff --git a/services/tests/uiservicestests/src/com/android/server/notification/SystemZenRulesTest.java b/services/tests/uiservicestests/src/com/android/server/notification/SystemZenRulesTest.java index 4d82c3ccf4a1..949c5e2e1b0a 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/SystemZenRulesTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/SystemZenRulesTest.java @@ -69,6 +69,8 @@ public class SystemZenRulesTest extends UiServiceTestCase { R.string.zen_mode_trigger_summary_range_symbol_combination, "%1$s-%2$s"); mContext.getOrCreateTestableResources().addOverride( R.string.zen_mode_trigger_summary_divider_text, ","); + mContext.getOrCreateTestableResources().addOverride( + R.string.zen_mode_trigger_summary_combined, "%1$s,%2$s"); } @Test diff --git a/services/tests/wmtests/src/com/android/server/wm/ContentRecorderTests.java b/services/tests/wmtests/src/com/android/server/wm/ContentRecorderTests.java index c51261f40ed5..76b994d013f3 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ContentRecorderTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ContentRecorderTests.java @@ -49,6 +49,7 @@ import android.content.pm.ActivityInfo; import android.content.res.Configuration; import android.graphics.Point; import android.graphics.Rect; +import android.media.projection.StopReason; import android.os.IBinder; import android.platform.test.annotations.Presubmit; import android.view.ContentRecordingSession; @@ -213,7 +214,7 @@ public class ContentRecorderTests extends WindowTestsBase { mContentRecorder.setContentRecordingSession(session); mContentRecorder.updateRecording(); assertThat(mContentRecorder.isCurrentlyRecording()).isFalse(); - verify(mMediaProjectionManagerWrapper).stopActiveProjection(); + verify(mMediaProjectionManagerWrapper).stopActiveProjection(StopReason.STOP_ERROR); } @Test @@ -225,7 +226,7 @@ public class ContentRecorderTests extends WindowTestsBase { mContentRecorder.setContentRecordingSession(invalidTaskSession); mContentRecorder.updateRecording(); assertThat(mContentRecorder.isCurrentlyRecording()).isFalse(); - verify(mMediaProjectionManagerWrapper).stopActiveProjection(); + verify(mMediaProjectionManagerWrapper).stopActiveProjection(StopReason.STOP_ERROR); } @Test @@ -310,8 +311,7 @@ public class ContentRecorderTests extends WindowTestsBase { mVirtualDisplayContent.getConfiguration().orientation, WINDOWING_MODE_FULLSCREEN); // No resize is issued, only the initial transformations when we started recording. - verify(mTransaction).setPosition(eq(mRecordedSurface), anyFloat(), - anyFloat()); + verify(mTransaction).setPosition(eq(mRecordedSurface), anyFloat(), anyFloat()); verify(mTransaction).setMatrix(eq(mRecordedSurface), anyFloat(), anyFloat(), anyFloat(), anyFloat()); } @@ -386,19 +386,18 @@ public class ContentRecorderTests extends WindowTestsBase { // WHEN a configuration change arrives, and the recorded content is a different size. Configuration configuration = mTask.getConfiguration(); - configuration.windowConfiguration.setBounds(new Rect(0, 0, recordedWidth, recordedHeight)); - configuration.windowConfiguration.setAppBounds( - new Rect(0, 0, recordedWidth, recordedHeight)); + Rect newBounds = new Rect(0, 0, recordedWidth, recordedHeight); + configuration.windowConfiguration.setBounds(newBounds); + configuration.windowConfiguration.setAppBounds(newBounds); mTask.onConfigurationChanged(configuration); assertThat(mContentRecorder.isCurrentlyRecording()).isTrue(); // THEN content in the captured DisplayArea is scaled to fit the surface size. - verify(mTransaction, atLeastOnce()).setMatrix(eq(mRecordedSurface), anyFloat(), eq(0f), - eq(0f), - anyFloat()); + verify(mTransaction, atLeastOnce()).setMatrix( + eq(mRecordedSurface), anyFloat(), eq(0f), eq(0f), anyFloat()); // THEN the resize callback is notified. - verify(mMediaProjectionManagerWrapper).notifyActiveProjectionCapturedContentResized( - recordedWidth, recordedHeight); + verify(mMediaProjectionManagerWrapper).notifyCaptureBoundsChanged( + mTaskSession.getContentToRecord(), mTaskSession.getTargetUid(), newBounds); } @Test @@ -649,7 +648,7 @@ public class ContentRecorderTests extends WindowTestsBase { mTask.removeImmediately(); - verify(mMediaProjectionManagerWrapper).stopActiveProjection(); + verify(mMediaProjectionManagerWrapper).stopActiveProjection(StopReason.STOP_TARGET_REMOVED); } @Test @@ -684,8 +683,8 @@ public class ContentRecorderTests extends WindowTestsBase { int xInset = (mSurfaceSize.x - scaledWidth) / 2; verify(mTransaction, atLeastOnce()).setPosition(mRecordedSurface, xInset, 0); // THEN the resize callback is notified. - verify(mMediaProjectionManagerWrapper).notifyActiveProjectionCapturedContentResized( - displayAreaBounds.width(), displayAreaBounds.height()); + verify(mMediaProjectionManagerWrapper).notifyCaptureBoundsChanged( + mDisplaySession.getContentToRecord(), mDisplaySession.getTargetUid(), displayAreaBounds); } @Test diff --git a/services/tests/wmtests/src/com/android/server/wm/DeferredDisplayUpdaterDiffTest.java b/services/tests/wmtests/src/com/android/server/wm/DeferredDisplayUpdaterDiffTest.java index c9c31dfe5307..a0f4ae77452c 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DeferredDisplayUpdaterDiffTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/DeferredDisplayUpdaterDiffTest.java @@ -239,6 +239,9 @@ public class DeferredDisplayUpdaterDiffTest { } else if (type.equals(FrameRateCategoryRate.class)) { field.set(first, new FrameRateCategoryRate(16666667, 11111111)); field.set(second, new FrameRateCategoryRate(11111111, 8333333)); + } else if (type.isArray() && type.getComponentType().equals(float.class)) { + field.set(first, new float[]{60.0f}); + field.set(second, new float[]{120.0f}); } else { throw new IllegalArgumentException("Field " + field + " is not supported by this test, please add implementation of setting " diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayRotationImmersiveAppCompatPolicyTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayRotationImmersiveAppCompatPolicyTests.java index c8fc4822259e..63973345b5fb 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayRotationImmersiveAppCompatPolicyTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayRotationImmersiveAppCompatPolicyTests.java @@ -20,16 +20,19 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM; import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW; import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; +import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; import static android.content.res.Configuration.ORIENTATION_LANDSCAPE; import static android.content.res.Configuration.ORIENTATION_PORTRAIT; import static android.content.res.Configuration.ORIENTATION_UNDEFINED; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock; +import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; import static com.android.dx.mockito.inline.extended.ExtendedMockito.when; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.verify; import android.platform.test.annotations.Presubmit; import android.view.Surface; @@ -54,6 +57,7 @@ public class DisplayRotationImmersiveAppCompatPolicyTests extends WindowTestsBas private DisplayRotationImmersiveAppCompatPolicy mPolicy; + private DisplayRotation mMockDisplayRotation; private AppCompatConfiguration mMockAppCompatConfiguration; private ActivityRecord mMockActivityRecord; private Task mMockTask; @@ -98,6 +102,7 @@ public class DisplayRotationImmersiveAppCompatPolicyTests extends WindowTestsBas when(mockDisplayRotation.isLandscapeOrSeascape(Surface.ROTATION_90)).thenReturn(true); when(mockDisplayRotation.isLandscapeOrSeascape(Surface.ROTATION_180)).thenReturn(false); when(mockDisplayRotation.isLandscapeOrSeascape(Surface.ROTATION_270)).thenReturn(true); + mMockDisplayRotation = mockDisplayRotation; return mockDisplayRotation; } @@ -196,6 +201,24 @@ public class DisplayRotationImmersiveAppCompatPolicyTests extends WindowTestsBas } @Test + public void testDeferOrientationUpdate() { + assertFalse(mPolicy.deferOrientationUpdate()); + + doReturn(SCREEN_ORIENTATION_UNSPECIFIED).when(mMockDisplayRotation).getLastOrientation(); + final WindowOrientationListener orientationListener = mock(WindowOrientationListener.class); + doReturn(Surface.ROTATION_90).when(orientationListener).getProposedRotation(); + doReturn(orientationListener).when(mMockDisplayRotation).getOrientationListener(); + spyOn(mDisplayContent.mTransitionController); + doReturn(true).when(mDisplayContent.mTransitionController) + .hasTransientLaunch(mDisplayContent); + + assertTrue(mPolicy.deferOrientationUpdate()); + mDisplayContent.mTransitionController.mStateValidators.getFirst().run(); + + verify(mWm).updateRotation(false, false); + } + + @Test public void testRotationChoiceEnforcedOnly_nullTopRunningActivity_lockNotEnforced() { when(mDisplayContent.topRunningActivity()).thenReturn(null); diff --git a/services/tests/wmtests/src/com/android/server/wm/FrameRateSelectionPriorityTests.java b/services/tests/wmtests/src/com/android/server/wm/FrameRateSelectionPriorityTests.java index a0c5b54603f9..c016c5ead23c 100644 --- a/services/tests/wmtests/src/com/android/server/wm/FrameRateSelectionPriorityTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/FrameRateSelectionPriorityTests.java @@ -69,7 +69,9 @@ public class FrameRateSelectionPriorityTests extends WindowTestsBase { private static final FrameRateVote FRAME_RATE_VOTE_60_PREFERRED = new FrameRateVote(60, Surface.FRAME_RATE_COMPATIBILITY_DEFAULT, SurfaceControl.FRAME_RATE_SELECTION_STRATEGY_OVERRIDE_CHILDREN); - + private static final float HI_REFRESH_RATE = 90; + private static final float MID_REFRESH_RATE = 70; + private static final float LOW_REFRESH_RATE = 60; WindowState createWindow(String name) { WindowState window = createWindow(null, TYPE_APPLICATION, name); when(window.mWmService.mDisplayManagerInternal.getRefreshRateSwitchingType()) @@ -82,14 +84,16 @@ public class FrameRateSelectionPriorityTests extends WindowTestsBase { DisplayInfo di = new DisplayInfo(mDisplayInfo); Mode defaultMode = di.getDefaultMode(); Mode hiMode = new Mode(1, - defaultMode.getPhysicalWidth(), defaultMode.getPhysicalHeight(), 90); + defaultMode.getPhysicalWidth(), defaultMode.getPhysicalHeight(), HI_REFRESH_RATE); Mode midMode = new Mode(2, - defaultMode.getPhysicalWidth(), defaultMode.getPhysicalHeight(), 70); + defaultMode.getPhysicalWidth(), defaultMode.getPhysicalHeight(), MID_REFRESH_RATE); Mode lowMode = new Mode(LOW_MODE_ID, - defaultMode.getPhysicalWidth(), defaultMode.getPhysicalHeight(), 60); + defaultMode.getPhysicalWidth(), defaultMode.getPhysicalHeight(), LOW_REFRESH_RATE); di.supportedModes = new Mode[] { hiMode, midMode }; di.appsSupportedModes = new Mode[] { hiMode, midMode, lowMode }; + di.supportedRefreshRates = new float[] {HI_REFRESH_RATE, MID_REFRESH_RATE, + LOW_REFRESH_RATE}; di.defaultModeId = 1; mRefreshRatePolicy = new RefreshRatePolicy(mWm, di, mDenylist); when(mDisplayPolicy.getRefreshRatePolicy()).thenReturn(mRefreshRatePolicy); diff --git a/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java b/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java index 7ed8283efffd..aa992504f9a5 100644 --- a/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java @@ -434,6 +434,7 @@ public class RecentTasksTest extends WindowTestsBase { @Test public void testAddTaskCompatibleWindowingMode_withFreeformAndFullscreen_expectRemove() { Task task1 = createTaskBuilder(".Task1") + .setTaskId(1) .setFlags(FLAG_ACTIVITY_NEW_TASK) .build(); doReturn(WINDOWING_MODE_FREEFORM).when(task1).getWindowingMode(); @@ -452,6 +453,10 @@ public class RecentTasksTest extends WindowTestsBase { assertThat(mCallbacksRecorder.mTrimmed).isEmpty(); assertThat(mCallbacksRecorder.mRemoved).hasSize(1); assertThat(mCallbacksRecorder.mRemoved).contains(task1); + + TaskChangeNotificationController controller = + mAtm.getTaskChangeNotificationController(); + verify(controller, times(1)).notifyRecentTaskRemovedForAddTask(task1.mTaskId); } @Test diff --git a/services/tests/wmtests/src/com/android/server/wm/RefreshRatePolicyTest.java b/services/tests/wmtests/src/com/android/server/wm/RefreshRatePolicyTest.java index cc38f02ccc4c..73e5f58fa7e0 100644 --- a/services/tests/wmtests/src/com/android/server/wm/RefreshRatePolicyTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/RefreshRatePolicyTest.java @@ -101,6 +101,8 @@ public class RefreshRatePolicyTest extends WindowTestsBase { defaultMode.getPhysicalWidth(), defaultMode.getPhysicalHeight(), LOW_REFRESH_RATE); mDisplayInfo.supportedModes = new Mode[] { hiMode, midMode }; mDisplayInfo.appsSupportedModes = new Mode[] { hiMode, midMode, lowMode }; + mDisplayInfo.supportedRefreshRates = new float[] {HI_REFRESH_RATE, MID_REFRESH_RATE, + LOW_REFRESH_RATE}; mDisplayInfo.defaultModeId = HI_MODE_ID; mPolicy = new RefreshRatePolicy(mWm, mDisplayInfo, mDenylist); } diff --git a/services/tests/wmtests/src/com/android/server/wm/SafeActivityOptionsTest.java b/services/tests/wmtests/src/com/android/server/wm/SafeActivityOptionsTest.java index 791b5b59535a..a92fe3afbd78 100644 --- a/services/tests/wmtests/src/com/android/server/wm/SafeActivityOptionsTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/SafeActivityOptionsTest.java @@ -162,6 +162,10 @@ public class SafeActivityOptionsTest { verifySecureExceptionThrown(activityOptions, taskSupervisor); activityOptions = ActivityOptions.makeBasic(); + activityOptions.setTaskAlwaysOnTop(true); + verifySecureExceptionThrown(activityOptions, taskSupervisor); + + activityOptions = ActivityOptions.makeBasic(); activityOptions.setLaunchDisplayId(DEFAULT_DISPLAY); verifySecureExceptionThrown(activityOptions, taskSupervisor); diff --git a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java index ad6611827524..4fbe492ea7fb 100644 --- a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java @@ -4928,6 +4928,7 @@ public class SizeCompatTests extends WindowTestsBase { spyOn(pm); final PackageManager.Property property = new PackageManager.Property("propertyName", true /* value */, name.getPackageName(), name.getClassName()); + // Activity level. try { doReturn(property).when(pm).getPropertyAsUser( WindowManager.PROPERTY_COMPAT_ALLOW_RESTRICTED_RESIZABILITY, @@ -4938,6 +4939,19 @@ public class SizeCompatTests extends WindowTestsBase { final ActivityRecord optOutActivity = new ActivityBuilder(mAtm) .setComponent(name).setTask(mTask).build(); assertFalse(optOutActivity.isUniversalResizeable()); + + // Application level. + try { + doReturn(property).when(pm).getProperty( + WindowManager.PROPERTY_COMPAT_ALLOW_RESTRICTED_RESIZABILITY, + name.getPackageName()); + } catch (PackageManager.NameNotFoundException e) { + throw new RuntimeException(e); + } + final ActivityRecord optOutAppActivity = new ActivityBuilder(mAtm) + .setComponent(getUniqueComponentName(mContext.getPackageName())) + .setTask(mTask).build(); + assertFalse(optOutAppActivity.isUniversalResizeable()); } diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java index e22d75e4dfe3..ad5d42ad5a68 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -19599,4 +19599,37 @@ public class TelephonyManager { throw ex.rethrowAsRuntimeException(); } } + + /** + * Returns carrier id maps to the passing CarrierIdentifier. + * To recognize a carrier (including MVNO) as a first-class identity, + * Android assigns each carrier with a canonical integer a.k.a. carrier id. + * The carrier ID is an Android platform-wide identifier for a carrier. + * AOSP maintains carrier ID assignments in + * <a href="https://android.googlesource.com/platform/packages/providers/TelephonyProvider/+/master/assets/latest_carrier_id/carrier_list.textpb">here</a> + * + * @param carrierIdentifier {@link CarrierIdentifier} + * + * @return Carrier id. Return {@link #UNKNOWN_CARRIER_ID} if the carrier cannot be identified. + * @throws UnsupportedOperationException If the device does not have + * {@link PackageManager#FEATURE_TELEPHONY_SUBSCRIPTION}. + * + * @hide + */ + @FlaggedApi(Flags.FLAG_CARRIER_ID_FROM_CARRIER_IDENTIFIER) + @SystemApi + @WorkerThread + @RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION) + @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) + public int getCarrierIdFromCarrierIdentifier(@NonNull CarrierIdentifier carrierIdentifier) { + try { + ITelephony service = getITelephony(); + if (service != null) { + return service.getCarrierIdFromIdentifier(carrierIdentifier); + } + } catch (RemoteException ex) { + // This could happen if binder process crashes. + } + return UNKNOWN_CARRIER_ID; + } } diff --git a/telephony/java/android/telephony/satellite/SatelliteManager.java b/telephony/java/android/telephony/satellite/SatelliteManager.java index 23203ed65e9a..bf103d52d0bf 100644 --- a/telephony/java/android/telephony/satellite/SatelliteManager.java +++ b/telephony/java/android/telephony/satellite/SatelliteManager.java @@ -746,7 +746,7 @@ public final class SatelliteManager { * @hide */ public static final String ACTION_SATELLITE_SUBSCRIBER_ID_LIST_CHANGED = - "android.telephony.action.ACTION_SATELLITE_SUBSCRIBER_ID_LIST_CHANGED"; + "android.telephony.satellite.action.SATELLITE_SUBSCRIBER_ID_LIST_CHANGED"; /** @@ -757,7 +757,7 @@ public final class SatelliteManager { * @hide */ public static final String ACTION_SATELLITE_START_NON_EMERGENCY_SESSION = - "android.telephony.action.ACTION_SATELLITE_START_NON_EMERGENCY_SESSION"; + "android.telephony.satellite.action.SATELLITE_START_NON_EMERGENCY_SESSION"; /** * Meta-data represents whether the application supports P2P SMS over carrier roaming satellite * which needs manual trigger to connect to satellite. The messaging applications that supports diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl index d22e9fa20101..294c93c8e493 100644 --- a/telephony/java/com/android/internal/telephony/ITelephony.aidl +++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl @@ -3519,4 +3519,15 @@ interface ITelephony { * @hide */ void setNtnSmsSupported(boolean ntnSmsSupported); + + /** + * Returns carrier id maps to the passing {@link CarrierIdentifier}. + * + * @param {@link CarrierIdentifier}. + * + * @return carrier id from passing {@link CarrierIdentifier} or {@link #UNKNOWN_CARRIER_ID} + * if the carrier cannot be identified + * @hide + */ + int getCarrierIdFromIdentifier(in CarrierIdentifier carrierIdentifier); } diff --git a/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/DesktopModeAppHelper.kt b/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/DesktopModeAppHelper.kt index 64328275085d..e0900a64c52f 100644 --- a/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/DesktopModeAppHelper.kt +++ b/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/DesktopModeAppHelper.kt @@ -23,6 +23,7 @@ import android.graphics.Rect import android.graphics.Region import android.os.SystemClock import android.platform.uiautomatorhelpers.DeviceHelpers +import android.tools.PlatformConsts import android.tools.device.apphelpers.IStandardAppHelper import android.tools.helpers.SYSTEMUI_PACKAGE import android.tools.traces.parsers.WindowManagerStateHelper @@ -163,7 +164,10 @@ open class DesktopModeAppHelper(private val innerHelper: IStandardAppHelper) : .StateSyncBuilder() .withAppTransitionIdle() .apply { - if (isPip) withPipShown() else withWindowSurfaceDisappeared(innerHelper) + if (isPip) withPipShown() + else + withWindowSurfaceDisappeared(innerHelper) + .withActivityState(innerHelper, PlatformConsts.STATE_STOPPED) } .waitForAndVerify() } diff --git a/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/PipAppHelper.kt b/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/PipAppHelper.kt index 931e4f88aa8d..db4838ee6092 100644 --- a/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/PipAppHelper.kt +++ b/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/PipAppHelper.kt @@ -250,18 +250,13 @@ open class PipAppHelper(instrumentation: Instrumentation) : wmHelper, launchedAppComponentMatcherOverride, action, - stringExtras, - waitConditionsBuilder = - wmHelper - .StateSyncBuilder() - .add(ConditionsFactory.isWMStateComplete()) - .withAppTransitionIdle() - .add(ConditionsFactory.hasPipWindow()) + stringExtras ) wmHelper .StateSyncBuilder() .withWindowSurfaceAppeared(this) + .add(ConditionsFactory.isWMStateComplete()) .withPipShown() .waitForAndVerify() } diff --git a/tests/PackageWatchdog/src/com/android/server/CrashRecoveryTest.java b/tests/PackageWatchdog/src/com/android/server/CrashRecoveryTest.java index fe974e3da3be..af87bf724a30 100644 --- a/tests/PackageWatchdog/src/com/android/server/CrashRecoveryTest.java +++ b/tests/PackageWatchdog/src/com/android/server/CrashRecoveryTest.java @@ -1014,7 +1014,7 @@ public class CrashRecoveryTest { triggerFailureCount = 1; } for (int i = 0; i < triggerFailureCount; i++) { - watchdog.onPackageFailure(packages, failureReason); + watchdog.notifyPackageFailure(packages, failureReason); } mTestLooper.dispatchAll(); if (Flags.recoverabilityDetection()) { diff --git a/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java b/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java index c25bed21a602..5a8a6bedf9eb 100644 --- a/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java +++ b/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java @@ -392,7 +392,7 @@ public class PackageWatchdogTest { // Then fail APP_A below the threshold for (int i = 0; i < watchdog.getTriggerFailureCount() - 1; i++) { - watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)), + watchdog.notifyPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)), PackageWatchdog.FAILURE_REASON_UNKNOWN); } @@ -1025,14 +1025,14 @@ public class PackageWatchdogTest { watchdog.startObservingHealth(observer, Arrays.asList(APP_A), SHORT_DURATION); // Fail APP_A below the threshold which should not trigger package failures for (int i = 0; i < PackageWatchdog.DEFAULT_TRIGGER_FAILURE_COUNT - 1; i++) { - watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)), + watchdog.notifyPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)), PackageWatchdog.FAILURE_REASON_UNKNOWN); } mTestLooper.dispatchAll(); assertThat(observer.mHealthCheckFailedPackages).isEmpty(); // One more to trigger the package failure - watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)), + watchdog.notifyPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)), PackageWatchdog.FAILURE_REASON_UNKNOWN); mTestLooper.dispatchAll(); assertThat(observer.mHealthCheckFailedPackages).containsExactly(APP_A); @@ -1051,10 +1051,10 @@ public class PackageWatchdogTest { TestObserver observer = new TestObserver(OBSERVER_NAME_1); watchdog.startObservingHealth(observer, Arrays.asList(APP_A, APP_B), Long.MAX_VALUE); - watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)), + watchdog.notifyPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)), PackageWatchdog.FAILURE_REASON_UNKNOWN); moveTimeForwardAndDispatch(PackageWatchdog.DEFAULT_TRIGGER_FAILURE_DURATION_MS + 1); - watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)), + watchdog.notifyPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)), PackageWatchdog.FAILURE_REASON_UNKNOWN); mTestLooper.dispatchAll(); @@ -1062,10 +1062,10 @@ public class PackageWatchdogTest { // DEFAULT_TRIGGER_FAILURE_DURATION_MS. assertThat(observer.mHealthCheckFailedPackages).isEmpty(); - watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_B, VERSION_CODE)), + watchdog.notifyPackageFailure(Arrays.asList(new VersionedPackage(APP_B, VERSION_CODE)), PackageWatchdog.FAILURE_REASON_UNKNOWN); moveTimeForwardAndDispatch(PackageWatchdog.DEFAULT_TRIGGER_FAILURE_DURATION_MS - 1); - watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_B, VERSION_CODE)), + watchdog.notifyPackageFailure(Arrays.asList(new VersionedPackage(APP_B, VERSION_CODE)), PackageWatchdog.FAILURE_REASON_UNKNOWN); mTestLooper.dispatchAll(); @@ -1129,17 +1129,17 @@ public class PackageWatchdogTest { watchdog.startObservingHealth(observer, Arrays.asList(APP_A), Long.MAX_VALUE); // Raise 2 failures at t=0 and t=900 respectively - watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)), + watchdog.notifyPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)), PackageWatchdog.FAILURE_REASON_UNKNOWN); moveTimeForwardAndDispatch(900); - watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)), + watchdog.notifyPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)), PackageWatchdog.FAILURE_REASON_UNKNOWN); // Raise 2 failures at t=1100 moveTimeForwardAndDispatch(200); - watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)), + watchdog.notifyPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)), PackageWatchdog.FAILURE_REASON_UNKNOWN); - watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)), + watchdog.notifyPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)), PackageWatchdog.FAILURE_REASON_UNKNOWN); mTestLooper.dispatchAll(); @@ -1433,13 +1433,13 @@ public class PackageWatchdogTest { TestObserver observer = new TestObserver(OBSERVER_NAME_1); watchdog.startObservingHealth(observer, List.of(APP_A), SHORT_DURATION); for (int i = 0; i < PackageWatchdog.DEFAULT_TRIGGER_FAILURE_COUNT - 1; i++) { - watchdog.onPackageFailure(List.of(new VersionedPackage(APP_A, VERSION_CODE)), + watchdog.notifyPackageFailure(List.of(new VersionedPackage(APP_A, VERSION_CODE)), PackageWatchdog.FAILURE_REASON_UNKNOWN); } mTestLooper.dispatchAll(); assertThat(observer.mMitigatedPackages).isEmpty(); watchdog.startObservingHealth(observer, List.of(APP_A), LONG_DURATION); - watchdog.onPackageFailure(List.of(new VersionedPackage(APP_A, VERSION_CODE)), + watchdog.notifyPackageFailure(List.of(new VersionedPackage(APP_A, VERSION_CODE)), PackageWatchdog.FAILURE_REASON_UNKNOWN); mTestLooper.dispatchAll(); assertThat(observer.mMitigatedPackages).isEqualTo(List.of(APP_A)); @@ -1737,7 +1737,7 @@ public class PackageWatchdogTest { triggerFailureCount = 1; } for (int i = 0; i < triggerFailureCount; i++) { - watchdog.onPackageFailure(packages, failureReason); + watchdog.notifyPackageFailure(packages, failureReason); } mTestLooper.dispatchAll(); if (Flags.recoverabilityDetection()) { diff --git a/tools/aapt2/util/Util.h b/tools/aapt2/util/Util.h index 40ff5b633d97..03da460affb5 100644 --- a/tools/aapt2/util/Util.h +++ b/tools/aapt2/util/Util.h @@ -111,8 +111,8 @@ const char* GetToolName(); // Retrieves the build fingerprint of aapt2. std::string GetToolFingerprint(); -template <typename T> -typename std::enable_if<std::is_arithmetic<T>::value, int>::type compare(const T& a, const T& b) { +template <std::integral T> +int compare(T a, T b) { if (a < b) { return -1; } else if (a > b) { @@ -123,10 +123,7 @@ typename std::enable_if<std::is_arithmetic<T>::value, int>::type compare(const T // Makes a std::unique_ptr<> with the template parameter inferred by the compiler. // This will be present in C++14 and can be removed then. -template <typename T, class... Args> -std::unique_ptr<T> make_unique(Args&&... args) { - return std::unique_ptr<T>(new T{std::forward<Args>(args)...}); -} +using std::make_unique; // Writes a set of items to the std::ostream, joining the times with the provided separator. template <typename Container> diff --git a/tools/systemfeatures/Android.bp b/tools/systemfeatures/Android.bp index e6d0a3d4149f..2ebede39504e 100644 --- a/tools/systemfeatures/Android.bp +++ b/tools/systemfeatures/Android.bp @@ -13,6 +13,7 @@ java_library_host { srcs: [ "src/**/*.java", "src/**/*.kt", + ":framework-metalava-annotations", ], static_libs: [ "guava", @@ -26,6 +27,12 @@ java_binary_host { static_libs: ["systemfeatures-gen-lib"], } +java_plugin { + name: "systemfeatures-metadata-processor", + processor_class: "com.android.systemfeatures.SystemFeaturesMetadataProcessor", + static_libs: ["systemfeatures-gen-lib"], +} + genrule { name: "systemfeatures-gen-tests-srcs", cmd: "$(location systemfeatures-gen-tool) com.android.systemfeatures.RwNoFeatures --readonly=false > $(location RwNoFeatures.java) && " + @@ -61,6 +68,7 @@ java_test_host { "systemfeatures-gen-lib", "truth", ], + plugins: ["systemfeatures-metadata-processor"], } // Rename the goldens as they may be copied into the source tree, and we don't diff --git a/tools/systemfeatures/src/com/android/systemfeatures/SystemFeaturesMetadataProcessor.kt b/tools/systemfeatures/src/com/android/systemfeatures/SystemFeaturesMetadataProcessor.kt new file mode 100644 index 000000000000..100d869a663f --- /dev/null +++ b/tools/systemfeatures/src/com/android/systemfeatures/SystemFeaturesMetadataProcessor.kt @@ -0,0 +1,110 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemfeatures + +import android.annotation.SdkConstant +import com.squareup.javapoet.FieldSpec +import com.squareup.javapoet.JavaFile +import com.squareup.javapoet.TypeSpec +import java.io.IOException +import javax.annotation.processing.AbstractProcessor +import javax.annotation.processing.ProcessingEnvironment +import javax.annotation.processing.RoundEnvironment +import javax.lang.model.SourceVersion +import javax.lang.model.element.Modifier +import javax.lang.model.element.TypeElement +import javax.tools.Diagnostic + +/* + * Simple Java code generator for computing metadata for system features. + * + * <p>The output is a single class file, `com.android.internal.pm.SystemFeaturesMetadata`, with + * properties computed from feature constant definitions in the PackageManager class. This + * class is only produced if the processed environment includes PackageManager; all other + * invocations are ignored. + */ +class SystemFeaturesMetadataProcessor : AbstractProcessor() { + + private lateinit var packageManagerType: TypeElement + + override fun getSupportedSourceVersion(): SourceVersion = SourceVersion.latestSupported() + + override fun getSupportedAnnotationTypes() = setOf(SDK_CONSTANT_ANNOTATION_NAME) + + override fun init(processingEnv: ProcessingEnvironment) { + super.init(processingEnv) + packageManagerType = + processingEnv.elementUtils.getTypeElement("android.content.pm.PackageManager")!! + } + + override fun process(annotations: Set<TypeElement>, roundEnv: RoundEnvironment): Boolean { + if (roundEnv.processingOver()) { + return false + } + + // We're only interested in feature constants defined in PackageManager. + var featureCount = 0 + roundEnv.getElementsAnnotatedWith(SdkConstant::class.java).forEach { + if ( + it.enclosingElement == packageManagerType && + it.getAnnotation(SdkConstant::class.java).value == + SdkConstant.SdkConstantType.FEATURE + ) { + featureCount++ + } + } + + if (featureCount == 0) { + // This is fine, and happens for any environment that doesn't include PackageManager. + return false + } + + val systemFeatureMetadata = + TypeSpec.classBuilder("SystemFeaturesMetadata") + .addModifiers(Modifier.PUBLIC, Modifier.FINAL) + .addJavadoc("@hide") + .addField( + FieldSpec.builder(Int::class.java, "SDK_FEATURE_COUNT") + .addModifiers(Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL) + .addJavadoc( + "The number of `@SdkConstant` features defined in PackageManager." + ) + .addJavadoc("@hide") + .initializer("\$L", featureCount) + .build() + ) + .build() + + try { + JavaFile.builder("com.android.internal.pm", systemFeatureMetadata) + .skipJavaLangImports(true) + .build() + .writeTo(processingEnv.filer) + } catch (e: IOException) { + processingEnv.messager.printMessage( + Diagnostic.Kind.ERROR, + "Failed to write file: ${e.message}", + ) + } + + return true + } + + companion object { + private val SDK_CONSTANT_ANNOTATION_NAME = SdkConstant::class.qualifiedName + } +} diff --git a/tools/systemfeatures/tests/src/PackageManager.java b/tools/systemfeatures/tests/src/PackageManager.java index db670482065a..839a9377476d 100644 --- a/tools/systemfeatures/tests/src/PackageManager.java +++ b/tools/systemfeatures/tests/src/PackageManager.java @@ -16,14 +16,33 @@ package android.content.pm; +import android.annotation.SdkConstant; +import android.annotation.SdkConstant.SdkConstantType; + /** Stub for testing */ public class PackageManager { + @SdkConstant(SdkConstantType.FEATURE) public static final String FEATURE_AUTO = "automotive"; + + @SdkConstant(SdkConstantType.FEATURE) public static final String FEATURE_PC = "pc"; + + @SdkConstant(SdkConstantType.FEATURE) public static final String FEATURE_VULKAN = "vulkan"; + + @SdkConstant(SdkConstantType.FEATURE) public static final String FEATURE_WATCH = "watch"; + + @SdkConstant(SdkConstantType.FEATURE) public static final String FEATURE_WIFI = "wifi"; + @SdkConstant(SdkConstantType.INTENT_CATEGORY) + public static final String FEATURE_INTENT_CATEGORY = "intent_category_with_feature_name_prefix"; + + public static final String FEATURE_NOT_ANNOTATED = "not_annotated"; + + public static final String NOT_FEATURE = "not_feature"; + /** @hide */ public boolean hasSystemFeature(String featureName, int version) { return false; diff --git a/tools/systemfeatures/tests/src/SystemFeaturesMetadataProcessorTest.java b/tools/systemfeatures/tests/src/SystemFeaturesMetadataProcessorTest.java new file mode 100644 index 000000000000..4ffb5b979d75 --- /dev/null +++ b/tools/systemfeatures/tests/src/SystemFeaturesMetadataProcessorTest.java @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemfeatures; + +import static com.google.common.truth.Truth.assertThat; + +import com.android.internal.pm.SystemFeaturesMetadata; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) +public class SystemFeaturesMetadataProcessorTest { + + @Test + public void testSdkFeatureCount() { + // See the fake PackageManager definition in this directory. + // It defines 5 annotated features, and any/all other constants should be ignored. + assertThat(SystemFeaturesMetadata.SDK_FEATURE_COUNT).isEqualTo(5); + } +} |