diff --git a/AconfigFlags.bp b/AconfigFlags.bp index e18470498f391d107dc07d113f2ef6ababc85dcf..7977d73599e8f618e5a6e880ba1d336aed18e070 100644 --- a/AconfigFlags.bp +++ b/AconfigFlags.bp @@ -23,7 +23,7 @@ aconfig_declarations_group { "aconfig_mediacodec_flags_java_lib", "aconfig_settingslib_flags_java_lib", "aconfig_trade_in_mode_flags_java_lib", - "android-sdk-flags-java", + "adpf_flags_java_lib", "android.adaptiveauth.flags-aconfig-java", "android.app.appfunctions.flags-aconfig-java", "android.app.assist.flags-aconfig-java", @@ -63,6 +63,7 @@ aconfig_declarations_group { "android.os.vibrator.flags-aconfig-java", "android.permission.flags-aconfig-java", "android.provider.flags-aconfig-java", + "android.sdk.flags-aconfig-java", "android.security.flags-aconfig-java", "android.server.app.flags-aconfig-java", "android.service.autofill.flags-aconfig-java", @@ -99,12 +100,14 @@ aconfig_declarations_group { "com.android.media.flags.editing-aconfig-java", "com.android.media.flags.performance-aconfig-java", "com.android.media.flags.projection-aconfig-java", + "com.android.net.http.flags-aconfig-exported-java", "com.android.net.thread.platform.flags-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", "com.android.window.flags.window-aconfig-java", + "conscrypt_exported_aconfig_flags_lib", "device_policy_aconfig_flags_lib", "display_flags_lib", "dropbox_flags_lib", @@ -194,6 +197,14 @@ java_aconfig_library { defaults: ["framework-minus-apex-aconfig-java-defaults"], } +// Conscrypt +java_aconfig_library { + name: "conscrypt_exported_aconfig_flags_lib", + aconfig_declarations: "conscrypt-aconfig-flags", + mode: "exported", + defaults: ["framework-minus-apex-aconfig-java-defaults"], +} + // Telecom java_aconfig_library { name: "telecom_flags_core_java_lib", @@ -328,6 +339,7 @@ cc_aconfig_library { name: "android_nfc_flags_aconfig_c_lib", vendor_available: true, aconfig_declarations: "android.nfc.flags-aconfig", + min_sdk_version: "34", apex_available: [ "//apex_available:platform", "com.android.nfcservices", @@ -437,6 +449,8 @@ java_aconfig_library { min_sdk_version: "30", apex_available: [ "//apex_available:platform", + "com.android.art", + "com.android.art.debug", "com.android.btservices", "com.android.mediaprovider", "com.android.permission", @@ -652,6 +666,8 @@ java_aconfig_library { min_sdk_version: "30", apex_available: [ "//apex_available:platform", + "com.android.art", + "com.android.art.debug", "com.android.permission", ], } @@ -871,6 +887,13 @@ java_aconfig_library { defaults: ["framework-minus-apex-aconfig-java-defaults"], } +// Adaptive Performance +java_aconfig_library { + name: "adpf_flags_java_lib", + aconfig_declarations: "adpf_flags", + defaults: ["framework-minus-apex-aconfig-java-defaults"], +} + // Graphics java_aconfig_library { name: "hwui_flags_java_lib", @@ -966,6 +989,13 @@ java_aconfig_library { defaults: ["framework-minus-apex-aconfig-java-defaults"], } +java_aconfig_library { + name: "android.app.flags-aconfig-java-host", + aconfig_declarations: "android.app.flags-aconfig", + host_supported: true, + defaults: ["framework-minus-apex-aconfig-java-defaults"], +} + // Broadcast Radio aconfig_declarations { name: "android.hardware.radio.flags-aconfig", diff --git a/Android.bp b/Android.bp index 424a4a71ce404a3fad3bd63989a996c44194b6a6..42028e010e8432de5a5b0e534034c5a958758f6b 100644 --- a/Android.bp +++ b/Android.bp @@ -83,7 +83,6 @@ filegroup { ":framework-telecomm-sources", ":framework-telephony-common-sources", ":framework-telephony-sources", - ":framework-vcn-util-sources", ":framework-wifi-annotations", ":framework-wifi-non-updatable-sources", ":PacProcessor-aidl-sources", @@ -313,7 +312,6 @@ java_defaults { ":framework-telecomm-sources", ":framework-telephony-common-sources", ":framework-telephony-sources", - ":framework-vcn-util-sources", ":framework-wifi-annotations", ":framework-wifi-non-updatable-sources", ":PacProcessor-aidl-sources", @@ -371,6 +369,7 @@ java_defaults { "view-inspector-annotation-processor", "staledataclass-annotation-processor", "error_prone_android_framework", + "systemfeatures-metadata-processor", ], // Exports needed for staledataclass-annotation-processor, see b/139342589. javacflags: [ @@ -597,7 +596,7 @@ filegroup { srcs: [ "core/java/com/android/internal/util/HexDump.java", "core/java/com/android/internal/util/WakeupMessage.java", - "services/core/java/com/android/server/vcn/util/PersistableBundleUtils.java", + "core/java/android/net/vcn/util/PersistableBundleUtils.java", "telephony/java/android/telephony/Annotation.java", ], } diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg index d748a3bebfef2740e8a29a8d6454a4246ab69e16..d83109a1a9866d8febaf497e7c34df9354dc3e95 100644 --- a/PREUPLOAD.cfg +++ b/PREUPLOAD.cfg @@ -18,7 +18,7 @@ clang_format = --commit ${PREUPLOAD_COMMIT} --style file --extensions c,h,cc,cpp tests/ tools/ bpfmt = -d -ktfmt = --kotlinlang-style --include-dirs=services/permission,packages/SystemUI,libs/WindowManager/Shell/src/com/android/wm/shell/freeform,libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/education +ktfmt = --kotlinlang-style --include-dirs=services/permission,packages/SystemUI,libs/WindowManager/Shell/src/com/android/wm/shell/freeform,libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode [Hook Scripts] checkstyle_hook = ${REPO_ROOT}/prebuilts/checkstyle/checkstyle.py --sha ${PREUPLOAD_COMMIT} diff --git a/android-sdk-flags/Android.bp b/android-sdk-flags/Android.bp index 79a0b9a4f27300eacf0819bc1b93a6c50e0c6430..d1df2ca69f50bf10333c132ecee2c5cd40870d56 100644 --- a/android-sdk-flags/Android.bp +++ b/android-sdk-flags/Android.bp @@ -17,14 +17,21 @@ package { } aconfig_declarations { - name: "android-sdk-flags", + name: "android.sdk.flags-aconfig", package: "android.sdk", container: "system", srcs: ["flags.aconfig"], } java_aconfig_library { - name: "android-sdk-flags-java", - aconfig_declarations: "android-sdk-flags", + name: "android.sdk.flags-aconfig-java", + aconfig_declarations: "android.sdk.flags-aconfig", + defaults: ["framework-minus-apex-aconfig-java-defaults"], +} + +java_aconfig_library { + name: "android.sdk.flags-aconfig-java-host", + aconfig_declarations: "android.sdk.flags-aconfig", + host_supported: true, defaults: ["framework-minus-apex-aconfig-java-defaults"], } diff --git a/apex/jobscheduler/framework/aconfig/job.aconfig b/apex/jobscheduler/framework/aconfig/job.aconfig index 47a85498f51be84254a9450857b0f9b888ba06a3..63624d8cad4a03b4d22f9fc7cb07cad4780b8577 100644 --- a/apex/jobscheduler/framework/aconfig/job.aconfig +++ b/apex/jobscheduler/framework/aconfig/job.aconfig @@ -29,6 +29,7 @@ flag { namespace: "backstage_power" description: "Detect, report and take action on jobs that maybe abandoned by the app without calling jobFinished." bug: "372529068" + is_exported: true } flag { @@ -36,6 +37,7 @@ flag { namespace: "backstage_power" description: "Ignore the important_while_foreground flag and change the related APIs to be not effective" bug: "374175032" + is_exported: true } flag { diff --git a/core/api/current.txt b/core/api/current.txt index af7d6f1a5da1a8d514b3a930b6c04f782d805824..d9338a5798299d2d63aa0fec181ab3af956518b1 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -1203,6 +1203,7 @@ package android { field public static final int minResizeHeight = 16843670; // 0x1010396 field public static final int minResizeWidth = 16843669; // 0x1010395 field public static final int minSdkVersion = 16843276; // 0x101020c + field @FlaggedApi("android.sdk.major_minor_versioning_scheme") public static final int minSdkVersionFull; field public static final int minWidth = 16843071; // 0x101013f field public static final int minimumHorizontalAngle = 16843901; // 0x101047d field public static final int minimumVerticalAngle = 16843902; // 0x101047e @@ -2186,6 +2187,18 @@ package android { public static final class R.dimen { ctor public R.dimen(); field public static final int app_icon_size = 17104896; // 0x1050000 + field @FlaggedApi("android.os.material_motion_tokens") public static final int config_motionExpressiveDefaultEffectDamping; + field @FlaggedApi("android.os.material_motion_tokens") public static final int config_motionExpressiveDefaultSpatialDamping; + field @FlaggedApi("android.os.material_motion_tokens") public static final int config_motionExpressiveFastEffectDamping; + field @FlaggedApi("android.os.material_motion_tokens") public static final int config_motionExpressiveFastSpatialDamping; + field @FlaggedApi("android.os.material_motion_tokens") public static final int config_motionExpressiveSlowEffectDamping; + field @FlaggedApi("android.os.material_motion_tokens") public static final int config_motionExpressiveSlowSpatialDamping; + field @FlaggedApi("android.os.material_motion_tokens") public static final int config_motionStandardDefaultEffectDamping; + field @FlaggedApi("android.os.material_motion_tokens") public static final int config_motionStandardDefaultSpatialDamping; + field @FlaggedApi("android.os.material_motion_tokens") public static final int config_motionStandardFastEffectDamping; + field @FlaggedApi("android.os.material_motion_tokens") public static final int config_motionStandardFastSpatialDamping; + field @FlaggedApi("android.os.material_motion_tokens") public static final int config_motionStandardSlowEffectDamping; + field @FlaggedApi("android.os.material_motion_tokens") public static final int config_motionStandardSlowSpatialDamping; field public static final int dialog_min_width_major = 17104899; // 0x1050003 field public static final int dialog_min_width_minor = 17104900; // 0x1050004 field public static final int notification_large_icon_height = 17104902; // 0x1050006 @@ -2482,6 +2495,18 @@ package android { ctor public R.integer(); field public static final int config_longAnimTime = 17694722; // 0x10e0002 field public static final int config_mediumAnimTime = 17694721; // 0x10e0001 + field @FlaggedApi("android.os.material_motion_tokens") public static final int config_motionExpressiveDefaultEffectStiffness; + field @FlaggedApi("android.os.material_motion_tokens") public static final int config_motionExpressiveDefaultSpatialStiffness; + field @FlaggedApi("android.os.material_motion_tokens") public static final int config_motionExpressiveFastEffectStiffness; + field @FlaggedApi("android.os.material_motion_tokens") public static final int config_motionExpressiveFastSpatialStiffness; + field @FlaggedApi("android.os.material_motion_tokens") public static final int config_motionExpressiveSlowEffectStiffness; + field @FlaggedApi("android.os.material_motion_tokens") public static final int config_motionExpressiveSlowSpatialStiffness; + field @FlaggedApi("android.os.material_motion_tokens") public static final int config_motionStandardDefaultEffectStiffness; + field @FlaggedApi("android.os.material_motion_tokens") public static final int config_motionStandardDefaultSpatialStiffness; + field @FlaggedApi("android.os.material_motion_tokens") public static final int config_motionStandardFastEffectStiffness; + field @FlaggedApi("android.os.material_motion_tokens") public static final int config_motionStandardFastSpatialStiffness; + field @FlaggedApi("android.os.material_motion_tokens") public static final int config_motionStandardSlowEffectStiffness; + field @FlaggedApi("android.os.material_motion_tokens") public static final int config_motionStandardSlowSpatialStiffness; field public static final int config_shortAnimTime = 17694720; // 0x10e0000 field @Deprecated public static final int status_bar_notification_info_maxnum = 17694723; // 0x10e0003 } @@ -8916,6 +8941,7 @@ package android.app.assist { method public void writeToParcel(android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator CREATOR; field @FlaggedApi("android.app.appfunctions.flags.enable_app_function_manager") public static final String EXTRA_APP_FUNCTION_DATA = "android.app.assist.extra.APP_FUNCTION_DATA"; + field @FlaggedApi("com.android.window.flags.enable_desktop_windowing_app_to_web_education") public static final String EXTRA_SESSION_TRANSFER_WEB_URI = "android.app.assist.extra.SESSION_TRANSFER_WEB_URI"; } public class AssistStructure implements android.os.Parcelable { @@ -9998,12 +10024,12 @@ package android.companion { method public int describeContents(); method @Nullable public android.companion.AssociatedDevice getAssociatedDevice(); method @FlaggedApi("android.companion.association_device_icon") @Nullable public android.graphics.drawable.Icon getDeviceIcon(); + method @FlaggedApi("android.companion.association_tag") @Nullable public android.companion.DeviceId getDeviceId(); method @Nullable public android.net.MacAddress getDeviceMacAddress(); method @Nullable public String getDeviceProfile(); method @Nullable public CharSequence getDisplayName(); method public int getId(); method public int getSystemDataSyncFlags(); - method @FlaggedApi("android.companion.association_tag") @Nullable public String getTag(); method public boolean isSelfManaged(); method public void writeToParcel(@NonNull android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator CREATOR; @@ -10076,7 +10102,6 @@ package android.companion { method @RequiresPermission(android.Manifest.permission.DELIVER_COMPANION_MESSAGES) public void attachSystemDataTransport(int, @NonNull java.io.InputStream, @NonNull java.io.OutputStream) throws android.companion.DeviceNotAssociatedException; method @Nullable public android.content.IntentSender buildAssociationCancellationIntent(); method @Nullable public android.content.IntentSender buildPermissionTransferUserConsentIntent(int) throws android.companion.DeviceNotAssociatedException; - method @FlaggedApi("android.companion.association_tag") public void clearAssociationTag(int); method @RequiresPermission(android.Manifest.permission.DELIVER_COMPANION_MESSAGES) public void detachSystemDataTransport(int) throws android.companion.DeviceNotAssociatedException; method public void disableSystemDataSyncForTypes(int, int); method @Deprecated public void disassociate(@NonNull String); @@ -10088,11 +10113,11 @@ package android.companion { method @FlaggedApi("android.companion.perm_sync_user_consent") public boolean isPermissionTransferUserConsented(int); method @FlaggedApi("android.companion.unpair_associated_device") @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean removeBond(int); method public void requestNotificationAccess(android.content.ComponentName); - method @FlaggedApi("android.companion.association_tag") public void setAssociationTag(int, @NonNull String); - method @RequiresPermission(android.Manifest.permission.REQUEST_OBSERVE_COMPANION_DEVICE_PRESENCE) public void startObservingDevicePresence(@NonNull String) throws android.companion.DeviceNotAssociatedException; + method @FlaggedApi("android.companion.association_tag") public void setDeviceId(int, @Nullable android.companion.DeviceId); + method @Deprecated @FlaggedApi("android.companion.device_presence") @RequiresPermission(android.Manifest.permission.REQUEST_OBSERVE_COMPANION_DEVICE_PRESENCE) public void startObservingDevicePresence(@NonNull String) throws android.companion.DeviceNotAssociatedException; method @FlaggedApi("android.companion.device_presence") @RequiresPermission(android.Manifest.permission.REQUEST_OBSERVE_COMPANION_DEVICE_PRESENCE) public void startObservingDevicePresence(@NonNull android.companion.ObservingDevicePresenceRequest); method public void startSystemDataTransfer(int, @NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver) throws android.companion.DeviceNotAssociatedException; - method @RequiresPermission(android.Manifest.permission.REQUEST_OBSERVE_COMPANION_DEVICE_PRESENCE) public void stopObservingDevicePresence(@NonNull String) throws android.companion.DeviceNotAssociatedException; + method @Deprecated @FlaggedApi("android.companion.device_presence") @RequiresPermission(android.Manifest.permission.REQUEST_OBSERVE_COMPANION_DEVICE_PRESENCE) public void stopObservingDevicePresence(@NonNull String) throws android.companion.DeviceNotAssociatedException; method @FlaggedApi("android.companion.device_presence") @RequiresPermission(android.Manifest.permission.REQUEST_OBSERVE_COMPANION_DEVICE_PRESENCE) public void stopObservingDevicePresence(@NonNull android.companion.ObservingDevicePresenceRequest); field public static final String EXTRA_ASSOCIATION = "android.companion.extra.ASSOCIATION"; field @Deprecated public static final String EXTRA_DEVICE = "android.companion.extra.DEVICE"; @@ -10120,9 +10145,9 @@ package android.companion { method @RequiresPermission(android.Manifest.permission.DELIVER_COMPANION_MESSAGES) public final void detachSystemDataTransport(int) throws android.companion.DeviceNotAssociatedException; method @Nullable public final android.os.IBinder onBind(@NonNull android.content.Intent); method @Deprecated @MainThread public void onDeviceAppeared(@NonNull String); - method @MainThread public void onDeviceAppeared(@NonNull android.companion.AssociationInfo); + method @Deprecated @FlaggedApi("android.companion.device_presence") @MainThread public void onDeviceAppeared(@NonNull android.companion.AssociationInfo); method @Deprecated @MainThread public void onDeviceDisappeared(@NonNull String); - method @MainThread public void onDeviceDisappeared(@NonNull android.companion.AssociationInfo); + method @Deprecated @FlaggedApi("android.companion.device_presence") @MainThread public void onDeviceDisappeared(@NonNull android.companion.AssociationInfo); method @FlaggedApi("android.companion.device_presence") @MainThread public void onDevicePresenceEvent(@NonNull android.companion.DevicePresenceEvent); field public static final String SERVICE_INTERFACE = "android.companion.CompanionDeviceService"; } @@ -10133,6 +10158,21 @@ package android.companion { public interface DeviceFilter extends android.os.Parcelable { } + @FlaggedApi("android.companion.association_tag") public final class DeviceId implements android.os.Parcelable { + method public int describeContents(); + method @Nullable public String getCustomId(); + method @Nullable public android.net.MacAddress getMacAddress(); + method public void writeToParcel(@NonNull android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator CREATOR; + } + + public static final class DeviceId.Builder { + ctor public DeviceId.Builder(); + method @NonNull public android.companion.DeviceId build(); + method @NonNull public android.companion.DeviceId.Builder setCustomId(@Nullable String); + method @NonNull public android.companion.DeviceId.Builder setMacAddress(@Nullable android.net.MacAddress); + } + public class DeviceNotAssociatedException extends java.lang.RuntimeException { } @@ -20767,6 +20807,7 @@ package android.hardware.display { public final class VirtualDisplayConfig implements android.os.Parcelable { method public int describeContents(); + method @FlaggedApi("android.companion.virtualdevice.flags.device_aware_display_power") @FloatRange(from=0.0f, to=1.0f) public float getDefaultBrightness(); method public int getDensityDpi(); method @NonNull public java.util.Set getDisplayCategories(); method public int getFlags(); @@ -20779,10 +20820,16 @@ package android.hardware.display { field @NonNull public static final android.os.Parcelable.Creator CREATOR; } + @FlaggedApi("android.companion.virtualdevice.flags.device_aware_display_power") public static interface VirtualDisplayConfig.BrightnessListener { + method public void onBrightnessChanged(@FloatRange(from=0.0f, to=1.0f) float); + } + public static final class VirtualDisplayConfig.Builder { ctor public VirtualDisplayConfig.Builder(@NonNull String, @IntRange(from=1) int, @IntRange(from=1) int, @IntRange(from=1) int); method @NonNull public android.hardware.display.VirtualDisplayConfig.Builder addDisplayCategory(@NonNull String); method @NonNull public android.hardware.display.VirtualDisplayConfig build(); + method @FlaggedApi("android.companion.virtualdevice.flags.device_aware_display_power") @NonNull public android.hardware.display.VirtualDisplayConfig.Builder setBrightnessListener(@NonNull java.util.concurrent.Executor, @NonNull android.hardware.display.VirtualDisplayConfig.BrightnessListener); + method @FlaggedApi("android.companion.virtualdevice.flags.device_aware_display_power") @NonNull public android.hardware.display.VirtualDisplayConfig.Builder setDefaultBrightness(@FloatRange(from=0.0f, to=1.0f) float); method @NonNull public android.hardware.display.VirtualDisplayConfig.Builder setDisplayCategories(@NonNull java.util.Set); method @NonNull public android.hardware.display.VirtualDisplayConfig.Builder setFlags(int); method @NonNull public android.hardware.display.VirtualDisplayConfig.Builder setRequestedRefreshRate(@FloatRange(from=0.0f) float); @@ -24852,7 +24899,9 @@ package android.media { method @Nullable public android.net.Uri getIconUri(); method @NonNull public String getId(); method @NonNull public CharSequence getName(); + method @FlaggedApi("com.android.media.flags.enable_route_visibility_control_api") @NonNull public java.util.Set getRequiredPermissions(); method @FlaggedApi("com.android.media.flags.enable_built_in_speaker_route_suitability_statuses") public int getSuitabilityStatus(); + method @FlaggedApi("com.android.media.flags.enable_mirroring_in_media_router_2") public int getSupportedRoutingTypes(); method public int getType(); method public int getVolume(); method public int getVolumeHandling(); @@ -24868,6 +24917,8 @@ package android.media { field public static final String FEATURE_REMOTE_AUDIO_PLAYBACK = "android.media.route.feature.REMOTE_AUDIO_PLAYBACK"; field public static final String FEATURE_REMOTE_PLAYBACK = "android.media.route.feature.REMOTE_PLAYBACK"; field public static final String FEATURE_REMOTE_VIDEO_PLAYBACK = "android.media.route.feature.REMOTE_VIDEO_PLAYBACK"; + field @FlaggedApi("com.android.media.flags.enable_mirroring_in_media_router_2") public static final int FLAG_ROUTING_TYPE_REMOTE = 4; // 0x4 + field @FlaggedApi("com.android.media.flags.enable_mirroring_in_media_router_2") public static final int FLAG_ROUTING_TYPE_SYSTEM_AUDIO = 1; // 0x1 field public static final int PLAYBACK_VOLUME_FIXED = 0; // 0x0 field public static final int PLAYBACK_VOLUME_VARIABLE = 1; // 0x1 field @FlaggedApi("com.android.media.flags.enable_built_in_speaker_route_suitability_statuses") public static final int SUITABILITY_STATUS_NOT_SUITABLE_FOR_TRANSFER = 2; // 0x2 @@ -24917,7 +24968,9 @@ package android.media { method @NonNull public android.media.MediaRoute2Info.Builder setDescription(@Nullable CharSequence); method @NonNull public android.media.MediaRoute2Info.Builder setExtras(@Nullable android.os.Bundle); method @NonNull public android.media.MediaRoute2Info.Builder setIconUri(@Nullable android.net.Uri); + method @FlaggedApi("com.android.media.flags.enable_route_visibility_control_api") @NonNull public android.media.MediaRoute2Info.Builder setRequiredPermissions(@NonNull java.util.Set); method @FlaggedApi("com.android.media.flags.enable_built_in_speaker_route_suitability_statuses") @NonNull public android.media.MediaRoute2Info.Builder setSuitabilityStatus(int); + method @FlaggedApi("com.android.media.flags.enable_mirroring_in_media_router_2") @NonNull public android.media.MediaRoute2Info.Builder setSupportedRoutingTypes(int); method @NonNull public android.media.MediaRoute2Info.Builder setType(int); method @NonNull public android.media.MediaRoute2Info.Builder setVisibilityPublic(); method @NonNull public android.media.MediaRoute2Info.Builder setVisibilityRestricted(@NonNull java.util.Set); @@ -29836,6 +29889,7 @@ package android.net.http { public class X509TrustManagerExtensions { ctor public X509TrustManagerExtensions(javax.net.ssl.X509TrustManager) throws java.lang.IllegalArgumentException; method public java.util.List checkServerTrusted(java.security.cert.X509Certificate[], String, String) throws java.security.cert.CertificateException; + method @FlaggedApi("android.net.platform.flags.x509_extensions_certificate_transparency") @NonNull public java.util.List checkServerTrusted(@NonNull java.security.cert.X509Certificate[], @Nullable byte[], @Nullable byte[], @NonNull String, @NonNull String) throws java.security.cert.CertificateException; method public boolean isSameTrustConfiguration(String, String); method public boolean isUserAddedCertificate(java.security.cert.X509Certificate); } @@ -33612,14 +33666,12 @@ package android.os { @FlaggedApi("android.os.cpu_gpu_headrooms") public final class CpuHeadroomParams { ctor public CpuHeadroomParams(); method public int getCalculationType(); - method @IntRange(from=android.os.CpuHeadroomParams.CPU_HEADROOM_CALCULATION_WINDOW_MILLIS_MIN, to=android.os.CpuHeadroomParams.CPU_HEADROOM_CALCULATION_WINDOW_MILLIS_MAX) public long getCalculationWindowMillis(); + method @IntRange(from=0x32, to=0x2710) public long getCalculationWindowMillis(); method public void setCalculationType(int); - method public void setCalculationWindowMillis(@IntRange(from=android.os.CpuHeadroomParams.CPU_HEADROOM_CALCULATION_WINDOW_MILLIS_MIN, to=android.os.CpuHeadroomParams.CPU_HEADROOM_CALCULATION_WINDOW_MILLIS_MAX) int); + method public void setCalculationWindowMillis(@IntRange(from=0x32, to=0x2710) int); method public void setTids(@NonNull int...); field public static final int CPU_HEADROOM_CALCULATION_TYPE_AVERAGE = 1; // 0x1 field public static final int CPU_HEADROOM_CALCULATION_TYPE_MIN = 0; // 0x0 - field public static final int CPU_HEADROOM_CALCULATION_WINDOW_MILLIS_MAX = 10000; // 0x2710 - field public static final int CPU_HEADROOM_CALCULATION_WINDOW_MILLIS_MIN = 50; // 0x32 } public final class CpuUsageInfo implements android.os.Parcelable { @@ -33872,13 +33924,11 @@ package android.os { @FlaggedApi("android.os.cpu_gpu_headrooms") public final class GpuHeadroomParams { ctor public GpuHeadroomParams(); method public int getCalculationType(); - method @IntRange(from=android.os.GpuHeadroomParams.GPU_HEADROOM_CALCULATION_WINDOW_MILLIS_MIN, to=android.os.GpuHeadroomParams.GPU_HEADROOM_CALCULATION_WINDOW_MILLIS_MAX) public int getCalculationWindowMillis(); + method @IntRange(from=0x32, to=0x2710) public int getCalculationWindowMillis(); method public void setCalculationType(int); - method public void setCalculationWindowMillis(@IntRange(from=android.os.GpuHeadroomParams.GPU_HEADROOM_CALCULATION_WINDOW_MILLIS_MIN, to=android.os.GpuHeadroomParams.GPU_HEADROOM_CALCULATION_WINDOW_MILLIS_MAX) int); + method public void setCalculationWindowMillis(@IntRange(from=0x32, to=0x2710) int); field public static final int GPU_HEADROOM_CALCULATION_TYPE_AVERAGE = 1; // 0x1 field public static final int GPU_HEADROOM_CALCULATION_TYPE_MIN = 0; // 0x0 - field public static final int GPU_HEADROOM_CALCULATION_WINDOW_MILLIS_MAX = 10000; // 0x2710 - field public static final int GPU_HEADROOM_CALCULATION_WINDOW_MILLIS_MIN = 50; // 0x32 } public class Handler { diff --git a/core/api/module-lib-current.txt b/core/api/module-lib-current.txt index 1a949d84c0527f470efccdac2f88cd4549866572..804210fe3bb5b44d39899517e9908180d3a17b72 100644 --- a/core/api/module-lib-current.txt +++ b/core/api/module-lib-current.txt @@ -100,6 +100,7 @@ package android.content { method @NonNull public android.content.Context createContextForSdkInSandbox(@NonNull android.content.pm.ApplicationInfo, int) throws android.content.pm.PackageManager.NameNotFoundException; method @NonNull public android.os.IBinder getProcessToken(); method @NonNull public android.os.UserHandle getUser(); + field @FlaggedApi("android.app.ondeviceintelligence.flags.enable_on_device_intelligence_module") public static final int BIND_FOREGROUND_SERVICE = 67108864; // 0x4000000 field public static final String PAC_PROXY_SERVICE = "pac_proxy"; field public static final String TEST_NETWORK_SERVICE = "test_network"; field @FlaggedApi("android.os.mainline_vcn_platform_api") public static final String VCN_MANAGEMENT_SERVICE = "vcn_management"; @@ -129,6 +130,7 @@ package android.content.pm { public abstract class PackageManager { method @NonNull public String getSdkSandboxPackageName(); + method @FlaggedApi("android.content.pm.cloud_compilation_pm") @NonNull public static android.content.pm.SigningInfo getVerifiedSigningInfo(@NonNull String, int) throws android.content.pm.SigningInfoException; method @RequiresPermission(android.Manifest.permission.MAKE_UID_VISIBLE) public void makeUidVisible(int, int); field public static final String EXTRA_VERIFICATION_ROOT_HASH = "android.content.pm.extra.VERIFICATION_ROOT_HASH"; field public static final int MATCH_STATIC_SHARED_AND_SDK_LIBRARIES = 67108864; // 0x4000000 @@ -139,6 +141,18 @@ package android.content.pm { method @NonNull public String getPackageName(); } + public final class SigningInfo implements android.os.Parcelable { + method @FlaggedApi("android.content.pm.cloud_compilation_pm") public boolean signersMatchExactly(@NonNull android.content.pm.SigningInfo); + field @FlaggedApi("android.content.pm.cloud_compilation_pm") public static final int VERSION_JAR = 1; // 0x1 + field @FlaggedApi("android.content.pm.cloud_compilation_pm") public static final int VERSION_SIGNING_BLOCK_V2 = 2; // 0x2 + field @FlaggedApi("android.content.pm.cloud_compilation_pm") public static final int VERSION_SIGNING_BLOCK_V3 = 3; // 0x3 + field @FlaggedApi("android.content.pm.cloud_compilation_pm") public static final int VERSION_SIGNING_BLOCK_V4 = 4; // 0x4 + } + + @FlaggedApi("android.content.pm.cloud_compilation_pm") public class SigningInfoException extends java.lang.Exception { + method @FlaggedApi("android.content.pm.cloud_compilation_pm") public int getCode(); + } + } package android.hardware.usb { diff --git a/core/api/system-current.txt b/core/api/system-current.txt index 83699ac30939bc3a16607bf30b08af585524fb66..612a48ac00a7bb57f2d219bde85fb4ebe9ae3949 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -516,6 +516,7 @@ package android { field public static final int config_defaultCallScreening = 17039398; // 0x1040026 field public static final int config_defaultDialer = 17039395; // 0x1040023 field public static final int config_defaultNotes = 17039429; // 0x1040045 + field @FlaggedApi("android.permission.flags.cross_user_role_platform_api_enabled") public static final int config_defaultReservedForTestingProfileGroupExclusivity; field @FlaggedApi("android.permission.flags.retail_demo_role_enabled") public static final int config_defaultRetailDemo = 17039432; // 0x1040048 field public static final int config_defaultSms = 17039396; // 0x1040024 field @FlaggedApi("android.permission.flags.wallet_role_enabled") public static final int config_defaultWallet = 17039433; // 0x1040049 @@ -902,7 +903,7 @@ package android.app { public static final class AppOpsManager.OpEventProxyInfo implements android.os.Parcelable { method public int describeContents(); method @Nullable public String getAttributionTag(); - method @FlaggedApi("android.permission.flags.device_id_in_op_proxy_info_enabled") @Nullable public String getDeviceId(); + method @FlaggedApi("android.permission.flags.device_id_in_op_proxy_info_enabled") @NonNull public String getDeviceId(); method @Nullable public String getPackageName(); method @IntRange(from=0) public int getUid(); method public void writeToParcel(@NonNull android.os.Parcel, int); @@ -3543,6 +3544,7 @@ package android.companion.virtual { public static interface VirtualDeviceManager.ActivityListener { method @FlaggedApi("android.companion.virtualdevice.flags.activity_control_api") public default void onActivityLaunchBlocked(int, @NonNull android.content.ComponentName, @NonNull android.os.UserHandle, @Nullable android.content.IntentSender); method public void onDisplayEmpty(int); + method @FlaggedApi("android.companion.virtualdevice.flags.activity_control_api") public default void onSecureWindowHidden(int); method @FlaggedApi("android.companion.virtualdevice.flags.activity_control_api") public default void onSecureWindowShown(int, @NonNull android.content.ComponentName, @NonNull android.os.UserHandle); method @Deprecated public void onTopActivityChanged(int, @NonNull android.content.ComponentName); method public default void onTopActivityChanged(int, @NonNull android.content.ComponentName, int); @@ -5455,19 +5457,13 @@ package android.hardware.display { field public static final int VIRTUAL_DISPLAY_FLAG_TRUSTED = 1024; // 0x400 } - public abstract static class VirtualDisplay.Callback { - method @FlaggedApi("android.companion.virtualdevice.flags.device_aware_display_power") public void onRequestedBrightnessChanged(@FloatRange(from=0.0f, to=1.0f) float); - } - public final class VirtualDisplayConfig implements android.os.Parcelable { - method @FlaggedApi("android.companion.virtualdevice.flags.device_aware_display_power") @FloatRange(from=0.0f, to=1.0f) public float getDefaultBrightness(); method @FlaggedApi("android.companion.virtualdevice.flags.virtual_display_insets") @Nullable public android.view.DisplayCutout getDisplayCutout(); method @FlaggedApi("android.companion.virtual.flags.vdm_custom_home") public boolean isHomeSupported(); method @FlaggedApi("com.android.window.flags.vdm_force_app_universal_resizable_api") public boolean isIgnoreActivitySizeRestrictions(); } public static final class VirtualDisplayConfig.Builder { - method @FlaggedApi("android.companion.virtualdevice.flags.device_aware_display_power") @NonNull public android.hardware.display.VirtualDisplayConfig.Builder setDefaultBrightness(@FloatRange(from=0.0f, to=1.0f) float); method @FlaggedApi("android.companion.virtualdevice.flags.virtual_display_insets") @NonNull public android.hardware.display.VirtualDisplayConfig.Builder setDisplayCutout(@Nullable android.view.DisplayCutout); method @FlaggedApi("android.companion.virtual.flags.vdm_custom_home") @NonNull public android.hardware.display.VirtualDisplayConfig.Builder setHomeSupported(boolean); method @FlaggedApi("com.android.window.flags.vdm_force_app_universal_resizable_api") @NonNull public android.hardware.display.VirtualDisplayConfig.Builder setIgnoreActivitySizeRestrictions(boolean); @@ -7196,8 +7192,8 @@ package android.hardware.soundtrigger { method public int getAudioCapabilities(); method @NonNull public byte[] getData(); method @NonNull public java.util.List getKeyphrases(); - method public boolean isAllowMultipleTriggers(); method public boolean isCaptureRequested(); + method public boolean isMultipleTriggersAllowed(); method public void writeToParcel(@NonNull android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator CREATOR; } @@ -7205,11 +7201,11 @@ package android.hardware.soundtrigger { public static final class SoundTrigger.RecognitionConfig.Builder { ctor public SoundTrigger.RecognitionConfig.Builder(); method @NonNull public android.hardware.soundtrigger.SoundTrigger.RecognitionConfig build(); - method @NonNull public android.hardware.soundtrigger.SoundTrigger.RecognitionConfig.Builder setAllowMultipleTriggers(boolean); method @NonNull public android.hardware.soundtrigger.SoundTrigger.RecognitionConfig.Builder setAudioCapabilities(int); method @NonNull public android.hardware.soundtrigger.SoundTrigger.RecognitionConfig.Builder setCaptureRequested(boolean); method @NonNull public android.hardware.soundtrigger.SoundTrigger.RecognitionConfig.Builder setData(@NonNull byte[]); method @NonNull public android.hardware.soundtrigger.SoundTrigger.RecognitionConfig.Builder setKeyphrases(@NonNull java.util.Collection); + method @NonNull public android.hardware.soundtrigger.SoundTrigger.RecognitionConfig.Builder setMultipleTriggersAllowed(boolean); } public static class SoundTrigger.RecognitionEvent { @@ -7779,7 +7775,7 @@ package android.media { } public final class MediaCas implements java.lang.AutoCloseable { - method @FlaggedApi("android.media.tv.flags.set_resource_holder_retain") @RequiresPermission("android.permission.TUNER_RESOURCE_ACCESS") public void setResourceHolderRetain(boolean); + method @FlaggedApi("android.media.tv.flags.set_resource_holder_retain") @RequiresPermission("android.permission.TUNER_RESOURCE_ACCESS") public void setResourceOwnershipRetention(boolean); method @FlaggedApi("android.media.tv.flags.mediacas_update_client_profile_priority") @RequiresPermission("android.permission.TUNER_RESOURCE_ACCESS") public boolean updateResourcePriority(int, int); } @@ -8692,8 +8688,8 @@ package android.media.tv.tuner { method public int setLnaEnabled(boolean); method public int setMaxNumberOfFrontends(int, @IntRange(from=0) int); method public void setOnTuneEventListener(@NonNull java.util.concurrent.Executor, @NonNull android.media.tv.tuner.frontend.OnTuneEventListener); - method @FlaggedApi("android.media.tv.flags.set_resource_holder_retain") @RequiresPermission("android.permission.TUNER_RESOURCE_ACCESS") public void setResourceHolderRetain(boolean); method public void setResourceLostListener(@NonNull java.util.concurrent.Executor, @NonNull android.media.tv.tuner.Tuner.OnResourceLostListener); + method @FlaggedApi("android.media.tv.flags.set_resource_holder_retain") @RequiresPermission("android.permission.TUNER_RESOURCE_ACCESS") public void setResourceOwnershipRetention(boolean); method public void shareFrontendFromTuner(@NonNull android.media.tv.tuner.Tuner); method public int transferOwner(@NonNull android.media.tv.tuner.Tuner); method public int tune(@NonNull android.media.tv.tuner.frontend.FrontendSettings); @@ -16095,6 +16091,10 @@ package android.telephony { field @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public static final int EVENT_CALL_FORWARDING_INDICATOR_CHANGED = 4; // 0x4 field public static final int EVENT_CALL_STATE_CHANGED = 6; // 0x6 field public static final int EVENT_CARRIER_NETWORK_CHANGED = 17; // 0x11 + field @FlaggedApi("com.android.internal.telephony.flags.satellite_system_apis") @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public static final int EVENT_CARRIER_ROAMING_NTN_AVAILABLE_SERVICES_CHANGED = 44; // 0x2c + field @FlaggedApi("com.android.internal.telephony.flags.satellite_system_apis") @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public static final int EVENT_CARRIER_ROAMING_NTN_ELIGIBLE_STATE_CHANGED = 43; // 0x2b + field @FlaggedApi("com.android.internal.telephony.flags.satellite_system_apis") @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public static final int EVENT_CARRIER_ROAMING_NTN_MODE_CHANGED = 42; // 0x2a + field @FlaggedApi("com.android.internal.telephony.flags.satellite_system_apis") @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public static final int EVENT_CARRIER_ROAMING_NTN_SIGNAL_STRENGTH_CHANGED = 45; // 0x2d field @FlaggedApi("com.android.internal.telephony.flags.cellular_identifier_disclosure_indications") @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public static final int EVENT_CELLULAR_IDENTIFIER_DISCLOSED_CHANGED = 47; // 0x2f field @RequiresPermission(allOf={android.Manifest.permission.READ_PHONE_STATE, android.Manifest.permission.ACCESS_FINE_LOCATION}) public static final int EVENT_CELL_INFO_CHANGED = 11; // 0xb field @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public static final int EVENT_CELL_LOCATION_CHANGED = 5; // 0x5 @@ -16139,6 +16139,13 @@ package android.telephony { method @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public default void onCallStatesChanged(@NonNull java.util.List); } + @FlaggedApi("com.android.internal.telephony.flags.satellite_system_apis") public static interface TelephonyCallback.CarrierRoamingNtnModeListener { + method public default void onCarrierRoamingNtnAvailableServicesChanged(@NonNull int[]); + method public default void onCarrierRoamingNtnEligibleStateChanged(boolean); + method public void onCarrierRoamingNtnModeChanged(boolean); + method public default void onCarrierRoamingNtnSignalStrengthChanged(@NonNull android.telephony.satellite.NtnSignalStrength); + } + @FlaggedApi("com.android.internal.telephony.flags.cellular_identifier_disclosure_indications") public static interface TelephonyCallback.CellularIdentifierDisclosedListener { method public void onCellularIdentifierDisclosedChanged(@NonNull android.telephony.CellularIdentifierDisclosure); } @@ -16264,6 +16271,7 @@ package android.telephony { method @FlaggedApi("android.permission.flags.get_emergency_role_holder_api_enabled") @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getEmergencyAssistancePackageName(); method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean getEmergencyCallbackMode(); method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getEmergencyNumberDbVersion(); + method @FlaggedApi("com.android.internal.telephony.flags.get_group_id_level2") @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getGroupIdLevel2(); method @FlaggedApi("com.android.internal.telephony.flags.support_isim_record") @NonNull @RequiresPermission(value=android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, conditional=true) public java.util.List getImsPcscfAddresses(); method @FlaggedApi("com.android.internal.telephony.flags.support_isim_record") @Nullable @RequiresPermission(android.Manifest.permission.USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER) public String getImsPrivateUserIdentity(); method @FlaggedApi("com.android.internal.telephony.flags.support_isim_record") @NonNull @RequiresPermission(value=android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, conditional=true) public java.util.List getImsPublicUserIdentities(); @@ -18741,6 +18749,14 @@ package android.telephony.satellite { field @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") @NonNull public static final android.os.Parcelable.Creator CREATOR; } + @FlaggedApi("com.android.internal.telephony.flags.satellite_system_apis") public final class EarfcnRange implements android.os.Parcelable { + method public int describeContents(); + method @IntRange(from=0, to=65535) public int getEndEarfcn(); + method @IntRange(from=0, to=65535) public int getStartEarfcn(); + method public void writeToParcel(@NonNull android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator CREATOR; + } + @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") public class EnableRequestAttributes { method @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") public boolean isDemoMode(); method @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") public boolean isEmergencyMode(); @@ -18779,6 +18795,14 @@ package android.telephony.satellite { field @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") @NonNull public static final android.os.Parcelable.Creator CREATOR; } + @FlaggedApi("com.android.internal.telephony.flags.satellite_system_apis") public final class SatelliteAccessConfiguration implements android.os.Parcelable { + method public int describeContents(); + method @NonNull public java.util.List getSatelliteInfos(); + method @NonNull public java.util.List getTagIds(); + method public void writeToParcel(@NonNull android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator CREATOR; + } + @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") public final class SatelliteCapabilities implements android.os.Parcelable { method @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") public int describeContents(); method @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") @NonNull public java.util.Map getAntennaPositionMap(); @@ -18793,6 +18817,11 @@ package android.telephony.satellite { method @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") public void onSatelliteCapabilitiesChanged(@NonNull android.telephony.satellite.SatelliteCapabilities); } + @FlaggedApi("com.android.internal.telephony.flags.satellite_system_apis") public interface SatelliteCommunicationAllowedStateCallback { + method public default void onSatelliteAccessConfigurationChanged(@Nullable android.telephony.satellite.SatelliteAccessConfiguration); + method public void onSatelliteCommunicationAllowedStateChanged(boolean); + } + @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") public final class SatelliteDatagram implements android.os.Parcelable { method @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") public int describeContents(); method @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") @NonNull public byte[] getSatelliteDatagram(); @@ -18804,18 +18833,32 @@ package android.telephony.satellite { method @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") public void onSatelliteDatagramReceived(long, @NonNull android.telephony.satellite.SatelliteDatagram, int, @NonNull java.util.function.Consumer); } + @FlaggedApi("com.android.internal.telephony.flags.satellite_system_apis") public final class SatelliteInfo implements android.os.Parcelable { + method public int describeContents(); + method @NonNull public java.util.List getBands(); + method @NonNull public java.util.List getEarfcnRanges(); + method @NonNull public java.util.UUID getSatelliteId(); + method @NonNull public android.telephony.satellite.SatellitePosition getSatellitePosition(); + method public void writeToParcel(@NonNull android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator CREATOR; + } + @FlaggedApi("com.android.internal.telephony.flags.satellite_state_change_listener") public final class SatelliteManager { method @FlaggedApi("com.android.internal.telephony.flags.carrier_enabled_satellite_flag") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public void addAttachRestrictionForCarrier(int, int, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer); + method @FlaggedApi("com.android.internal.telephony.flags.satellite_system_apis") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public void deprovisionSatellite(@NonNull java.util.List, @NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver); method @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public void deprovisionService(@NonNull String, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer); method @FlaggedApi("com.android.internal.telephony.flags.carrier_enabled_satellite_flag") @NonNull @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public java.util.Set getAttachRestrictionReasonsForCarrier(int); method @FlaggedApi("com.android.internal.telephony.flags.carrier_enabled_satellite_flag") @NonNull @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public java.util.List getSatellitePlmnsForCarrier(int); method @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public void pollPendingDatagrams(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer); + method @FlaggedApi("com.android.internal.telephony.flags.satellite_system_apis") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public void provisionSatellite(@NonNull java.util.List, @NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver); method @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public void provisionService(@NonNull String, @NonNull byte[], @Nullable android.os.CancellationSignal, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer); method @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public int registerForCapabilitiesChanged(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.satellite.SatelliteCapabilitiesCallback); + method @FlaggedApi("com.android.internal.telephony.flags.satellite_system_apis") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public int registerForCommunicationAllowedStateChanged(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.satellite.SatelliteCommunicationAllowedStateCallback); method @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public int registerForIncomingDatagram(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.satellite.SatelliteDatagramCallback); method @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public int registerForModemStateChanged(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.satellite.SatelliteModemStateCallback); method @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public void registerForNtnSignalStrengthChanged(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.satellite.NtnSignalStrengthCallback); method @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public int registerForProvisionStateChanged(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.satellite.SatelliteProvisionStateCallback); + method @FlaggedApi("com.android.internal.telephony.flags.satellite_system_apis") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public int registerForSupportedStateChanged(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.satellite.SatelliteSupportedStateCallback); method @FlaggedApi("com.android.internal.telephony.flags.carrier_enabled_satellite_flag") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public void removeAttachRestrictionForCarrier(int, int, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer); method @FlaggedApi("com.android.internal.telephony.flags.carrier_enabled_satellite_flag") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public void requestAttachEnabledForCarrier(int, boolean, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer); method @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public void requestCapabilities(@NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver); @@ -18828,16 +18871,21 @@ package android.telephony.satellite { method @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public void requestIsProvisioned(@NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver); method @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") public void requestIsSupported(@NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver); method @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public void requestNtnSignalStrength(@NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver); + method @FlaggedApi("com.android.internal.telephony.flags.satellite_system_apis") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public void requestSatelliteSubscriberProvisionStatus(@NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver,android.telephony.satellite.SatelliteManager.SatelliteException>); method @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public void requestTimeForNextSatelliteVisibility(@NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver); method @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public void sendDatagram(int, @NonNull android.telephony.satellite.SatelliteDatagram, boolean, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer); method @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public void setDeviceAlignedWithSatellite(boolean); method @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public void startTransmissionUpdates(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer, @NonNull android.telephony.satellite.SatelliteTransmissionUpdateCallback); method @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public void stopTransmissionUpdates(@NonNull android.telephony.satellite.SatelliteTransmissionUpdateCallback, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer); method @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public void unregisterForCapabilitiesChanged(@NonNull android.telephony.satellite.SatelliteCapabilitiesCallback); + method @FlaggedApi("com.android.internal.telephony.flags.satellite_system_apis") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public void unregisterForCommunicationAllowedStateChanged(@NonNull android.telephony.satellite.SatelliteCommunicationAllowedStateCallback); method @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public void unregisterForIncomingDatagram(@NonNull android.telephony.satellite.SatelliteDatagramCallback); method @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public void unregisterForModemStateChanged(@NonNull android.telephony.satellite.SatelliteModemStateCallback); method @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public void unregisterForNtnSignalStrengthChanged(@NonNull android.telephony.satellite.NtnSignalStrengthCallback); method @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public void unregisterForProvisionStateChanged(@NonNull android.telephony.satellite.SatelliteProvisionStateCallback); + method @FlaggedApi("com.android.internal.telephony.flags.satellite_system_apis") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public void unregisterForSupportedStateChanged(@NonNull android.telephony.satellite.SatelliteSupportedStateCallback); + field @FlaggedApi("com.android.internal.telephony.flags.satellite_system_apis") public static final String ACTION_SATELLITE_START_NON_EMERGENCY_SESSION = "android.telephony.satellite.action.SATELLITE_START_NON_EMERGENCY_SESSION"; + field @FlaggedApi("com.android.internal.telephony.flags.satellite_system_apis") public static final String ACTION_SATELLITE_SUBSCRIBER_ID_LIST_CHANGED = "android.telephony.satellite.action.SATELLITE_SUBSCRIBER_ID_LIST_CHANGED"; field @FlaggedApi("com.android.internal.telephony.flags.satellite_system_apis") public static final int DATAGRAM_TYPE_CHECK_PENDING_INCOMING_SMS = 7; // 0x7 field @FlaggedApi("com.android.internal.telephony.flags.satellite_system_apis") public static final int DATAGRAM_TYPE_KEEP_ALIVE = 3; // 0x3 field @FlaggedApi("com.android.internal.telephony.flags.satellite_system_apis") public static final int DATAGRAM_TYPE_LAST_SOS_MESSAGE_NO_HELP_NEEDED = 5; // 0x5 @@ -18856,6 +18904,7 @@ package android.telephony.satellite { field @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") public static final int DISPLAY_MODE_UNKNOWN = 0; // 0x0 field @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") public static final int EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_SOS = 1; // 0x1 field @FlaggedApi("com.android.internal.telephony.flags.carrier_enabled_satellite_flag") public static final int EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_T911 = 2; // 0x2 + field @FlaggedApi("com.android.internal.telephony.flags.satellite_system_apis") public static final String METADATA_SATELLITE_MANUAL_CONNECT_P2P_SUPPORT = "android.telephony.METADATA_SATELLITE_MANUAL_CONNECT_P2P_SUPPORT"; field @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") public static final int NT_RADIO_TECHNOLOGY_EMTC_NTN = 3; // 0x3 field @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") public static final int NT_RADIO_TECHNOLOGY_NB_IOT_NTN = 1; // 0x1 field @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") public static final int NT_RADIO_TECHNOLOGY_NR_NTN = 2; // 0x2 @@ -18922,18 +18971,100 @@ package android.telephony.satellite { method @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") public int getErrorCode(); } + @FlaggedApi("com.android.internal.telephony.flags.satellite_system_apis") public final class SatelliteModemEnableRequestAttributes implements android.os.Parcelable { + method public int describeContents(); + method @NonNull public android.telephony.satellite.SatelliteSubscriptionInfo getSatelliteSubscriptionInfo(); + method public boolean isDemoMode(); + method public boolean isEmergencyMode(); + method public boolean isEnabled(); + method public void writeToParcel(@NonNull android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator CREATOR; + } + @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") public interface SatelliteModemStateCallback { method @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") public void onSatelliteModemStateChanged(int); } + @FlaggedApi("com.android.internal.telephony.flags.satellite_system_apis") public final class SatellitePosition implements android.os.Parcelable { + method public int describeContents(); + method public double getAltitudeKm(); + method public double getLongitudeDegrees(); + method public void writeToParcel(@NonNull android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator CREATOR; + } + @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") public interface SatelliteProvisionStateCallback { method @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") public void onSatelliteProvisionStateChanged(boolean); + method @FlaggedApi("com.android.internal.telephony.flags.satellite_system_apis") public default void onSatelliteSubscriptionProvisionStateChanged(@NonNull java.util.List); + } + + @FlaggedApi("com.android.internal.telephony.flags.satellite_system_apis") public final class SatelliteSubscriberInfo implements android.os.Parcelable { + method public int describeContents(); + method public int getCarrierId(); + method @NonNull public String getNiddApn(); + method public int getSubId(); + method @NonNull public String getSubscriberId(); + method public int getSubscriberIdType(); + method public void writeToParcel(@NonNull android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator CREATOR; + field public static final int ICCID = 0; // 0x0 + field public static final int IMSI_MSISDN = 1; // 0x1 + } + + public static final class SatelliteSubscriberInfo.Builder { + ctor public SatelliteSubscriberInfo.Builder(); + method @NonNull public android.telephony.satellite.SatelliteSubscriberInfo build(); + method @NonNull public android.telephony.satellite.SatelliteSubscriberInfo.Builder setCarrierId(int); + method @NonNull public android.telephony.satellite.SatelliteSubscriberInfo.Builder setNiddApn(@NonNull String); + method @NonNull public android.telephony.satellite.SatelliteSubscriberInfo.Builder setSubId(int); + method @NonNull public android.telephony.satellite.SatelliteSubscriberInfo.Builder setSubscriberId(@NonNull String); + method @NonNull public android.telephony.satellite.SatelliteSubscriberInfo.Builder setSubscriberIdType(int); + } + + @FlaggedApi("com.android.internal.telephony.flags.satellite_system_apis") public final class SatelliteSubscriberProvisionStatus implements android.os.Parcelable { + method public int describeContents(); + method @NonNull public android.telephony.satellite.SatelliteSubscriberInfo getSatelliteSubscriberInfo(); + method public boolean isProvisioned(); + method public void writeToParcel(@NonNull android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator CREATOR; + } + + public static final class SatelliteSubscriberProvisionStatus.Builder { + ctor public SatelliteSubscriberProvisionStatus.Builder(); + method @NonNull public android.telephony.satellite.SatelliteSubscriberProvisionStatus build(); + method @NonNull public android.telephony.satellite.SatelliteSubscriberProvisionStatus.Builder setProvisioned(boolean); + method @NonNull public android.telephony.satellite.SatelliteSubscriberProvisionStatus.Builder setSatelliteSubscriberInfo(@NonNull android.telephony.satellite.SatelliteSubscriberInfo); + } + + @FlaggedApi("com.android.internal.telephony.flags.satellite_system_apis") public final class SatelliteSubscriptionInfo implements android.os.Parcelable { + method public int describeContents(); + method @NonNull public String getIccId(); + method @NonNull public String getNiddApn(); + method public void writeToParcel(@NonNull android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator CREATOR; + } + + @FlaggedApi("com.android.internal.telephony.flags.satellite_system_apis") public interface SatelliteSupportedStateCallback { + method public void onSatelliteSupportedStateChanged(boolean); } @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") public interface SatelliteTransmissionUpdateCallback { method @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") public void onReceiveDatagramStateChanged(int, int, int); method @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") public void onSatellitePositionChanged(@NonNull android.telephony.satellite.PointingInfo); + method @FlaggedApi("com.android.internal.telephony.flags.satellite_system_apis") public default void onSendDatagramRequested(int); method @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") public void onSendDatagramStateChanged(int, int, int); + method @FlaggedApi("com.android.internal.telephony.flags.satellite_system_apis") public default void onSendDatagramStateChanged(int, int, int, int); + } + + @FlaggedApi("com.android.internal.telephony.flags.satellite_system_apis") public final class SystemSelectionSpecifier implements android.os.Parcelable { + method public int describeContents(); + method @NonNull public int[] getBands(); + method @NonNull public int[] getEarfcns(); + method @NonNull public String getMccMnc(); + method @NonNull public java.util.List getSatelliteInfos(); + method @NonNull public int[] getTagIds(); + method public void writeToParcel(@NonNull android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator CREATOR; } } diff --git a/core/api/test-current.txt b/core/api/test-current.txt index 967f6194969e1e563c3dfc3939fde5855b47968c..603677e89240a5a0cf66db070875ac5d17b75d64 100644 --- a/core/api/test-current.txt +++ b/core/api/test-current.txt @@ -541,7 +541,9 @@ package android.app { method @Nullable public android.graphics.Rect peekBitmapDimensions(); method @Nullable public android.graphics.Rect peekBitmapDimensions(int); method @FlaggedApi("com.android.window.flags.multi_crop") @RequiresPermission(android.Manifest.permission.SET_WALLPAPER) public int setBitmapWithCrops(@Nullable android.graphics.Bitmap, @NonNull java.util.Map, boolean, int) throws java.io.IOException; + method @FlaggedApi("android.app.live_wallpaper_content_handling") @RequiresPermission(android.Manifest.permission.SET_WALLPAPER) public int setBitmapWithDescription(@Nullable android.graphics.Bitmap, @NonNull android.app.wallpaper.WallpaperDescription, boolean, int) throws java.io.IOException; method @FlaggedApi("com.android.window.flags.multi_crop") @RequiresPermission(android.Manifest.permission.SET_WALLPAPER) public int setStreamWithCrops(@NonNull java.io.InputStream, @NonNull java.util.Map, boolean, int) throws java.io.IOException; + method @FlaggedApi("android.app.live_wallpaper_content_handling") @RequiresPermission(android.Manifest.permission.SET_WALLPAPER) public int setStreamWithDescription(@NonNull java.io.InputStream, @NonNull android.app.wallpaper.WallpaperDescription, boolean, int) throws java.io.IOException; method public void setWallpaperZoomOut(@NonNull android.os.IBinder, float); method public boolean shouldEnableWideColorGamut(); method public boolean wallpaperSupportsWcg(int); @@ -907,6 +909,15 @@ package android.app.usage { } +package android.app.wallpaper { + + public static final class WallpaperDescription.Builder { + method @NonNull public android.app.wallpaper.WallpaperDescription.Builder setCropHints(@NonNull java.util.Map); + method @NonNull public android.app.wallpaper.WallpaperDescription.Builder setCropHints(@NonNull android.util.SparseArray); + } + +} + package android.appwidget { public class AppWidgetManager { @@ -923,6 +934,7 @@ package android.companion { method @NonNull public android.companion.AssociationInfo build(); method @NonNull public android.companion.AssociationInfo.Builder setAssociatedDevice(@Nullable android.companion.AssociatedDevice); method @FlaggedApi("android.companion.association_device_icon") @NonNull public android.companion.AssociationInfo.Builder setDeviceIcon(@Nullable android.graphics.drawable.Icon); + method @FlaggedApi("android.companion.association_tag") @NonNull public android.companion.AssociationInfo.Builder setDeviceId(@Nullable android.companion.DeviceId); method @NonNull public android.companion.AssociationInfo.Builder setDeviceMacAddress(@Nullable android.net.MacAddress); method @NonNull public android.companion.AssociationInfo.Builder setDeviceProfile(@Nullable String); method @NonNull public android.companion.AssociationInfo.Builder setDisplayName(@Nullable CharSequence); @@ -931,7 +943,6 @@ package android.companion { method @NonNull public android.companion.AssociationInfo.Builder setRevoked(boolean); method @NonNull public android.companion.AssociationInfo.Builder setSelfManaged(boolean); method @NonNull public android.companion.AssociationInfo.Builder setSystemDataSyncFlags(int); - method @FlaggedApi("android.companion.association_tag") @NonNull public android.companion.AssociationInfo.Builder setTag(@Nullable String); method @NonNull public android.companion.AssociationInfo.Builder setTimeApproved(long); } diff --git a/core/java/android/animation/Animator.java b/core/java/android/animation/Animator.java index d1eb8e8fa2ff200bf13b8a5a29816c5ef9cb2a75..4bf87f91cb2fc581a372c22cecafc1fc759abb73 100644 --- a/core/java/android/animation/Animator.java +++ b/core/java/android/animation/Animator.java @@ -140,6 +140,14 @@ public abstract class Animator implements Cloneable { sPostNotifyEndListenerEnabled = enable; } + /** + * @see #sPostNotifyEndListenerEnabled + * @hide + */ + public static boolean isPostNotifyEndListenerEnabled() { + return sPostNotifyEndListenerEnabled; + } + /** * Starts this animation. If the animation has a nonzero startDelay, the animation will start * running after that delay elapses. A non-delayed animation will have its initial diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index f8186d68e21034f27b35c5aeb0a20fce27b689d8..3c1cce973b3a2fc5617505e0b7c8abcc960b7ad5 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -6995,21 +6995,44 @@ public final class ActivityThread extends ClientTransactionHandler final void handleProfilerControl(boolean start, ProfilerInfo profilerInfo, int profileType) { if (start) { - try { - switch (profileType) { - default: + switch (profileType) { + case ProfilerInfo.PROFILE_TYPE_LOW_OVERHEAD: + if (!com.android.art.flags.Flags.alwaysEnableProfileCode()) { + Slog.w(TAG, "Low overhead tracing feature is not enabled"); + break; + } + VMDebug.startLowOverheadTrace(); + break; + default: + try { mProfiler.setProfiler(profilerInfo); mProfiler.startProfiling(); break; - } - } catch (RuntimeException e) { - Slog.w(TAG, "Profiling failed on path " + profilerInfo.profileFile - + " -- can the process access this path?"); - } finally { - profilerInfo.closeFd(); + } catch (RuntimeException e) { + Slog.w(TAG, "Profiling failed on path " + profilerInfo.profileFile + + " -- can the process access this path?"); + } finally { + profilerInfo.closeFd(); + } } } else { switch (profileType) { + case ProfilerInfo.PROFILE_TYPE_LOW_OVERHEAD: + if (!com.android.art.flags.Flags.alwaysEnableProfileCode()) { + if (profilerInfo != null) { + profilerInfo.closeFd(); + } + Slog.w(TAG, "Low overhead tracing feature is not enabled"); + break; + } + if (profilerInfo != null) { + FileDescriptor fd = profilerInfo.profileFd.getFileDescriptor(); + VMDebug.TraceDestination dst = + VMDebug.TraceDestination.fromFileDescriptor(fd); + VMDebug.dumpLowOverheadTrace(dst); + } + VMDebug.stopLowOverheadTrace(); + break; default: mProfiler.stopProfiling(); break; diff --git a/core/java/android/app/AppCompatTaskInfo.java b/core/java/android/app/AppCompatTaskInfo.java index 009cd7249dcdb0d252ae16a631f3bdaa590b885c..61b56877589bba8978f2cb25e04d659a0e818c39 100644 --- a/core/java/android/app/AppCompatTaskInfo.java +++ b/core/java/android/app/AppCompatTaskInfo.java @@ -21,6 +21,7 @@ import static android.app.TaskInfo.PROPERTY_VALUE_UNSET; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; +import android.graphics.Rect; import android.os.Parcel; import android.os.Parcelable; @@ -68,6 +69,14 @@ public class AppCompatTaskInfo implements Parcelable { */ public int topActivityLetterboxAppWidth = PROPERTY_VALUE_UNSET; + /** + * Contains the top activity bounds when the activity is letterboxed. + * It's {@code null} if there's no top activity in the task or it's not letterboxed. + */ + // TODO(b/379824541) Remove duplicate information. + @Nullable + public Rect topActivityLetterboxBounds; + /** * Stores camera-related app compat information about a particular Task. */ @@ -378,6 +387,7 @@ public class AppCompatTaskInfo implements Parcelable { topActivityLetterboxHeight = source.readInt(); topActivityLetterboxAppWidth = source.readInt(); topActivityLetterboxAppHeight = source.readInt(); + topActivityLetterboxBounds = source.readTypedObject(Rect.CREATOR); cameraCompatTaskInfo = source.readTypedObject(CameraCompatTaskInfo.CREATOR); } @@ -393,6 +403,7 @@ public class AppCompatTaskInfo implements Parcelable { dest.writeInt(topActivityLetterboxHeight); dest.writeInt(topActivityLetterboxAppWidth); dest.writeInt(topActivityLetterboxAppHeight); + dest.writeTypedObject(topActivityLetterboxBounds, flags); dest.writeTypedObject(cameraCompatTaskInfo, flags); } @@ -415,6 +426,7 @@ public class AppCompatTaskInfo implements Parcelable { + " isUserFullscreenOverrideEnabled=" + isUserFullscreenOverrideEnabled() + " isSystemFullscreenOverrideEnabled=" + isSystemFullscreenOverrideEnabled() + " hasMinAspectRatioOverride=" + hasMinAspectRatioOverride() + + " topActivityLetterboxBounds=" + topActivityLetterboxBounds + " cameraCompatTaskInfo=" + cameraCompatTaskInfo.toString() + "}"; } diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java index 34765781d1059bbd36028cf9e6331c61c5bee9e6..19138126698cdb9028947f38c86f0b43abe1d681 100644 --- a/core/java/android/app/AppOpsManager.java +++ b/core/java/android/app/AppOpsManager.java @@ -3586,7 +3586,7 @@ public class AppOpsManager { /** Attribution tag of the proxy that noted the op */ private @Nullable String mAttributionTag; /** Persistent device Id of the proxy that noted the op */ - private @Nullable String mDeviceId; + private @NonNull String mDeviceId; /** * Reinit existing object with new state. @@ -3599,7 +3599,7 @@ public class AppOpsManager { * @hide */ public void reinit(@IntRange(from = 0) int uid, @Nullable String packageName, - @Nullable String attributionTag, @Nullable String deviceId) { + @Nullable String attributionTag, @NonNull String deviceId) { mUid = Preconditions.checkArgumentNonnegative(uid); mPackageName = packageName; mAttributionTag = attributionTag; @@ -3662,7 +3662,8 @@ public class AppOpsManager { "from", 0); this.mPackageName = packageName; this.mAttributionTag = attributionTag; - this.mDeviceId = deviceId; + this.mDeviceId = deviceId == null ? VirtualDeviceManager.PERSISTENT_DEVICE_ID_DEFAULT + : deviceId; } /** * Copy constructor @@ -3705,7 +3706,7 @@ public class AppOpsManager { * Persistent device Id of the proxy that noted the op */ @FlaggedApi(Flags.FLAG_DEVICE_ID_IN_OP_PROXY_INFO_ENABLED) - public @Nullable String getDeviceId() { return mDeviceId; } + public @NonNull String getDeviceId() { return mDeviceId; } @Override @DataClass.Generated.Member @@ -3716,12 +3717,12 @@ public class AppOpsManager { byte flg = 0; if (mPackageName != null) flg |= 0x2; if (mAttributionTag != null) flg |= 0x4; - if (mDeviceId != null) flg |= 0x8; + flg |= 0x8; dest.writeByte(flg); dest.writeInt(mUid); if (mPackageName != null) dest.writeString(mPackageName); if (mAttributionTag != null) dest.writeString(mAttributionTag); - if (mDeviceId != null) dest.writeString(mDeviceId); + dest.writeString(mDeviceId); } @Override @@ -3739,7 +3740,8 @@ public class AppOpsManager { int uid = in.readInt(); String packageName = (flg & 0x2) == 0 ? null : in.readString(); String attributionTag = (flg & 0x4) == 0 ? null : in.readString(); - String deviceId = (flg & 0x8) == 0 ? null : in.readString(); + String deviceId = (flg & 0x8) == 0 ? VirtualDeviceManager.PERSISTENT_DEVICE_ID_DEFAULT + : in.readString(); this.mUid = uid; com.android.internal.util.AnnotationValidations.validate( IntRange.class, null, mUid, diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java index 3cbea87e135e42370dfba09e2bf6a495f080d311..da338474a4488523cea7d9ca100367bf700ece30 100644 --- a/core/java/android/app/ApplicationPackageManager.java +++ b/core/java/android/app/ApplicationPackageManager.java @@ -798,7 +798,7 @@ public class ApplicationPackageManager extends PackageManager { private final static PropertyInvalidatedCache mHasSystemFeatureCache = new PropertyInvalidatedCache<>( new PropertyInvalidatedCache.Args(MODULE_SYSTEM) - .api(HAS_SYSTEM_FEATURE_API).maxEntries(256).isolateUids(false), + .api(HAS_SYSTEM_FEATURE_API).maxEntries(SDK_FEATURE_COUNT).isolateUids(false), HAS_SYSTEM_FEATURE_API, null) { @Override diff --git a/core/java/android/app/BroadcastStickyCache.java b/core/java/android/app/BroadcastStickyCache.java new file mode 100644 index 0000000000000000000000000000000000000000..fe2e1075235545c504d5e160383b5913df3a8f6c --- /dev/null +++ b/core/java/android/app/BroadcastStickyCache.java @@ -0,0 +1,215 @@ +/* + * 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.app; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.annotation.UserIdInt; +import android.content.Context.RegisterReceiverFlags; +import android.content.Intent; +import android.content.IntentFilter; +import android.hardware.usb.UsbManager; +import android.media.AudioManager; +import android.net.ConnectivityManager; +import android.net.TetheringManager; +import android.net.nsd.NsdManager; +import android.net.wifi.WifiManager; +import android.net.wifi.p2p.WifiP2pManager; +import android.os.IpcDataCache; +import android.os.IpcDataCache.Config; +import android.os.UpdateLock; +import android.telephony.TelephonyManager; +import android.util.ArrayMap; +import android.view.WindowManagerPolicyConstants; + +import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.util.ArrayUtils; + +/** @hide */ +public class BroadcastStickyCache { + + @VisibleForTesting + public static final String[] STICKY_BROADCAST_ACTIONS = { + AudioManager.ACTION_HDMI_AUDIO_PLUG, + AudioManager.ACTION_HEADSET_PLUG, + AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED, + AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED, + AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION, + AudioManager.RINGER_MODE_CHANGED_ACTION, + ConnectivityManager.CONNECTIVITY_ACTION, + Intent.ACTION_BATTERY_CHANGED, + Intent.ACTION_DEVICE_STORAGE_FULL, + Intent.ACTION_DEVICE_STORAGE_LOW, + Intent.ACTION_SIM_STATE_CHANGED, + NsdManager.ACTION_NSD_STATE_CHANGED, + TelephonyManager.ACTION_SERVICE_PROVIDERS_UPDATED, + TetheringManager.ACTION_TETHER_STATE_CHANGED, + UpdateLock.UPDATE_LOCK_CHANGED, + UsbManager.ACTION_USB_STATE, + WifiManager.ACTION_WIFI_SCAN_AVAILABILITY_CHANGED, + WifiManager.NETWORK_STATE_CHANGED_ACTION, + WifiManager.SUPPLICANT_STATE_CHANGED_ACTION, + WifiManager.WIFI_STATE_CHANGED_ACTION, + WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION, + WindowManagerPolicyConstants.ACTION_HDMI_PLUGGED, + "android.net.conn.INET_CONDITION_ACTION" // ConnectivityManager.INET_CONDITION_ACTION + }; + + @VisibleForTesting + public static final ArrayMap sActionApiNameMap = new ArrayMap<>(); + + private static final ArrayMap sActionConfigMap = new ArrayMap<>(); + + private static final ArrayMap> + sFilterCacheMap = new ArrayMap<>(); + + static { + sActionApiNameMap.put(AudioManager.ACTION_HDMI_AUDIO_PLUG, "hdmi_audio_plug"); + sActionApiNameMap.put(AudioManager.ACTION_HEADSET_PLUG, "headset_plug"); + sActionApiNameMap.put(AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED, + "sco_audio_state_changed"); + sActionApiNameMap.put(AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED, + "action_sco_audio_state_updated"); + sActionApiNameMap.put(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION, + "internal_ringer_mode_changed_action"); + sActionApiNameMap.put(AudioManager.RINGER_MODE_CHANGED_ACTION, + "ringer_mode_changed"); + sActionApiNameMap.put(ConnectivityManager.CONNECTIVITY_ACTION, + "connectivity_change"); + sActionApiNameMap.put(Intent.ACTION_BATTERY_CHANGED, "battery_changed"); + sActionApiNameMap.put(Intent.ACTION_DEVICE_STORAGE_FULL, "device_storage_full"); + sActionApiNameMap.put(Intent.ACTION_DEVICE_STORAGE_LOW, "device_storage_low"); + sActionApiNameMap.put(Intent.ACTION_SIM_STATE_CHANGED, "sim_state_changed"); + sActionApiNameMap.put(NsdManager.ACTION_NSD_STATE_CHANGED, "nsd_state_changed"); + sActionApiNameMap.put(TelephonyManager.ACTION_SERVICE_PROVIDERS_UPDATED, + "service_providers_updated"); + sActionApiNameMap.put(TetheringManager.ACTION_TETHER_STATE_CHANGED, + "tether_state_changed"); + sActionApiNameMap.put(UpdateLock.UPDATE_LOCK_CHANGED, "update_lock_changed"); + sActionApiNameMap.put(UsbManager.ACTION_USB_STATE, "usb_state"); + sActionApiNameMap.put(WifiManager.ACTION_WIFI_SCAN_AVAILABILITY_CHANGED, + "wifi_scan_availability_changed"); + sActionApiNameMap.put(WifiManager.NETWORK_STATE_CHANGED_ACTION, + "network_state_change"); + sActionApiNameMap.put(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION, + "supplicant_state_change"); + sActionApiNameMap.put(WifiManager.WIFI_STATE_CHANGED_ACTION, "wifi_state_changed"); + sActionApiNameMap.put( + WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION, "wifi_p2p_state_changed"); + sActionApiNameMap.put( + WindowManagerPolicyConstants.ACTION_HDMI_PLUGGED, "hdmi_plugged"); + sActionApiNameMap.put( + "android.net.conn.INET_CONDITION_ACTION", "inet_condition_action"); + } + + /** + * Checks whether we can use caching for the given filter. + */ + public static boolean useCache(@Nullable IntentFilter filter) { + return Flags.useStickyBcastCache() + && filter != null + && filter.safeCountActions() == 1 + && ArrayUtils.contains(STICKY_BROADCAST_ACTIONS, filter.getAction(0)); + } + + public static void invalidateCache(@NonNull String action) { + if (!Flags.useStickyBcastCache() + || !ArrayUtils.contains(STICKY_BROADCAST_ACTIONS, action)) { + return; + } + IpcDataCache.invalidateCache(IpcDataCache.MODULE_SYSTEM, + sActionApiNameMap.get(action)); + } + + public static void invalidateAllCaches() { + for (int i = sActionApiNameMap.size() - 1; i >= 0; i--) { + IpcDataCache.invalidateCache(IpcDataCache.MODULE_SYSTEM, + sActionApiNameMap.valueAt(i)); + } + } + + /** + * Returns the cached {@link Intent} based on the filter, if exits otherwise + * fetches the value from the service. + */ + @Nullable + public static Intent getIntent( + @NonNull IApplicationThread applicationThread, + @NonNull String mBasePackageName, + @Nullable String attributionTag, + @NonNull IntentFilter filter, + @Nullable String broadcastPermission, + @UserIdInt int userId, + @RegisterReceiverFlags int flags) { + IpcDataCache intentDataCache = findIpcDataCache(filter); + + if (intentDataCache == null) { + final String action = filter.getAction(0); + final StickyBroadcastFilter stickyBroadcastFilter = + new StickyBroadcastFilter(filter, action); + final Config config = getConfig(action); + + intentDataCache = + new IpcDataCache<>(config, + (query) -> ActivityManager.getService().registerReceiverWithFeature( + applicationThread, + mBasePackageName, + attributionTag, + /* receiverId= */ "null", + /* receiver= */ null, + filter, + broadcastPermission, + userId, + flags)); + sFilterCacheMap.put(stickyBroadcastFilter, intentDataCache); + } + return intentDataCache.query(null); + } + + @VisibleForTesting + public static void clearCacheForTest() { + sFilterCacheMap.clear(); + } + + @Nullable + private static IpcDataCache findIpcDataCache( + @NonNull IntentFilter filter) { + for (int i = sFilterCacheMap.size() - 1; i >= 0; i--) { + StickyBroadcastFilter existingFilter = sFilterCacheMap.keyAt(i); + if (filter.getAction(0).equals(existingFilter.action()) + && IntentFilter.filterEquals(existingFilter.filter(), filter)) { + return sFilterCacheMap.valueAt(i); + } + } + return null; + } + + @NonNull + private static IpcDataCache.Config getConfig(@NonNull String action) { + if (!sActionConfigMap.containsKey(action)) { + // We only need 1 entry per cache but just to be on the safer side we are choosing 32 + // although we don't expect more than 1. + sActionConfigMap.put(action, + new Config(32, IpcDataCache.MODULE_SYSTEM, sActionApiNameMap.get(action))); + } + + return sActionConfigMap.get(action); + } + + @VisibleForTesting + private record StickyBroadcastFilter(@NonNull IntentFilter filter, @NonNull String action) { + } +} diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java index cd56957ed5d17cb9a0a26a09b4096ef786cab593..dcbdc2348fbc244e9b84dbc39a24c3838552137d 100644 --- a/core/java/android/app/ContextImpl.java +++ b/core/java/android/app/ContextImpl.java @@ -1922,10 +1922,23 @@ class ContextImpl extends Context { } } try { - final Intent intent = ActivityManager.getService().registerReceiverWithFeature( - mMainThread.getApplicationThread(), mBasePackageName, getAttributionTag(), - AppOpsManager.toReceiverId(receiver), rd, filter, broadcastPermission, userId, - flags); + final Intent intent; + if (receiver == null && BroadcastStickyCache.useCache(filter)) { + intent = BroadcastStickyCache.getIntent( + mMainThread.getApplicationThread(), + mBasePackageName, + getAttributionTag(), + filter, + broadcastPermission, + userId, + flags); + } else { + intent = ActivityManager.getService().registerReceiverWithFeature( + mMainThread.getApplicationThread(), mBasePackageName, getAttributionTag(), + AppOpsManager.toReceiverId(receiver), rd, filter, broadcastPermission, + userId, flags); + } + if (intent != null) { intent.setExtrasClassLoader(getClassLoader()); // TODO: determine at registration time if caller is diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl index 0668958b2d5ca1f0f4dd2db2186b097e182886c9..50486611a5a9553678c8749930ffc927077b62a9 100644 --- a/core/java/android/app/IActivityManager.aidl +++ b/core/java/android/app/IActivityManager.aidl @@ -1028,4 +1028,14 @@ interface IActivityManager { @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.DEVICE_POWER)") void noteAppRestrictionEnabled(in String packageName, int uid, int restrictionType, boolean enabled, int reason, in String subReason, int source, long threshold); + + /** + * Creates and returns a new IntentCreatorToken that keeps the creatorUid and refreshes key + * fields of the intent passed in. + * + * @param intent The intent with key fields out of sync of the IntentCreatorToken it contains. + * @hide + */ + @EnforcePermission("INTERACT_ACROSS_USERS_FULL") + IBinder refreshIntentCreatorToken(in Intent intent); } diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java index 7fcae45ea4525dcda956c4b7dade42d3219ea99b..a4d8a5cd4673834e27f63dc2858a1fffd087d9af 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -817,18 +817,18 @@ public class Notification implements Parcelable R.layout.notification_2025_template_expanded_base, R.layout.notification_2025_template_heads_up_base, R.layout.notification_2025_template_header, + R.layout.notification_2025_template_conversation, + R.layout.notification_2025_template_collapsed_call, + R.layout.notification_2025_template_expanded_call, R.layout.notification_2025_template_collapsed_messaging, + R.layout.notification_2025_template_expanded_messaging, R.layout.notification_2025_template_collapsed_media, - R.layout.notification_template_material_big_picture, - R.layout.notification_template_material_big_text, - R.layout.notification_template_material_inbox, - R.layout.notification_template_material_big_messaging, - R.layout.notification_template_material_conversation, - R.layout.notification_template_material_big_media, - R.layout.notification_template_material_call, - R.layout.notification_template_material_big_call, - R.layout.notification_template_header -> true; - case R.layout.notification_template_material_progress -> Flags.apiRichOngoing(); + R.layout.notification_2025_template_expanded_media, + R.layout.notification_2025_template_expanded_big_picture, + R.layout.notification_2025_template_expanded_big_text, + R.layout.notification_2025_template_expanded_inbox -> true; + case R.layout.notification_2025_template_expanded_progress + -> Flags.apiRichOngoing(); default -> false; }; } @@ -5964,7 +5964,7 @@ public class Notification implements Parcelable private static void setHeaderlessVerticalMargins(RemoteViews contentView, StandardTemplateParams p, boolean hasSecondLine) { - if (!p.mHeaderless) { + if (Flags.notificationsRedesignTemplates() || !p.mHeaderless) { return; } int marginDimen = hasSecondLine @@ -6445,10 +6445,13 @@ public class Notification implements Parcelable // Clear view padding to allow buttons to start on the left edge. // This must be done before 'setEmphasizedMode' which sets top/bottom margins. big.setViewPadding(R.id.actions, 0, 0, 0, 0); - // Add an optional indent that will make buttons start at the correct column when - // there is enough space to do so (and fall back to the left edge if not). - big.setInt(R.id.actions, "setCollapsibleIndentDimen", - R.dimen.call_notification_collapsible_indent); + if (!Flags.notificationsRedesignTemplates()) { + // Add an optional indent that will make buttons start at the correct column + // when there is enough space to do so (and fall back to the left edge if not). + // This is handled directly in NotificationActionListLayout in the new design. + big.setInt(R.id.actions, "setCollapsibleIndentDimen", + R.dimen.call_notification_collapsible_indent); + } if (evenlyDividedCallStyleActionLayout()) { if (CallStyle.DEBUG_NEW_ACTION_LAYOUT) { Log.d(TAG, "setting evenly divided mode on action list"); @@ -6763,19 +6766,6 @@ public class Notification implements Parcelable return header; } - /** - * Construct a RemoteViews for the ambient version of the notification. - * - * @hide - */ - public RemoteViews makeAmbientNotification() { - RemoteViews headsUpContentView = createHeadsUpContentView(false /* increasedHeight */); - if (headsUpContentView != null) { - return headsUpContentView; - } - return createContentView(); - } - /** * Adapt the Notification header if this view is used as an expanded view. * @@ -7561,15 +7551,27 @@ public class Notification implements Parcelable } private int getBigPictureLayoutResource() { - return R.layout.notification_template_material_big_picture; + if (Flags.notificationsRedesignTemplates()) { + return R.layout.notification_2025_template_expanded_big_picture; + } else { + return R.layout.notification_template_material_big_picture; + } } private int getBigTextLayoutResource() { - return R.layout.notification_template_material_big_text; + if (Flags.notificationsRedesignTemplates()) { + return R.layout.notification_2025_template_expanded_big_text; + } else { + return R.layout.notification_template_material_big_text; + } } private int getInboxLayoutResource() { - return R.layout.notification_template_material_inbox; + if (Flags.notificationsRedesignTemplates()) { + return R.layout.notification_2025_template_expanded_inbox; + } else { + return R.layout.notification_template_material_inbox; + } } private int getCollapsedMessagingLayoutResource() { @@ -7581,7 +7583,11 @@ public class Notification implements Parcelable } private int getExpandedMessagingLayoutResource() { - return R.layout.notification_template_material_big_messaging; + if (Flags.notificationsRedesignTemplates()) { + return R.layout.notification_2025_template_expanded_messaging; + } else { + return R.layout.notification_template_material_big_messaging; + } } private int getCollapsedMediaLayoutResource() { @@ -7592,12 +7598,44 @@ public class Notification implements Parcelable } } + private int getExpandedMediaLayoutResource() { + if (Flags.notificationsRedesignTemplates()) { + return R.layout.notification_2025_template_expanded_media; + } else { + return R.layout.notification_template_material_big_media; + } + } + private int getConversationLayoutResource() { - return R.layout.notification_template_material_conversation; + if (Flags.notificationsRedesignTemplates()) { + return R.layout.notification_2025_template_conversation; + } else { + return R.layout.notification_template_material_conversation; + } + } + + private int getCollapsedCallLayoutResource() { + if (Flags.notificationsRedesignTemplates()) { + return R.layout.notification_2025_template_collapsed_call; + } else { + return R.layout.notification_template_material_call; + } + } + + private int getExpandedCallLayoutResource() { + if (Flags.notificationsRedesignTemplates()) { + return R.layout.notification_2025_template_expanded_call; + } else { + return R.layout.notification_template_material_big_call; + } } private int getProgressLayoutResource() { - return R.layout.notification_template_material_progress; + if (Flags.notificationsRedesignTemplates()) { + return R.layout.notification_2025_template_expanded_progress; + } else { + return R.layout.notification_template_material_progress; + } } private int getActionLayoutResource() { @@ -10521,7 +10559,7 @@ public class Notification implements Parcelable .fillTextsFrom(mBuilder); TemplateBindResult result = new TemplateBindResult(); RemoteViews template = mBuilder.applyStandardTemplate( - R.layout.notification_template_material_big_media, p , result); + mBuilder.getExpandedMediaLayoutResource(), p , result); for (int i = 0; i < MAX_MEDIA_BUTTONS; i++) { if (i < actionCount) { @@ -10944,10 +10982,10 @@ public class Notification implements Parcelable final RemoteViews contentView; if (isCollapsed) { contentView = mBuilder.applyStandardTemplate( - R.layout.notification_template_material_call, p, null /* result */); + mBuilder.getCollapsedCallLayoutResource(), p, null /* result */); } else { contentView = mBuilder.applyStandardTemplateWithActions( - R.layout.notification_template_material_big_call, p, null /* result */); + mBuilder.getExpandedCallLayoutResource(), p, null /* result */); } // Bind some extra conversation-specific header fields. @@ -14798,12 +14836,23 @@ public class Notification implements Parcelable } else { mBackgroundColor = rawColor; } - mPrimaryTextColor = ContrastColorUtil.findAlphaToMeetContrast( - ContrastColorUtil.resolvePrimaryColor(ctx, mBackgroundColor, nightMode), - mBackgroundColor, 4.5); - mSecondaryTextColor = ContrastColorUtil.findAlphaToMeetContrast( - ContrastColorUtil.resolveSecondaryColor(ctx, mBackgroundColor, nightMode), - mBackgroundColor, 4.5); + if (Flags.uiRichOngoing()) { + boolean isBgDark = Notification.Builder.isColorDark(mBackgroundColor); + int onSurfaceColorExtreme = isBgDark ? Color.WHITE : Color.BLACK; + mPrimaryTextColor = ContrastColorUtil.ensureContrast( + ColorUtils.blendARGB(mBackgroundColor, onSurfaceColorExtreme, 0.9f), + mBackgroundColor, isBgDark, 4.5); + mSecondaryTextColor = ContrastColorUtil.ensureContrast( + ColorUtils.blendARGB(mBackgroundColor, onSurfaceColorExtreme, 0.8f), + mBackgroundColor, isBgDark, 4.5); + } else { + mPrimaryTextColor = ContrastColorUtil.findAlphaToMeetContrast( + ContrastColorUtil.resolvePrimaryColor(ctx, mBackgroundColor, nightMode), + mBackgroundColor, 4.5); + mSecondaryTextColor = ContrastColorUtil.findAlphaToMeetContrast( + ContrastColorUtil.resolveSecondaryColor(ctx, + mBackgroundColor, nightMode), mBackgroundColor, 4.5); + } mContrastColor = mPrimaryTextColor; mPrimaryAccentColor = mPrimaryTextColor; mSecondaryAccentColor = mSecondaryTextColor; diff --git a/core/java/android/app/ProfilerInfo.java b/core/java/android/app/ProfilerInfo.java index bcae22a38f9e032dd3c122fb3911b37dff5cb641..0348b6de99645005c5512037c025e14b92e5560b 100644 --- a/core/java/android/app/ProfilerInfo.java +++ b/core/java/android/app/ProfilerInfo.java @@ -32,6 +32,12 @@ import java.util.Objects; * {@hide} */ public class ProfilerInfo implements Parcelable { + // Regular profiling which provides different modes of profiling at some performance cost. + public static final int PROFILE_TYPE_REGULAR = 0; + + // Low overhead profiling that captures a simple sliding window of past events. + public static final int PROFILE_TYPE_LOW_OVERHEAD = 1; + // Version of the profiler output public static final int OUTPUT_VERSION_DEFAULT = 1; // CLOCK_TYPE_DEFAULT chooses the default used by ART. ART uses CLOCK_TYPE_DUAL by default (see diff --git a/core/java/android/app/TEST_MAPPING b/core/java/android/app/TEST_MAPPING index 5ed1f4e355335d2ce6c43c521832c8b5524b3042..637187e01160f3bcd6611915ad3db332a28f7fdb 100644 --- a/core/java/android/app/TEST_MAPPING +++ b/core/java/android/app/TEST_MAPPING @@ -177,6 +177,10 @@ { "file_patterns": ["(/|^)AppOpsManager.java"], "name": "CtsAppOpsTestCases" + }, + { + "file_patterns": ["(/|^)BroadcastStickyCache.java"], + "name": "BroadcastUnitTests" } ] } diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java index abb2dd465576baaa1ef61830c39cade1aa45e50b..a8671cf746193d9bd00848477bfb9b334436e2e9 100644 --- a/core/java/android/app/WallpaperManager.java +++ b/core/java/android/app/WallpaperManager.java @@ -2491,6 +2491,27 @@ public class WallpaperManager { return result.getInt(EXTRA_NEW_WALLPAPER_ID, 0); } + /** + * Version of setBitmap that allows specification of wallpaper metadata including how the + * wallpaper will be positioned for different display sizes. + * + * @param fullImage A bitmap that will supply the wallpaper imagery. + * @param description Wallpaper metadata including desired cropping + * @param allowBackup {@code true} if the OS is permitted to back up this wallpaper + * image for restore to a future device; {@code false} otherwise. + * @param which Flags indicating which wallpaper(s) to configure with the new imagery. + * @hide + */ + @FlaggedApi(FLAG_LIVE_WALLPAPER_CONTENT_HANDLING) + @TestApi + @RequiresPermission(android.Manifest.permission.SET_WALLPAPER) + public int setBitmapWithDescription(@Nullable Bitmap fullImage, + @NonNull WallpaperDescription description, boolean allowBackup, + @SetWallpaperFlags int which) throws IOException { + return setBitmapWithCrops(fullImage, description.getCropHints(), allowBackup, which, + mContext.getUserId()); + } + private final void validateRect(Rect rect) { if (rect != null && rect.isEmpty()) { throw new IllegalArgumentException("visibleCrop rectangle must be valid and non-empty"); @@ -2699,6 +2720,27 @@ public class WallpaperManager { return result.getInt(EXTRA_NEW_WALLPAPER_ID, 0); } + /** + * Version of setStream that allows specification of wallpaper metadata including how the + * wallpaper will be positioned for different display sizes. + * + * @param bitmapData A stream containing the raw data to install as a wallpaper. This + * data can be in any format handled by {@link BitmapRegionDecoder}. + * @param description Wallpaper metadata including desired cropping + * @param allowBackup {@code true} if the OS is permitted to back up this wallpaper + * image for restore to a future device; {@code false} otherwise. + * @param which Flags indicating which wallpaper(s) to configure with the new imagery. + * @hide + */ + @FlaggedApi(FLAG_LIVE_WALLPAPER_CONTENT_HANDLING) + @TestApi + @RequiresPermission(android.Manifest.permission.SET_WALLPAPER) + public int setStreamWithDescription(@NonNull InputStream bitmapData, + @NonNull WallpaperDescription description, boolean allowBackup, + @SetWallpaperFlags int which) throws IOException { + return setStreamWithCrops(bitmapData, description.getCropHints(), allowBackup, which); + } + /** * Return whether any users are currently set to use the wallpaper * with the given resource ID. That is, their wallpaper has been diff --git a/core/java/android/app/activity_manager.aconfig b/core/java/android/app/activity_manager.aconfig index 1f31ab5d1849cd27db9e01cd3ffed1b8d5a8757a..44940aee6a49c58b8acb7937d78b986427b43d0b 100644 --- a/core/java/android/app/activity_manager.aconfig +++ b/core/java/android/app/activity_manager.aconfig @@ -164,4 +164,5 @@ flag { name: "app_start_info_component" description: "Control ApplicationStartInfo component field and API" bug: "362537357" + is_exported: true } diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index 74d729857cc8da9daefcdb73a74fe77a12c73c25..8372078b46a59ba6534ca2d299a3cd1fe03d2527 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -12485,6 +12485,36 @@ public class DevicePolicyManager { return null; } + /** + * Returns the {@link EnforcingAdmin} who have set this policy. + * + *

Important: this API is a temporary solution, hence should be kept hidden. That is because + * the string argument can't define policies with arguments. + * + *

Note that for {@link #POLICY_SUSPEND_PACKAGES} it returns the PO or DO to keep the + * behavior the same as before the bug fix for b/192245204. + * + *

This API is only callable by the system UID + * + * @param userId The user for whom to retrieve the information. + * @param identifier The policy enforced by admins. It could be any user restriction or + * policy like {@link DevicePolicyManager#POLICY_DISABLE_CAMERA} and + * {@link DevicePolicyManager#POLICY_DISABLE_SCREEN_CAPTURE}. This also works + * for {@link DevicePolicyIdentifiers#MEMORY_TAGGING_POLICY}. + * + * @hide + */ + public @Nullable EnforcingAdmin getEnforcingAdmin(int userId, String identifier) { + if (mService != null) { + try { + return mService.getEnforcingAdmin(userId, identifier); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + return null; + } + /** * Returns the list of {@link EnforcingAdmin}s who have set this restriction. * diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl index e7be822d52d3367193241cf91069b1b5ee04e64c..03a9f99550864e8df1ba335e7565cdcfc77c5694 100644 --- a/core/java/android/app/admin/IDevicePolicyManager.aidl +++ b/core/java/android/app/admin/IDevicePolicyManager.aidl @@ -279,8 +279,9 @@ interface IDevicePolicyManager { boolean isNotificationListenerServicePermitted(in String packageName, int userId); Intent createAdminSupportIntent(in String restriction); - Bundle getEnforcingAdminAndUserDetails(int userId,String restriction); - List getEnforcingAdminsForRestriction(int userId,String restriction); + Bundle getEnforcingAdminAndUserDetails(int userId, String restriction); + EnforcingAdmin getEnforcingAdmin(int userId, String identifier); + List getEnforcingAdminsForRestriction(int userId, String restriction); boolean setApplicationHidden(in ComponentName admin, in String callerPackage, in String packageName, boolean hidden, boolean parent); boolean isApplicationHidden(in ComponentName admin, in String callerPackage, in String packageName, boolean parent); diff --git a/core/java/android/app/admin/UnknownAuthority.java b/core/java/android/app/admin/UnknownAuthority.java index fdad898b7bd9797aee50fd9b2a2ef0b37dd3b11d..82dcf7e1a115514a0d63a684c20883ce377ea057 100644 --- a/core/java/android/app/admin/UnknownAuthority.java +++ b/core/java/android/app/admin/UnknownAuthority.java @@ -22,6 +22,8 @@ import android.annotation.SystemApi; import android.annotation.TestApi; import android.os.Parcel; +import java.util.Objects; + /** * Class used to identify a default value for the authority of the {@link EnforcingAdmin} setting * a policy, meaning it is not one of the other known subclasses of {@link Authority}, this would be @@ -31,6 +33,7 @@ import android.os.Parcel; */ @SystemApi public final class UnknownAuthority extends Authority { + private final String mName; /** * Object representing an unknown authority. @@ -45,22 +48,40 @@ public final class UnknownAuthority extends Authority { * Creates an authority that represents an admin that can set a policy but * doesn't have a known authority (e.g. a system components). */ - public UnknownAuthority() {} + public UnknownAuthority() { + mName = null; + } + + /** @hide */ + public UnknownAuthority(String name) { + mName = name; + } + + private UnknownAuthority(Parcel source) { + this(source.readString8()); + } + + /** @hide */ + public String getName() { + return mName; + } @Override public String toString() { - return "DefaultAuthority {}"; + return "DefaultAuthority {" + mName + "}"; } @Override public boolean equals(@Nullable Object o) { if (this == o) return true; - return o != null && getClass() == o.getClass(); + if (o != null && getClass() == o.getClass()) return false; + UnknownAuthority other = (UnknownAuthority) o; + return Objects.equals(mName, other.mName); } @Override public int hashCode() { - return 0; + return mName.hashCode(); } @Override @@ -69,14 +90,16 @@ public final class UnknownAuthority extends Authority { } @Override - public void writeToParcel(@NonNull Parcel dest, int flags) {} + public void writeToParcel(@NonNull Parcel dest, int flags) { + dest.writeString8(mName); + } @NonNull public static final Creator CREATOR = new Creator() { @Override public UnknownAuthority createFromParcel(Parcel source) { - return UNKNOWN_AUTHORITY; + return new UnknownAuthority(source); } @Override diff --git a/core/java/android/app/admin/flags/flags.aconfig b/core/java/android/app/admin/flags/flags.aconfig index 581efa5d2efab6fbd225a0fc568a0f20aeb36aad..22bc356899f4c262ec201f86d574f002e0d15d49 100644 --- a/core/java/android/app/admin/flags/flags.aconfig +++ b/core/java/android/app/admin/flags/flags.aconfig @@ -285,6 +285,16 @@ flag { } } +flag { + name: "unsuspend_not_suspended" + namespace: "enterprise" + description: "When admin unsuspends packages, pass previously not suspended packages to PM too" + bug: "378766314" + metadata { + purpose: PURPOSE_BUGFIX + } +} + flag { name: "backup_connected_apps_settings" namespace: "enterprise" @@ -367,6 +377,7 @@ flag { namespace: "enterprise" description: "API that removes a given managed profile." bug: "372652841" + is_exported: true } flag { @@ -390,6 +401,7 @@ flag { namespace: "enterprise" description: "Split up existing create and provision managed profile API." bug: "375382324" + is_exported: true } flag { diff --git a/core/java/android/app/appfunctions/AppFunctionException.java b/core/java/android/app/appfunctions/AppFunctionException.java index cbd1d932ab00e7d860063aced888c648d818eb3c..c8d80d3afe43ad33be727f1780bcdd840a75c8ad 100644 --- a/core/java/android/app/appfunctions/AppFunctionException.java +++ b/core/java/android/app/appfunctions/AppFunctionException.java @@ -29,7 +29,14 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.Objects; -/** Represents an app function related errors. */ +/** + * Represents an app function related error. + * + *

This exception may include an {@link AppFunctionException#getExtras() Bundle} + * containing additional error-specific metadata. + * + *

The AppFunction SDK can expose structured APIs by packing and unpacking this Bundle. + */ @FlaggedApi(FLAG_ENABLE_APP_FUNCTION_MANAGER) public final class AppFunctionException extends Exception implements Parcelable { /** diff --git a/core/java/android/app/appfunctions/ExecuteAppFunctionRequest.java b/core/java/android/app/appfunctions/ExecuteAppFunctionRequest.java index 1557815a8468993cbef54039fad55a8691daf770..a88198a4ec7cf04a93a8f83cbca2bc854070a546 100644 --- a/core/java/android/app/appfunctions/ExecuteAppFunctionRequest.java +++ b/core/java/android/app/appfunctions/ExecuteAppFunctionRequest.java @@ -27,7 +27,16 @@ import android.os.Parcelable; import java.util.Objects; -/** A request to execute an app function. */ +/** + * A request to execute an app function. + * + *

The {@link ExecuteAppFunctionRequest#getParameters()} contains the parameters for the function + * to be executed in a GenericDocument. Structured classes defined in the AppFunction SDK can be + * converted into GenericDocuments. + * + *

The {@link ExecuteAppFunctionRequest#getExtras()} provides any extra metadata for the request. + * Structured APIs can be exposed in the SDK by packing and unpacking this Bundle. + */ @FlaggedApi(FLAG_ENABLE_APP_FUNCTION_MANAGER) public final class ExecuteAppFunctionRequest implements Parcelable { @NonNull diff --git a/core/java/android/app/appfunctions/ExecuteAppFunctionResponse.java b/core/java/android/app/appfunctions/ExecuteAppFunctionResponse.java index acad43b782e520f2974c25fb45ca2c98f011e5af..a4952f48605934ba163ad9b4df540c1e3f03a969 100644 --- a/core/java/android/app/appfunctions/ExecuteAppFunctionResponse.java +++ b/core/java/android/app/appfunctions/ExecuteAppFunctionResponse.java @@ -27,7 +27,16 @@ import android.os.Parcelable; import java.util.Objects; -/** The response to an app function execution. */ +/** + * The response to an app function execution. + * + *

The {@link ExecuteAppFunctionResponse#getResultDocument()} contains the function's return + * value as a GenericDocument. This can be converted back into a structured class using the + * AppFunction SDK. + * + *

The {@link ExecuteAppFunctionResponse#getExtras()} provides any extra metadata returned by the + * function. The AppFunction SDK can expose structured APIs by packing and unpacking this Bundle. + */ @FlaggedApi(FLAG_ENABLE_APP_FUNCTION_MANAGER) public final class ExecuteAppFunctionResponse implements Parcelable { @NonNull diff --git a/core/java/android/app/assist/AssistContent.java b/core/java/android/app/assist/AssistContent.java index 43a46ba7885d112000775a928d3ef78dc3dd4622..3e3ca2488bd3923856ce9c23779c5205a984b785 100644 --- a/core/java/android/app/assist/AssistContent.java +++ b/core/java/android/app/assist/AssistContent.java @@ -30,6 +30,31 @@ public class AssistContent implements Parcelable { public static final String EXTRA_APP_FUNCTION_DATA = "android.app.assist.extra.APP_FUNCTION_DATA"; + /** + * This extra can be optionally supplied in the {@link #getExtras} bundle to provide a + * {@link Uri} which will be utilized when transitioning a user's session to another surface. + * + *

If provided, instead of using the URI provided in {@link #setWebUri}, the + * "Open in browser" feature will use this URI to transition the current session from one + * surface to the other. Apps may choose to encode session or user information into this + * URI in order to provide a better session transfer experience. + * + *

Unlike {@link #setWebUri}, this URI will not be used for features where the user might + * accidentally share it with another user. However, developers should not encode + * authentication credentials into this URI, because it will be surfaced in the browser URL + * bar and may be copied and shared from there. + * + *

When providing this extra, developers should still continue to provide + * {@link #setWebUri} for backwards compatibility with features such as + * + * recents URL sharing which do not benefit from a session-transfer web URI. + * + * @see android.app.Activity#requestOpenInBrowserEducation() + */ + @FlaggedApi(com.android.window.flags.Flags.FLAG_ENABLE_DESKTOP_WINDOWING_APP_TO_WEB_EDUCATION) + public static final String EXTRA_SESSION_TRANSFER_WEB_URI = + "android.app.assist.extra.SESSION_TRANSFER_WEB_URI"; + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) private boolean mIsAppProvidedIntent = false; private boolean mIsAppProvidedWebUri = false; diff --git a/core/java/android/app/contextualsearch/flags.aconfig b/core/java/android/app/contextualsearch/flags.aconfig index 5e09517d1edcdef96a8ca0e11a16550ae56c18af..529b59ac424dbda645bdfb805db48ffdab7963f6 100644 --- a/core/java/android/app/contextualsearch/flags.aconfig +++ b/core/java/android/app/contextualsearch/flags.aconfig @@ -6,6 +6,7 @@ flag { namespace: "machine_learning" description: "Flag to enable the service" bug: "309689654" + is_exported: true } flag { name: "enable_token_refresh" diff --git a/core/java/android/app/jank/flags.aconfig b/core/java/android/app/jank/flags.aconfig index 5657f7ee5194263ec8a9ea37843cb0a476becf35..a62df1b3cbf7562e92151f7857ec2971c2f9b464 100644 --- a/core/java/android/app/jank/flags.aconfig +++ b/core/java/android/app/jank/flags.aconfig @@ -6,6 +6,7 @@ flag { namespace: "system_performance" description: "Control the API portion of Detailed Application Jank Metrics" bug: "366264614" + is_exported: true } flag { diff --git a/core/java/android/app/supervision/flags.aconfig b/core/java/android/app/supervision/flags.aconfig index d5e696d49ff41cb78fbc2ff0febe25e61aa6e54c..d4f82f665fd418fa13995451897abfd4f419e549 100644 --- a/core/java/android/app/supervision/flags.aconfig +++ b/core/java/android/app/supervision/flags.aconfig @@ -16,3 +16,11 @@ flag { description: "Flag to enable the SupervisionService on Wear devices" bug: "373358935" } + +flag { + name: "enable_sync_with_dpm" + is_exported: true + namespace: "supervision" + description: "Flag that enables supervision when the supervision app is the profile owner" + bug: "377261590" +} diff --git a/core/java/android/app/wallpaper/WallpaperDescription.java b/core/java/android/app/wallpaper/WallpaperDescription.java index 4a142bb5287afb94d001ed3a32a0d1ea0cbef688..3ee00ca3d9412c389393ad41ac212e6dd32976d1 100644 --- a/core/java/android/app/wallpaper/WallpaperDescription.java +++ b/core/java/android/app/wallpaper/WallpaperDescription.java @@ -19,8 +19,14 @@ package android.app.wallpaper; import static android.app.Flags.FLAG_LIVE_WALLPAPER_CONTENT_HANDLING; import android.annotation.FlaggedApi; +import android.annotation.SuppressLint; +import android.annotation.TestApi; import android.app.WallpaperInfo; +import android.app.WallpaperManager; +import android.app.WallpaperManager.ScreenOrientation; import android.content.ComponentName; +import android.graphics.Point; +import android.graphics.Rect; import android.net.Uri; import android.os.Parcel; import android.os.Parcelable; @@ -29,6 +35,8 @@ import android.text.Html; import android.text.Spanned; import android.text.SpannedString; import android.util.Log; +import android.util.Pair; +import android.util.SparseArray; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -43,6 +51,7 @@ import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.Map; import java.util.Objects; /** @@ -71,12 +80,15 @@ public final class WallpaperDescription implements Parcelable { @Nullable private final Uri mContextUri; @Nullable private final CharSequence mContextDescription; @NonNull private final PersistableBundle mContent; + @NonNull private final SparseArray mCropHints; + private final float mSampleSize; private WallpaperDescription(@Nullable ComponentName component, @Nullable String id, @Nullable Uri thumbnail, @Nullable CharSequence title, @Nullable List description, @Nullable Uri contextUri, @Nullable CharSequence contextDescription, - @Nullable PersistableBundle content) { + @Nullable PersistableBundle content, @NonNull SparseArray cropHints, + float sampleSize) { this.mComponent = component; this.mId = id; this.mThumbnail = thumbnail; @@ -85,6 +97,8 @@ public final class WallpaperDescription implements Parcelable { this.mContextUri = contextUri; this.mContextDescription = contextDescription; this.mContent = (content != null) ? content : new PersistableBundle(); + this.mCropHints = cropHints; + this.mSampleSize = sampleSize; } /** @return the component for this wallpaper, or {@code null} for a static wallpaper */ @@ -134,6 +148,24 @@ public final class WallpaperDescription implements Parcelable { return mContent; } + /** + * @return the cropping for the current image as described in + * {@link Builder#setCropHints(SparseArray)} + * @hide + */ + @NonNull + public SparseArray getCropHints() { + return mCropHints; + } + + /** + * @return the subsamling size as described in {@link Builder#setSampleSize(float)}. + * @hide + */ + public float getSampleSize() { + return mSampleSize; + } + ////// Comparison overrides @Override @@ -163,9 +195,23 @@ public final class WallpaperDescription implements Parcelable { if (mContextDescription != null) { out.attribute(null, "contextdescription", toHtml(mContextDescription)); } + + for (Pair pair : screenDimensionPairs()) { + @ScreenOrientation int orientation = pair.first; + String attrName = pair.second; + Rect cropHint = mCropHints.get(orientation); + if (cropHint == null) continue; + out.attributeInt(null, "cropLeft" + attrName, cropHint.left); + out.attributeInt(null, "cropTop" + attrName, cropHint.top); + out.attributeInt(null, "cropRight" + attrName, cropHint.right); + out.attributeInt(null, "cropBottom" + attrName, cropHint.bottom); + } + out.attributeFloat(null, "sampleSize", mSampleSize); + out.startTag(null, XML_TAG_DESCRIPTION); for (CharSequence s : mDescription) out.attribute(null, "descriptionline", toHtml(s)); out.endTag(null, XML_TAG_DESCRIPTION); + try { out.startTag(null, XML_TAG_CONTENT); mContent.saveToXml(out); @@ -194,6 +240,19 @@ public final class WallpaperDescription implements Parcelable { CharSequence contextDescription = fromHtml( in.getAttributeValue(null, "contextdescription")); + SparseArray cropHints = new SparseArray<>(); + screenDimensionPairs().forEach(pair -> { + @ScreenOrientation int orientation = pair.first; + String attrName = pair.second; + Rect crop = new Rect( + in.getAttributeInt(null, "cropLeft" + attrName, 0), + in.getAttributeInt(null, "cropTop" + attrName, 0), + in.getAttributeInt(null, "cropRight" + attrName, 0), + in.getAttributeInt(null, "cropBottom" + attrName, 0)); + if (!crop.isEmpty()) cropHints.put(orientation, crop); + }); + float sampleSize = in.getAttributeFloat(null, "sampleSize", 1f); + List description = new ArrayList<>(); PersistableBundle content = null; int type; @@ -213,7 +272,7 @@ public final class WallpaperDescription implements Parcelable { } return new WallpaperDescription(componentName, id, thumbnail, title, description, - contextUri, contextDescription, content); + contextUri, contextDescription, content, cropHints, sampleSize); } private static String toHtml(@NonNull CharSequence c) { @@ -253,6 +312,13 @@ public final class WallpaperDescription implements Parcelable { mContextUri = Uri.CREATOR.createFromParcel(in); mContextDescription = in.readCharSequence(); mContent = PersistableBundle.CREATOR.createFromParcel(in); + mCropHints = new SparseArray<>(); + screenDimensionPairs().forEach(pair -> { + int orientation = pair.first; + Rect crop = in.readTypedObject(Rect.CREATOR); + if (crop != null) mCropHints.put(orientation, crop); + }); + mSampleSize = in.readFloat(); } @NonNull @@ -283,6 +349,11 @@ public final class WallpaperDescription implements Parcelable { Uri.writeToParcel(dest, mContextUri); dest.writeCharSequence(mContextDescription); dest.writePersistableBundle(mContent); + screenDimensionPairs().forEach(pair -> { + int orientation = pair.first; + dest.writeTypedObject(mCropHints.get(orientation), flags); + }); + dest.writeFloat(mSampleSize); } ////// Builder @@ -293,9 +364,17 @@ public final class WallpaperDescription implements Parcelable { */ @NonNull public Builder toBuilder() { - return new Builder().setComponent(mComponent).setId(mId).setThumbnail(mThumbnail).setTitle( - mTitle).setDescription(mDescription).setContextUri( - mContextUri).setContextDescription(mContextDescription).setContent(mContent); + return new Builder() + .setComponent(mComponent) + .setId(mId) + .setThumbnail(mThumbnail) + .setTitle(mTitle) + .setDescription(mDescription) + .setContextUri(mContextUri) + .setContextDescription(mContextDescription) + .setContent(mContent) + .setCropHints(mCropHints) + .setSampleSize(mSampleSize); } /** Builder for the immutable {@link WallpaperDescription} class */ @@ -308,6 +387,9 @@ public final class WallpaperDescription implements Parcelable { @Nullable private Uri mContextUri; @Nullable private CharSequence mContextDescription; @NonNull private PersistableBundle mContent = new PersistableBundle(); + @NonNull + private SparseArray mCropHints = new SparseArray<>(); + private float mSampleSize = 1f; /** Creates a new, empty {@link Builder}. */ public Builder() {} @@ -416,11 +498,69 @@ public final class WallpaperDescription implements Parcelable { return this; } + /** + * Defines which part of the source wallpaper image is in the stored crop file. + * + * @param cropHints map from screen dimensions to a sub-region of the image to display + * for those dimensions. The {@code Rect} sub-region may have a larger + * width/height ratio than the screen dimensions to apply a horizontal + * parallax effect. If the map is empty or some entries are missing, the + * system will apply a default strategy to position the wallpaper for + * any unspecified screen dimensions. + * @hide + */ + @NonNull + @TestApi + @SuppressLint("MissingGetterMatchingBuilder") + public Builder setCropHints(@NonNull Map cropHints) { + mCropHints = new SparseArray<>(); + cropHints.forEach( + (point, rect) -> mCropHints.put(WallpaperManager.getOrientation(point), rect)); + return this; + } + + /** + * Defines which part of the source wallpaper image is in the stored crop file. + * + * @param cropHints map from {@link ScreenOrientation} to a sub-region of the image to + * display for that screen orientation. + * @hide + */ + @NonNull + @TestApi + @SuppressLint("MissingGetterMatchingBuilder") + public Builder setCropHints(@NonNull SparseArray cropHints) { + mCropHints = cropHints; + return this; + } + + /** + * How much the crop is sub-sampled. A value > 1 means that the image quality was reduced. + * This is the ratio between the cropHint height and the actual stored crop file height. + * height. + * + * @param sampleSize Sub-sampling value + * @hide + */ + @NonNull + public Builder setSampleSize(float sampleSize) { + mSampleSize = sampleSize; + return this; + } + /** Creates and returns the {@link WallpaperDescription} represented by this builder. */ @NonNull public WallpaperDescription build() { return new WallpaperDescription(mComponent, mId, mThumbnail, mTitle, mDescription, - mContextUri, mContextDescription, mContent); + mContextUri, mContextDescription, mContent, mCropHints, mSampleSize); } } + + private static List> screenDimensionPairs() { + return List.of( + new Pair<>(WallpaperManager.ORIENTATION_PORTRAIT, "Portrait"), + new Pair<>(WallpaperManager.ORIENTATION_LANDSCAPE, "Landscape"), + new Pair<>(WallpaperManager.ORIENTATION_SQUARE_PORTRAIT, "SquarePortrait"), + new Pair<>(WallpaperManager.ORIENTATION_SQUARE_LANDSCAPE, "SquareLandscape")); + } } diff --git a/core/java/android/appwidget/flags.aconfig b/core/java/android/appwidget/flags.aconfig index 17bcdb013673ed42fdaa1925e727ac954b82684f..9914ba2b020ab54f9dbfa7f17ffaaf2e68c3a572 100644 --- a/core/java/android/appwidget/flags.aconfig +++ b/core/java/android/appwidget/flags.aconfig @@ -111,4 +111,5 @@ flag { namespace: "app_widgets" description: "Enable collection of widget engagement metrics" bug: "364655296" + is_exported: true } diff --git a/core/java/android/companion/AssociationInfo.java b/core/java/android/companion/AssociationInfo.java index 124973489dd197f7b4abb16702022e6fb2badd65..2f161150a89bfac74169fe571ac2dcffc3a1642a 100644 --- a/core/java/android/companion/AssociationInfo.java +++ b/core/java/android/companion/AssociationInfo.java @@ -54,8 +54,6 @@ public final class AssociationInfo implements Parcelable { @NonNull private final String mPackageName; @Nullable - private final String mTag; - @Nullable private final MacAddress mDeviceMacAddress; @Nullable private final CharSequence mDisplayName; @@ -85,6 +83,8 @@ public final class AssociationInfo implements Parcelable { */ private final long mLastTimeConnectedMs; private final int mSystemDataSyncFlags; + @Nullable + private final DeviceId mDeviceId; /** * A device icon displayed on a selfManaged association dialog. @@ -97,11 +97,11 @@ public final class AssociationInfo implements Parcelable { * @hide */ public AssociationInfo(int id, @UserIdInt int userId, @NonNull String packageName, - @Nullable String tag, @Nullable MacAddress macAddress, - @Nullable CharSequence displayName, @Nullable String deviceProfile, - @Nullable AssociatedDevice associatedDevice, boolean selfManaged, - boolean notifyOnDeviceNearby, boolean revoked, boolean pending, long timeApprovedMs, - long lastTimeConnectedMs, int systemDataSyncFlags, @Nullable Icon deviceIcon) { + @Nullable MacAddress macAddress, @Nullable CharSequence displayName, + @Nullable String deviceProfile, @Nullable AssociatedDevice associatedDevice, + boolean selfManaged, boolean notifyOnDeviceNearby, boolean revoked, boolean pending, + long timeApprovedMs, long lastTimeConnectedMs, int systemDataSyncFlags, + @Nullable Icon deviceIcon, @Nullable DeviceId deviceId) { if (id <= 0) { throw new IllegalArgumentException("Association ID should be greater than 0"); } @@ -115,7 +115,6 @@ public final class AssociationInfo implements Parcelable { mPackageName = packageName; mDeviceMacAddress = macAddress; mDisplayName = displayName; - mTag = tag; mDeviceProfile = deviceProfile; mAssociatedDevice = associatedDevice; mSelfManaged = selfManaged; @@ -126,6 +125,7 @@ public final class AssociationInfo implements Parcelable { mLastTimeConnectedMs = lastTimeConnectedMs; mSystemDataSyncFlags = systemDataSyncFlags; mDeviceIcon = deviceIcon; + mDeviceId = deviceId; } /** @@ -155,13 +155,13 @@ public final class AssociationInfo implements Parcelable { } /** - * @return the tag of this association. - * @see CompanionDeviceManager#setAssociationTag(int, String) + * @return the {@link DeviceId} of this association. + * @see CompanionDeviceManager#setDeviceId(int, DeviceId) */ @FlaggedApi(Flags.FLAG_ASSOCIATION_TAG) @Nullable - public String getTag() { - return mTag; + public DeviceId getDeviceId() { + return mDeviceId; } /** @@ -355,7 +355,6 @@ public final class AssociationInfo implements Parcelable { + "mId=" + mId + ", mUserId=" + mUserId + ", mPackageName='" + mPackageName + '\'' - + ", mTag='" + mTag + '\'' + ", mDeviceMacAddress=" + mDeviceMacAddress + ", mDisplayName='" + mDisplayName + '\'' + ", mDeviceProfile='" + mDeviceProfile + '\'' @@ -369,6 +368,7 @@ public final class AssociationInfo implements Parcelable { mLastTimeConnectedMs == Long.MAX_VALUE ? LAST_TIME_CONNECTED_NONE : new Date(mLastTimeConnectedMs)) + ", mSystemDataSyncFlags=" + mSystemDataSyncFlags + + ", mDeviceId='" + mDeviceId + '}'; } @@ -386,21 +386,22 @@ public final class AssociationInfo implements Parcelable { && mTimeApprovedMs == that.mTimeApprovedMs && mLastTimeConnectedMs == that.mLastTimeConnectedMs && Objects.equals(mPackageName, that.mPackageName) - && Objects.equals(mTag, that.mTag) && Objects.equals(mDeviceMacAddress, that.mDeviceMacAddress) && Objects.equals(mDisplayName, that.mDisplayName) && Objects.equals(mDeviceProfile, that.mDeviceProfile) && Objects.equals(mAssociatedDevice, that.mAssociatedDevice) && mSystemDataSyncFlags == that.mSystemDataSyncFlags && (mDeviceIcon == null ? that.mDeviceIcon == null - : mDeviceIcon.sameAs(that.mDeviceIcon)); + : mDeviceIcon.sameAs(that.mDeviceIcon)) + && Objects.equals(mDeviceId, that.mDeviceId); } @Override public int hashCode() { - return Objects.hash(mId, mUserId, mPackageName, mTag, mDeviceMacAddress, mDisplayName, + return Objects.hash(mId, mUserId, mPackageName, mDeviceMacAddress, mDisplayName, mDeviceProfile, mAssociatedDevice, mSelfManaged, mNotifyOnDeviceNearby, mRevoked, - mPending, mTimeApprovedMs, mLastTimeConnectedMs, mSystemDataSyncFlags, mDeviceIcon); + mPending, mTimeApprovedMs, mLastTimeConnectedMs, mSystemDataSyncFlags, mDeviceIcon, + mDeviceId); } @Override @@ -413,7 +414,6 @@ public final class AssociationInfo implements Parcelable { dest.writeInt(mId); dest.writeInt(mUserId); dest.writeString(mPackageName); - dest.writeString(mTag); dest.writeTypedObject(mDeviceMacAddress, 0); dest.writeCharSequence(mDisplayName); dest.writeString(mDeviceProfile); @@ -431,13 +431,19 @@ public final class AssociationInfo implements Parcelable { } else { dest.writeInt(0); } + + if (Flags.associationTag() && mDeviceId != null) { + dest.writeInt(1); + dest.writeTypedObject(mDeviceId, flags); + } else { + dest.writeInt(0); + } } private AssociationInfo(@NonNull Parcel in) { mId = in.readInt(); mUserId = in.readInt(); mPackageName = in.readString(); - mTag = in.readString(); mDeviceMacAddress = in.readTypedObject(MacAddress.CREATOR); mDisplayName = in.readCharSequence(); mDeviceProfile = in.readString(); @@ -454,6 +460,12 @@ public final class AssociationInfo implements Parcelable { } else { mDeviceIcon = null; } + int deviceId = in.readInt(); + if (Flags.associationTag() && deviceId == 1) { + mDeviceId = in.readTypedObject(DeviceId.CREATOR); + } else { + mDeviceId = null; + } } @NonNull @@ -481,7 +493,6 @@ public final class AssociationInfo implements Parcelable { private final int mId; private final int mUserId; private final String mPackageName; - private String mTag; private MacAddress mDeviceMacAddress; private CharSequence mDisplayName; private String mDeviceProfile; @@ -494,6 +505,7 @@ public final class AssociationInfo implements Parcelable { private long mLastTimeConnectedMs; private int mSystemDataSyncFlags; private Icon mDeviceIcon; + private DeviceId mDeviceId; /** @hide */ @TestApi @@ -509,7 +521,6 @@ public final class AssociationInfo implements Parcelable { mId = info.mId; mUserId = info.mUserId; mPackageName = info.mPackageName; - mTag = info.mTag; mDeviceMacAddress = info.mDeviceMacAddress; mDisplayName = info.mDisplayName; mDeviceProfile = info.mDeviceProfile; @@ -522,6 +533,7 @@ public final class AssociationInfo implements Parcelable { mLastTimeConnectedMs = info.mLastTimeConnectedMs; mSystemDataSyncFlags = info.mSystemDataSyncFlags; mDeviceIcon = info.mDeviceIcon; + mDeviceId = info.mDeviceId; } /** @@ -534,7 +546,6 @@ public final class AssociationInfo implements Parcelable { mId = id; mUserId = userId; mPackageName = packageName; - mTag = info.mTag; mDeviceMacAddress = info.mDeviceMacAddress; mDisplayName = info.mDisplayName; mDeviceProfile = info.mDeviceProfile; @@ -547,14 +558,15 @@ public final class AssociationInfo implements Parcelable { mLastTimeConnectedMs = info.mLastTimeConnectedMs; mSystemDataSyncFlags = info.mSystemDataSyncFlags; mDeviceIcon = info.mDeviceIcon; + mDeviceId = info.mDeviceId; } /** @hide */ @FlaggedApi(Flags.FLAG_ASSOCIATION_TAG) @TestApi @NonNull - public Builder setTag(@Nullable String tag) { - mTag = tag; + public Builder setDeviceId(@Nullable DeviceId deviceId) { + mDeviceId = deviceId; return this; } @@ -684,7 +696,6 @@ public final class AssociationInfo implements Parcelable { mId, mUserId, mPackageName, - mTag, mDeviceMacAddress, mDisplayName, mDeviceProfile, @@ -696,7 +707,8 @@ public final class AssociationInfo implements Parcelable { mTimeApprovedMs, mLastTimeConnectedMs, mSystemDataSyncFlags, - mDeviceIcon + mDeviceIcon, + mDeviceId ); } } diff --git a/core/java/android/companion/CompanionDeviceManager.java b/core/java/android/companion/CompanionDeviceManager.java index 4472c3d13d7c7cb0b4ddd609301cd3d23acd9a79..a96ba11eb482befeff81b567af42fb7ff29c6e73 100644 --- a/core/java/android/companion/CompanionDeviceManager.java +++ b/core/java/android/companion/CompanionDeviceManager.java @@ -277,12 +277,6 @@ public final class CompanionDeviceManager { */ public static final int MESSAGE_ONEWAY_TO_WEARABLE = 0x43847987; // +TOW - /** - * The length limit of Association tag. - * @hide - */ - private static final int ASSOCIATION_TAG_LENGTH_LIMIT = 1024; - /** * Callback for applications to receive updates about and the outcome of * {@link AssociationRequest} issued via {@code associate()} call. @@ -1229,7 +1223,6 @@ public final class CompanionDeviceManager { } } - // TODO(b/315163162) Add @Deprecated keyword after 24Q2 cut. /** * Register to receive callbacks whenever the associated device comes in and out of range. * @@ -1261,7 +1254,12 @@ public final class CompanionDeviceManager { * * @throws DeviceNotAssociatedException if the given device was not previously associated * with this app. + * + * @deprecated use {@link #startObservingDevicePresence(ObservingDevicePresenceRequest)} + * instead. */ + @FlaggedApi(Flags.FLAG_DEVICE_PRESENCE) + @Deprecated @RequiresPermission(android.Manifest.permission.REQUEST_OBSERVE_COMPANION_DEVICE_PRESENCE) public void startObservingDevicePresence(@NonNull String deviceAddress) throws DeviceNotAssociatedException { @@ -1288,7 +1286,7 @@ public final class CompanionDeviceManager { callingUid, callingPid); } } - // TODO(b/315163162) Add @Deprecated keyword after 24Q2 cut. + /** * Unregister for receiving callbacks whenever the associated device comes in and out of range. * @@ -1305,7 +1303,12 @@ public final class CompanionDeviceManager { * * @throws DeviceNotAssociatedException if the given device was not previously associated * with this app. + * + * @deprecated use {@link #stopObservingDevicePresence(ObservingDevicePresenceRequest)} + * instead. */ + @FlaggedApi(Flags.FLAG_DEVICE_PRESENCE) + @Deprecated @RequiresPermission(android.Manifest.permission.REQUEST_OBSERVE_COMPANION_DEVICE_PRESENCE) public void stopObservingDevicePresence(@NonNull String deviceAddress) throws DeviceNotAssociatedException { @@ -1771,57 +1774,25 @@ public final class CompanionDeviceManager { } /** - * Sets the {@link AssociationInfo#getTag() tag} for this association. - * - *

The length of the tag must be at most 1024 characters to save disk space. - * - *

This allows to store useful information about the associated devices. - * - * @param associationId The unique {@link AssociationInfo#getId ID} assigned to the Association - * of the companion device recorded by CompanionDeviceManager - * @param tag the tag of this association - */ - @FlaggedApi(Flags.FLAG_ASSOCIATION_TAG) - @UserHandleAware - public void setAssociationTag(int associationId, @NonNull String tag) { - if (mService == null) { - Log.w(TAG, "CompanionDeviceManager service is not available."); - return; - } - - Objects.requireNonNull(tag, "tag cannot be null"); - - if (tag.length() > ASSOCIATION_TAG_LENGTH_LIMIT) { - throw new IllegalArgumentException("Length of the tag must be at most" - + ASSOCIATION_TAG_LENGTH_LIMIT + " characters"); - } - - try { - mService.setAssociationTag(associationId, tag); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } - - /** - * Clears the {@link AssociationInfo#getTag() tag} for this association. + * Sets the {@link DeviceId deviceId} for this association. * - *

The tag will be set to null for this association when calling this API. + *

This device id helps the system uniquely identify your device for efficient device + * management and prevents duplicate entries. * * @param associationId The unique {@link AssociationInfo#getId ID} assigned to the Association - * of the companion device recorded by CompanionDeviceManager - * @see CompanionDeviceManager#setAssociationTag(int, String) + * of the companion device recorded by CompanionDeviceManager. + * @param deviceId to be used as device identifier to represent the associated device. */ @FlaggedApi(Flags.FLAG_ASSOCIATION_TAG) @UserHandleAware - public void clearAssociationTag(int associationId) { + public void setDeviceId(int associationId, @Nullable DeviceId deviceId) { if (mService == null) { Log.w(TAG, "CompanionDeviceManager service is not available."); return; } try { - mService.clearAssociationTag(associationId); + mService.setDeviceId(associationId, deviceId); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } diff --git a/core/java/android/companion/CompanionDeviceService.java b/core/java/android/companion/CompanionDeviceService.java index db080fcc7702786afac51d8e151519180e3a9f41..316d129bd6b9d83bf2efd1ca0a164137cf88f5f6 100644 --- a/core/java/android/companion/CompanionDeviceService.java +++ b/core/java/android/companion/CompanionDeviceService.java @@ -247,12 +247,14 @@ public abstract class CompanionDeviceService extends Service { .detachSystemDataTransport(associationId); } - // TODO(b/315163162) Add @Deprecated keyword after 24Q2 cut. /** * Called by the system when an associated device is nearby or connected. * * @param associationInfo A record for the companion device. + * @deprecated use {@link #onDevicePresenceEvent(DevicePresenceEvent)}} instead. */ + @FlaggedApi(Flags.FLAG_DEVICE_PRESENCE) + @Deprecated @MainThread public void onDeviceAppeared(@NonNull AssociationInfo associationInfo) { if (!associationInfo.isSelfManaged()) { @@ -260,12 +262,14 @@ public abstract class CompanionDeviceService extends Service { } } - // TODO(b/315163162) Add @Deprecated keyword after 24Q2 cut. /** * Called by the system when an associated device is out of range or disconnected. * * @param associationInfo A record for the companion device. + * @deprecated use {@link #onDevicePresenceEvent(DevicePresenceEvent)}} instead. */ + @FlaggedApi(Flags.FLAG_DEVICE_PRESENCE) + @Deprecated @MainThread public void onDeviceDisappeared(@NonNull AssociationInfo associationInfo) { if (!associationInfo.isSelfManaged()) { diff --git a/core/java/android/companion/DeviceId.aidl b/core/java/android/companion/DeviceId.aidl new file mode 100644 index 0000000000000000000000000000000000000000..d60d5f40eb6af13a11a1c667811ecbd7dc9fc8a0 --- /dev/null +++ b/core/java/android/companion/DeviceId.aidl @@ -0,0 +1,19 @@ +/* + * 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.companion; + +parcelable DeviceId; \ No newline at end of file diff --git a/core/java/android/companion/DeviceId.java b/core/java/android/companion/DeviceId.java new file mode 100644 index 0000000000000000000000000000000000000000..f66a1ae5c1758b68ff9d092a2af6a82c478dfb5c --- /dev/null +++ b/core/java/android/companion/DeviceId.java @@ -0,0 +1,210 @@ +/* + * 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.companion; + +import android.annotation.FlaggedApi; +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.net.MacAddress; +import android.os.Parcel; +import android.os.Parcelable; +import android.provider.OneTimeUseBuilder; + +import java.util.Locale; +import java.util.Objects; + +/** + * A device id represents a device identifier managed by the companion app. + */ +@FlaggedApi(Flags.FLAG_ASSOCIATION_TAG) +public final class DeviceId implements Parcelable { + /** + * The length limit of custom id. + */ + private static final int CUSTOM_ID_LENGTH_LIMIT = 1024; + + private final String mCustomId; + private final MacAddress mMacAddress; + + /** + * @hide + */ + public DeviceId(@Nullable String customId, @Nullable MacAddress macAddress) { + mCustomId = customId; + mMacAddress = macAddress; + } + + /** + * Returns true if two Device ids are represent the same device. False otherwise. + * @hide + */ + public boolean isSameDevice(@Nullable DeviceId other) { + if (other == null) { + return false; + } + + if (this.mCustomId != null && other.mCustomId != null) { + return this.mCustomId.equals(other.mCustomId); + } + if (this.mMacAddress != null && other.mMacAddress != null) { + return this.mMacAddress.equals(other.mMacAddress); + } + + return false; + } + + /** @hide */ + @Nullable + public String getMacAddressAsString() { + return mMacAddress != null ? mMacAddress.toString().toUpperCase(Locale.US) : null; + } + + /** + * @return the custom id that managed by the companion app. + */ + @Nullable + public String getCustomId() { + return mCustomId; + } + + /** + * @return the mac address that managed by the companion app. + */ + @Nullable + public MacAddress getMacAddress() { + return mMacAddress; + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(@NonNull Parcel dest, int flags) { + if (mCustomId != null) { + dest.writeInt(1); + dest.writeString8(mCustomId); + } else { + dest.writeInt(0); + } + dest.writeTypedObject(mMacAddress, 0); + + } + + private DeviceId(@NonNull Parcel in) { + int flg = in.readInt(); + if (flg == 1) { + mCustomId = in.readString8(); + } else { + mCustomId = null; + } + mMacAddress = in.readTypedObject(MacAddress.CREATOR); + } + + @NonNull + public static final Parcelable.Creator CREATOR = + new Parcelable.Creator() { + @Override + public DeviceId[] newArray(int size) { + return new DeviceId[size]; + } + + @Override + public DeviceId createFromParcel(@android.annotation.NonNull Parcel in) { + return new DeviceId(in); + } + }; + + @Override + public int hashCode() { + return Objects.hash(mCustomId, mMacAddress); + } + + @Override + public boolean equals(@Nullable Object o) { + if (this == o) return true; + if (!(o instanceof DeviceId that)) return false; + + return Objects.equals(mCustomId, that.mCustomId) + && Objects.equals(mMacAddress, that.mMacAddress); + } + + @Override + public String toString() { + return "DeviceId{" + + "," + "mCustomId= " + mCustomId + + "," + "mMacAddress= " + mMacAddress + + "}"; + } + + /** + * A builder for {@link DeviceId} + */ + public static final class Builder extends OneTimeUseBuilder { + private String mCustomId; + private MacAddress mMacAddress; + + public Builder() {} + + /** + * Sets the custom device id. This id is used by the Companion app to + * identify a specific device. + * + * @param customId the custom device id + * @throws IllegalArgumentException length of the custom id must more than 1024 + * characters to save disk space. + */ + @NonNull + public Builder setCustomId(@Nullable String customId) { + checkNotUsed(); + if (customId != null + && customId.length() > CUSTOM_ID_LENGTH_LIMIT) { + throw new IllegalArgumentException("Length of the custom id must be at most " + + CUSTOM_ID_LENGTH_LIMIT + " characters"); + } + this.mCustomId = customId; + return this; + } + + /** + * Sets the mac address. This mac address is used by the Companion app to + * identify a specific device. + * + * @param macAddress the remote device mac address + * @throws IllegalArgumentException length of the custom id must more than 1024 + * characters to save disk space. + */ + @NonNull + public Builder setMacAddress(@Nullable MacAddress macAddress) { + checkNotUsed(); + mMacAddress = macAddress; + return this; + } + + @NonNull + @Override + public DeviceId build() { + markUsed(); + if (mCustomId == null && mMacAddress == null) { + throw new IllegalArgumentException("At least one device id property must be" + + "non-null to build a DeviceId."); + } + return new DeviceId(mCustomId, mMacAddress); + } + } +} diff --git a/core/java/android/companion/ICompanionDeviceManager.aidl b/core/java/android/companion/ICompanionDeviceManager.aidl index de3ddec05d27186af9138373534fc5cb8bdbf569..a2b7dd9c3d0ecfa5ea76416b7a671f1fb6fe38ce 100644 --- a/core/java/android/companion/ICompanionDeviceManager.aidl +++ b/core/java/android/companion/ICompanionDeviceManager.aidl @@ -28,6 +28,7 @@ import android.companion.ObservingDevicePresenceRequest; import android.companion.datatransfer.PermissionSyncRequest; import android.content.ComponentName; import android.os.ParcelUuid; +import android.companion.DeviceId; /** @@ -134,9 +135,7 @@ interface ICompanionDeviceManager { @EnforcePermission("MANAGE_COMPANION_DEVICES") void enableSecureTransport(boolean enabled); - void setAssociationTag(int associationId, String tag); - - void clearAssociationTag(int associationId); + void setDeviceId(int associationId, in DeviceId deviceId); byte[] getBackupPayload(int userId); diff --git a/core/java/android/companion/flags.aconfig b/core/java/android/companion/flags.aconfig index 2539a12a2a14dd0568e0887edd1c3c4ec72cdced..2b9f70037279530dd17472a3bdebb06f826c9d30 100644 --- a/core/java/android/companion/flags.aconfig +++ b/core/java/android/companion/flags.aconfig @@ -46,6 +46,7 @@ flag { namespace: "companion" description: "Unpair with an associated bluetooth device" bug: "322237619" + is_exported: true } flag { diff --git a/core/java/android/companion/virtual/IVirtualDevice.aidl b/core/java/android/companion/virtual/IVirtualDevice.aidl index 367f1afc912be28b1d7ef48fe0eb9623908ca505..f8ac27de175446250b8d5917f77c5918a72b6105 100644 --- a/core/java/android/companion/virtual/IVirtualDevice.aidl +++ b/core/java/android/companion/virtual/IVirtualDevice.aidl @@ -90,6 +90,12 @@ 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/IVirtualDeviceActivityListener.aidl b/core/java/android/companion/virtual/IVirtualDeviceActivityListener.aidl index 767f52a92566ebb4674fc326aec09c12f55dc34c..448793d12bcb903cbb928fe4f1096edebceec867 100644 --- a/core/java/android/companion/virtual/IVirtualDeviceActivityListener.aidl +++ b/core/java/android/companion/virtual/IVirtualDeviceActivityListener.aidl @@ -63,4 +63,11 @@ oneway interface IVirtualDeviceActivityListener { * @param user The user associated with the activity. */ void onSecureWindowShown(int displayId, in ComponentName componentName, in UserHandle user); + + /** + * Called when a secure surface is no longer shown on the device. + * + * @param displayId The display ID on which the secure surface was shown. + */ + void onSecureWindowHidden(int displayId); } diff --git a/core/java/android/companion/virtual/VirtualDeviceInternal.java b/core/java/android/companion/virtual/VirtualDeviceInternal.java index d63a4434d7d827dd61aa2a7c64b1ecd06382727c..42c74414ecd93a0ff256c0cb5eba9bdcf5e11a59 100644 --- a/core/java/android/companion/virtual/VirtualDeviceInternal.java +++ b/core/java/android/companion/virtual/VirtualDeviceInternal.java @@ -166,6 +166,20 @@ public class VirtualDeviceInternal { Binder.restoreCallingIdentity(token); } } + + @Override + public void onSecureWindowHidden(int displayId) { + final long token = Binder.clearCallingIdentity(); + try { + synchronized (mActivityListenersLock) { + for (int i = 0; i < mActivityListeners.size(); i++) { + mActivityListeners.valueAt(i).onSecureWindowHidden(displayId); + } + } + } finally { + Binder.restoreCallingIdentity(token); + } + } }; private final IVirtualDeviceSoundEffectListener mSoundEffectListener = @@ -617,6 +631,10 @@ public class VirtualDeviceInternal { mExecutor.execute(() -> mActivityListener.onSecureWindowShown(displayId, componentName, user)); } + + public void onSecureWindowHidden(int displayId) { + mExecutor.execute(() -> mActivityListener.onSecureWindowHidden(displayId)); + } } /** diff --git a/core/java/android/companion/virtual/VirtualDeviceManager.java b/core/java/android/companion/virtual/VirtualDeviceManager.java index 6ea7834243a410e6f8492f8ce34b971fa13e8b47..b3f09a98d6237aa8a5b2004eca9e275c5e326a12 100644 --- a/core/java/android/companion/virtual/VirtualDeviceManager.java +++ b/core/java/android/companion/virtual/VirtualDeviceManager.java @@ -1288,6 +1288,17 @@ public final class VirtualDeviceManager { @FlaggedApi(android.companion.virtualdevice.flags.Flags.FLAG_ACTIVITY_CONTROL_API) default void onSecureWindowShown(int displayId, @NonNull ComponentName componentName, @NonNull UserHandle user) {} + + /** + * Called when a window with a secure surface is no longer shown on the device. + * + * @param displayId The display ID on which the window was shown before. + * + * @see Display#FLAG_SECURE + * @see WindowManager.LayoutParams#FLAG_SECURE + */ + @FlaggedApi(android.companion.virtualdevice.flags.Flags.FLAG_ACTIVITY_CONTROL_API) + default void onSecureWindowHidden(int displayId) {} } /** diff --git a/core/java/android/content/ClipData.java b/core/java/android/content/ClipData.java index cc57dc05d6b10664d6c81ba11a5a8cb2343517ca..e271cf4f60ece7c6fb33488d7e31461529e70037 100644 --- a/core/java/android/content/ClipData.java +++ b/core/java/android/content/ClipData.java @@ -945,6 +945,34 @@ public class ClipData implements Parcelable { return mParcelItemActivityInfos; } + /** + * Make a clone of ClipData that only contains URIs. This reduces the size of data transfer over + * IPC and only retains important information for the purpose of verifying creator token of an + * Intent. + * @return a copy of ClipData with only URIs remained. + * @hide + */ + public ClipData cloneOnlyUriItems() { + ArrayList items = null; + final int N = mItems.size(); + for (int i = 0; i < N; i++) { + Item item = mItems.get(i); + if (item.getUri() != null) { + if (items == null) { + items = new ArrayList<>(N); + } + items.add(new Item(item.getUri())); + } else if (item.getIntent() != null) { + if (items == null) { + items = new ArrayList<>(N); + } + items.add(new Item(item.getIntent().cloneForCreatorToken())); + } + } + if (items == null || items.isEmpty()) return null; + return new ClipData(new ClipDescription("", new String[0]), items); + } + /** * Create a new ClipData holding data of the type * {@link ClipDescription#MIMETYPE_TEXT_PLAIN}. diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index 6e2ca2c109f157258187be4b94d82c1c02d79688..6ec6a62ff639f303b33ff1a7b2cf2d63a141cb71 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -18,6 +18,7 @@ package android.content; import static android.app.appfunctions.flags.Flags.FLAG_ENABLE_APP_FUNCTION_MANAGER; import static android.content.flags.Flags.FLAG_ENABLE_BIND_PACKAGE_ISOLATED_PROCESS; +import static android.app.ondeviceintelligence.flags.Flags.FLAG_ENABLE_ON_DEVICE_INTELLIGENCE_MODULE; import static android.security.Flags.FLAG_SECURE_LOCKDOWN; import android.annotation.AttrRes; @@ -640,12 +641,15 @@ public abstract class Context { public static final int BIND_FOREGROUND_SERVICE_WHILE_AWAKE = 0x02000000; /** - * @hide Flag for {@link #bindService}: For only the case where the binding + * Flag for {@link #bindService}: For only the case where the binding * is coming from the system, set the process state to BOUND_FOREGROUND_SERVICE * instead of the normal maximum of IMPORTANT_FOREGROUND. That is, this is * saying that the process shouldn't participate in the normal power reduction * modes (removing network access etc). + * @hide */ + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + @FlaggedApi(FLAG_ENABLE_ON_DEVICE_INTELLIGENCE_MODULE) public static final int BIND_FOREGROUND_SERVICE = 0x04000000; /** diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java index 02eed1a7553f9ebb5c6442ddd7d46ce46d8076b1..d7660172a2f13dbb220b2cb9f5c50129fbfb6765 100644 --- a/core/java/android/content/Intent.java +++ b/core/java/android/content/Intent.java @@ -7969,6 +7969,24 @@ public class Intent implements Parcelable, Cloneable { return new Intent(this, COPY_MODE_FILTER); } + /** + * Make a copy of all members important to identify an intent with its creator token. + * @hide + */ + public @NonNull Intent cloneForCreatorToken() { + Intent clone = new Intent() + .setAction(this.mAction) + .setDataAndType(this.mData, this.mType) + .setPackage(this.mPackage) + .setComponent(this.mComponent) + .setFlags(this.mFlags & IMMUTABLE_FLAGS); + if (this.mClipData != null) { + clone.setClipData(this.mClipData.cloneOnlyUriItems()); + } + clone.mCreatorTokenInfo = this.mCreatorTokenInfo; + return clone; + } + /** * Create an intent with a given action. All other fields (data, type, * class) are null. Note that the action must be in a @@ -11684,7 +11702,7 @@ public class Intent implements Parcelable, Cloneable { Log.w(TAG, "Failure filling in extras", e); } } - mCreatorTokenInfo = other.mCreatorTokenInfo; + fillInCreatorTokenInfo(other.mCreatorTokenInfo, changes); if (mayHaveCopiedUris && mContentUserHint == UserHandle.USER_CURRENT && other.mContentUserHint != UserHandle.USER_CURRENT) { mContentUserHint = other.mContentUserHint; @@ -11692,6 +11710,45 @@ public class Intent implements Parcelable, Cloneable { return changes; } + // keep original creator token and merge nested intent keys. + private void fillInCreatorTokenInfo(CreatorTokenInfo otherCreatorTokenInfo, int changes) { + if (otherCreatorTokenInfo != null && otherCreatorTokenInfo.mNestedIntentKeys != null) { + if (mCreatorTokenInfo == null) { + mCreatorTokenInfo = new CreatorTokenInfo(); + } + ArraySet otherNestedIntentKeys = + otherCreatorTokenInfo.mNestedIntentKeys; + if (mCreatorTokenInfo.mNestedIntentKeys == null) { + mCreatorTokenInfo.mNestedIntentKeys = new ArraySet<>(otherNestedIntentKeys); + } else { + ArraySet otherKeys; + if ((changes & FILL_IN_CLIP_DATA) == 0) { + // If clip data is Not filled in from other, do not merge clip data keys. + otherKeys = new ArraySet<>(); + int N = otherNestedIntentKeys.size(); + for (int i = 0; i < N; i++) { + NestedIntentKey key = otherNestedIntentKeys.valueAt(i); + if (key.mType != NestedIntentKey.NESTED_INTENT_KEY_TYPE_CLIP_DATA) { + otherKeys.add(key); + } + } + } else { + // If clip data is filled in from other, remove clip data keys from this + // creatorTokenInfo and then merge every key from the others. + int N = mCreatorTokenInfo.mNestedIntentKeys.size(); + for (int i = N - 1; i >= 0; i--) { + NestedIntentKey key = mCreatorTokenInfo.mNestedIntentKeys.valueAt(i); + if (key.mType == NestedIntentKey.NESTED_INTENT_KEY_TYPE_CLIP_DATA) { + mCreatorTokenInfo.mNestedIntentKeys.removeAt(i); + } + } + otherKeys = otherNestedIntentKeys; + } + mCreatorTokenInfo.mNestedIntentKeys.addAll(otherKeys); + } + } + } + /** * Merge the extras data in this intent with that of other supplied intent using the * strategy specified using {@code extrasMerger}. @@ -12228,6 +12285,7 @@ public class Intent implements Parcelable, Cloneable { private IBinder mCreatorToken; // Stores all extra keys whose values are intents for a top level intent. private ArraySet mNestedIntentKeys; + } /** diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index 23d3693628e77bc8cc6f2d985f81c2daf61f6e43..a06eb1c5b4ad83fe14f2fe6ddacd9330badc5357 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -16,6 +16,7 @@ package android.content.pm; +import static android.content.pm.SigningInfo.AppSigningSchemeVersion; import static android.media.audio.Flags.FLAG_FEATURE_SPATIAL_AUDIO_HEADTRACKING_LOW_LATENCY; import static com.android.internal.pm.pkg.parsing.ParsingPackageUtils.PARSE_COLLECT_CERTIFICATES; @@ -59,6 +60,8 @@ import android.content.IntentFilter; import android.content.IntentSender; import android.content.pm.PackageInstaller.SessionParams; import android.content.pm.dex.ArtManager; +import android.content.pm.parsing.result.ParseResult; +import android.content.pm.parsing.result.ParseTypeImpl; import android.content.pm.verify.domain.DomainVerificationManager; import android.content.res.Configuration; import android.content.res.Resources; @@ -94,6 +97,7 @@ import android.telephony.ims.RcsUceAdapter; import android.telephony.ims.SipDelegateManager; import android.util.AndroidException; import android.util.Log; +import android.util.apk.ApkSignatureVerifier; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.pm.parsing.PackageInfoCommonUtils; @@ -3146,6 +3150,16 @@ public abstract class PackageManager { */ public static final long MAXIMUM_VERIFICATION_TIMEOUT = 60*60*1000; + /** + * As the generated feature count is useful for classes that may not be compiled in the same + * annotation processing unit as PackageManager, we redeclare it here for visibility. + * + * @hide + */ + @VisibleForTesting + public static final int SDK_FEATURE_COUNT = + com.android.internal.pm.SystemFeaturesMetadata.SDK_FEATURE_COUNT; + /** * Feature for {@link #getSystemAvailableFeatures} and {@link #hasSystemFeature}: The device's * audio pipeline is low-latency, more suitable for audio applications sensitive to delays or @@ -11987,4 +12001,31 @@ public abstract class PackageManager { throw new UnsupportedOperationException( "parseServiceMetadata not implemented in subclass"); } + + /** + * Verifies and returns the + * app signing + * information of the file at the given path. This operation takes a few milliseconds. + * + * Unlike {@link #getPackageArchiveInfo(String, PackageInfoFlags)} with {@link + * #GET_SIGNING_CERTIFICATES}, this method does not require the file to be a package archive + * file. + * + * @throws SigningInfoException if the verification fails + * + * @hide + */ + @FlaggedApi(android.content.pm.Flags.FLAG_CLOUD_COMPILATION_PM) + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + public static @NonNull SigningInfo getVerifiedSigningInfo(@NonNull String path, + @AppSigningSchemeVersion int minAppSigningSchemeVersion) throws SigningInfoException { + ParseTypeImpl input = ParseTypeImpl.forDefaultParsing(); + ParseResult result = + ApkSignatureVerifier.verify(input, path, minAppSigningSchemeVersion); + if (result.isError()) { + throw new SigningInfoException( + result.getErrorCode(), result.getErrorMessage(), result.getException()); + } + return new SigningInfo(result.getResult()); + } } diff --git a/core/java/android/content/pm/SigningInfo.java b/core/java/android/content/pm/SigningInfo.java index 23daaf2d4138511c9c535f437fdd5086288b44a4..e4fbd1f28dbbc6e896cb23032cc0d1f1b1d7ddfd 100644 --- a/core/java/android/content/pm/SigningInfo.java +++ b/core/java/android/content/pm/SigningInfo.java @@ -16,14 +16,20 @@ package android.content.pm; +import static android.content.pm.SigningDetails.SignatureSchemeVersion; + import android.annotation.FlaggedApi; +import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.SystemApi; import android.content.pm.SigningDetails.SignatureSchemeVersion; import android.os.Parcel; import android.os.Parcelable; import android.util.ArraySet; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.security.PublicKey; import java.util.Collection; @@ -31,6 +37,55 @@ import java.util.Collection; * Information pertaining to the signing certificates used to sign a package. */ public final class SigningInfo implements Parcelable { + /** + * JAR signing (v1 scheme). + * See https://source.android.com/docs/security/features/apksigning#v1. + * + * @hide + */ + @FlaggedApi(Flags.FLAG_CLOUD_COMPILATION_PM) + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + public static final int VERSION_JAR = SignatureSchemeVersion.JAR; + + /** + * APK signature scheme v2. + * See https://source.android.com/docs/security/features/apksigning/v2. + * + * @hide + */ + @FlaggedApi(Flags.FLAG_CLOUD_COMPILATION_PM) + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + public static final int VERSION_SIGNING_BLOCK_V2 = SignatureSchemeVersion.SIGNING_BLOCK_V2; + + /** + * APK signature scheme v3. + * See https://source.android.com/docs/security/features/apksigning/v3. + * + * @hide + */ + @FlaggedApi(Flags.FLAG_CLOUD_COMPILATION_PM) + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + public static final int VERSION_SIGNING_BLOCK_V3 = SignatureSchemeVersion.SIGNING_BLOCK_V3; + + /** + * APK signature scheme v4. + * See https://source.android.com/docs/security/features/apksigning/v4. + * + * @hide + */ + @FlaggedApi(Flags.FLAG_CLOUD_COMPILATION_PM) + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + public static final int VERSION_SIGNING_BLOCK_V4 = SignatureSchemeVersion.SIGNING_BLOCK_V4; + + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(prefix = {"VERSION_"}, value = { + VERSION_JAR, + VERSION_SIGNING_BLOCK_V2, + VERSION_SIGNING_BLOCK_V3, + VERSION_SIGNING_BLOCK_V4, + }) + public @interface AppSigningSchemeVersion {} @NonNull private final SigningDetails mSigningDetails; @@ -198,6 +253,17 @@ public final class SigningInfo implements Parcelable { return mSigningDetails; } + /** + * Returns true if the signing certificates in this and other match exactly. + * + * @hide + */ + @FlaggedApi(Flags.FLAG_CLOUD_COMPILATION_PM) + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + public boolean signersMatchExactly(@NonNull SigningInfo other) { + return mSigningDetails.signaturesMatchExactly(other.mSigningDetails); + } + public static final @android.annotation.NonNull Parcelable.Creator CREATOR = new Parcelable.Creator() { @Override diff --git a/core/java/android/content/pm/SigningInfoException.java b/core/java/android/content/pm/SigningInfoException.java new file mode 100644 index 0000000000000000000000000000000000000000..a81e07e73685a1d2fa0c2a43468634fef2e4d6df --- /dev/null +++ b/core/java/android/content/pm/SigningInfoException.java @@ -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 android.content.pm; + +import android.annotation.FlaggedApi; +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.annotation.SystemApi; + +/** + * Indicates an error when verifying the + * app signing + * information. + * + * @hide + */ +@FlaggedApi(Flags.FLAG_CLOUD_COMPILATION_PM) +@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) +public class SigningInfoException extends Exception { + private final int mCode; + + /** @hide */ + public SigningInfoException(int code, @NonNull String message, @Nullable Throwable cause) { + super(message, cause); + mCode = code; + } + + /** + * Returns a code representing the cause, in one of the installation parse return codes in + * {@link PackageManager}. + */ + @FlaggedApi(Flags.FLAG_CLOUD_COMPILATION_PM) + public int getCode() { + return mCode; + } +} diff --git a/core/java/android/content/pm/dependencyinstaller/DependencyInstallerCallback.java b/core/java/android/content/pm/dependencyinstaller/DependencyInstallerCallback.java index ba089f7fd33e16434b80a3492a1bf05e9fa7c590..35e5c443e4b236c1661fb08cdef891d563f3d3be 100644 --- a/core/java/android/content/pm/dependencyinstaller/DependencyInstallerCallback.java +++ b/core/java/android/content/pm/dependencyinstaller/DependencyInstallerCallback.java @@ -53,7 +53,14 @@ public final class DependencyInstallerCallback implements Parcelable { * Callback to indicate that all the requested dependencies have been resolved and their * sessions created. See {@link DependencyInstallerService#onDependenciesRequired}. * + * The system will wait for the sessions to be installed before resuming the original session + * which requested dependency installation. + * + * If any of the session fails to install, the system may fail the original session. The caller + * is expected to handle clean up of any other pending sessions remanining. + * * @param sessionIds the install session IDs for all requested dependencies + * @throws IllegalArgumentException if session id doesn't exist or has already failed. */ public void onAllDependenciesResolved(@NonNull int[] sessionIds) { try { diff --git a/core/java/android/content/pm/dependencyinstaller/IDependencyInstallerCallback.aidl b/core/java/android/content/pm/dependencyinstaller/IDependencyInstallerCallback.aidl index 92d1d9e118e632339617712ca640526f53acb887..e4cf55d3ce5f1ee3459ecb44651358ddee986757 100644 --- a/core/java/android/content/pm/dependencyinstaller/IDependencyInstallerCallback.aidl +++ b/core/java/android/content/pm/dependencyinstaller/IDependencyInstallerCallback.aidl @@ -24,7 +24,7 @@ import java.util.List; * * {@hide} */ -oneway interface IDependencyInstallerCallback { +interface IDependencyInstallerCallback { /** * Callback to indicate that all the requested dependencies have been resolved and have been * committed for installation. See {@link DependencyInstallerService#onDependenciesRequired}. @@ -38,4 +38,4 @@ oneway interface IDependencyInstallerCallback { * and any associated sessions have been abandoned. */ void onFailureToResolveAllDependencies(); -} \ No newline at end of file +} diff --git a/core/java/android/content/pm/flags.aconfig b/core/java/android/content/pm/flags.aconfig index fbe581c5d524e4d033510f0af99562621f65f29e..8ba2dcc2a7cf41643d13ebdcc70a4fa19c0aacc4 100644 --- a/core/java/android/content/pm/flags.aconfig +++ b/core/java/android/content/pm/flags.aconfig @@ -341,6 +341,7 @@ flag { description: "Feature flag to introduce a new way to change the launcher badging." bug: "364760703" is_fixed_read_only: true + is_exported: true } flag { @@ -357,6 +358,7 @@ flag { namespace: "package_manager_service" description: "Block app installations that specify an incompatible minor SDK version" bug: "377302905" + is_exported: true } flag { diff --git a/core/java/android/content/pm/multiuser.aconfig b/core/java/android/content/pm/multiuser.aconfig index 833260a15c45d0176f22ce376dd53c936d83d65d..f29e2e8f10a3d18d78aab0942b644d7117cfb281 100644 --- a/core/java/android/content/pm/multiuser.aconfig +++ b/core/java/android/content/pm/multiuser.aconfig @@ -363,6 +363,17 @@ flag { is_fixed_read_only: true } +flag { + name: "cache_user_restrictions_read_only" + namespace: "multiuser" + description: "Cache hasUserRestriction to avoid unnecessary binder calls" + bug: "350419621" + metadata { + purpose: PURPOSE_BUGFIX + } + is_fixed_read_only: true +} + # This flag guards the private space feature and all its implementations excluding the APIs. APIs are guarded by android.os.Flags.allow_private_profile. flag { name: "enable_private_space_features" @@ -582,4 +593,5 @@ flag { namespace: "profile_experiences" description: "Add support for LauncherUserInfo configs" bug: "346553745" + is_exported: true } diff --git a/core/java/android/content/pm/parsing/FrameworkParsingPackageUtils.java b/core/java/android/content/pm/parsing/FrameworkParsingPackageUtils.java index 153dd9a934901236c8ba757b16ff741da87bd57e..e30f871b68eb18733e74a32d50c555b2ca42e4af 100644 --- a/core/java/android/content/pm/parsing/FrameworkParsingPackageUtils.java +++ b/core/java/android/content/pm/parsing/FrameworkParsingPackageUtils.java @@ -329,6 +329,36 @@ public class FrameworkParsingPackageUtils { } } + /** + * Check if a package is compatible with this platform with regards to its + * its minSdkVersionFull. + * + * @param minSdkVersionFullString A string representation of a major.minor version, + * e.g. "12.34" + * @param platformMinSdkVersionFull The major and minor version of the platform, i.e. the value + * of Build.VERSION.SDK_INT_FULL + * @param input A ParseInput object to report success or failure + */ + public static ParseResult verifyMinSdkVersionFull(@NonNull String minSdkVersionFullString, + int platformMinSdkVersionFull, @NonNull ParseInput input) { + int minSdkVersionFull; + try { + minSdkVersionFull = Build.parseFullVersion(minSdkVersionFullString); + } catch (IllegalStateException e) { + return input.error(PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED, + e.getMessage()); + } + if (minSdkVersionFull <= platformMinSdkVersionFull) { + return input.success(null); + } + return input.error(PackageManager.INSTALL_FAILED_OLDER_SDK, + "Requires newer sdk version " + + Build.fullVersionToString(minSdkVersionFull) + + " (current version is " + + Build.fullVersionToString(platformMinSdkVersionFull) + + ")"); + } + /** * Computes the targetSdkVersion to use at runtime. If the package is not compatible with this * platform, populates {@code outError[0]} with an error message. diff --git a/core/java/android/content/pm/xr.aconfig b/core/java/android/content/pm/xr.aconfig index 61835c162c498112dd28200c7843aafeac2898d2..a26f48e30c7e6449392109f0549fafb3cdb5745b 100644 --- a/core/java/android/content/pm/xr.aconfig +++ b/core/java/android/content/pm/xr.aconfig @@ -6,4 +6,5 @@ flag { name: "xr_manifest_entries" description: "Adds manifest entries used by Android XR" bug: "364416355" + is_exported: true } \ No newline at end of file diff --git a/core/java/android/hardware/biometrics/flags.aconfig b/core/java/android/hardware/biometrics/flags.aconfig index 7a23033754c54e0e7d589424adf2b5754ceb1a4c..73b6417a6ba484a4925c18f22645cec736f43c01 100644 --- a/core/java/android/hardware/biometrics/flags.aconfig +++ b/core/java/android/hardware/biometrics/flags.aconfig @@ -53,6 +53,7 @@ flag { namespace: "biometrics_framework" description: "This flag is for API changes related to Identity Check" bug: "373424727" + is_exported: true } flag { diff --git a/core/java/android/hardware/camera2/CameraManager.java b/core/java/android/hardware/camera2/CameraManager.java index 266efb7b759ceeefda4a4d55979f694c061a2fbd..aba2345f28d8482593b1180a14e8093451dfd29d 100644 --- a/core/java/android/hardware/camera2/CameraManager.java +++ b/core/java/android/hardware/camera2/CameraManager.java @@ -1699,17 +1699,18 @@ public final class CameraManager { } if (context != null) { - final ActivityManager activityManager = - context.getSystemService(ActivityManager.class); - for (ActivityManager.AppTask appTask : activityManager.getAppTasks()) { - final TaskInfo taskInfo = appTask.getTaskInfo(); - final int freeformCameraCompatMode = - taskInfo.appCompatTaskInfo.cameraCompatTaskInfo.freeformCameraCompatMode; - if (freeformCameraCompatMode != 0 - && taskInfo.topActivity != null - && taskInfo.topActivity.getPackageName().equals(packageName)) { - // WindowManager has requested rotation override. - return getRotationOverrideForCompatFreeform(freeformCameraCompatMode); + final ActivityManager activityManager = context.getSystemService(ActivityManager.class); + if (activityManager != null) { + for (ActivityManager.AppTask appTask : activityManager.getAppTasks()) { + final TaskInfo taskInfo = appTask.getTaskInfo(); + final int freeformCameraCompatMode = taskInfo.appCompatTaskInfo + .cameraCompatTaskInfo.freeformCameraCompatMode; + if (freeformCameraCompatMode != 0 + && taskInfo.topActivity != null + && taskInfo.topActivity.getPackageName().equals(packageName)) { + // WindowManager has requested rotation override. + return getRotationOverrideForCompatFreeform(freeformCameraCompatMode); + } } } } diff --git a/core/java/android/hardware/camera2/TotalCaptureResult.java b/core/java/android/hardware/camera2/TotalCaptureResult.java index 7e42f43056e1d2ee8a43e694bfe3bf5e949ebfc1..29eaab8eebccc5c9639732a55af918f77969ad39 100644 --- a/core/java/android/hardware/camera2/TotalCaptureResult.java +++ b/core/java/android/hardware/camera2/TotalCaptureResult.java @@ -86,7 +86,8 @@ public final class TotalCaptureResult extends CaptureResult { mPhysicalCaptureResults = new HashMap(); for (PhysicalCaptureResultInfo onePhysicalResult : physicalResults) { TotalCaptureResult physicalResult = new TotalCaptureResult( - onePhysicalResult.getCameraId(), onePhysicalResult.getCameraMetadata(), + onePhysicalResult.getCameraId(), + onePhysicalResult.getCameraMetadata(), parent, extras, /*partials*/null, sessionId, new PhysicalCaptureResultInfo[0]); mPhysicalCaptureResults.put(onePhysicalResult.getCameraId(), physicalResult); @@ -115,7 +116,8 @@ public final class TotalCaptureResult extends CaptureResult { mPhysicalCaptureResults = new HashMap(); for (PhysicalCaptureResultInfo onePhysicalResult : physicalResults) { TotalCaptureResult physicalResult = new TotalCaptureResult( - onePhysicalResult.getCameraId(), onePhysicalResult.getCameraMetadata(), + onePhysicalResult.getCameraId(), + onePhysicalResult.getCameraMetadata(), parent, requestId, frameNumber, /*partials*/null, sessionId, new PhysicalCaptureResultInfo[0]); mPhysicalCaptureResults.put(onePhysicalResult.getCameraId(), diff --git a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java index ea70abb55b48b5050cd622c8ea8d768003e22555..34c0f7b19da9d6ac0b3982536c5be619b708e0f9 100644 --- a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java +++ b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java @@ -34,6 +34,7 @@ import android.hardware.camera2.CameraDevice; import android.hardware.camera2.CameraExtensionCharacteristics; import android.hardware.camera2.CameraManager; import android.hardware.camera2.CameraMetadata; +import android.hardware.camera2.CameraMetadataInfo; import android.hardware.camera2.CameraOfflineSession; import android.hardware.camera2.CaptureFailure; import android.hardware.camera2.CaptureRequest; @@ -59,6 +60,8 @@ import android.os.Build; import android.os.Handler; import android.os.IBinder; import android.os.Looper; +import android.os.Parcel; +import android.os.Parcelable; import android.os.RemoteException; import android.os.ServiceSpecificException; import android.os.SystemClock; @@ -129,6 +132,8 @@ public class CameraDeviceImpl extends CameraDevice final Object mInterfaceLock = new Object(); // access from this class and Session only! private final CameraDeviceCallbacks mCallbacks = new CameraDeviceCallbacks(); + private long mFMQReader; // native fmq reader ptr + private final StateCallback mDeviceCallback; private volatile StateCallbackKK mSessionStateCallback; private final Executor mDeviceExecutor; @@ -476,6 +481,9 @@ public class CameraDeviceImpl extends CameraDevice if (mInError) return; mRemoteDevice = new ICameraDeviceUserWrapper(remoteDevice); + Parcel resultParcel = Parcel.obtain(); + mRemoteDevice.getCaptureResultMetadataQueue().writeToParcel(resultParcel, 0); + mFMQReader = nativeCreateFMQReader(resultParcel); IBinder remoteDeviceBinder = remoteDevice.asBinder(); // For legacy camera device, remoteDevice is in the same process, and @@ -1682,6 +1690,7 @@ public class CameraDeviceImpl extends CameraDevice if (mRemoteDevice != null || mInError) { mDeviceExecutor.execute(mCallOnClosed); } + nativeClose(mFMQReader); mRemoteDevice = null; } @@ -2416,27 +2425,61 @@ public class CameraDeviceImpl extends CameraDevice } } } + private PhysicalCaptureResultInfo[] readMetadata( + PhysicalCaptureResultInfo[] srcPhysicalResults) { + PhysicalCaptureResultInfo[] retVal = + new PhysicalCaptureResultInfo[srcPhysicalResults.length]; + int i = 0; + long fmqSize = 0; + for (PhysicalCaptureResultInfo srcPhysicalResult : srcPhysicalResults) { + CameraMetadataNative physicalCameraMetadata = null; + if (srcPhysicalResult.getCameraMetadataInfo().getTag() == + CameraMetadataInfo.fmqSize) { + fmqSize = srcPhysicalResult.getCameraMetadataInfo().getFmqSize(); + physicalCameraMetadata = + new CameraMetadataNative(nativeReadResultMetadata(mFMQReader, fmqSize)); + } else { + physicalCameraMetadata = srcPhysicalResult.getCameraMetadata(); + } + PhysicalCaptureResultInfo physicalResultInfo = + new PhysicalCaptureResultInfo( + srcPhysicalResult.getCameraId(), physicalCameraMetadata); + retVal[i] = physicalResultInfo; + i++; + } + return retVal; + } @Override - public void onResultReceived(CameraMetadataNative result, + public void onResultReceived(CameraMetadataInfo resultInfo, CaptureResultExtras resultExtras, PhysicalCaptureResultInfo physicalResults[]) throws RemoteException { int requestId = resultExtras.getRequestId(); long frameNumber = resultExtras.getFrameNumber(); - - if (DEBUG) { - Log.v(TAG, "Received result frame " + frameNumber + " for id " - + requestId); - } - synchronized(mInterfaceLock) { if (mRemoteDevice == null) return; // Camera already closed - + PhysicalCaptureResultInfo savedPhysicalResults[] = physicalResults; + CameraMetadataNative result; + if (resultInfo.getTag() == CameraMetadataInfo.fmqSize) { + CameraMetadataNative fmqMetadata = + new CameraMetadataNative( + nativeReadResultMetadata(mFMQReader, resultInfo.getFmqSize())); + result = fmqMetadata; + } else { + result = resultInfo.getMetadata(); + } + physicalResults = readMetadata(savedPhysicalResults); + if (DEBUG) { + Log.v(TAG, "Received result frame " + frameNumber + " for id " + + requestId); + } // Redirect device callback to the offline session in case we are in the middle // of an offline switch if (mOfflineSessionImpl != null) { - mOfflineSessionImpl.getCallbacks().onResultReceived(result, resultExtras, + CameraMetadataInfo resultInfoOffline = CameraMetadataInfo.metadata(result); + mOfflineSessionImpl.getCallbacks().onResultReceived(resultInfoOffline, + resultExtras, physicalResults); return; } @@ -2824,6 +2867,11 @@ public class CameraDeviceImpl extends CameraDevice } } + private static native long nativeCreateFMQReader(Parcel resultQueue); + //TODO: Investigate adding FastNative b/62791857 + private static native long nativeReadResultMetadata(long ptr, long metadataSize); + private static native void nativeClose(long ptr); + @Override public @CAMERA_AUDIO_RESTRICTION int getCameraAudioRestriction() throws CameraAccessException { synchronized(mInterfaceLock) { @@ -2870,4 +2918,4 @@ public class CameraDeviceImpl extends CameraDevice } } } -} +} \ No newline at end of file diff --git a/core/java/android/hardware/camera2/impl/CameraMetadataNative.java b/core/java/android/hardware/camera2/impl/CameraMetadataNative.java index c0a5928a369bd0eb60b20d7a93398a110e3becf6..d7b6f116e452555efb5298506590cf8f5e909ec0 100644 --- a/core/java/android/hardware/camera2/impl/CameraMetadataNative.java +++ b/core/java/android/hardware/camera2/impl/CameraMetadataNative.java @@ -390,6 +390,18 @@ public class CameraMetadataNative implements Parcelable { updateNativeAllocation(); } + /** + * Take ownership of native metadata + */ + public CameraMetadataNative(long metadataPtr) { + super(); + mMetadataPtr = metadataPtr; + if (mMetadataPtr == 0) { + throw new OutOfMemoryError("Failed to allocate native CameraMetadata"); + } + updateNativeAllocation(); + } + /** * Move the contents from {@code other} into a new camera metadata instance.

* diff --git a/core/java/android/hardware/camera2/impl/CameraOfflineSessionImpl.java b/core/java/android/hardware/camera2/impl/CameraOfflineSessionImpl.java index 1769c4638805af9bf21edbfef3846c70f50a1369..e660d6aba854446e91d689e69e85654e990221d0 100644 --- a/core/java/android/hardware/camera2/impl/CameraOfflineSessionImpl.java +++ b/core/java/android/hardware/camera2/impl/CameraOfflineSessionImpl.java @@ -28,6 +28,7 @@ import android.hardware.camera2.CameraOfflineSession.CameraOfflineSessionCallbac import android.hardware.camera2.CaptureFailure; import android.hardware.camera2.CaptureRequest; import android.hardware.camera2.CaptureResult; +import android.hardware.camera2.CameraMetadataInfo; import android.hardware.camera2.ICameraDeviceCallbacks; import android.hardware.camera2.ICameraOfflineSession; import android.hardware.camera2.TotalCaptureResult; @@ -291,10 +292,10 @@ public class CameraOfflineSessionImpl extends CameraOfflineSession } @Override - public void onResultReceived(CameraMetadataNative result, + public void onResultReceived(CameraMetadataInfo resultInfo, CaptureResultExtras resultExtras, PhysicalCaptureResultInfo physicalResults[]) throws RemoteException { - + CameraMetadataNative result = resultInfo.getMetadata(); int requestId = resultExtras.getRequestId(); long frameNumber = resultExtras.getFrameNumber(); diff --git a/core/java/android/hardware/camera2/impl/ICameraDeviceUserWrapper.java b/core/java/android/hardware/camera2/impl/ICameraDeviceUserWrapper.java index 831c75ec5d33c3df86211d0445433de1d24b250b..a79e084b7f4144f65be39d64708e334b99ace6f9 100644 --- a/core/java/android/hardware/camera2/impl/ICameraDeviceUserWrapper.java +++ b/core/java/android/hardware/camera2/impl/ICameraDeviceUserWrapper.java @@ -26,6 +26,7 @@ import android.hardware.camera2.params.OutputConfiguration; import android.hardware.camera2.params.SessionConfiguration; import android.hardware.camera2.utils.ExceptionUtils; import android.hardware.camera2.utils.SubmitInfo; +import android.hardware.common.fmq.MQDescriptor; import android.os.IBinder; import android.os.RemoteException; import android.os.ServiceSpecificException; @@ -313,4 +314,15 @@ public class ICameraDeviceUserWrapper { throw ExceptionUtils.throwAsPublicException(e); } } -} + + public MQDescriptor getCaptureResultMetadataQueue() throws CameraAccessException { + try { + return mRemoteDevice.getCaptureResultMetadataQueue(); + } catch (ServiceSpecificException e) { + throw ExceptionUtils.throwAsPublicException(e); + } catch (RemoteException e) { + throw ExceptionUtils.throwAsPublicException(e); + } + } + +} \ No newline at end of file diff --git a/core/java/android/hardware/camera2/impl/PhysicalCaptureResultInfo.java b/core/java/android/hardware/camera2/impl/PhysicalCaptureResultInfo.java index 09619d0f5c7e05f707a2a57ce79d96a5c8a27132..77296d1c1877a2fce83768b53e98afbc5bb97be8 100644 --- a/core/java/android/hardware/camera2/impl/PhysicalCaptureResultInfo.java +++ b/core/java/android/hardware/camera2/impl/PhysicalCaptureResultInfo.java @@ -15,6 +15,7 @@ */ package android.hardware.camera2.impl; +import android.hardware.camera2.CameraMetadataInfo; import android.hardware.camera2.impl.CameraMetadataNative; import android.os.Parcel; @@ -25,7 +26,7 @@ import android.os.Parcelable; */ public class PhysicalCaptureResultInfo implements Parcelable { private String cameraId; - private CameraMetadataNative cameraMetadata; + private CameraMetadataInfo cameraMetadataInfo; public static final @android.annotation.NonNull Parcelable.Creator CREATOR = new Parcelable.Creator() { @@ -46,7 +47,7 @@ public class PhysicalCaptureResultInfo implements Parcelable { public PhysicalCaptureResultInfo(String cameraId, CameraMetadataNative cameraMetadata) { this.cameraId = cameraId; - this.cameraMetadata = cameraMetadata; + this.cameraMetadataInfo = CameraMetadataInfo.metadata(cameraMetadata); } @Override @@ -57,13 +58,12 @@ public class PhysicalCaptureResultInfo implements Parcelable { @Override public void writeToParcel(Parcel dest, int flags) { dest.writeString(cameraId); - cameraMetadata.writeToParcel(dest, flags); + cameraMetadataInfo.writeToParcel(dest, flags); } public void readFromParcel(Parcel in) { cameraId = in.readString(); - cameraMetadata = new CameraMetadataNative(); - cameraMetadata.readFromParcel(in); + cameraMetadataInfo = CameraMetadataInfo.CREATOR.createFromParcel(in); } public String getCameraId() { @@ -71,6 +71,11 @@ public class PhysicalCaptureResultInfo implements Parcelable { } public CameraMetadataNative getCameraMetadata() { - return cameraMetadata; + return cameraMetadataInfo.getMetadata(); } -} + + public CameraMetadataInfo getCameraMetadataInfo() { + return cameraMetadataInfo; + } + +} \ No newline at end of file diff --git a/core/java/android/hardware/display/DisplayManager.java b/core/java/android/hardware/display/DisplayManager.java index 25327a9b1d52583d7b7a36350c97bd089ea55981..7054c37cbc3b6424d7e12a6c6f9b51b72b43b915 100644 --- a/core/java/android/hardware/display/DisplayManager.java +++ b/core/java/android/hardware/display/DisplayManager.java @@ -24,6 +24,7 @@ import static android.view.Display.INVALID_DISPLAY; import static com.android.server.display.feature.flags.Flags.FLAG_DISPLAY_LISTENER_PERFORMANCE_IMPROVEMENTS; import android.Manifest; +import android.annotation.CallbackExecutor; import android.annotation.FlaggedApi; import android.annotation.FloatRange; import android.annotation.IntDef; @@ -70,6 +71,7 @@ import java.util.ArrayList; import java.util.List; import java.util.Objects; import java.util.concurrent.Executor; +import java.util.function.Consumer; import java.util.function.Predicate; @@ -1840,6 +1842,30 @@ public final class DisplayManager { mGlobal.setDisplayTopology(topology); } + /** + * Register a listener to receive display topology updates. + * @param executor The executor specifying the thread on which the callbacks will be invoked + * @param listener The listener + * + * @hide + */ + @RequiresPermission(MANAGE_DISPLAYS) + public void registerTopologyListener(@NonNull @CallbackExecutor Executor executor, + @NonNull Consumer listener) { + mGlobal.registerTopologyListener(executor, listener, ActivityThread.currentPackageName()); + } + + /** + * Unregister a display topology listener. + * @param listener The listener to unregister + * + * @hide + */ + @RequiresPermission(MANAGE_DISPLAYS) + public void unregisterTopologyListener(@NonNull Consumer listener) { + mGlobal.unregisterTopologyListener(listener); + } + /** * Listens for changes in available display devices. */ diff --git a/core/java/android/hardware/display/DisplayManagerGlobal.java b/core/java/android/hardware/display/DisplayManagerGlobal.java index 1e66beea42a63ff95498f0e1d2af95242ab1ecd1..ffa546067effb5a6f763f9befbd3716fce5f6071 100644 --- a/core/java/android/hardware/display/DisplayManagerGlobal.java +++ b/core/java/android/hardware/display/DisplayManagerGlobal.java @@ -23,6 +23,7 @@ import static android.Manifest.permission.MANAGE_DISPLAYS; import static android.view.Display.HdrCapabilities.HdrType; import android.Manifest; +import android.annotation.CallbackExecutor; import android.annotation.FlaggedApi; import android.annotation.FloatRange; import android.annotation.IntDef; @@ -73,6 +74,7 @@ import java.util.Objects; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.Executor; import java.util.concurrent.atomic.AtomicLong; +import java.util.function.Consumer; /** * Manager communication with the display manager service on behalf of @@ -126,7 +128,7 @@ public final class DisplayManagerGlobal { public static final int EVENT_DISPLAY_REFRESH_RATE_CHANGED = 8; public static final int EVENT_DISPLAY_STATE_CHANGED = 9; - @LongDef(prefix = {"INTERNAL_EVENT_DISPLAY"}, flag = true, value = { + @LongDef(prefix = {"INTERNAL_EVENT_FLAG_"}, flag = true, value = { INTERNAL_EVENT_FLAG_DISPLAY_ADDED, INTERNAL_EVENT_FLAG_DISPLAY_CHANGED, INTERNAL_EVENT_FLAG_DISPLAY_REMOVED, @@ -134,7 +136,8 @@ public final class DisplayManagerGlobal { INTERNAL_EVENT_FLAG_DISPLAY_HDR_SDR_RATIO_CHANGED, INTERNAL_EVENT_FLAG_DISPLAY_CONNECTION_CHANGED, INTERNAL_EVENT_FLAG_DISPLAY_REFRESH_RATE, - INTERNAL_EVENT_FLAG_DISPLAY_STATE + INTERNAL_EVENT_FLAG_DISPLAY_STATE, + INTERNAL_EVENT_FLAG_TOPOLOGY_UPDATED, }) @Retention(RetentionPolicy.SOURCE) public @interface InternalEventFlag {} @@ -147,6 +150,7 @@ public final class DisplayManagerGlobal { public static final long INTERNAL_EVENT_FLAG_DISPLAY_CONNECTION_CHANGED = 1L << 5; public static final long INTERNAL_EVENT_FLAG_DISPLAY_REFRESH_RATE = 1L << 6; public static final long INTERNAL_EVENT_FLAG_DISPLAY_STATE = 1L << 7; + public static final long INTERNAL_EVENT_FLAG_TOPOLOGY_UPDATED = 1L << 8; @UnsupportedAppUsage private static DisplayManagerGlobal sInstance; @@ -164,6 +168,9 @@ public final class DisplayManagerGlobal { private final CopyOnWriteArrayList mDisplayListeners = new CopyOnWriteArrayList<>(); + private final CopyOnWriteArrayList mTopologyListeners = + new CopyOnWriteArrayList<>(); + private final SparseArray mDisplayInfoCache = new SparseArray<>(); private final ColorSpace mWideColorSpace; private final OverlayProperties mOverlayProperties; @@ -457,6 +464,18 @@ public final class DisplayManagerGlobal { } } + private void maybeLogAllTopologyListeners() { + if (!extraLogging()) { + return; + } + Slog.i(TAG, "Currently registered display topology listeners:"); + int i = 0; + for (DisplayTopologyListenerDelegate d : mTopologyListeners) { + Slog.i(TAG, i + ": " + d); + i++; + } + } + /** * Called when there is a display-related window configuration change. Reroutes the event from * WindowManager to make sure the {@link Display} fields are up-to-date in the last callback. @@ -502,9 +521,22 @@ public final class DisplayManagerGlobal { | INTERNAL_EVENT_FLAG_DISPLAY_CHANGED | INTERNAL_EVENT_FLAG_DISPLAY_REMOVED; } + if (!mTopologyListeners.isEmpty()) { + mask |= INTERNAL_EVENT_FLAG_TOPOLOGY_UPDATED; + } return mask; } + private DisplayTopologyListenerDelegate findTopologyListenerLocked( + @NonNull Consumer listener) { + for (DisplayTopologyListenerDelegate delegate : mTopologyListeners) { + if (delegate.mListener == listener) { + return delegate; + } + } + return null; + } + private void registerCallbackIfNeededLocked() { if (mCallback == null) { mCallback = new DisplayManagerCallback(); @@ -1316,6 +1348,9 @@ public final class DisplayManagerGlobal { */ @RequiresPermission(MANAGE_DISPLAYS) public void setDisplayTopology(DisplayTopology topology) { + if (topology == null) { + throw new IllegalArgumentException("Topology must not be null"); + } try { mDm.setDisplayTopology(topology); } catch (RemoteException ex) { @@ -1323,6 +1358,57 @@ public final class DisplayManagerGlobal { } } + /** + * @see DisplayManager#registerTopologyListener + */ + @RequiresPermission(MANAGE_DISPLAYS) + public void registerTopologyListener(@NonNull @CallbackExecutor Executor executor, + @NonNull Consumer listener, String packageName) { + if (!Flags.displayTopology()) { + return; + } + if (listener == null) { + throw new IllegalArgumentException("listener must not be null"); + } + if (extraLogging()) { + Slog.i(TAG, "Registering display topology listener: packageName=" + packageName); + } + synchronized (mLock) { + DisplayTopologyListenerDelegate delegate = findTopologyListenerLocked(listener); + if (delegate == null) { + mTopologyListeners.add(new DisplayTopologyListenerDelegate(listener, executor, + packageName)); + registerCallbackIfNeededLocked(); + updateCallbackIfNeededLocked(); + } + maybeLogAllTopologyListeners(); + } + } + + /** + * @see DisplayManager#unregisterTopologyListener + */ + @RequiresPermission(MANAGE_DISPLAYS) + public void unregisterTopologyListener(@NonNull Consumer listener) { + if (!Flags.displayTopology()) { + return; + } + if (listener == null) { + throw new IllegalArgumentException("listener must not be null"); + } + if (extraLogging()) { + Slog.i(TAG, "Unregistering display topology listener: " + listener); + } + synchronized (mLock) { + DisplayTopologyListenerDelegate delegate = findTopologyListenerLocked(listener); + if (delegate != null) { + mTopologyListeners.remove(delegate); + updateCallbackIfNeededLocked(); + } + } + maybeLogAllTopologyListeners(); + } + private final class DisplayManagerCallback extends IDisplayManagerCallback.Stub { @Override public void onDisplayEvent(int displayId, @DisplayEvent int event) { @@ -1332,6 +1418,16 @@ public final class DisplayManagerGlobal { } handleDisplayEvent(displayId, event, false /* forceUpdate */); } + + @Override + public void onTopologyChanged(DisplayTopology topology) { + if (DEBUG) { + Log.d(TAG, "onTopologyChanged: " + topology); + } + for (DisplayTopologyListenerDelegate listener : mTopologyListeners) { + listener.onTopologyChanged(topology); + } + } } private static final class DisplayListenerDelegate { @@ -1507,12 +1603,30 @@ public final class DisplayManagerGlobal { mExecutor.execute(mCallback::onStopped); } } + } - @Override // Binder call - public void onRequestedBrightnessChanged(float brightness) { - if (mCallback != null) { - mExecutor.execute(() -> mCallback.onRequestedBrightnessChanged(brightness)); + private static final class DisplayTopologyListenerDelegate { + private final Consumer mListener; + private final Executor mExecutor; + private final String mPackageName; + + DisplayTopologyListenerDelegate(@NonNull Consumer listener, + @NonNull @CallbackExecutor Executor executor, String packageName) { + mExecutor = executor; + mListener = listener; + mPackageName = packageName; + } + + @Override + public String toString() { + return "DisplayTopologyListener {packageName=" + mPackageName + "}"; + } + + void onTopologyChanged(DisplayTopology topology) { + if (extraLogging()) { + Slog.i(TAG, "Sending topology update: " + topology); } + mExecutor.execute(() -> mListener.accept(topology)); } } diff --git a/core/java/android/hardware/display/DisplayTopology.java b/core/java/android/hardware/display/DisplayTopology.java index f00c3a53ad0cb050a685001ea2714b4aa5c8672f..54d0dd0eb8f8e1c59bf1bb8064796422b29805d5 100644 --- a/core/java/android/hardware/display/DisplayTopology.java +++ b/core/java/android/hardware/display/DisplayTopology.java @@ -28,6 +28,7 @@ import android.graphics.RectF; import android.os.Parcel; import android.os.Parcelable; import android.util.IndentingPrintWriter; +import android.util.MathUtils; import android.util.Pair; import android.util.Slog; import android.view.Display; @@ -283,6 +284,154 @@ public final class DisplayTopology implements Parcelable { normalize(); } + /** + * Clamp offsets and remove any overlaps between displays. + */ + public void normalize() { + if (mRoot == null) { + return; + } + clampOffsets(mRoot); + + Map bounds = new HashMap<>(); + Map depths = new HashMap<>(); + Map parents = new HashMap<>(); + getInfo(bounds, depths, parents, mRoot, /* x= */ 0, /* y= */ 0, /* depth= */ 0); + + // Sort the displays first by their depth in the tree, then by the distance of their top + // left point from the root display's origin (0, 0). This way we process the displays + // starting at the root and we push out a display if necessary. + Comparator comparator = (d1, d2) -> { + if (d1 == d2) { + return 0; + } + + int compareDepths = Integer.compare(depths.get(d1), depths.get(d2)); + if (compareDepths != 0) { + return compareDepths; + } + + RectF bounds1 = bounds.get(d1); + RectF bounds2 = bounds.get(d2); + return Double.compare(Math.hypot(bounds1.left, bounds1.top), + Math.hypot(bounds2.left, bounds2.top)); + }; + List displays = new ArrayList<>(bounds.keySet()); + displays.sort(comparator); + + for (int i = 1; i < displays.size(); i++) { + TreeNode targetDisplay = displays.get(i); + TreeNode lastIntersectingSourceDisplay = null; + float lastOffsetX = 0; + float lastOffsetY = 0; + + for (int j = 0; j < i; j++) { + TreeNode sourceDisplay = displays.get(j); + RectF sourceBounds = bounds.get(sourceDisplay); + RectF targetBounds = bounds.get(targetDisplay); + + if (!RectF.intersects(sourceBounds, targetBounds)) { + continue; + } + + // Find the offset by which to move the display. Pick the smaller one among the x + // and y axes. + float offsetX = targetBounds.left >= 0 + ? sourceBounds.right - targetBounds.left + : sourceBounds.left - targetBounds.right; + float offsetY = targetBounds.top >= 0 + ? sourceBounds.bottom - targetBounds.top + : sourceBounds.top - targetBounds.bottom; + if (Math.abs(offsetX) <= Math.abs(offsetY)) { + targetBounds.left += offsetX; + targetBounds.right += offsetX; + // We need to also update the offset in the tree + if (targetDisplay.mPosition == POSITION_TOP + || targetDisplay.mPosition == POSITION_BOTTOM) { + targetDisplay.mOffset += offsetX; + } + offsetY = 0; + } else { + targetBounds.top += offsetY; + targetBounds.bottom += offsetY; + // We need to also update the offset in the tree + if (targetDisplay.mPosition == POSITION_LEFT + || targetDisplay.mPosition == POSITION_RIGHT) { + targetDisplay.mOffset += offsetY; + } + offsetX = 0; + } + + lastIntersectingSourceDisplay = sourceDisplay; + lastOffsetX = offsetX; + lastOffsetY = offsetY; + } + + // Now re-parent the target display to the last intersecting source display if it no + // longer touches its parent. + if (lastIntersectingSourceDisplay == null) { + // There was no overlap. + continue; + } + TreeNode parent = parents.get(targetDisplay); + if (parent == lastIntersectingSourceDisplay) { + // The displays are moved in such a way that they're adjacent to the intersecting + // display. If the last intersecting display happens to be the parent then we + // already know that the display is adjacent to its parent. + continue; + } + + RectF childBounds = bounds.get(targetDisplay); + RectF parentBounds = bounds.get(parent); + // Check that the edges are on the same line + boolean areTouching = switch (targetDisplay.mPosition) { + case POSITION_LEFT -> floatEquals(parentBounds.left, childBounds.right); + case POSITION_RIGHT -> floatEquals(parentBounds.right, childBounds.left); + case POSITION_TOP -> floatEquals(parentBounds.top, childBounds.bottom); + case POSITION_BOTTOM -> floatEquals(parentBounds.bottom, childBounds.top); + default -> throw new IllegalStateException( + "Unexpected value: " + targetDisplay.mPosition); + }; + // Check that the offset is within bounds + areTouching &= switch (targetDisplay.mPosition) { + case POSITION_LEFT, POSITION_RIGHT -> + childBounds.bottom + EPSILON >= parentBounds.top + && childBounds.top <= parentBounds.bottom + EPSILON; + case POSITION_TOP, POSITION_BOTTOM -> + childBounds.right + EPSILON >= parentBounds.left + && childBounds.left <= parentBounds.right + EPSILON; + default -> throw new IllegalStateException( + "Unexpected value: " + targetDisplay.mPosition); + }; + + if (!areTouching) { + // Re-parent the display. + parent.mChildren.remove(targetDisplay); + RectF lastIntersectingSourceDisplayBounds = + bounds.get(lastIntersectingSourceDisplay); + lastIntersectingSourceDisplay.mChildren.add(targetDisplay); + + if (lastOffsetX != 0) { + targetDisplay.mPosition = lastOffsetX > 0 ? POSITION_RIGHT : POSITION_LEFT; + targetDisplay.mOffset = + childBounds.top - lastIntersectingSourceDisplayBounds.top; + } else if (lastOffsetY != 0) { + targetDisplay.mPosition = lastOffsetY > 0 ? POSITION_BOTTOM : POSITION_TOP; + targetDisplay.mOffset = + childBounds.left - lastIntersectingSourceDisplayBounds.left; + } + } + } + } + + /** + * @return A deep copy of the topology that will not be modified by the system. + */ + public DisplayTopology copy() { + TreeNode rootCopy = mRoot == null ? null : mRoot.copy(); + return new DisplayTopology(rootCopy, mPrimaryDisplayId); + } + @Override public int describeContents() { return 0; @@ -433,145 +582,6 @@ public final class DisplayTopology implements Parcelable { } } - /** - * Update the topology to remove any overlaps between displays. - */ - @VisibleForTesting - public void normalize() { - if (mRoot == null) { - return; - } - Map bounds = new HashMap<>(); - Map depths = new HashMap<>(); - Map parents = new HashMap<>(); - getInfo(bounds, depths, parents, mRoot, /* x= */ 0, /* y= */ 0, /* depth= */ 0); - - // Sort the displays first by their depth in the tree, then by the distance of their top - // left point from the root display's origin (0, 0). This way we process the displays - // starting at the root and we push out a display if necessary. - Comparator comparator = (d1, d2) -> { - if (d1 == d2) { - return 0; - } - - int compareDepths = Integer.compare(depths.get(d1), depths.get(d2)); - if (compareDepths != 0) { - return compareDepths; - } - - RectF bounds1 = bounds.get(d1); - RectF bounds2 = bounds.get(d2); - return Double.compare(Math.hypot(bounds1.left, bounds1.top), - Math.hypot(bounds2.left, bounds2.top)); - }; - List displays = new ArrayList<>(bounds.keySet()); - displays.sort(comparator); - - for (int i = 1; i < displays.size(); i++) { - TreeNode targetDisplay = displays.get(i); - TreeNode lastIntersectingSourceDisplay = null; - float lastOffsetX = 0; - float lastOffsetY = 0; - - for (int j = 0; j < i; j++) { - TreeNode sourceDisplay = displays.get(j); - RectF sourceBounds = bounds.get(sourceDisplay); - RectF targetBounds = bounds.get(targetDisplay); - - if (!RectF.intersects(sourceBounds, targetBounds)) { - continue; - } - - // Find the offset by which to move the display. Pick the smaller one among the x - // and y axes. - float offsetX = targetBounds.left >= 0 - ? sourceBounds.right - targetBounds.left - : sourceBounds.left - targetBounds.right; - float offsetY = targetBounds.top >= 0 - ? sourceBounds.bottom - targetBounds.top - : sourceBounds.top - targetBounds.bottom; - if (Math.abs(offsetX) <= Math.abs(offsetY)) { - targetBounds.left += offsetX; - targetBounds.right += offsetX; - // We need to also update the offset in the tree - if (targetDisplay.mPosition == POSITION_TOP - || targetDisplay.mPosition == POSITION_BOTTOM) { - targetDisplay.mOffset += offsetX; - } - offsetY = 0; - } else { - targetBounds.top += offsetY; - targetBounds.bottom += offsetY; - // We need to also update the offset in the tree - if (targetDisplay.mPosition == POSITION_LEFT - || targetDisplay.mPosition == POSITION_RIGHT) { - targetDisplay.mOffset += offsetY; - } - offsetX = 0; - } - - lastIntersectingSourceDisplay = sourceDisplay; - lastOffsetX = offsetX; - lastOffsetY = offsetY; - } - - // Now re-parent the target display to the last intersecting source display if it no - // longer touches its parent. - if (lastIntersectingSourceDisplay == null) { - // There was no overlap. - continue; - } - TreeNode parent = parents.get(targetDisplay); - if (parent == lastIntersectingSourceDisplay) { - // The displays are moved in such a way that they're adjacent to the intersecting - // display. If the last intersecting display happens to be the parent then we - // already know that the display is adjacent to its parent. - continue; - } - - RectF childBounds = bounds.get(targetDisplay); - RectF parentBounds = bounds.get(parent); - // Check that the edges are on the same line - boolean areTouching = switch (targetDisplay.mPosition) { - case POSITION_LEFT -> floatEquals(parentBounds.left, childBounds.right); - case POSITION_RIGHT -> floatEquals(parentBounds.right, childBounds.left); - case POSITION_TOP -> floatEquals(parentBounds.top, childBounds.bottom); - case POSITION_BOTTOM -> floatEquals(parentBounds.bottom, childBounds.top); - default -> throw new IllegalStateException( - "Unexpected value: " + targetDisplay.mPosition); - }; - // Check that the offset is within bounds - areTouching &= switch (targetDisplay.mPosition) { - case POSITION_LEFT, POSITION_RIGHT -> - childBounds.bottom + EPSILON >= parentBounds.top - && childBounds.top <= parentBounds.bottom + EPSILON; - case POSITION_TOP, POSITION_BOTTOM -> - childBounds.right + EPSILON >= parentBounds.left - && childBounds.left <= parentBounds.right + EPSILON; - default -> throw new IllegalStateException( - "Unexpected value: " + targetDisplay.mPosition); - }; - - if (!areTouching) { - // Re-parent the display. - parent.mChildren.remove(targetDisplay); - RectF lastIntersectingSourceDisplayBounds = - bounds.get(lastIntersectingSourceDisplay); - lastIntersectingSourceDisplay.mChildren.add(targetDisplay); - - if (lastOffsetX != 0) { - targetDisplay.mPosition = lastOffsetX > 0 ? POSITION_RIGHT : POSITION_LEFT; - targetDisplay.mOffset = - childBounds.top - lastIntersectingSourceDisplayBounds.top; - } else if (lastOffsetY != 0) { - targetDisplay.mPosition = lastOffsetY > 0 ? POSITION_BOTTOM : POSITION_TOP; - targetDisplay.mOffset = - childBounds.left - lastIntersectingSourceDisplayBounds.left; - } - } - } - } - /** * Tests whether two brightness float values are within a small enough tolerance * of each other. @@ -597,6 +607,24 @@ public final class DisplayTopology implements Parcelable { return found; } + /** + * Ensure that the offsets of all displays within the given tree are within bounds. + * @param display The starting node + */ + private void clampOffsets(TreeNode display) { + if (display == null) { + return; + } + for (TreeNode child : display.mChildren) { + if (child.mPosition == POSITION_LEFT || child.mPosition == POSITION_RIGHT) { + child.mOffset = MathUtils.constrain(child.mOffset, -child.mHeight, display.mHeight); + } else if (child.mPosition == POSITION_TOP || child.mPosition == POSITION_BOTTOM) { + child.mOffset = MathUtils.constrain(child.mOffset, -child.mWidth, display.mWidth); + } + clampOffsets(child); + } + } + public static final class TreeNode implements Parcelable { public static final int POSITION_LEFT = 0; public static final int POSITION_TOP = 1; @@ -694,6 +722,17 @@ public final class DisplayTopology implements Parcelable { return Collections.unmodifiableList(mChildren); } + /** + * @return A deep copy of the node that will not be modified by the system. + */ + public TreeNode copy() { + TreeNode copy = new TreeNode(mDisplayId, mWidth, mHeight, mPosition, mOffset); + for (TreeNode child : mChildren) { + copy.mChildren.add(child.copy()); + } + return copy; + } + @Override public String toString() { return "Display {id=" + mDisplayId + ", width=" + mWidth + ", height=" + mHeight diff --git a/core/java/android/hardware/display/IBrightnessListener.aidl b/core/java/android/hardware/display/IBrightnessListener.aidl new file mode 100644 index 0000000000000000000000000000000000000000..f5d37435b287fbdd7edb805159864c4c51fab09b --- /dev/null +++ b/core/java/android/hardware/display/IBrightnessListener.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.hardware.display; + +/** + * Interface for notifying the display owner about brightness changes. + * + * @hide + */ +oneway interface IBrightnessListener { + /** + * Called when the display's brightness has changed. + * + * @param brightness the new brightness of the display. Value of {@code 0.0} indicates the + * minimum supported brightness and value of {@code 1.0} indicates the maximum supported + * brightness. + */ + void onBrightnessChanged(float brightness); +} diff --git a/core/java/android/hardware/display/IDisplayManagerCallback.aidl b/core/java/android/hardware/display/IDisplayManagerCallback.aidl index c50e3fb26156348363c178dd441adcc4b25c912b..d05a1b8400b0d30a78737f5786072a6ce53a7eff 100644 --- a/core/java/android/hardware/display/IDisplayManagerCallback.aidl +++ b/core/java/android/hardware/display/IDisplayManagerCallback.aidl @@ -16,7 +16,10 @@ package android.hardware.display; +import android.hardware.display.DisplayTopology; + /** @hide */ interface IDisplayManagerCallback { oneway void onDisplayEvent(int displayId, int event); + oneway void onTopologyChanged(in DisplayTopology topology); } diff --git a/core/java/android/hardware/display/IVirtualDisplayCallback.aidl b/core/java/android/hardware/display/IVirtualDisplayCallback.aidl index 9cc0364f27296dbd6bd32695f725304403880a30..c3490d177be256d18bfb926ac96bec1a2039636f 100644 --- a/core/java/android/hardware/display/IVirtualDisplayCallback.aidl +++ b/core/java/android/hardware/display/IVirtualDisplayCallback.aidl @@ -38,9 +38,4 @@ oneway interface IVirtualDisplayCallback { * of the application to release() the virtual display. */ void onStopped(); - - /** - * Called when the virtual display's requested brightness has changed. - */ - void onRequestedBrightnessChanged(float brightness); } diff --git a/core/java/android/hardware/display/VirtualDisplay.java b/core/java/android/hardware/display/VirtualDisplay.java index 3b573ea98c279e1b05f583e5c55ca1021d9ab697..32b640583734bd0e224ebaa268826fd820307ff4 100644 --- a/core/java/android/hardware/display/VirtualDisplay.java +++ b/core/java/android/hardware/display/VirtualDisplay.java @@ -16,8 +16,6 @@ package android.hardware.display; import android.annotation.FlaggedApi; -import android.annotation.FloatRange; -import android.annotation.SystemApi; import android.view.Display; import android.view.Surface; @@ -166,25 +164,5 @@ public final class VirtualDisplay { * of the application to release() the virtual display. */ public void onStopped() { } - - /** - * Called when the requested brightness of the display has changed. - * - *

The system may adjust the display's brightness based on user or app activity. This - * callback will only be invoked if the display has an explicitly specified default - * brightness value.

- * - *

Value of {@code 0.0} indicates the minimum supported brightness and value of - * {@code 1.0} indicates the maximum supported brightness.

- * - * @see android.view.View#setKeepScreenOn(boolean) - * @see android.view.WindowManager.LayoutParams#screenBrightness - * @see VirtualDisplayConfig.Builder#setDefaultBrightness(float) - * @hide - */ - @FlaggedApi(android.companion.virtualdevice.flags.Flags.FLAG_DEVICE_AWARE_DISPLAY_POWER) - @SystemApi - public void onRequestedBrightnessChanged( - @FloatRange(from = 0.0f, to = 1.0f) float brightness) {} } } diff --git a/core/java/android/hardware/display/VirtualDisplayConfig.java b/core/java/android/hardware/display/VirtualDisplayConfig.java index 57d9d28a9d475024a629c927da844c5e94e9b5fc..eceaa8ff4c952268ee7bbf01baba9fe87f04ec9e 100644 --- a/core/java/android/hardware/display/VirtualDisplayConfig.java +++ b/core/java/android/hardware/display/VirtualDisplayConfig.java @@ -18,11 +18,13 @@ package android.hardware.display; import static android.view.Display.DEFAULT_DISPLAY; +import android.annotation.CallbackExecutor; import android.annotation.FlaggedApi; import android.annotation.FloatRange; import android.annotation.IntRange; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.SuppressLint; import android.annotation.SystemApi; import android.hardware.display.DisplayManager.VirtualDisplayFlag; import android.media.projection.MediaProjection; @@ -38,6 +40,7 @@ import android.view.Surface; import java.util.Collections; import java.util.Objects; import java.util.Set; +import java.util.concurrent.Executor; /** * Holds configuration used to create {@link VirtualDisplay} instances. @@ -63,6 +66,7 @@ public final class VirtualDisplayConfig implements Parcelable { private final DisplayCutout mDisplayCutout; private final boolean mIgnoreActivitySizeRestrictions; private final float mDefaultBrightness; + private final IBrightnessListener mBrightnessListener; private VirtualDisplayConfig( @NonNull String name, @@ -79,7 +83,8 @@ public final class VirtualDisplayConfig implements Parcelable { boolean isHomeSupported, @Nullable DisplayCutout displayCutout, boolean ignoreActivitySizeRestrictions, - @FloatRange(from = 0.0f, to = 1.0f) float defaultBrightness) { + @FloatRange(from = 0.0f, to = 1.0f) float defaultBrightness, + IBrightnessListener brightnessListener) { mName = name; mWidth = width; mHeight = height; @@ -95,6 +100,7 @@ public final class VirtualDisplayConfig implements Parcelable { mDisplayCutout = displayCutout; mIgnoreActivitySizeRestrictions = ignoreActivitySizeRestrictions; mDefaultBrightness = defaultBrightness; + mBrightnessListener = brightnessListener; } /** @@ -167,14 +173,20 @@ public final class VirtualDisplayConfig implements Parcelable { * indicates the maximum supported brightness.

* * @see Builder#setDefaultBrightness(float) - * @hide */ @FlaggedApi(android.companion.virtualdevice.flags.Flags.FLAG_DEVICE_AWARE_DISPLAY_POWER) - @SystemApi public @FloatRange(from = 0.0f, to = 1.0f) float getDefaultBrightness() { return mDefaultBrightness; } + /** + * Returns the listener to get notified about changes in the display brightness. + * @hide + */ + @Nullable + public IBrightnessListener getBrightnessListener() { + return mBrightnessListener; + } /** * Returns the unique identifier for the display. Shouldn't be displayed to the user. @@ -266,6 +278,7 @@ public final class VirtualDisplayConfig implements Parcelable { DisplayCutout.ParcelableWrapper.writeCutoutToParcel(mDisplayCutout, dest, flags); dest.writeBoolean(mIgnoreActivitySizeRestrictions); dest.writeFloat(mDefaultBrightness); + dest.writeStrongBinder(mBrightnessListener != null ? mBrightnessListener.asBinder() : null); } @Override @@ -294,7 +307,9 @@ public final class VirtualDisplayConfig implements Parcelable { && mIsHomeSupported == that.mIsHomeSupported && mIgnoreActivitySizeRestrictions == that.mIgnoreActivitySizeRestrictions && Objects.equals(mDisplayCutout, that.mDisplayCutout) - && mDefaultBrightness == that.mDefaultBrightness; + && mDefaultBrightness == that.mDefaultBrightness + && Objects.equals(mBrightnessListener, that.mBrightnessListener); + } @Override @@ -303,7 +318,7 @@ public final class VirtualDisplayConfig implements Parcelable { mName, mWidth, mHeight, mDensityDpi, mFlags, mSurface, mUniqueId, mDisplayIdToMirror, mWindowManagerMirroringEnabled, mDisplayCategories, mRequestedRefreshRate, mIsHomeSupported, mDisplayCutout, - mIgnoreActivitySizeRestrictions, mDefaultBrightness); + mIgnoreActivitySizeRestrictions, mDefaultBrightness, mBrightnessListener); return hashCode; } @@ -345,6 +360,43 @@ public final class VirtualDisplayConfig implements Parcelable { mDisplayCutout = DisplayCutout.ParcelableWrapper.readCutoutFromParcel(in); mIgnoreActivitySizeRestrictions = in.readBoolean(); mDefaultBrightness = in.readFloat(); + mBrightnessListener = IBrightnessListener.Stub.asInterface(in.readStrongBinder()); + + } + + /** + * Listener for display brightness changes. + */ + @FlaggedApi(android.companion.virtualdevice.flags.Flags.FLAG_DEVICE_AWARE_DISPLAY_POWER) + public interface BrightnessListener { + + /** + * Called when the display's brightness has changed. + * + * @param brightness the new brightness of the display. Value of {@code 0.0} indicates the + * minimum supported brightness and value of {@code 1.0} indicates the maximum supported + * brightness. + */ + void onBrightnessChanged(@FloatRange(from = 0.0f, to = 1.0f) float brightness); + } + + private static class BrightnessListenerDelegate extends IBrightnessListener.Stub { + + @NonNull + private final Executor mExecutor; + @NonNull + private final BrightnessListener mListener; + + BrightnessListenerDelegate(@NonNull @CallbackExecutor Executor executor, + @NonNull BrightnessListener listener) { + mExecutor = executor; + mListener = listener; + } + + @Override + public void onBrightnessChanged(float brightness) { + mExecutor.execute(() -> mListener.onBrightnessChanged(brightness)); + } } @NonNull @@ -380,6 +432,7 @@ public final class VirtualDisplayConfig implements Parcelable { private DisplayCutout mDisplayCutout = null; private boolean mIgnoreActivitySizeRestrictions = false; private float mDefaultBrightness = 0.0f; + private IBrightnessListener mBrightnessListener = null; /** * Creates a new Builder. @@ -575,7 +628,7 @@ public final class VirtualDisplayConfig implements Parcelable { * Sets the default brightness of the display. * *

The system will use this brightness value whenever the display should be bright, i.e. - * it is powered on and not dimmed due to user activity or app activity.

+ * it is powered on and not modified due to user activity or app activity.

* *

Value of {@code 0.0} indicates the minimum supported brightness and value of * {@code 1.0} indicates the maximum supported brightness.

@@ -583,12 +636,9 @@ public final class VirtualDisplayConfig implements Parcelable { *

If unset, defaults to {@code 0.0}

* * @see android.view.View#setKeepScreenOn(boolean) - * @see Builder#setDefaultBrightness(float) - * @see VirtualDisplay.Callback#onRequestedBrightnessChanged(float) - * @hide + * @see #setBrightnessListener(Executor, BrightnessListener) */ @FlaggedApi(android.companion.virtualdevice.flags.Flags.FLAG_DEVICE_AWARE_DISPLAY_POWER) - @SystemApi @NonNull public Builder setDefaultBrightness(@FloatRange(from = 0.0f, to = 1.0f) float brightness) { if (brightness < PowerManager.BRIGHTNESS_MIN @@ -600,6 +650,22 @@ public final class VirtualDisplayConfig implements Parcelable { return this; } + /** + * Sets the listener to get notified about changes in the display brightness. + * + * @param executor The executor where the callback is executed on. + * @param listener The listener to get notified when the display brightness has changed. + */ + @SuppressLint("MissingGetterMatchingBuilder") // The hidden getter returns the AIDL object + @FlaggedApi(android.companion.virtualdevice.flags.Flags.FLAG_DEVICE_AWARE_DISPLAY_POWER) + @NonNull + public Builder setBrightnessListener(@NonNull @CallbackExecutor Executor executor, + @NonNull BrightnessListener listener) { + mBrightnessListener = new BrightnessListenerDelegate( + Objects.requireNonNull(executor), Objects.requireNonNull(listener)); + return this; + } + /** * Builds the {@link VirtualDisplayConfig} instance. */ @@ -620,7 +686,8 @@ public final class VirtualDisplayConfig implements Parcelable { mIsHomeSupported, mDisplayCutout, mIgnoreActivitySizeRestrictions, - mDefaultBrightness); + mDefaultBrightness, + mBrightnessListener); } } } diff --git a/core/java/android/hardware/input/InputSettings.java b/core/java/android/hardware/input/InputSettings.java index 114459e5e81991ed28de05115febdef251f165f6..3f9317aa24f124e7a64a062efb7d36067d952118 100644 --- a/core/java/android/hardware/input/InputSettings.java +++ b/core/java/android/hardware/input/InputSettings.java @@ -27,6 +27,7 @@ import static com.android.hardware.input.Flags.keyboardA11ySlowKeysFlag; import static com.android.hardware.input.Flags.keyboardA11yStickyKeysFlag; import static com.android.hardware.input.Flags.mouseReverseVerticalScrolling; import static com.android.hardware.input.Flags.mouseSwapPrimaryButton; +import static com.android.hardware.input.Flags.touchpadSystemGestureDisable; import static com.android.hardware.input.Flags.touchpadTapDragging; import static com.android.hardware.input.Flags.touchpadThreeFingerTapShortcut; import static com.android.hardware.input.Flags.touchpadVisualizer; @@ -373,6 +374,15 @@ public class InputSettings { return touchpadTapDragging(); } + /** + * Returns true if the feature flag for disabling system gestures on touchpads is enabled. + * + * @hide + */ + public static boolean isTouchpadSystemGestureDisableFeatureFlagEnabled() { + return touchpadSystemGestureDisable(); + } + /** * Returns true if the feature flag for touchpad visualizer is enabled. * @@ -529,6 +539,40 @@ public class InputSettings { && isTouchpadThreeFingerTapShortcutFeatureFlagEnabled(); } + /** + * Returns true if system gestures (three- and four-finger swipes) should be enabled for + * touchpads. + * + * @param context The application context. + * @return Whether system gestures on touchpads are enabled + * + * @hide + */ + public static boolean useTouchpadSystemGestures(@NonNull Context context) { + if (!isTouchpadSystemGestureDisableFeatureFlagEnabled()) { + return true; + } + return Settings.System.getIntForUser(context.getContentResolver(), + Settings.System.TOUCHPAD_SYSTEM_GESTURES, 1, UserHandle.USER_CURRENT) == 1; + } + + /** + * Sets whether system gestures are enabled for touchpads. + * + * @param context The application context. + * @param enabled True to enable system gestures. + * + * @hide + */ + @RequiresPermission(Manifest.permission.WRITE_SETTINGS) + public static void setTouchpadSystemGesturesEnabled(@NonNull Context context, boolean enabled) { + if (!isTouchpadSystemGestureDisableFeatureFlagEnabled()) { + return; + } + Settings.System.putIntForUser(context.getContentResolver(), + Settings.System.TOUCHPAD_SYSTEM_GESTURES, enabled ? 1 : 0, UserHandle.USER_CURRENT); + } + /** * Whether a pointer icon will be shown over the location of a stylus pointer. * diff --git a/core/java/android/hardware/input/input_framework.aconfig b/core/java/android/hardware/input/input_framework.aconfig index 0c89059a475a5eb25d7d094a33f38fd524410637..ebb617249993e54f61706ee08fbbe89e0a6b54bd 100644 --- a/core/java/android/hardware/input/input_framework.aconfig +++ b/core/java/android/hardware/input/input_framework.aconfig @@ -148,6 +148,13 @@ flag { bug: "373458181" } +flag { + name: "touchpad_system_gesture_disable" + namespace: "input" + description: "Adds an accessibility setting to disable system navigation gestures (3- and 4-finger swipes) on touchpads" + bug: "353947750" +} + flag { name: "enable_customizable_input_gestures" namespace: "input" @@ -160,6 +167,7 @@ flag { namespace: "input" description: "Enables new 25Q2 keycodes" bug: "365920375" + is_exported: true } flag { diff --git a/core/java/android/hardware/location/ContextHubManager.java b/core/java/android/hardware/location/ContextHubManager.java index 117d8fe24809c85c1be69ab22c29966d2d0abd44..3a74130d5e831c78ebe4300147d9b1bc9e3eb999 100644 --- a/core/java/android/hardware/location/ContextHubManager.java +++ b/core/java/android/hardware/location/ContextHubManager.java @@ -1267,6 +1267,9 @@ public final class ContextHubManager { * registration succeeds, the endpoint can receive notifications through the provided callback. * * @param hubEndpoint {@link HubEndpoint} object created by {@link HubEndpoint.Builder} + * @throws IllegalStateException if the registration failed, for example if too many endpoints + * are registered at the service + * @throws UnsupportedOperationException if endpoint registration is not supported */ @RequiresPermission(android.Manifest.permission.ACCESS_CONTEXT_HUB) @FlaggedApi(Flags.FLAG_OFFLOAD_API) diff --git a/core/java/android/hardware/soundtrigger/ConversionUtil.java b/core/java/android/hardware/soundtrigger/ConversionUtil.java index 2ba1078055697a6d02c5a4622bc6a23f8bd6f20a..73c8e3e130a18d60a0bd37e9634252dc3b9e8039 100644 --- a/core/java/android/hardware/soundtrigger/ConversionUtil.java +++ b/core/java/android/hardware/soundtrigger/ConversionUtil.java @@ -157,7 +157,7 @@ public class ConversionUtil { SoundTrigger.RecognitionConfig apiConfig) { RecognitionConfig aidlConfig = new RecognitionConfig(); aidlConfig.captureRequested = apiConfig.isCaptureRequested(); - // apiConfig.isAllowMultipleTriggers() is ignored by the lower layers. + // apiConfig.isMultipleTriggersAllowed() is ignored by the lower layers. aidlConfig.phraseRecognitionExtras = new PhraseRecognitionExtra[apiConfig.getKeyphrases().size()]; for (int i = 0; i < apiConfig.getKeyphrases().size(); ++i) { @@ -178,7 +178,7 @@ public class ConversionUtil { } return new SoundTrigger.RecognitionConfig.Builder() .setCaptureRequested(aidlConfig.captureRequested) - .setAllowMultipleTriggers(false) + .setMultipleTriggersAllowed(false) .setKeyphrases(keyphrases) .setData(Arrays.copyOf(aidlConfig.data, aidlConfig.data.length)) .setAudioCapabilities(aidl2apiAudioCapabilities(aidlConfig.audioCapabilities)) diff --git a/core/java/android/hardware/soundtrigger/SoundTrigger.java b/core/java/android/hardware/soundtrigger/SoundTrigger.java index 7745b036bcbe3371476ba280a8217b0448cb1550..7c4ddc669968bc3e968bb5f16b3782891314b461 100644 --- a/core/java/android/hardware/soundtrigger/SoundTrigger.java +++ b/core/java/android/hardware/soundtrigger/SoundTrigger.java @@ -1518,7 +1518,7 @@ public class SoundTrigger { @FlaggedApi(android.media.soundtrigger.Flags.FLAG_MANAGER_API) public static final class RecognitionConfig implements Parcelable { private final boolean mCaptureRequested; - private final boolean mAllowMultipleTriggers; + private final boolean mMultipleTriggersAllowed; private final KeyphraseRecognitionExtra mKeyphrases[]; private final byte[] mData; private final @ModuleProperties.AudioCapabilities int mAudioCapabilities; @@ -1529,7 +1529,7 @@ public class SoundTrigger { * {@link SoundTriggerModule#startRecognition(int, RecognitionConfig)} * * @param captureRequested Whether the DSP should capture the trigger sound. - * @param allowMultipleTriggers Whether the service should restart listening after the DSP + * @param multipleTriggersAllowed Whether the service should restart listening after the DSP * triggers. * @param keyphrases List of keyphrases in the sound model. * @param data Opaque data for use by system applications who know about voice engine @@ -1537,11 +1537,11 @@ public class SoundTrigger { * @param audioCapabilities Bit field encoding of the AudioCapabilities. See * {@link ModuleProperties.AudioCapabilities} for details. */ - private RecognitionConfig(boolean captureRequested, boolean allowMultipleTriggers, + private RecognitionConfig(boolean captureRequested, boolean multipleTriggersAllowed, @Nullable KeyphraseRecognitionExtra[] keyphrases, @Nullable byte[] data, @ModuleProperties.AudioCapabilities int audioCapabilities) { this.mCaptureRequested = captureRequested; - this.mAllowMultipleTriggers = allowMultipleTriggers; + this.mMultipleTriggersAllowed = multipleTriggersAllowed; this.mKeyphrases = keyphrases != null ? keyphrases : new KeyphraseRecognitionExtra[0]; this.mData = data != null ? data : new byte[0]; this.mAudioCapabilities = audioCapabilities; @@ -1553,7 +1553,7 @@ public class SoundTrigger { * * @deprecated Use {@link Builder} instead. * @param captureRequested Whether the DSP should capture the trigger sound. - * @param allowMultipleTriggers Whether the service should restart listening after the DSP + * @param multipleTriggersAllowed Whether the service should restart listening after the DSP * triggers. * @param keyphrases List of keyphrases in the sound model. * @param data Opaque data for use by system applications. @@ -1563,9 +1563,9 @@ public class SoundTrigger { @UnsupportedAppUsage @Deprecated @TestApi - public RecognitionConfig(boolean captureRequested, boolean allowMultipleTriggers, + public RecognitionConfig(boolean captureRequested, boolean multipleTriggersAllowed, @Nullable KeyphraseRecognitionExtra[] keyphrases, @Nullable byte[] data) { - this(captureRequested, allowMultipleTriggers, keyphrases, data, 0); + this(captureRequested, multipleTriggersAllowed, keyphrases, data, 0); } public static final @android.annotation.NonNull Parcelable.Creator CREATOR @@ -1593,8 +1593,8 @@ public class SoundTrigger { *

Note: This config flag is currently used at the service layer rather than by * the DSP. */ - public boolean isAllowMultipleTriggers() { - return mAllowMultipleTriggers; + public boolean isMultipleTriggersAllowed() { + return mMultipleTriggersAllowed; } /** @@ -1627,19 +1627,19 @@ public class SoundTrigger { private static RecognitionConfig fromParcel(Parcel in) { boolean captureRequested = in.readBoolean(); - boolean allowMultipleTriggers = in.readBoolean(); + boolean multipleTriggersAllowed = in.readBoolean(); KeyphraseRecognitionExtra[] keyphrases = in.createTypedArray(KeyphraseRecognitionExtra.CREATOR); byte[] data = in.createByteArray(); int audioCapabilities = in.readInt(); - return new RecognitionConfig(captureRequested, allowMultipleTriggers, keyphrases, data, - audioCapabilities); + return new RecognitionConfig(captureRequested, multipleTriggersAllowed, keyphrases, + data, audioCapabilities); } @Override public void writeToParcel(@NonNull Parcel dest, int flags) { dest.writeBoolean(mCaptureRequested); - dest.writeBoolean(mAllowMultipleTriggers); + dest.writeBoolean(mMultipleTriggersAllowed); dest.writeTypedArray(mKeyphrases, flags); dest.writeByteArray(mData); dest.writeInt(mAudioCapabilities); @@ -1653,7 +1653,7 @@ public class SoundTrigger { @Override public String toString() { return "RecognitionConfig [captureRequested=" + mCaptureRequested - + ", allowMultipleTriggers=" + mAllowMultipleTriggers + ", keyphrases=" + + ", multipleTriggersAllowed=" + mMultipleTriggersAllowed + ", keyphrases=" + Arrays.toString(mKeyphrases) + ", data=" + Arrays.toString(mData) + ", audioCapabilities=" + Integer.toHexString(mAudioCapabilities) + "]"; } @@ -1670,7 +1670,7 @@ public class SoundTrigger { if (mCaptureRequested != other.mCaptureRequested) { return false; } - if (mAllowMultipleTriggers != other.mAllowMultipleTriggers) { + if (mMultipleTriggersAllowed != other.mMultipleTriggersAllowed) { return false; } if (!Arrays.equals(mKeyphrases, other.mKeyphrases)) { @@ -1690,7 +1690,7 @@ public class SoundTrigger { final int prime = 31; int result = 1; result = prime * result + (mCaptureRequested ? 1 : 0); - result = prime * result + (mAllowMultipleTriggers ? 1 : 0); + result = prime * result + (mMultipleTriggersAllowed ? 1 : 0); result = prime * result + Arrays.hashCode(mKeyphrases); result = prime * result + Arrays.hashCode(mData); result = prime * result + mAudioCapabilities; @@ -1702,7 +1702,7 @@ public class SoundTrigger { */ public static final class Builder { private boolean mCaptureRequested; - private boolean mAllowMultipleTriggers; + private boolean mMultipleTriggersAllowed; @Nullable private KeyphraseRecognitionExtra[] mKeyphrases; @Nullable private byte[] mData; private @ModuleProperties.AudioCapabilities int mAudioCapabilities; @@ -1725,12 +1725,12 @@ public class SoundTrigger { /** * Sets allow multiple triggers state. - * @param allowMultipleTriggers Whether the service should restart listening after the + * @param multipleTriggersAllowed Whether the service should restart listening after the * DSP triggers. * @return the same Builder instance. */ - public @NonNull Builder setAllowMultipleTriggers(boolean allowMultipleTriggers) { - mAllowMultipleTriggers = allowMultipleTriggers; + public @NonNull Builder setMultipleTriggersAllowed(boolean multipleTriggersAllowed) { + mMultipleTriggersAllowed = multipleTriggersAllowed; return this; } @@ -1779,7 +1779,7 @@ public class SoundTrigger { public @NonNull RecognitionConfig build() { RecognitionConfig config = new RecognitionConfig( /* captureRequested= */ mCaptureRequested, - /* allowMultipleTriggers= */ mAllowMultipleTriggers, + /* multipleTriggersAllowed= */ mMultipleTriggersAllowed, /* keyphrases= */ mKeyphrases, /* data= */ mData, /* audioCapabilities= */ mAudioCapabilities); diff --git a/core/java/android/hardware/usb/flags/usb_framework_flags.aconfig b/core/java/android/hardware/usb/flags/usb_framework_flags.aconfig index b719a7c6daacede3ffcb0ec684417324d179c161..9403f78383dd67692034f2d13953f66399c6c980 100644 --- a/core/java/android/hardware/usb/flags/usb_framework_flags.aconfig +++ b/core/java/android/hardware/usb/flags/usb_framework_flags.aconfig @@ -30,6 +30,7 @@ flag { namespace: "usb" description: "Feature flag to enable exposing usb speed system api" bug: "373653182" + is_exported: true } flag { diff --git a/core/java/android/net/LocalSocket.java b/core/java/android/net/LocalSocket.java index a86396cd7c8de6d5abc4a22218d8cf2b3e23341a..0fedf8ecbb23b307bbd84e5387e102aa87b8d7fa 100644 --- a/core/java/android/net/LocalSocket.java +++ b/core/java/android/net/LocalSocket.java @@ -65,7 +65,7 @@ public class LocalSocket implements Closeable { } /** - * Creates a AF_LOCAL/UNIX domain stream socket with given socket type + * Creates a AF_LOCAL/UNIX domain socket with the given socket type. * * @param sockType either {@link #SOCKET_DGRAM}, {@link #SOCKET_STREAM} * or {@link #SOCKET_SEQPACKET} diff --git a/core/java/android/net/flags.aconfig b/core/java/android/net/flags.aconfig index f7dc7906d50da367d32ddb97613437114063fa35..95b5f697969ef1cc8ba0ae7498db8da40fb7f8e3 100644 --- a/core/java/android/net/flags.aconfig +++ b/core/java/android/net/flags.aconfig @@ -27,4 +27,13 @@ flag { metadata { purpose: PURPOSE_BUGFIX } + is_exported: true +} + +flag { + name: "x509_extensions_certificate_transparency" + is_exported: true + namespace: "network_security" + description: "Flag to use checkServerTrusted to verify SCTs in OCSP and TLS Data" + bug: "319829948" } diff --git a/core/java/android/net/http/X509TrustManagerExtensions.java b/core/java/android/net/http/X509TrustManagerExtensions.java index 280dad0284b69b1edea3c82be4bfbe02a2c3934e..b44f75a585d5dd0455176f9991ed81887c42af8d 100644 --- a/core/java/android/net/http/X509TrustManagerExtensions.java +++ b/core/java/android/net/http/X509TrustManagerExtensions.java @@ -16,6 +16,13 @@ package android.net.http; +import static com.android.org.conscrypt.flags.Flags.certificateTransparencyCheckservertrustedApi; + +import android.annotation.FlaggedApi; +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.annotation.SuppressLint; +import android.net.platform.flags.Flags; import android.security.net.config.UserCertificateSource; import com.android.org.conscrypt.TrustManagerImpl; @@ -24,6 +31,7 @@ import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; +import java.util.Collections; import java.util.List; import javax.net.ssl.X509TrustManager; @@ -31,9 +39,9 @@ import javax.net.ssl.X509TrustManager; /** * X509TrustManager wrapper exposing Android-added features. *

- * The checkServerTrusted method allows callers to perform additional - * verification of certificate chains after they have been successfully verified - * by the platform. + * The checkServerTrusted methods allow callers to provide some additional + * context for the verification. This is particularly useful when an SSLEngine + * or SSLSocket is not available. *

*/ public class X509TrustManagerExtensions { @@ -42,6 +50,7 @@ public class X509TrustManagerExtensions { // Methods to use when mDelegate is not a TrustManagerImpl and duck typing is being used. private final X509TrustManager mTrustManager; private final Method mCheckServerTrusted; + private final Method mCheckServerTrustedOcspAndTlsData; private final Method mIsSameTrustConfiguration; /** @@ -55,6 +64,7 @@ public class X509TrustManagerExtensions { mDelegate = (TrustManagerImpl) tm; mTrustManager = null; mCheckServerTrusted = null; + mCheckServerTrustedOcspAndTlsData = null; mIsSameTrustConfiguration = null; return; } @@ -69,8 +79,19 @@ public class X509TrustManagerExtensions { String.class); } catch (NoSuchMethodException e) { throw new IllegalArgumentException("Required method" - + " checkServerTrusted(X509Certificate[], String, String, String) missing"); + + " checkServerTrusted(X509Certificate[], String, String) missing"); } + // Check that the OCSP and TlsData aware checkServerTrusted is present. + Method checkServerTrustedOcspAndTlsData = null; + try { + checkServerTrustedOcspAndTlsData = tm.getClass().getMethod("checkServerTrusted", + X509Certificate[].class, + Byte[].class, + Byte[].class, + String.class, + String.class); + } catch (ReflectiveOperationException ignored) { } + mCheckServerTrustedOcspAndTlsData = checkServerTrustedOcspAndTlsData; // Get the option isSameTrustConfiguration method. Method isSameTrustConfiguration = null; try { @@ -114,6 +135,65 @@ public class X509TrustManagerExtensions { } } + /** + * Verifies the given certificate chain. + * + *

See {@link X509TrustManager#checkServerTrusted(X509Certificate[], String)} for a + * description of the chain and authType parameters. The final parameter, host, should be the + * hostname of the server.

+ * + *

ocspData and tlsSctData may be provided to verify any Signed Certificate Timestamp (SCT) + * attached to the connection. These are ASN.1 octet strings (SignedCertificateTimestampList) + * as described in RFC 6962, Section 3.3. Note that SCTs embedded in the certificate chain + * will automatically be processed. + *

+ * + * @throws CertificateException if the chain does not verify correctly. + * @throws IllegalArgumentException if the TrustManager is not compatible. + * @return the properly ordered chain used for verification as a list of X509Certificates. + */ + @FlaggedApi(Flags.FLAG_X509_EXTENSIONS_CERTIFICATE_TRANSPARENCY) + @NonNull + public List checkServerTrusted( + @SuppressLint("ArrayReturn") @NonNull X509Certificate[] chain, + @Nullable byte[] ocspData, + @Nullable byte[] tlsSctData, + @NonNull String authType, + @NonNull String host) throws CertificateException { + List result; + if (mDelegate != null) { + if (certificateTransparencyCheckservertrustedApi()) { + result = mDelegate.checkServerTrusted(chain, ocspData, tlsSctData, authType, host); + return result == null ? Collections.emptyList() : result; + } else { + // The conscrypt mainline module does not have the required method. + throw new IllegalArgumentException("Required method" + + " checkServerTrusted(X509Certificate[], byte[], byte[], String, String)" + + " not available in TrustManagerImpl"); + } + } + if (mCheckServerTrustedOcspAndTlsData == null) { + throw new IllegalArgumentException("Required method" + + " checkServerTrusted(X509Certificate[], byte[], byte[], String, String)" + + " missing"); + } + try { + result = (List) mCheckServerTrustedOcspAndTlsData.invoke(mTrustManager, + ocspData, tlsSctData, chain, authType, host); + return result == null ? Collections.emptyList() : result; + } catch (IllegalAccessException e) { + throw new CertificateException("Failed to call checkServerTrusted", e); + } catch (InvocationTargetException e) { + if (e.getCause() instanceof CertificateException) { + throw (CertificateException) e.getCause(); + } + if (e.getCause() instanceof RuntimeException) { + throw (RuntimeException) e.getCause(); + } + throw new CertificateException("checkServerTrusted failed", e.getCause()); + } + } + /** * Checks whether a CA certificate is added by an user. * diff --git a/core/java/android/net/vcn/VcnCellUnderlyingNetworkTemplate.java b/core/java/android/net/vcn/VcnCellUnderlyingNetworkTemplate.java index c0398ce1fcf1a01399bc2fa1438be2ce42b61af7..ded94159a94545b4ba8f0f495e4cd1d9f6038663 100644 --- a/core/java/android/net/vcn/VcnCellUnderlyingNetworkTemplate.java +++ b/core/java/android/net/vcn/VcnCellUnderlyingNetworkTemplate.java @@ -23,18 +23,19 @@ import static android.net.NetworkCapabilities.NET_CAPABILITY_MMS; import static android.net.NetworkCapabilities.NET_CAPABILITY_RCS; import static android.net.vcn.VcnUnderlyingNetworkTemplate.MATCH_ANY; import static android.net.vcn.VcnUnderlyingNetworkTemplate.getMatchCriteriaString; +import static android.net.vcn.util.PersistableBundleUtils.INTEGER_DESERIALIZER; +import static android.net.vcn.util.PersistableBundleUtils.INTEGER_SERIALIZER; +import static android.net.vcn.util.PersistableBundleUtils.STRING_DESERIALIZER; +import static android.net.vcn.util.PersistableBundleUtils.STRING_SERIALIZER; import static com.android.internal.annotations.VisibleForTesting.Visibility; -import static com.android.server.vcn.util.PersistableBundleUtils.INTEGER_DESERIALIZER; -import static com.android.server.vcn.util.PersistableBundleUtils.INTEGER_SERIALIZER; -import static com.android.server.vcn.util.PersistableBundleUtils.STRING_DESERIALIZER; -import static com.android.server.vcn.util.PersistableBundleUtils.STRING_SERIALIZER; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SuppressLint; import android.net.NetworkCapabilities; import android.net.vcn.VcnUnderlyingNetworkTemplate.MatchCriteria; +import android.net.vcn.util.PersistableBundleUtils; import android.os.PersistableBundle; import android.telephony.SubscriptionInfo; import android.telephony.SubscriptionManager; @@ -44,7 +45,6 @@ import android.util.IndentingPrintWriter; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.Preconditions; -import com.android.server.vcn.util.PersistableBundleUtils; import java.util.ArrayList; import java.util.Collections; diff --git a/core/java/android/net/vcn/VcnConfig.java b/core/java/android/net/vcn/VcnConfig.java index a27e9230d4738af6e06bb01c3b93ff2690ba1dbe..0d0efb2f73f92323e3107199b23abbc3ca757492 100644 --- a/core/java/android/net/vcn/VcnConfig.java +++ b/core/java/android/net/vcn/VcnConfig.java @@ -18,10 +18,10 @@ package android.net.vcn; import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; import static android.net.NetworkCapabilities.TRANSPORT_TEST; import static android.net.NetworkCapabilities.TRANSPORT_WIFI; +import static android.net.vcn.util.PersistableBundleUtils.INTEGER_DESERIALIZER; +import static android.net.vcn.util.PersistableBundleUtils.INTEGER_SERIALIZER; import static com.android.internal.annotations.VisibleForTesting.Visibility; -import static com.android.server.vcn.util.PersistableBundleUtils.INTEGER_DESERIALIZER; -import static com.android.server.vcn.util.PersistableBundleUtils.INTEGER_SERIALIZER; import android.annotation.IntDef; import android.annotation.NonNull; @@ -29,6 +29,7 @@ import android.annotation.Nullable; import android.content.Context; import android.net.NetworkCapabilities; import android.net.NetworkRequest; +import android.net.vcn.util.PersistableBundleUtils; import android.os.Parcel; import android.os.Parcelable; import android.os.PersistableBundle; @@ -37,7 +38,6 @@ import android.util.Log; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.Preconditions; -import com.android.server.vcn.util.PersistableBundleUtils; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; diff --git a/core/java/android/net/vcn/VcnGatewayConnectionConfig.java b/core/java/android/net/vcn/VcnGatewayConnectionConfig.java index b270062cbffc75ede140f867e3ab43562d9dda91..067144e6f4749745e36870e48f0adafaaf0d4015 100644 --- a/core/java/android/net/vcn/VcnGatewayConnectionConfig.java +++ b/core/java/android/net/vcn/VcnGatewayConnectionConfig.java @@ -32,12 +32,12 @@ import android.net.Network; import android.net.NetworkCapabilities; import android.net.ipsec.ike.IkeTunnelConnectionParams; import android.net.vcn.persistablebundleutils.TunnelConnectionParamsUtils; +import android.net.vcn.util.PersistableBundleUtils; import android.os.PersistableBundle; import android.util.ArraySet; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.Preconditions; -import com.android.server.vcn.util.PersistableBundleUtils; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; diff --git a/core/java/android/net/vcn/VcnWifiUnderlyingNetworkTemplate.java b/core/java/android/net/vcn/VcnWifiUnderlyingNetworkTemplate.java index c7b2f188ba96001eb114a391b066ac23e5a1787f..770a8c118a4de90ad327a05636d28c091c898143 100644 --- a/core/java/android/net/vcn/VcnWifiUnderlyingNetworkTemplate.java +++ b/core/java/android/net/vcn/VcnWifiUnderlyingNetworkTemplate.java @@ -17,22 +17,22 @@ package android.net.vcn; import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET; import static android.net.vcn.VcnUnderlyingNetworkTemplate.MATCH_ANY; +import static android.net.vcn.util.PersistableBundleUtils.STRING_DESERIALIZER; +import static android.net.vcn.util.PersistableBundleUtils.STRING_SERIALIZER; import static com.android.internal.annotations.VisibleForTesting.Visibility; -import static com.android.server.vcn.util.PersistableBundleUtils.STRING_DESERIALIZER; -import static com.android.server.vcn.util.PersistableBundleUtils.STRING_SERIALIZER; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SuppressLint; import android.net.NetworkCapabilities; import android.net.vcn.VcnUnderlyingNetworkTemplate.MatchCriteria; +import android.net.vcn.util.PersistableBundleUtils; import android.os.PersistableBundle; import android.util.ArraySet; import android.util.IndentingPrintWriter; import com.android.internal.annotations.VisibleForTesting; -import com.android.server.vcn.util.PersistableBundleUtils; import java.util.ArrayList; import java.util.Collections; diff --git a/core/java/android/net/vcn/persistablebundleutils/ChildSaProposalUtils.java b/core/java/android/net/vcn/persistablebundleutils/ChildSaProposalUtils.java index ce5ec75f01a2e3e82126c7007dbe3aa0c82acef4..48c1b25a97ab050342a2db671dd41dcd28349d2e 100644 --- a/core/java/android/net/vcn/persistablebundleutils/ChildSaProposalUtils.java +++ b/core/java/android/net/vcn/persistablebundleutils/ChildSaProposalUtils.java @@ -20,10 +20,10 @@ import static com.android.internal.annotations.VisibleForTesting.Visibility; import android.annotation.NonNull; import android.net.ipsec.ike.ChildSaProposal; +import android.net.vcn.util.PersistableBundleUtils; import android.os.PersistableBundle; import com.android.internal.annotations.VisibleForTesting; -import com.android.server.vcn.util.PersistableBundleUtils; import java.util.List; import java.util.Objects; diff --git a/core/java/android/net/vcn/persistablebundleutils/EapSessionConfigUtils.java b/core/java/android/net/vcn/persistablebundleutils/EapSessionConfigUtils.java index 853a52da766a5e6c3e559697a98fa8804d4428d1..dc1ee36b71c127f63ee5a75c652de25ccb7e945a 100644 --- a/core/java/android/net/vcn/persistablebundleutils/EapSessionConfigUtils.java +++ b/core/java/android/net/vcn/persistablebundleutils/EapSessionConfigUtils.java @@ -28,10 +28,10 @@ import android.net.eap.EapSessionConfig.EapMsChapV2Config; import android.net.eap.EapSessionConfig.EapSimConfig; import android.net.eap.EapSessionConfig.EapTtlsConfig; import android.net.eap.EapSessionConfig.EapUiccConfig; +import android.net.vcn.util.PersistableBundleUtils; import android.os.PersistableBundle; import com.android.internal.annotations.VisibleForTesting; -import com.android.server.vcn.util.PersistableBundleUtils; import java.security.cert.CertificateEncodingException; import java.security.cert.X509Certificate; diff --git a/core/java/android/net/vcn/persistablebundleutils/IkeIdentificationUtils.java b/core/java/android/net/vcn/persistablebundleutils/IkeIdentificationUtils.java index 6acb34ebb78ee8d31aab4f9401073a968d7b3865..6e8616fc9cb063483c5808a687504907a9c78746 100644 --- a/core/java/android/net/vcn/persistablebundleutils/IkeIdentificationUtils.java +++ b/core/java/android/net/vcn/persistablebundleutils/IkeIdentificationUtils.java @@ -27,10 +27,10 @@ import android.net.ipsec.ike.IkeIpv4AddrIdentification; import android.net.ipsec.ike.IkeIpv6AddrIdentification; import android.net.ipsec.ike.IkeKeyIdIdentification; import android.net.ipsec.ike.IkeRfc822AddrIdentification; +import android.net.vcn.util.PersistableBundleUtils; import android.os.PersistableBundle; import com.android.internal.annotations.VisibleForTesting; -import com.android.server.vcn.util.PersistableBundleUtils; import java.net.Inet4Address; import java.net.Inet6Address; diff --git a/core/java/android/net/vcn/persistablebundleutils/IkeSaProposalUtils.java b/core/java/android/net/vcn/persistablebundleutils/IkeSaProposalUtils.java index 1459671f4136afe74a144983e18bf81f877fbb4a..b590148de51f1da2df9450d1854f8b20f6b5f7e9 100644 --- a/core/java/android/net/vcn/persistablebundleutils/IkeSaProposalUtils.java +++ b/core/java/android/net/vcn/persistablebundleutils/IkeSaProposalUtils.java @@ -20,10 +20,10 @@ import static com.android.internal.annotations.VisibleForTesting.Visibility; import android.annotation.NonNull; import android.net.ipsec.ike.IkeSaProposal; +import android.net.vcn.util.PersistableBundleUtils; import android.os.PersistableBundle; import com.android.internal.annotations.VisibleForTesting; -import com.android.server.vcn.util.PersistableBundleUtils; import java.util.List; import java.util.Objects; diff --git a/core/java/android/net/vcn/persistablebundleutils/IkeSessionParamsUtils.java b/core/java/android/net/vcn/persistablebundleutils/IkeSessionParamsUtils.java index d1531a119a0d7ed8621895ec8991ab66dc7e6cba..aefac2e89aea0229a64005502ac649639ec0eb81 100644 --- a/core/java/android/net/vcn/persistablebundleutils/IkeSessionParamsUtils.java +++ b/core/java/android/net/vcn/persistablebundleutils/IkeSessionParamsUtils.java @@ -35,12 +35,12 @@ import android.net.ipsec.ike.IkeSessionParams.IkeAuthDigitalSignRemoteConfig; import android.net.ipsec.ike.IkeSessionParams.IkeAuthEapConfig; import android.net.ipsec.ike.IkeSessionParams.IkeAuthPskConfig; import android.net.ipsec.ike.IkeSessionParams.IkeConfigRequest; +import android.net.vcn.util.PersistableBundleUtils; import android.os.PersistableBundle; import android.util.ArraySet; import android.util.Log; import com.android.internal.annotations.VisibleForTesting; -import com.android.server.vcn.util.PersistableBundleUtils; import java.net.InetAddress; import java.security.PrivateKey; diff --git a/core/java/android/net/vcn/persistablebundleutils/SaProposalUtilsBase.java b/core/java/android/net/vcn/persistablebundleutils/SaProposalUtilsBase.java index 0c9ee84327988014b92ba4ff9785bd1532e41b72..469966a48465d591bffac906d8e0eef3bf83b054 100644 --- a/core/java/android/net/vcn/persistablebundleutils/SaProposalUtilsBase.java +++ b/core/java/android/net/vcn/persistablebundleutils/SaProposalUtilsBase.java @@ -18,11 +18,10 @@ package android.net.vcn.persistablebundleutils; import android.annotation.NonNull; import android.net.ipsec.ike.SaProposal; +import android.net.vcn.util.PersistableBundleUtils; import android.os.PersistableBundle; import android.util.Pair; -import com.android.server.vcn.util.PersistableBundleUtils; - import java.util.ArrayList; import java.util.List; import java.util.Objects; diff --git a/core/java/android/net/vcn/persistablebundleutils/TunnelModeChildSessionParamsUtils.java b/core/java/android/net/vcn/persistablebundleutils/TunnelModeChildSessionParamsUtils.java index e62acac14bd7df3a32722ec83b03e3b32296fb0e..3f4ba345a118ab98d1c6d0aff11ad66d835a0916 100644 --- a/core/java/android/net/vcn/persistablebundleutils/TunnelModeChildSessionParamsUtils.java +++ b/core/java/android/net/vcn/persistablebundleutils/TunnelModeChildSessionParamsUtils.java @@ -34,11 +34,11 @@ import android.net.ipsec.ike.TunnelModeChildSessionParams.ConfigRequestIpv4Netma import android.net.ipsec.ike.TunnelModeChildSessionParams.ConfigRequestIpv6Address; import android.net.ipsec.ike.TunnelModeChildSessionParams.ConfigRequestIpv6DnsServer; import android.net.ipsec.ike.TunnelModeChildSessionParams.TunnelModeChildConfigRequest; +import android.net.vcn.util.PersistableBundleUtils; import android.os.PersistableBundle; import android.util.Log; import com.android.internal.annotations.VisibleForTesting; -import com.android.server.vcn.util.PersistableBundleUtils; import java.net.Inet4Address; import java.net.Inet6Address; diff --git a/services/core/java/com/android/server/vcn/util/LogUtils.java b/core/java/android/net/vcn/util/LogUtils.java similarity index 96% rename from services/core/java/com/android/server/vcn/util/LogUtils.java rename to core/java/android/net/vcn/util/LogUtils.java index 93728ceb27c5bcf60d43f310e1ccc51f5d3e4243..7f7f85271603b93665081f95953458bdcf1a3ca8 100644 --- a/services/core/java/com/android/server/vcn/util/LogUtils.java +++ b/core/java/android/net/vcn/util/LogUtils.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.server.vcn.util; +package android.net.vcn.util; import android.annotation.Nullable; import android.os.ParcelUuid; diff --git a/services/core/java/com/android/server/vcn/util/MtuUtils.java b/core/java/android/net/vcn/util/MtuUtils.java similarity index 99% rename from services/core/java/com/android/server/vcn/util/MtuUtils.java rename to core/java/android/net/vcn/util/MtuUtils.java index 356c71f5f26a8f797613505888523a18ec721bc7..c3123bcecf33f56070a1d9a1150b750ddc3ca5b9 100644 --- a/services/core/java/com/android/server/vcn/util/MtuUtils.java +++ b/core/java/android/net/vcn/util/MtuUtils.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.server.vcn.util; +package android.net.vcn.util; import static android.net.ipsec.ike.SaProposal.ENCRYPTION_ALGORITHM_3DES; import static android.net.ipsec.ike.SaProposal.ENCRYPTION_ALGORITHM_AES_CBC; diff --git a/services/core/java/com/android/server/vcn/util/OneWayBoolean.java b/core/java/android/net/vcn/util/OneWayBoolean.java similarity index 96% rename from services/core/java/com/android/server/vcn/util/OneWayBoolean.java rename to core/java/android/net/vcn/util/OneWayBoolean.java index e79bb2d2547dbcf90a8a0c86c647b7eaf3b497e4..a7ef67b187b9045ec71cf9c7ae5ad97b1577cb19 100644 --- a/services/core/java/com/android/server/vcn/util/OneWayBoolean.java +++ b/core/java/android/net/vcn/util/OneWayBoolean.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.server.vcn.util; +package android.net.vcn.util; /** * OneWayBoolean is an abstraction for a boolean that MUST only ever be flipped from false to true diff --git a/services/core/java/com/android/server/vcn/util/PersistableBundleUtils.java b/core/java/android/net/vcn/util/PersistableBundleUtils.java similarity index 99% rename from services/core/java/com/android/server/vcn/util/PersistableBundleUtils.java rename to core/java/android/net/vcn/util/PersistableBundleUtils.java index d6761a2b37d8f0b02572b8b8f7733e0cf02e0308..4dc42c7827f89e19d9bf7b169a9fa7d91c036cdc 100644 --- a/services/core/java/com/android/server/vcn/util/PersistableBundleUtils.java +++ b/core/java/android/net/vcn/util/PersistableBundleUtils.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.server.vcn.util; +package android.net.vcn.util; import android.annotation.NonNull; import android.annotation.Nullable; diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java index c2e9260879a8ea87e49b38c30984929964a4279d..8b6da7e0ae58f5a0bc6e8dc52e1b7caa100d34aa 100644 --- a/core/java/android/os/Build.java +++ b/core/java/android/os/Build.java @@ -41,6 +41,8 @@ import android.util.ArraySet; import android.util.Slog; import android.view.View; +import com.android.internal.util.FrameworkStatsLog; + import dalvik.system.VMRuntime; import java.lang.annotation.Retention; @@ -1545,6 +1547,57 @@ public class Build { return sdkIntFull % VERSION_CODES_FULL.SDK_INT_MULTIPLIER; } + /** + * Convert a major.minor version String like "36.1" to an int that + * represents both major and minor version. + * + * @param version the String to parse + * @return an int encoding the major and minor version + * @throws IllegalArgumentException if the string could not be converted into an int + * + * @hide + */ + @SuppressWarnings("FlaggedApi") // SDK_INT_MULTIPLIER is defined in this file + public static @SdkIntFull int parseFullVersion(@NonNull String version) { + int index = version.indexOf('.'); + int major; + int minor = 0; + try { + if (index == -1) { + major = Integer.parseInt(version); + } else { + major = Integer.parseInt(version.substring(0, index)); + minor = Integer.parseInt(version.substring(index + 1)); + } + if (major < 0 || minor < 0) { + throw new NumberFormatException(); + } + } catch (NumberFormatException e) { + throw new IllegalArgumentException("failed to parse '" + version + + "' as a major.minor version code"); + } + return major * VERSION_CODES_FULL.SDK_INT_MULTIPLIER + minor; + } + + /** + * Convert an int representing a major.minor version like SDK_INT_FULL to a + * human readable string. The returned string is only intended for debug + * and error messages. + * + * @param version the int to convert to a string + * @return a String representing the same major.minor version as the int passed in + * @throws IllegalArgumentException if {@code version} is negative + * + * @hide + */ + public static String fullVersionToString(@SdkIntFull int version) { + if (version < 0) { + throw new IllegalArgumentException("failed to convert '" + version + + "' to string: not a valid major.minor version code"); + } + return String.format("%d.%d", getMajorSdkVersion(version), getMinorSdkVersion(version)); + } + /** * The vendor API for 2024 Q2 * @@ -1615,11 +1668,14 @@ public class Build { */ @FlaggedApi(android.os.Flags.FLAG_API_FOR_BACKPORTED_FIXES) public static @BackportedFixStatus int getBackportedFixStatus(long id) { - if (id <= 0 || id > 1023) { - return BACKPORTED_FIX_STATUS_UNKNOWN; + @BackportedFixStatus int status = BACKPORTED_FIX_STATUS_UNKNOWN; + int uid = Binder.getCallingUid(); + if (id > 0 && id <= 1023) { + status = isBitSet(BackportedFixesProperties.alias_bitset(), (int) id) + ? BACKPORTED_FIX_STATUS_FIXED : BACKPORTED_FIX_STATUS_UNKNOWN; } - return isBitSet(BackportedFixesProperties.alias_bitset(), (int) id) - ? BACKPORTED_FIX_STATUS_FIXED : BACKPORTED_FIX_STATUS_UNKNOWN; + FrameworkStatsLog.write(FrameworkStatsLog.BACKPORTED_FIX_STATUS_REPORTED, uid, id, status); + return status; } private static boolean isBitSet(List bitsetLongArray, int bitIndex) { diff --git a/core/java/android/os/CombinedMessageQueue/MessageQueue.java b/core/java/android/os/CombinedMessageQueue/MessageQueue.java index 476968151e18e8f06d6d8dcb6a7ffbf2c770c47b..23114c4318c72bc7c6197846c59e5a978ca8e98c 100644 --- a/core/java/android/os/CombinedMessageQueue/MessageQueue.java +++ b/core/java/android/os/CombinedMessageQueue/MessageQueue.java @@ -30,6 +30,8 @@ import android.util.Printer; import android.util.SparseArray; import android.util.proto.ProtoOutputStream; +import com.android.internal.ravenwood.RavenwoodEnvironment; + import dalvik.annotation.optimization.NeverCompile; import java.io.FileDescriptor; @@ -116,39 +118,58 @@ public final class MessageQueue { private native static void nativeSetFileDescriptorEvents(long ptr, int fd, int events); MessageQueue(boolean quitAllowed) { - 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()); + initIsProcessAllowedToUseConcurrent(); + mUseConcurrent = sIsProcessAllowedToUseConcurrent; + 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 == null - || processName.contains("test") - || processName.contains("Test")) { - useConcurrent = false; - } - } + private static void initIsProcessAllowedToUseConcurrent() { + if (sIsProcessAllowedToUseConcurrent != null) { + return; + } - // 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 (RavenwoodEnvironment.getInstance().isRunningOnRavenwood()) { + sIsProcessAllowedToUseConcurrent = false; + return; + } - // Holdback study. - if (useConcurrent && Flags.messageQueueForceLegacy()) { - useConcurrent = false; - } + final String processName = Process.myProcessName(); + if (processName == null) { + // Assume that this is a host-side test and avoid concurrent mode for now. + sIsProcessAllowedToUseConcurrent = false; + return; + } - sIsProcessAllowedToUseConcurrent = useConcurrent; - mUseConcurrent = useConcurrent; + // 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. + sIsProcessAllowedToUseConcurrent = UserHandle.isCore(Process.myUid()); + + if (sIsProcessAllowedToUseConcurrent) { + // Some platform tests run in core UIDs. + // Use this awful heuristic to detect them. + if (processName.contains("test") || processName.contains("Test")) { + sIsProcessAllowedToUseConcurrent = false; + } } else { - mUseConcurrent = sIsProcessAllowedToUseConcurrent; + // Also explicitly allow SystemUI processes. + // SystemUI doesn't run in a core UID, but we want to give it the performance boost, + // and we know that it's safe to use the concurrent implementation in SystemUI. + sIsProcessAllowedToUseConcurrent = + processName.equals("com.android.systemui") + || processName.startsWith("com.android.systemui:"); + // On Android distributions where SystemUI has a different process name, + // the above condition may need to be adjusted accordingly. } - mQuitAllowed = quitAllowed; - mPtr = nativeInit(); + // We can lift these restrictions in the future after we've made it possible for test + // authors to test Looper and MessageQueue without resorting to reflection. + + // Holdback study. + if (sIsProcessAllowedToUseConcurrent && Flags.messageQueueForceLegacy()) { + sIsProcessAllowedToUseConcurrent = false; + } } @Override diff --git a/core/java/android/os/CpuHeadroomParams.java b/core/java/android/os/CpuHeadroomParams.java index 8e78b7e355f91745c495bcaae2444c5d623d8b32..072c012d6db96ded82a0f713cd18e8176bb31482 100644 --- a/core/java/android/os/CpuHeadroomParams.java +++ b/core/java/android/os/CpuHeadroomParams.java @@ -56,15 +56,9 @@ public final class CpuHeadroomParams { */ public static final int CPU_HEADROOM_CALCULATION_TYPE_AVERAGE = 1; - /** - * Minimum CPU headroom calculation window size. - */ - public static final int CPU_HEADROOM_CALCULATION_WINDOW_MILLIS_MIN = 50; - - /** - * Maximum CPU headroom calculation window size. - */ - public static final int CPU_HEADROOM_CALCULATION_WINDOW_MILLIS_MAX = 10000; + private static final int CALCULATION_WINDOW_MILLIS_MIN = 50; + private static final int CALCULATION_WINDOW_MILLIS_MAX = 10000; + private static final int MAX_TID_COUNT = 5; /** * Sets the headroom calculation type. @@ -99,20 +93,18 @@ public final class CpuHeadroomParams { * Sets the headroom calculation window size in milliseconds. *

* - * @param windowMillis the window size in milliseconds, ranged from - * [{@link #CPU_HEADROOM_CALCULATION_WINDOW_MILLIS_MIN}, - * {@link #CPU_HEADROOM_CALCULATION_WINDOW_MILLIS_MAX}]. The smaller - * the value, the larger fluctuation in value should be expected. The - * default value can be retrieved from the + * @param windowMillis the window size in milliseconds ranges from [50, 10000]. The smaller the + * window size, the larger fluctuation in the headroom value should be + * expected. The default value can be retrieved from the * {@link #getCalculationWindowMillis}. The device will try to use the * closest feasible window size to this param. * @throws IllegalArgumentException if the window size is not in allowed range. */ public void setCalculationWindowMillis( - @IntRange(from = CPU_HEADROOM_CALCULATION_WINDOW_MILLIS_MIN, to = - CPU_HEADROOM_CALCULATION_WINDOW_MILLIS_MAX) int windowMillis) { - if (windowMillis < CPU_HEADROOM_CALCULATION_WINDOW_MILLIS_MIN - || windowMillis > CPU_HEADROOM_CALCULATION_WINDOW_MILLIS_MAX) { + @IntRange(from = CALCULATION_WINDOW_MILLIS_MIN, to = + CALCULATION_WINDOW_MILLIS_MAX) int windowMillis) { + if (windowMillis < CALCULATION_WINDOW_MILLIS_MIN + || windowMillis > CALCULATION_WINDOW_MILLIS_MAX) { throw new IllegalArgumentException("Invalid calculation window: " + windowMillis); } mInternal.calculationWindowMillis = windowMillis; @@ -121,10 +113,10 @@ public final class CpuHeadroomParams { /** * Gets the headroom calculation window size in milliseconds. *

- * This will return the default value chosen by the device if not set. + * This will return the default value chosen by the device if the params is not set. */ - public @IntRange(from = CPU_HEADROOM_CALCULATION_WINDOW_MILLIS_MIN, to = - CPU_HEADROOM_CALCULATION_WINDOW_MILLIS_MAX) long getCalculationWindowMillis() { + public @IntRange(from = CALCULATION_WINDOW_MILLIS_MIN, to = + CALCULATION_WINDOW_MILLIS_MAX) long getCalculationWindowMillis() { return mInternal.calculationWindowMillis; } @@ -141,7 +133,7 @@ public final class CpuHeadroomParams { * positive. */ public void setTids(@NonNull int... tids) { - if (tids.length == 0 || tids.length > 5) { + if (tids.length == 0 || tids.length > MAX_TID_COUNT) { throw new IllegalArgumentException("Invalid number of TIDs: " + tids.length); } for (int tid : tids) { diff --git a/core/java/android/os/GpuHeadroomParams.java b/core/java/android/os/GpuHeadroomParams.java index 4dc98264e57b94df70206eb8b673cb1c4e7ec389..126ee8cce3d07ea20696aaa783b4d8bb00a48fc9 100644 --- a/core/java/android/os/GpuHeadroomParams.java +++ b/core/java/android/os/GpuHeadroomParams.java @@ -54,15 +54,8 @@ public final class GpuHeadroomParams { */ public static final int GPU_HEADROOM_CALCULATION_TYPE_AVERAGE = 1; - /** - * Minimum GPU headroom calculation window size. - */ - public static final int GPU_HEADROOM_CALCULATION_WINDOW_MILLIS_MIN = 50; - - /** - * Maximum GPU headroom calculation window size. - */ - public static final int GPU_HEADROOM_CALCULATION_WINDOW_MILLIS_MAX = 10000; + private static final int CALCULATION_WINDOW_MILLIS_MIN = 50; + private static final int CALCULATION_WINDOW_MILLIS_MAX = 10000; /** * Sets the headroom calculation type. @@ -82,7 +75,7 @@ public final class GpuHeadroomParams { /** * Gets the headroom calculation type. - * Default to {@link #GPU_HEADROOM_CALCULATION_TYPE_MIN} if not set. + * Default to {@link #GPU_HEADROOM_CALCULATION_TYPE_MIN} if the params is not set. */ public @GpuHeadroomCalculationType int getCalculationType() { @GpuHeadroomCalculationType int validatedType = switch ((int) mInternal.calculationType) { @@ -97,20 +90,18 @@ public final class GpuHeadroomParams { * Sets the headroom calculation window size in milliseconds. *

* - * @param windowMillis the window size in milliseconds, ranged from - * [{@link #GPU_HEADROOM_CALCULATION_WINDOW_MILLIS_MIN}, - * {@link #GPU_HEADROOM_CALCULATION_WINDOW_MILLIS_MAX}]. The smaller - * the value, the larger fluctuation in value should be expected. The - * default value can be retrieved from the - * {@link #getCalculationWindowMillis}. If the device will try to use the + * @param windowMillis the window size in milliseconds ranges from [50, 10000]. The smaller the + * window size, the larger fluctuation in the headroom value should be + * expected. The default value can be retrieved from the + * {@link #getCalculationWindowMillis}. The device will try to use the * closest feasible window size to this param. * @throws IllegalArgumentException if the window is invalid. */ public void setCalculationWindowMillis( - @IntRange(from = GPU_HEADROOM_CALCULATION_WINDOW_MILLIS_MIN, to = - GPU_HEADROOM_CALCULATION_WINDOW_MILLIS_MAX) int windowMillis) { - if (windowMillis < GPU_HEADROOM_CALCULATION_WINDOW_MILLIS_MIN - || windowMillis > GPU_HEADROOM_CALCULATION_WINDOW_MILLIS_MAX) { + @IntRange(from = CALCULATION_WINDOW_MILLIS_MIN, to = + CALCULATION_WINDOW_MILLIS_MAX) int windowMillis) { + if (windowMillis < CALCULATION_WINDOW_MILLIS_MIN + || windowMillis > CALCULATION_WINDOW_MILLIS_MAX) { throw new IllegalArgumentException("Invalid calculation window: " + windowMillis); } mInternal.calculationWindowMillis = windowMillis; @@ -121,8 +112,8 @@ public final class GpuHeadroomParams { *

* This will return the default value chosen by the device if not set. */ - public @IntRange(from = GPU_HEADROOM_CALCULATION_WINDOW_MILLIS_MIN, to = - GPU_HEADROOM_CALCULATION_WINDOW_MILLIS_MAX) int getCalculationWindowMillis() { + public @IntRange(from = CALCULATION_WINDOW_MILLIS_MIN, to = + CALCULATION_WINDOW_MILLIS_MAX) int getCalculationWindowMillis() { return mInternal.calculationWindowMillis; } diff --git a/core/java/android/os/GraphicsEnvironment.java b/core/java/android/os/GraphicsEnvironment.java index 94768d111ca4e4fd9fc114b33458b4aafd04ae72..8f6a50843ddbe9eca6ab1dad25036f66a5147190 100644 --- a/core/java/android/os/GraphicsEnvironment.java +++ b/core/java/android/os/GraphicsEnvironment.java @@ -98,6 +98,7 @@ public class GraphicsEnvironment { private static final int VULKAN_1_1 = 0x00401000; private static final int VULKAN_1_2 = 0x00402000; private static final int VULKAN_1_3 = 0x00403000; + private static final int VULKAN_1_4 = 0x00404000; // Values for UPDATABLE_DRIVER_ALL_APPS // 0: Default (Invalid values fallback to default as well) @@ -179,6 +180,10 @@ public class GraphicsEnvironment { private int getVulkanVersion(PackageManager pm) { // PackageManager doesn't have an API to retrieve the version of a specific feature, and we // need to avoid retrieving all system features here and looping through them. + if (pm.hasSystemFeature(PackageManager.FEATURE_VULKAN_HARDWARE_VERSION, VULKAN_1_4)) { + return VULKAN_1_4; + } + if (pm.hasSystemFeature(PackageManager.FEATURE_VULKAN_HARDWARE_VERSION, VULKAN_1_3)) { return VULKAN_1_3; } diff --git a/core/java/android/os/IHintManager.aidl b/core/java/android/os/IHintManager.aidl index f1936b5e0ff9b714fdafbc3b3623ebbf3c8e6537..4a14a8d0faf8b3bb84ca649b2eb47555cfeb924e 100644 --- a/core/java/android/os/IHintManager.aidl +++ b/core/java/android/os/IHintManager.aidl @@ -64,4 +64,10 @@ interface IHintManager { * Get Maximum number of graphics pipeline threads allowed per-app. */ int getMaxGraphicsPipelineThreadsCount(); + + /** + * Used by the JNI to pass an interface to the SessionManager; + * for internal use only. + */ + oneway void passSessionManagerBinder(in IBinder sessionManager); } diff --git a/core/java/android/os/IHintSession.aidl b/core/java/android/os/IHintSession.aidl index 6fd4f3c7c01adaa778fcb91dc3ae4961c756c79b..e3f899de6d019abf07ab06ed9e6ebc26c2ee602c 100644 --- a/core/java/android/os/IHintSession.aidl +++ b/core/java/android/os/IHintSession.aidl @@ -27,4 +27,9 @@ oneway interface IHintSession { void sendHint(int hint); void setMode(int mode, boolean enabled); void reportActualWorkDuration2(in WorkDuration[] workDurations); + + /** + * Used by apps to associate a session to a given set of layers + */ + oneway void associateToLayers(in IBinder[] layerTokens); } diff --git a/core/java/android/os/OWNERS b/core/java/android/os/OWNERS index f9789c19b0d58dbebec40bb401708d2de957d62a..bfcc5cc6f18eae3b1839f7be5d591141b50875fa 100644 --- a/core/java/android/os/OWNERS +++ b/core/java/android/os/OWNERS @@ -93,10 +93,9 @@ per-file CpuHeadroom*.aidl = file:/ADPF_OWNERS per-file GpuHeadroom*.aidl = file:/ADPF_OWNERS per-file CpuHeadroom*.java = file:/ADPF_OWNERS per-file GpuHeadroom*.java = file:/ADPF_OWNERS -per-file PerformanceHintManager.java = file:/ADPF_OWNERS per-file WorkDuration.java = file:/ADPF_OWNERS -per-file IHintManager.aidl = file:/ADPF_OWNERS -per-file IHintSession.aidl = file:/ADPF_OWNERS +per-file *Hint* = file:/ADPF_OWNERS +per-file *Session* = file:/ADPF_OWNERS # IThermal interfaces per-file IThermal* = file:/THERMAL_OWNERS diff --git a/core/java/android/os/SessionCreationConfig.aidl b/core/java/android/os/SessionCreationConfig.aidl index cdc0ef461e0cf8766e7fa499d10046dd79ea4d87..17147e43cf8328f426d342332eef19ca00bf1c6a 100644 --- a/core/java/android/os/SessionCreationConfig.aidl +++ b/core/java/android/os/SessionCreationConfig.aidl @@ -36,4 +36,12 @@ parcelable SessionCreationConfig { * List of the modes to be enabled upon session creation. */ SessionMode[] modesToEnable; + + /** + * List of layers to attach this session to. + * + * Note: DO NOT STORE THESE IN HintSessionManager, as + * it will break the layer lifecycle. + */ + IBinder[] layerTokens; } diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java index a1ede5fee3f307f32eae2d1480d1c992d820f5b0..7e73a5d048664ae8e0916518e8d0a794ae9a8af1 100644 --- a/core/java/android/os/UserManager.java +++ b/core/java/android/os/UserManager.java @@ -3846,7 +3846,7 @@ public class UserManager { } /** - * Return the time when the context user was unlocked elapsed milliseconds since boot, + * Return the time when the calling user was unlocked elapsed milliseconds since boot, * or 0 if not unlocked. * * @hide diff --git a/core/java/android/os/flags.aconfig b/core/java/android/os/flags.aconfig index 3001fbd4fafa3ceee54badf4daaceb52fab11e63..6357baa1922699c0f6ac06726d7020fc09b10a78 100644 --- a/core/java/android/os/flags.aconfig +++ b/core/java/android/os/flags.aconfig @@ -96,6 +96,7 @@ flag { namespace: "crumpet" description: "Allow privileged apps to call bugreport generation without enforcing user consent and delegate it to the calling app instead" bug: "324046728" + is_exported: true } # This flag guards the private space feature, its APIs, and some of the feature implementations. The flag android.multiuser.Flags.enable_private_space_features exclusively guards all the implementations. @@ -178,6 +179,7 @@ flag { namespace: "game" description: "Feature flag for adding CPU/GPU headroom API" bug: "346604998" + is_exported: true } flag { @@ -222,6 +224,14 @@ flag { } } +flag { + name: "material_motion_tokens" + namespace: "systemui" + description: "Adding new Material Tokens for M3 Motion Spec" + bug: "324922198" + is_exported: true +} + flag { name: "message_queue_tail_tracking" namespace: "system_performance" diff --git a/core/java/android/permission/flags.aconfig b/core/java/android/permission/flags.aconfig index a7195834e6bb08005dbac3f4728da42f57f9fece..c2b8157de416f6013ce3134b9ef0e2d859589645 100644 --- a/core/java/android/permission/flags.aconfig +++ b/core/java/android/permission/flags.aconfig @@ -213,6 +213,7 @@ flag { namespace: "permissions" description: "Enable getDeviceId API in OpEventProxyInfo" bug: "337340961" + is_exported: true } flag { @@ -254,6 +255,7 @@ flag { namespace: "permissions" description: "New setOnOpNotedCallback API to allow subscribing to only sync ops." bug: "372910217" + is_exported: true } flag { @@ -445,3 +447,30 @@ flag { description: "Enable the Wallet role within profiles" bug: "356107987" } + +flag { + name: "text_classifier_choice_api_enabled" + is_fixed_read_only: true + is_exported: true + namespace: "permissions" + description: "API change to enable getTextClassifier by type" + bug: "377229653" +} + +flag { + name: "updatable_text_classifier_for_otp_detection_enabled" + is_fixed_read_only: true + is_exported: true + namespace: "permissions" + description: "Enables text classifier for OTP detection that is updatable from mainline module" + bug: "377229653" +} + +flag { + name: "cross_user_role_platform_api_enabled" + is_exported: true + is_fixed_read_only: true + namespace: "permissions" + description: "Enable cross-user roles platform API" + bug: "367732307" +} diff --git a/core/java/android/preference/PreferenceActivity.java b/core/java/android/preference/PreferenceActivity.java index f6bdc18c29ecc95f5bcc19b0866e9cba92fefc6e..e4a3c9fa7741627bc3f0ca42e0d8f1bb94619308 100644 --- a/core/java/android/preference/PreferenceActivity.java +++ b/core/java/android/preference/PreferenceActivity.java @@ -16,6 +16,8 @@ package android.preference; +import static android.window.OnBackInvokedDispatcher.PRIORITY_DEFAULT; + import android.animation.LayoutTransition; import android.annotation.Nullable; import android.annotation.StringRes; @@ -54,6 +56,8 @@ import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.ListView; import android.widget.TextView; +import android.window.OnBackInvokedCallback; +import android.window.WindowOnBackInvokedDispatcher; import com.android.internal.util.XmlUtils; @@ -209,6 +213,8 @@ public abstract class PreferenceActivity extends ListActivity implements private int mPreferenceHeaderItemResId = 0; private boolean mPreferenceHeaderRemoveEmptyIcon = false; + private final OnBackInvokedCallback mOnBackInvokedCallback = this::onBackInvoked; + /** * The starting request code given out to preference framework. */ @@ -699,10 +705,26 @@ public abstract class PreferenceActivity extends ListActivity implements skipButton.setVisibility(View.VISIBLE); } } + updateBackCallbackRegistrationState(); } @Override public void onBackPressed() { + onBackInvoked(); + } + + private void updateBackCallbackRegistrationState() { + if (!WindowOnBackInvokedDispatcher.isOnBackInvokedCallbackEnabled(this)) return; + if (mCurHeader != null && mSinglePane && getFragmentManager().getBackStackEntryCount() == 0 + && getIntent().getStringExtra(EXTRA_SHOW_FRAGMENT) == null) { + getOnBackInvokedDispatcher() + .registerOnBackInvokedCallback(PRIORITY_DEFAULT, mOnBackInvokedCallback); + } else { + getOnBackInvokedDispatcher().unregisterOnBackInvokedCallback(mOnBackInvokedCallback); + } + } + + private void onBackInvoked() { if (mCurHeader != null && mSinglePane && getFragmentManager().getBackStackEntryCount() == 0 && getIntent().getStringExtra(EXTRA_SHOW_FRAGMENT) == null) { mCurHeader = null; @@ -713,9 +735,10 @@ public abstract class PreferenceActivity extends ListActivity implements showBreadCrumbs(mActivityTitle, null); } getListView().clearChoices(); - } else { + } else if (!WindowOnBackInvokedDispatcher.isOnBackInvokedCallbackEnabled(this)) { super.onBackPressed(); } + updateBackCallbackRegistrationState(); } /** @@ -1221,6 +1244,7 @@ public abstract class PreferenceActivity extends ListActivity implements getListView().clearChoices(); } showBreadCrumbs(header); + updateBackCallbackRegistrationState(); } void showBreadCrumbs(Header header) { diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index d5b525884ac181156ac58e812f8b6a5e6c42e2ac..0ae9ffa655cd6b00988207eb596bcaae4ac45e57 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -85,6 +85,7 @@ import android.os.RemoteException; import android.os.ResultReceiver; import android.os.ServiceManager; import android.os.UserHandle; +import android.service.voice.VisualQueryDetectedResult; import android.speech.tts.TextToSpeech; import android.telephony.TelephonyManager; import android.text.TextUtils; @@ -6288,6 +6289,13 @@ public final class Settings { */ public static final String TOUCHPAD_RIGHT_CLICK_ZONE = "touchpad_right_click_zone"; + /** + * Whether to enable system gestures (three- and four-finger swipes) on touchpads. + * + * @hide + */ + public static final String TOUCHPAD_SYSTEM_GESTURES = "touchpad_system_gestures"; + /** * Whether to enable reversed vertical scrolling for connected mice. * @@ -6373,6 +6381,14 @@ public final class Settings { */ public static final String LOCALE_PREFERENCES = "locale_preferences"; + /** + * User can change the region from region settings. This records user's preferred region. + * + * E.g. : if user's locale is en-US, this will record US + * @hide + */ + public static final String PREFERRED_REGION = "preferred_region"; + /** * Setting to enable camera flash notification feature. *

    @@ -6541,12 +6557,14 @@ public final class Settings { PRIVATE_SETTINGS.add(TOUCHPAD_TAP_TO_CLICK); PRIVATE_SETTINGS.add(TOUCHPAD_TAP_DRAGGING); PRIVATE_SETTINGS.add(TOUCHPAD_RIGHT_CLICK_ZONE); + PRIVATE_SETTINGS.add(TOUCHPAD_SYSTEM_GESTURES); PRIVATE_SETTINGS.add(CAMERA_FLASH_NOTIFICATION); PRIVATE_SETTINGS.add(SCREEN_FLASH_NOTIFICATION); PRIVATE_SETTINGS.add(SCREEN_FLASH_NOTIFICATION_COLOR); PRIVATE_SETTINGS.add(DEFAULT_DEVICE_FONT_SCALE); PRIVATE_SETTINGS.add(MOUSE_REVERSE_VERTICAL_SCROLLING); PRIVATE_SETTINGS.add(MOUSE_SWAP_PRIMARY_BUTTON); + PRIVATE_SETTINGS.add(PREFERRED_REGION); } /** diff --git a/core/java/android/security/advancedprotection/AdvancedProtectionManager.java b/core/java/android/security/advancedprotection/AdvancedProtectionManager.java index 0302fafd2f6c2e40d437779811744ba9acdc2ffa..59628e8e69d70a0a254689fff947b611fad37314 100644 --- a/core/java/android/security/advancedprotection/AdvancedProtectionManager.java +++ b/core/java/android/security/advancedprotection/AdvancedProtectionManager.java @@ -16,7 +16,10 @@ package android.security.advancedprotection; +import static android.app.admin.DevicePolicyIdentifiers.MEMORY_TAGGING_POLICY; import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; +import static android.os.UserManager.DISALLOW_CELLULAR_2G; +import static android.os.UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES_GLOBALLY; import android.Manifest; import android.annotation.CallbackExecutor; @@ -343,6 +346,28 @@ public final class AdvancedProtectionManager { return intent; } + /** @hide */ + public @NonNull Intent createSupportIntentForPolicyIdentifierOrRestriction( + @NonNull String identifier, @Nullable @SupportDialogType String type) { + Objects.requireNonNull(identifier); + if (type != null && !ALL_SUPPORT_DIALOG_TYPES.contains(type)) { + throw new IllegalArgumentException(type + " is not a valid type. See" + + " SUPPORT_DIALOG_TYPE_* APIs."); + } + final String featureId; + if (DISALLOW_INSTALL_UNKNOWN_SOURCES_GLOBALLY.equals(identifier)) { + featureId = FEATURE_ID_DISALLOW_INSTALL_UNKNOWN_SOURCES; + } else if (DISALLOW_CELLULAR_2G.equals(identifier)) { + featureId = FEATURE_ID_DISALLOW_CELLULAR_2G; + } else if (android.app.admin.flags.Flags.setMtePolicyCoexistence() && MEMORY_TAGGING_POLICY + .equals(identifier)) { + featureId = FEATURE_ID_ENABLE_MTE; + } else { + throw new UnsupportedOperationException("Unsupported identifier: " + identifier); + } + return createSupportIntent(featureId, type); + } + /** * A callback class for monitoring changes to Advanced Protection state * diff --git a/core/java/android/security/advancedprotection/OWNERS b/core/java/android/security/advancedprotection/OWNERS index ddac8edb6f4a62bfc5becd0f80ee5ca909c49ba7..bfb7e16e15a81438bf47bbb55062ed15e25b98bf 100644 --- a/core/java/android/security/advancedprotection/OWNERS +++ b/core/java/android/security/advancedprotection/OWNERS @@ -2,7 +2,6 @@ achim@google.com azharaa@google.com -cpinelli@google.com eranm@google.com hanikazmi@google.com haok@google.com diff --git a/core/java/android/security/flags.aconfig b/core/java/android/security/flags.aconfig index 09004b3dcf0328512cc800c3b7005df9309f6e5c..34bae46b484c6dce049781876aa737ca2af14506 100644 --- a/core/java/android/security/flags.aconfig +++ b/core/java/android/security/flags.aconfig @@ -112,6 +112,7 @@ flag { namespace: "hardware_backed_security" description: "AFL feature" bug: "365994454" + is_exported: true } flag { @@ -127,6 +128,7 @@ flag { namespace: "hardware_backed_security" description: "Feature flag for exposing KeyStore grant APIs" bug: "351158708" + is_exported: true } flag { @@ -134,4 +136,5 @@ flag { namespace: "biometrics" description: "Feature flag for Secure Lockdown feature" bug: "373422357" + is_exported: true } \ No newline at end of file diff --git a/core/java/android/security/responsible_apis_flags.aconfig b/core/java/android/security/responsible_apis_flags.aconfig index a5c837b88fa4759a260caca6d5aa528ac736bb07..42dbd37860017ef08cb135b61d07e2876eb72ee1 100644 --- a/core/java/android/security/responsible_apis_flags.aconfig +++ b/core/java/android/security/responsible_apis_flags.aconfig @@ -78,6 +78,7 @@ flag { description: "Prevent intent redirect attacks" bug: "361143368" is_fixed_read_only: true + is_exported: true } flag { @@ -95,6 +96,21 @@ flag { is_fixed_read_only: true } +flag { + name: "prevent_intent_redirect_show_toast_if_nested_keys_not_collected" + namespace: "responsible_apis" + description: "Prevent intent redirect attacks by showing a toast if not yet collected" + bug: "361143368" + is_fixed_read_only: true +} + +flag { + name: "prevent_intent_redirect_show_toast_if_nested_keys_not_collected_r_w" + namespace: "responsible_apis" + description: "Prevent intent redirect attacks by showing a toast if not yet collected" + bug: "361143368" +} + flag { name: "prevent_intent_redirect_throw_exception_if_nested_keys_not_collected" namespace: "responsible_apis" diff --git a/core/java/android/service/autofill/FillEventHistory.java b/core/java/android/service/autofill/FillEventHistory.java index 14a14e69f208531f91ff44ff4d07f4b01fc68c76..fba8e42cc673ecbf4827e27191b5e67796e41dcb 100644 --- a/core/java/android/service/autofill/FillEventHistory.java +++ b/core/java/android/service/autofill/FillEventHistory.java @@ -170,6 +170,9 @@ public final class FillEventHistory implements Parcelable { } parcel.writeInt(event.mSaveDialogNotShowReason); parcel.writeInt(event.mUiType); + if (Flags.addLastFocusedIdToFillEventHistory()) { + parcel.writeParcelable(event.mFocusedId, 0); + } } } } @@ -375,6 +378,8 @@ public final class FillEventHistory implements Parcelable { @UiType private final int mUiType; + @Nullable private final AutofillId mFocusedId; + /** * Returns the type of the event. * @@ -388,7 +393,7 @@ public final class FillEventHistory implements Parcelable { @FlaggedApi(FLAG_AUTOFILL_W_METRICS) @Nullable public AutofillId getFocusedId() { - return null; + return mFocusedId; } /** @@ -624,6 +629,7 @@ public final class FillEventHistory implements Parcelable { * @param manuallyFilledDatasetIds The ids of datasets that had values matching the * respective entry on {@code manuallyFilledFieldIds}. * @param detectedFieldClassifications the field classification matches. + * @param focusedId the field which was focused at the time of event trigger * * @throws IllegalArgumentException If the length of {@code changedFieldIds} and * {@code changedDatasetIds} doesn't match. @@ -640,11 +646,12 @@ public final class FillEventHistory implements Parcelable { @Nullable ArrayList manuallyFilledFieldIds, @Nullable ArrayList> manuallyFilledDatasetIds, @Nullable AutofillId[] detectedFieldIds, - @Nullable FieldClassification[] detectedFieldClassifications) { + @Nullable FieldClassification[] detectedFieldClassifications, + @Nullable AutofillId focusedId) { this(eventType, datasetId, clientState, selectedDatasetIds, ignoredDatasetIds, changedFieldIds, changedDatasetIds, manuallyFilledFieldIds, manuallyFilledDatasetIds, detectedFieldIds, detectedFieldClassifications, - NO_SAVE_UI_REASON_NONE); + NO_SAVE_UI_REASON_NONE, focusedId); } /** @@ -665,6 +672,7 @@ public final class FillEventHistory implements Parcelable { * respective entry on {@code manuallyFilledFieldIds}. * @param detectedFieldClassifications the field classification matches. * @param saveDialogNotShowReason The reason why a save dialog was not shown. + * @param focusedId the field which was focused at the time of event trigger * * @throws IllegalArgumentException If the length of {@code changedFieldIds} and * {@code changedDatasetIds} doesn't match. @@ -682,11 +690,12 @@ public final class FillEventHistory implements Parcelable { @Nullable ArrayList> manuallyFilledDatasetIds, @Nullable AutofillId[] detectedFieldIds, @Nullable FieldClassification[] detectedFieldClassifications, - int saveDialogNotShowReason) { + int saveDialogNotShowReason, + @Nullable AutofillId focusedId) { this(eventType, datasetId, clientState, selectedDatasetIds, ignoredDatasetIds, changedFieldIds, changedDatasetIds, manuallyFilledFieldIds, manuallyFilledDatasetIds, detectedFieldIds, detectedFieldClassifications, - saveDialogNotShowReason, UI_TYPE_UNKNOWN); + saveDialogNotShowReason, UI_TYPE_UNKNOWN, focusedId); } /** @@ -708,6 +717,7 @@ public final class FillEventHistory implements Parcelable { * @param detectedFieldClassifications the field classification matches. * @param saveDialogNotShowReason The reason why a save dialog was not shown. * @param uiType The ui presentation type for fill suggestion. + * @param focusedId the field which was focused at the time of event trigger * * @throws IllegalArgumentException If the length of {@code changedFieldIds} and * {@code changedDatasetIds} doesn't match. @@ -725,7 +735,7 @@ public final class FillEventHistory implements Parcelable { @Nullable ArrayList> manuallyFilledDatasetIds, @Nullable AutofillId[] detectedFieldIds, @Nullable FieldClassification[] detectedFieldClassifications, - int saveDialogNotShowReason, int uiType) { + int saveDialogNotShowReason, int uiType, @Nullable AutofillId focusedId) { mEventType = Preconditions.checkArgumentInRange(eventType, 0, TYPE_VIEW_REQUESTED_AUTOFILL, "eventType"); mDatasetId = datasetId; @@ -756,6 +766,7 @@ public final class FillEventHistory implements Parcelable { NO_SAVE_UI_REASON_NONE, NO_SAVE_UI_REASON_DATASET_MATCH, "saveDialogNotShowReason"); mUiType = uiType; + mFocusedId = focusedId; } @Override @@ -852,13 +863,17 @@ public final class FillEventHistory implements Parcelable { : null; final int saveDialogNotShowReason = parcel.readInt(); final int uiType = parcel.readInt(); + AutofillId focusedId = null; + if (Flags.addLastFocusedIdToFillEventHistory()) { + focusedId = parcel.readParcelable(null, AutofillId.class); + } selection.addEvent(new Event(eventType, datasetId, clientState, selectedDatasetIds, ignoredDatasets, changedFieldIds, changedDatasetIds, manuallyFilledFieldIds, manuallyFilledDatasetIds, detectedFieldIds, detectedFieldClassifications, - saveDialogNotShowReason, uiType)); + saveDialogNotShowReason, uiType, focusedId)); } return selection; } diff --git a/core/java/android/service/notification/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java index 5d0ec73a024bb9da12c8bc8d283f8da53fa5ef55..72569075c2edf191b1f4f0e32b74e621eb6ef050 100644 --- a/core/java/android/service/notification/NotificationListenerService.java +++ b/core/java/android/service/notification/NotificationListenerService.java @@ -2363,7 +2363,6 @@ public abstract class NotificationListenerService extends Service { // -- parcelable interface -- private RankingMap(Parcel in) { - final ClassLoader cl = getClass().getClassLoader(); final int count = in.readInt(); mOrderedKeys.ensureCapacity(count); mRankings.ensureCapacity(count); diff --git a/core/java/android/service/quickaccesswallet/flags.aconfig b/core/java/android/service/quickaccesswallet/flags.aconfig index 7225f27c4555641f34a76f914b84ca343d4a0218..9736345ae3a95ee0a0f66967c2de9431e890dbeb 100644 --- a/core/java/android/service/quickaccesswallet/flags.aconfig +++ b/core/java/android/service/quickaccesswallet/flags.aconfig @@ -6,6 +6,7 @@ flag { namespace: "wallet_integration" description: "Option to launch the Wallet app on double-tap of the power button" bug: "378469025" + is_exported: true } flag { diff --git a/core/java/android/service/voice/AlwaysOnHotwordDetector.java b/core/java/android/service/voice/AlwaysOnHotwordDetector.java index 7d79fd3d44ea850dfbb9b3e213845287f2baac3b..68fd11592feed1aa667a403a591a8662e8b06b37 100644 --- a/core/java/android/service/voice/AlwaysOnHotwordDetector.java +++ b/core/java/android/service/voice/AlwaysOnHotwordDetector.java @@ -1541,7 +1541,7 @@ public class AlwaysOnHotwordDetector extends AbstractDetector { mInternalCallback, new RecognitionConfig.Builder() .setCaptureRequested(captureTriggerAudio) - .setAllowMultipleTriggers(allowMultipleTriggers) + .setMultipleTriggersAllowed(allowMultipleTriggers) .setKeyphrases(recognitionExtra) .setData(data) .setAudioCapabilities(audioCapabilities) diff --git a/core/java/android/service/voice/OWNERS b/core/java/android/service/voice/OWNERS index 5f9f6bde31291c08e8ddc8b98dd38f55e42f26e1..b6f0270dfbbcf9608e0a7d536bee4e6ced44899f 100644 --- a/core/java/android/service/voice/OWNERS +++ b/core/java/android/service/voice/OWNERS @@ -1,6 +1,6 @@ # Bug component: 533220 - include /core/java/android/app/assist/OWNERS +atneya@google.com # The owner here should not be assist owner adudani@google.com diff --git a/core/java/android/telephony/TelephonyCallback.java b/core/java/android/telephony/TelephonyCallback.java index 2c585e640fdd19ddc091644aa61aca8f36018981..e8b32ce5e3147baf5867f23297f54016332123be 100644 --- a/core/java/android/telephony/TelephonyCallback.java +++ b/core/java/android/telephony/TelephonyCallback.java @@ -658,12 +658,15 @@ public class TelephonyCallback { * * @hide */ + @SystemApi + @FlaggedApi(Flags.FLAG_SATELLITE_SYSTEM_APIS) + @RequiresPermission(Manifest.permission.READ_PHONE_STATE) public static final int EVENT_CARRIER_ROAMING_NTN_MODE_CHANGED = 42; /** * Event for listening to changes in carrier roaming non-terrestrial network eligibility. * - * @see CarrierRoamingNtnModeListener + * @see CarrierRoamingNtnModeListener#onCarrierRoamingNtnEligibleStateChanged(boolean) * * Device is eligible for satellite communication if all the following conditions are met: *
      @@ -679,11 +682,15 @@ public class TelephonyCallback { * * @hide */ + @SystemApi + @FlaggedApi(Flags.FLAG_SATELLITE_SYSTEM_APIS) + @RequiresPermission(Manifest.permission.READ_PHONE_STATE) public static final int EVENT_CARRIER_ROAMING_NTN_ELIGIBLE_STATE_CHANGED = 43; /** * Event for listening to changes in carrier roaming non-terrestrial network available services - * via callback onCarrierRoamingNtnAvailableServicesChanged(). + * via callback {@link + * CarrierRoamingNtnModeListener#onCarrierRoamingNtnAvailableServicesChanged(List)} * This callback is triggered when the available services provided by the carrier roaming * satellite changes. The carrier roaming satellite is defined by the following conditions. *
        @@ -693,15 +700,22 @@ public class TelephonyCallback { * * @hide */ + @SystemApi + @FlaggedApi(Flags.FLAG_SATELLITE_SYSTEM_APIS) + @RequiresPermission(Manifest.permission.READ_PHONE_STATE) public static final int EVENT_CARRIER_ROAMING_NTN_AVAILABLE_SERVICES_CHANGED = 44; /** * Event for listening to carrier roaming non-terrestrial network signal strength changes. * - * @see CarrierRoamingNtnModeListener + * @see CarrierRoamingNtnModeListener#onCarrierRoamingNtnSignalStrengthChanged( + * NtnSignalStrength) * * @hide */ + @SystemApi + @FlaggedApi(Flags.FLAG_SATELLITE_SYSTEM_APIS) + @RequiresPermission(Manifest.permission.READ_PHONE_STATE) public static final int EVENT_CARRIER_ROAMING_NTN_SIGNAL_STRENGTH_CHANGED = 45; /** @@ -1803,6 +1817,8 @@ public class TelephonyCallback { * * @hide */ + @SystemApi + @FlaggedApi(Flags.FLAG_SATELLITE_SYSTEM_APIS) public interface CarrierRoamingNtnModeListener { /** * Callback invoked when carrier roaming non-terrestrial network mode changes. @@ -1836,10 +1852,10 @@ public class TelephonyCallback { * Callback invoked when carrier roaming non-terrestrial network available * service changes. * - * @param availableServices The list of the supported services. + * @param availableServices array of supported services. */ default void onCarrierRoamingNtnAvailableServicesChanged( - @NetworkRegistrationInfo.ServiceType List availableServices) {} + @NonNull @NetworkRegistrationInfo.ServiceType int[] availableServices) {} /** * Callback invoked when carrier roaming non-terrestrial network signal strength changes. @@ -2343,10 +2359,8 @@ public class TelephonyCallback { (CarrierRoamingNtnModeListener) mTelephonyCallbackWeakRef.get(); if (listener == null) return; - List ServiceList = Arrays.stream(availableServices).boxed() - .collect(Collectors.toList()); Binder.withCleanCallingIdentity(() -> mExecutor.execute( - () -> listener.onCarrierRoamingNtnAvailableServicesChanged(ServiceList))); + () -> listener.onCarrierRoamingNtnAvailableServicesChanged(availableServices))); } public void onCarrierRoamingNtnSignalStrengthChanged( diff --git a/core/java/android/text/flags/flags.aconfig b/core/java/android/text/flags/flags.aconfig index f43f172d7d5b622b6bf20eef30d4a29b108df707..c2e542c57171e656d2bcdd11121954d33f342640 100644 --- a/core/java/android/text/flags/flags.aconfig +++ b/core/java/android/text/flags/flags.aconfig @@ -91,6 +91,7 @@ flag { metadata { purpose: PURPOSE_BUGFIX } + is_exported: true } flag { @@ -196,6 +197,7 @@ flag { namespace: "text" description: "Feature flag for adding a TYPE_DURATION to TtsSpan" bug: "337103893" + is_exported: true } flag { @@ -203,6 +205,7 @@ flag { namespace: "text" description: "Deprecate the Paint#elegantTextHeight API and stick it to true" bug: "349519475" + is_exported: true } flag { @@ -210,4 +213,5 @@ flag { namespace: "text" description: "Make Paint class work for vertical layout text." bug: "355296926" + is_exported: true } diff --git a/core/java/android/util/Log.java b/core/java/android/util/Log.java index 1dd9d46fdfb7c0e04ea41d8e483f4db30d73b743..f8737a55a5b09329a125b7f3bdf7cffec8d27068 100644 --- a/core/java/android/util/Log.java +++ b/core/java/android/util/Log.java @@ -75,7 +75,7 @@ import java.net.UnknownHostException; @android.ravenwood.annotation.RavenwoodClassLoadHook( "com.android.platform.test.ravenwood.runtimehelper.ClassLoadHook.onClassLoaded") // Uncomment the following annotation to switch to the Java substitution version. -@android.ravenwood.annotation.RavenwoodRedirectionClass("Log_host") +@android.ravenwood.annotation.RavenwoodRedirectionClass("Log_ravenwood") public final class Log { /** @hide */ @IntDef({ASSERT, ERROR, WARN, INFO, DEBUG, VERBOSE}) diff --git a/core/java/android/view/IDisplayWindowInsetsController.aidl b/core/java/android/view/IDisplayWindowInsetsController.aidl index 45dbe43bbdd531082d2bdaa1b7ecda19f6aecef4..21b969c1dedbad991b3a7ec90b4f4ebd8fcea707 100644 --- a/core/java/android/view/IDisplayWindowInsetsController.aidl +++ b/core/java/android/view/IDisplayWindowInsetsController.aidl @@ -60,5 +60,5 @@ oneway interface IDisplayWindowInsetsController { * Reports the requested IME visibility of the IME input target to * the IDisplayWindowInsetsController */ - void setImeInputTargetRequestedVisibility(boolean visible); + void setImeInputTargetRequestedVisibility(boolean visible, in ImeTracker.Token statsToken); } diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl index e5be53191e9e336593ec617a7ab3978333ef36d9..6d85e7589c482992e0682cbfa272fae04a282c68 100644 --- a/core/java/android/view/IWindowManager.aidl +++ b/core/java/android/view/IWindowManager.aidl @@ -62,6 +62,7 @@ import android.view.MotionEvent; import android.view.InputChannel; import android.view.InputDevice; import android.view.IInputFilter; +import android.view.inputmethod.ImeTracker; import android.view.AppTransitionAnimationSpec; import android.view.WindowContentFrameStats; import android.view.WindowManager; @@ -765,7 +766,8 @@ interface IWindowManager * container. */ @EnforcePermission("MANAGE_APP_TOKENS") - void updateDisplayWindowRequestedVisibleTypes(int displayId, int requestedVisibleTypes); + void updateDisplayWindowRequestedVisibleTypes(int displayId, int requestedVisibleTypes, + in @nullable ImeTracker.Token statsToken); /** * Called to get the expected window insets. diff --git a/core/java/android/view/LetterboxScrollProcessor.java b/core/java/android/view/LetterboxScrollProcessor.java index 1364a82e60a1723c248860e7334c8dc4da729f50..8c1b0f88f4eb857ec3c160a7ccac888f157d4e99 100644 --- a/core/java/android/view/LetterboxScrollProcessor.java +++ b/core/java/android/view/LetterboxScrollProcessor.java @@ -78,6 +78,11 @@ public class LetterboxScrollProcessor { @Nullable @VisibleForTesting(visibility = PACKAGE) public List processMotionEvent(@NonNull MotionEvent motionEvent) { + if (!motionEvent.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) { + // This is a non-pointer event that doesn't correspond to any location on the screen. + // Ignore it. + return null; + } mProcessedEvents.clear(); final Rect appBounds = getAppBounds(); diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 049189f8af8d4db876b234b4d6b16bcce32ba874..02c79015fab237adc74bdc30a943aa9816219adc 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -28277,7 +28277,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, mPrivateFlags |= PFLAG_FORCE_LAYOUT; mPrivateFlags |= PFLAG_INVALIDATED; - if (mParent != null && !mParent.isLayoutRequested()) { + if (mParent != null) { mParent.requestLayout(); } if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == this) { diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index a0feccd87a81d24c8e0a160b97dc1e9c9fc7cd42..31330204e8c60906babc0e1c56bd6df6121f30eb 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -16,7 +16,9 @@ package android.view; +import static android.adpf.Flags.adpfViewrootimplActionDownBoost; import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW; +import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM; import static android.content.pm.ActivityInfo.OVERRIDE_SANDBOX_VIEW_BOUNDS_APIS; import static android.graphics.HardwareRenderer.SYNC_CONTEXT_IS_STOPPED; import static android.graphics.HardwareRenderer.SYNC_LOST_SURFACE_REWARD_IF_FOUND; @@ -1208,6 +1210,8 @@ public final class ViewRootImpl implements ViewParent, private long mRenderThreadDrawStartTimeNs = -1; private long mFirstFramePresentedTimeNs = -1; + private final boolean mSendPerfHintOnTouch; + private static boolean sToolkitSetFrameRateReadOnlyFlagValue; private static boolean sToolkitFrameRateFunctionEnablingReadOnlyFlagValue; private static boolean sToolkitMetricsForFrameRateDecisionFlagValue; @@ -1337,6 +1341,8 @@ public final class ViewRootImpl implements ViewParent, CompatChanges.isChangeEnabled(DISABLE_DRAW_WAKE_LOCK) && disableDrawWakeLock(); mIsSubscribeGranularDisplayEventsEnabled = com.android.server.display.feature.flags.Flags.subscribeGranularDisplayEvents(); + + mSendPerfHintOnTouch = adpfViewrootimplActionDownBoost(); } public static void addFirstDrawHandler(Runnable callback) { @@ -2647,7 +2653,8 @@ public final class ViewRootImpl implements ViewParent, mStopped = stopped; final ThreadedRenderer renderer = mAttachInfo.mThreadedRenderer; if (renderer != null) { - if (DEBUG_DRAW) Log.d(mTag, "WindowStopped on " + getTitle() + " set to " + mStopped); + if (DEBUG_DRAW) + Log.d(mTag, "WindowStopped on " + getTitle() + " set to " + mStopped); renderer.setStopped(mStopped); } if (!mStopped) { @@ -7110,6 +7117,10 @@ public final class ViewRootImpl implements ViewParent, + "touch mode is " + mAttachInfo.mInTouchMode); if (mAttachInfo.mInTouchMode == inTouchMode) return false; + if (inTouchMode && mAttachInfo.mThreadedRenderer != null && mSendPerfHintOnTouch) { + mAttachInfo.mThreadedRenderer.notifyExpensiveFrame(); + } + // tell the window manager try { IWindowManager windowManager = WindowManagerGlobal.getWindowManagerService(); @@ -7968,8 +7979,9 @@ public final class ViewRootImpl implements ViewParent, } private boolean moveFocusToAdjacentWindow(@FocusDirection int direction) { - if (getConfiguration().windowConfiguration.getWindowingMode() - != WINDOWING_MODE_MULTI_WINDOW) { + final int windowingMode = getConfiguration().windowConfiguration.getWindowingMode(); + if (!(windowingMode == WINDOWING_MODE_MULTI_WINDOW + || windowingMode == WINDOWING_MODE_FREEFORM)) { return false; } try { diff --git a/core/java/android/view/WindowManagerImpl.java b/core/java/android/view/WindowManagerImpl.java index 330e46af63815d83ac38b53df4d9582016eb13d0..97cf8fc748e88300be868c941c44e1e37ca19fc6 100644 --- a/core/java/android/view/WindowManagerImpl.java +++ b/core/java/android/view/WindowManagerImpl.java @@ -85,7 +85,7 @@ import java.util.function.IntConsumer; * @see WindowManagerGlobal * @hide */ -public final class WindowManagerImpl implements WindowManager { +public class WindowManagerImpl implements WindowManager { private static final String TAG = "WindowManager"; @UnsupportedAppUsage diff --git a/core/java/android/view/accessibility/flags/accessibility_flags.aconfig b/core/java/android/view/accessibility/flags/accessibility_flags.aconfig index e60fc3ae6b472fb519879e9d3ee1b56dc4b9cb53..049ad20fd992be7550e3ea7c24d4f0ab159e9a65 100644 --- a/core/java/android/view/accessibility/flags/accessibility_flags.aconfig +++ b/core/java/android/view/accessibility/flags/accessibility_flags.aconfig @@ -8,6 +8,7 @@ flag { namespace: "accessibility" description: "Enables new APIs for an app to convey if a node is expanded or collapsed." bug: "362782536" + is_exported: true } flag { @@ -15,6 +16,7 @@ flag { namespace: "accessibility" description: "Adds an API to indicate whether a form field (or similar element) is required." bug: "362784403" + is_exported: true } flag { @@ -44,6 +46,7 @@ flag { namespace: "accessibility" description: "Enables new extra data key for an AccessibilityService to request character bounds in unmagnified window coordinates." bug: "375429616" + is_exported: true } flag { @@ -88,6 +91,7 @@ flag { name: "deprecate_accessibility_announcement_apis" description: "Controls the deprecation of platform APIs related to disruptive accessibility announcements" bug: "376727542" + is_exported: true } flag { @@ -95,6 +99,7 @@ flag { name: "deprecate_ani_label_for_apis" description: "Controls the deprecation of AccessibilityNodeInfo labelFor apis" bug: "333783827" + is_exported: true } flag { @@ -145,6 +150,7 @@ flag { name: "global_action_menu" description: "Allow AccessibilityService to perform GLOBAL_ACTION_MENU" bug: "334954140" + is_exported: true } flag { @@ -152,6 +158,7 @@ flag { name: "global_action_media_play_pause" description: "Allow AccessibilityService to perform GLOBAL_ACTION_MEDIA_PLAY_PAUSE" bug: "334954140" + is_exported: true } flag { @@ -230,6 +237,7 @@ flag { namespace: "accessibility" description: "Feature flag for supplemental description api" bug: "375266174" + is_exported: true } flag { @@ -237,6 +245,7 @@ flag { namespace: "accessibility" description: "Feature flag for supporting multiple labels in AccessibilityNodeInfo labeledby api" bug: "333780959" + is_exported: true } flag { @@ -251,6 +260,7 @@ flag { namespace: "accessibility" description: "Feature flag for adding tri-state checked api" bug: "333784774" + is_exported: true } flag { @@ -261,11 +271,12 @@ flag { metadata { purpose: PURPOSE_BUGFIX } - } +} - flag { +flag { name: "indeterminate_range_info" namespace: "accessibility" description: "Creates a way to create an INDETERMINATE RangeInfo" bug: "376108874" - } + is_exported: true +} diff --git a/core/java/android/view/autofill/AutofillFeatureFlags.java b/core/java/android/view/autofill/AutofillFeatureFlags.java index 905f350ca6c50fd7468d24dc98c884cdfa0abe6c..d527007e586e1a66df2817de786efba39a39e6ec 100644 --- a/core/java/android/view/autofill/AutofillFeatureFlags.java +++ b/core/java/android/view/autofill/AutofillFeatureFlags.java @@ -603,7 +603,7 @@ public class AutofillFeatureFlags { return DeviceConfig.getBoolean( DeviceConfig.NAMESPACE_AUTOFILL, DEVICE_CONFIG_ENABLE_RELAYOUT, - false); + true); } /** @hide */ @@ -611,7 +611,7 @@ public class AutofillFeatureFlags { return DeviceConfig.getBoolean( DeviceConfig.NAMESPACE_AUTOFILL, DEVICE_CONFIG_ENABLE_RELATIVE_LOCATION_FOR_RELAYOUT, - false); + true); } /** @hide **/ diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java index 52c5af8889ec494b81e3e65d583bcd86d94c55eb..1de0474182dd3a4a9df452a1482070fd953fc3c4 100644 --- a/core/java/android/view/autofill/AutofillManager.java +++ b/core/java/android/view/autofill/AutofillManager.java @@ -26,6 +26,7 @@ import static android.service.autofill.FillRequest.FLAG_SUPPORTS_FILL_DIALOG; import static android.service.autofill.FillRequest.FLAG_VIEW_NOT_FOCUSED; import static android.service.autofill.FillRequest.FLAG_VIEW_REQUESTS_CREDMAN_SERVICE; import static android.service.autofill.Flags.FLAG_FILL_DIALOG_IMPROVEMENTS; +import static android.service.autofill.Flags.relayoutFix; import static android.view.ContentInfo.SOURCE_AUTOFILL; import static android.view.autofill.Helper.sDebug; import static android.view.autofill.Helper.sVerbose; @@ -1013,7 +1014,7 @@ public final class AutofillManager { AutofillFeatureFlags.shouldIncludeInvisibleViewInAssistStructure(); mRelayoutFixDeprecated = AutofillFeatureFlags.shouldIgnoreRelayoutWhenAuthPending(); - mRelayoutFix = AutofillFeatureFlags.enableRelayoutFixes(); + mRelayoutFix = relayoutFix() && AutofillFeatureFlags.enableRelayoutFixes(); mRelativePositionForRelayout = AutofillFeatureFlags.enableRelativeLocationForRelayout(); mIsCredmanIntegrationEnabled = Flags.autofillCredmanIntegration(); } diff --git a/core/java/android/view/flags/refresh_rate_flags.aconfig b/core/java/android/view/flags/refresh_rate_flags.aconfig index 1c7570efc26ba450efd9942e7337865653cccc53..675e5a1b4804aa2af364e7c315d7b923cecb066d 100644 --- a/core/java/android/view/flags/refresh_rate_flags.aconfig +++ b/core/java/android/view/flags/refresh_rate_flags.aconfig @@ -127,6 +127,7 @@ flag { description: "Feature flag to introduce new frame rate setting APIs on ViewGroup" bug: "335874198" is_fixed_read_only: true + is_exported: true } flag { diff --git a/core/java/android/view/flags/scroll_capture.aconfig b/core/java/android/view/flags/scroll_capture.aconfig index fdf9c1ed8ad267d10945f23aa721bc627d03d0b1..9080b1669ed5c487c85b0e0b0218bf962501fea9 100644 --- a/core/java/android/view/flags/scroll_capture.aconfig +++ b/core/java/android/view/flags/scroll_capture.aconfig @@ -3,7 +3,7 @@ container: "system" flag { name: "scroll_capture_target_z_order_fix" - namespace: "system_ui" + namespace: "systemui" description: "Always prefer targets with higher z-order" bug: "365969802" metadata { diff --git a/core/java/android/view/flags/view_flags.aconfig b/core/java/android/view/flags/view_flags.aconfig index 3b6343e7c4ae88b424abe08dd550a930347fa6ee..641b01054acb28e0aa26a730f63731296222f989 100644 --- a/core/java/android/view/flags/view_flags.aconfig +++ b/core/java/android/view/flags/view_flags.aconfig @@ -116,6 +116,7 @@ flag { description: "Add a SurfaceView composition order control API." bug: "341021569" is_fixed_read_only: true + is_exported: true } flag { @@ -124,6 +125,7 @@ flag { description: "Add APIs to manage SurfacePackage of the parent SurfaceView." bug: "341021569" is_fixed_read_only: true + is_exported: true } flag { diff --git a/core/java/android/view/inputmethod/ImeTracker.java b/core/java/android/view/inputmethod/ImeTracker.java index dd32d57bd6504de3f3b6c25e94f8737b877d7ee8..4d354e0655f030978317b7ba7105a4df0f75344f 100644 --- a/core/java/android/view/inputmethod/ImeTracker.java +++ b/core/java/android/view/inputmethod/ImeTracker.java @@ -222,6 +222,8 @@ public interface ImeTracker { PHASE_CLIENT_ALREADY_HIDDEN, PHASE_CLIENT_VIEW_HANDLER_AVAILABLE, PHASE_SERVER_UPDATE_CLIENT_VISIBILITY, + PHASE_WM_DISPLAY_IME_CONTROLLER_SET_IME_REQUESTED_VISIBLE, + PHASE_WM_UPDATE_DISPLAY_WINDOW_REQUESTED_VISIBLE_TYPES, }) @Retention(RetentionPolicy.SOURCE) @interface Phase {} @@ -436,6 +438,12 @@ public interface ImeTracker { * app or the RemoteInsetsControlTarget). */ int PHASE_SERVER_UPDATE_CLIENT_VISIBILITY = ImeProtoEnums.PHASE_SERVER_UPDATE_CLIENT_VISIBILITY; + /** DisplayImeController received the requested visibility for the IME and stored it. */ + int PHASE_WM_DISPLAY_IME_CONTROLLER_SET_IME_REQUESTED_VISIBLE = + ImeProtoEnums.PHASE_WM_DISPLAY_IME_CONTROLLER_SET_IME_REQUESTED_VISIBLE; + /** The control target reported its requestedVisibleTypes back to WindowManagerService. */ + int PHASE_WM_UPDATE_DISPLAY_WINDOW_REQUESTED_VISIBLE_TYPES = + ImeProtoEnums.PHASE_WM_UPDATE_DISPLAY_WINDOW_REQUESTED_VISIBLE_TYPES; /** * Called when an IME request is started. diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java index 6303c7637a59c0acbc01d6b45530a6808af6aae2..5dd29b26730de085ed7e1b80d7bad1b2dc1c94fa 100644 --- a/core/java/android/view/inputmethod/InputMethodManager.java +++ b/core/java/android/view/inputmethod/InputMethodManager.java @@ -2626,10 +2626,12 @@ public final class InputMethodManager { // The view is running on a different thread than our own, so // we need to reschedule our work for over there. if (DEBUG) Log.v(TAG, "Hiding soft input: reschedule to view thread"); + final var finalStatsToken = statsToken; vh.post(() -> viewRootImpl.getInsetsController().hide( - WindowInsets.Type.ime())); + WindowInsets.Type.ime(), false /* fromIme */, finalStatsToken)); } else { - viewRootImpl.getInsetsController().hide(WindowInsets.Type.ime()); + viewRootImpl.getInsetsController().hide(WindowInsets.Type.ime(), + false /* fromIme */, statsToken); } } return true; diff --git a/core/java/android/view/inputmethod/flags.aconfig b/core/java/android/view/inputmethod/flags.aconfig index 73abc472be6d6f388ad3a25b25b650364e9145ed..41567fbf8b51733d3cf7c0d63811e6d64ff8019a 100644 --- a/core/java/android/view/inputmethod/flags.aconfig +++ b/core/java/android/view/inputmethod/flags.aconfig @@ -165,6 +165,7 @@ flag { description: "Writing tools API" bug: "373788889" is_fixed_read_only: true + is_exported: true } flag { @@ -191,4 +192,5 @@ flag { description: "Verify KeyEvents in IME" bug: "331730488" is_fixed_read_only: true + is_exported: true } diff --git a/core/java/android/webkit/UserPackage.java b/core/java/android/webkit/UserPackage.java index b18dbbc21cda8bc5812cdb33592e4b44270709bf..1bc952ca654606b6db06f7735677194276f8fc48 100644 --- a/core/java/android/webkit/UserPackage.java +++ b/core/java/android/webkit/UserPackage.java @@ -21,7 +21,6 @@ import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; -import android.os.Build; import android.os.UserHandle; import android.os.UserManager; @@ -36,8 +35,6 @@ public class UserPackage { private final UserHandle mUser; private final PackageInfo mPackageInfo; - public static final int MINIMUM_SUPPORTED_SDK = Build.VERSION_CODES.TIRAMISU; - public UserPackage(@NonNull UserHandle user, @Nullable PackageInfo packageInfo) { mUser = user; mPackageInfo = packageInfo; @@ -83,14 +80,6 @@ public class UserPackage { & ApplicationInfo.PRIVATE_FLAG_HIDDEN) == 0)); } - /** - * Returns whether the package represented by {@param packageInfo} targets a sdk version - * supported by the current framework version. - */ - public static boolean hasCorrectTargetSdkVersion(PackageInfo packageInfo) { - return packageInfo.applicationInfo.targetSdkVersion >= MINIMUM_SUPPORTED_SDK; - } - public UserHandle getUser() { return mUser; } diff --git a/core/java/android/webkit/WebViewFactory.java b/core/java/android/webkit/WebViewFactory.java index de303f80ff9eb4104385a9d2a464914fe6aa7e8c..1a48bbb77d60e1fbedf82a25df23b740c540446d 100644 --- a/core/java/android/webkit/WebViewFactory.java +++ b/core/java/android/webkit/WebViewFactory.java @@ -51,12 +51,6 @@ import java.lang.reflect.Method; */ @SystemApi public final class WebViewFactory { - - // visible for WebViewZygoteInit to look up the class by reflection and call preloadInZygote. - /** @hide */ - private static final String CHROMIUM_WEBVIEW_FACTORY = - "com.android.webview.chromium.WebViewChromiumFactoryProviderForT"; - private static final String CHROMIUM_WEBVIEW_FACTORY_METHOD = "create"; private static final String LOGTAG = "WebViewFactory"; @@ -275,8 +269,8 @@ public final class WebViewFactory { */ public static Class getWebViewProviderClass(ClassLoader clazzLoader) throws ClassNotFoundException { - return (Class) Class.forName(CHROMIUM_WEBVIEW_FACTORY, - true, clazzLoader); + return (Class) Class.forName( + WebViewFactoryProvider.getWebViewFactoryClassName(), true, clazzLoader); } /** diff --git a/core/java/android/webkit/WebViewFactoryProvider.java b/core/java/android/webkit/WebViewFactoryProvider.java index 3d6450632e0651c809a08cf824da239709927e92..4a2f9ba696a5311d20e8253445a933e0458a90f2 100644 --- a/core/java/android/webkit/WebViewFactoryProvider.java +++ b/core/java/android/webkit/WebViewFactoryProvider.java @@ -20,8 +20,11 @@ import android.annotation.NonNull; import android.annotation.SystemApi; import android.content.Context; import android.content.Intent; +import android.content.pm.PackageInfo; import android.net.Network; import android.net.Uri; +import android.os.Build; +import android.text.TextUtils; import java.util.List; @@ -33,6 +36,61 @@ import java.util.List; */ @SystemApi public interface WebViewFactoryProvider { + /** + * Used as the requirement when Flags.useBEntryPoint() is false. + * @hide + */ + int MINIMUM_SUPPORTED_TARGET_SDK = Build.VERSION_CODES.TIRAMISU; + + /** + * Used as the requirement when Flags.useBEntryPoint() is true. + * TODO: set to the actual minimum required version code - this is just the + * version shipped in V. + * @hide + */ + long MINIMUM_SUPPORTED_VERSION_CODE = 661308800L; + + /** + * Returns whether the WebView implementation represented by {@code packageInfo} + * is compatible with this version of Android. + * @hide + */ + static boolean isCompatibleImplementationPackage(@NonNull PackageInfo packageInfo) { + if (Flags.useBEntryPoint()) { + return packageInfo.versionCode >= MINIMUM_SUPPORTED_VERSION_CODE; + } else { + return packageInfo.applicationInfo.targetSdkVersion >= MINIMUM_SUPPORTED_TARGET_SDK; + } + } + + /** + * Returns a string describing the minimum requirement for a WebView implementation + * to be compatible with this version of Android, for debugging purposes. + * @hide + */ + static @NonNull String describeCompatibleImplementationPackage() { + if (Flags.useBEntryPoint()) { + return TextUtils.formatSimple("Minimum versionCode for OS support: %d", + MINIMUM_SUPPORTED_VERSION_CODE); + } else { + return TextUtils.formatSimple("Minimum targetSdkVersion: %d", + MINIMUM_SUPPORTED_TARGET_SDK); + } + } + + /** + * Returns the name of the class that should be used when loading the + * WebView implementation on this version of Android. + * @hide + */ + static @NonNull String getWebViewFactoryClassName() { + if (Flags.useBEntryPoint()) { + return "com.android.webview.chromium.WebViewChromiumFactoryProviderForB"; + } else { + return "com.android.webview.chromium.WebViewChromiumFactoryProviderForT"; + } + } + /** * This Interface provides glue for implementing the backend of WebView static methods which * cannot be implemented in-situ in the proxy class. diff --git a/core/java/android/webkit/flags.aconfig b/core/java/android/webkit/flags.aconfig index c9e94d2f57f65653267041c8316da8d6020bb278..c5176a2f1f158b326a48c8ca037512ff9568ec8e 100644 --- a/core/java/android/webkit/flags.aconfig +++ b/core/java/android/webkit/flags.aconfig @@ -42,3 +42,11 @@ flag { description: "New APIs required by File System Access" bug: "40101963" } + +flag { + name: "use_b_entry_point" + namespace: "webview" + description: "Use B-specific entry point to WebView APK" + bug: "373617389" + is_fixed_read_only: true +} diff --git a/core/java/android/widget/Button.java b/core/java/android/widget/Button.java index 0bf6380eb904db077f7a5faddfe407ca63382b9d..eb3b76873a8f3ae456c1f2f35c134007b9c8903d 100644 --- a/core/java/android/widget/Button.java +++ b/core/java/android/widget/Button.java @@ -134,6 +134,7 @@ public class Button extends TextView { // 1. app target sdk is 36 or above. // 2. feature flag rolled-out. // 3. device is a watch. + // 4. button uses Theme.DeviceDefault. // getButtonDefaultStyleAttr and getButtonDefaultStyleRes works together to alter the UI // while considering the conditions above. // Their results are mutual exclusive. i.e. when conditions above are all true, @@ -229,6 +230,7 @@ public class Button extends TextView { private static boolean useWearMaterial3Style(Context context) { return Flags.useWearMaterial3Ui() && CompatChanges.isChangeEnabled(WEAR_MATERIAL3_BUTTON) - && context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH); + && context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH) + && context.getThemeResId() == com.android.internal.R.style.Theme_DeviceDefault; } } diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index cb70466fcd81c32e39894178876f0127f1761cc1..d7750bd412a3790dce7a04f3eb9009a1d4518dbe 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -106,7 +106,6 @@ import android.os.Parcelable; import android.os.ParcelableParcel; import android.os.Process; import android.os.SystemClock; -import android.os.Trace; import android.os.UserHandle; import android.provider.Settings; import android.text.BoringLayout; @@ -9230,179 +9229,174 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener @Override protected void onDraw(Canvas canvas) { - Trace.traceBegin(Trace.TRACE_TAG_VIEW, "TextView.onDraw"); - try { - restartMarqueeIfNeeded(); - - // Draw the background for this view - super.onDraw(canvas); - - final int compoundPaddingLeft = getCompoundPaddingLeft(); - final int compoundPaddingTop = getCompoundPaddingTop(); - final int compoundPaddingRight = getCompoundPaddingRight(); - final int compoundPaddingBottom = getCompoundPaddingBottom(); - final int scrollX = mScrollX; - final int scrollY = mScrollY; - final int right = mRight; - final int left = mLeft; - final int bottom = mBottom; - final int top = mTop; - final boolean isLayoutRtl = isLayoutRtl(); - final int offset = getHorizontalOffsetForDrawables(); - final int leftOffset = isLayoutRtl ? 0 : offset; - final int rightOffset = isLayoutRtl ? offset : 0; - - final Drawables dr = mDrawables; - if (dr != null) { - /* - * Compound, not extended, because the icon is not clipped - * if the text height is smaller. - */ + restartMarqueeIfNeeded(); - int vspace = bottom - top - compoundPaddingBottom - compoundPaddingTop; - int hspace = right - left - compoundPaddingRight - compoundPaddingLeft; - - // IMPORTANT: The coordinates computed are also used in invalidateDrawable() - // Make sure to update invalidateDrawable() when changing this code. - if (dr.mShowing[Drawables.LEFT] != null) { - canvas.save(); - canvas.translate(scrollX + mPaddingLeft + leftOffset, - scrollY + compoundPaddingTop + (vspace - dr.mDrawableHeightLeft) / 2); - dr.mShowing[Drawables.LEFT].draw(canvas); - canvas.restore(); - } + // Draw the background for this view + super.onDraw(canvas); + + final int compoundPaddingLeft = getCompoundPaddingLeft(); + final int compoundPaddingTop = getCompoundPaddingTop(); + final int compoundPaddingRight = getCompoundPaddingRight(); + final int compoundPaddingBottom = getCompoundPaddingBottom(); + final int scrollX = mScrollX; + final int scrollY = mScrollY; + final int right = mRight; + final int left = mLeft; + final int bottom = mBottom; + final int top = mTop; + final boolean isLayoutRtl = isLayoutRtl(); + final int offset = getHorizontalOffsetForDrawables(); + final int leftOffset = isLayoutRtl ? 0 : offset; + final int rightOffset = isLayoutRtl ? offset : 0; - // IMPORTANT: The coordinates computed are also used in invalidateDrawable() - // Make sure to update invalidateDrawable() when changing this code. - if (dr.mShowing[Drawables.RIGHT] != null) { - canvas.save(); - canvas.translate(scrollX + right - left - mPaddingRight - - dr.mDrawableSizeRight - rightOffset, - scrollY + compoundPaddingTop + (vspace - dr.mDrawableHeightRight) / 2); - dr.mShowing[Drawables.RIGHT].draw(canvas); - canvas.restore(); - } + final Drawables dr = mDrawables; + if (dr != null) { + /* + * Compound, not extended, because the icon is not clipped + * if the text height is smaller. + */ - // IMPORTANT: The coordinates computed are also used in invalidateDrawable() - // Make sure to update invalidateDrawable() when changing this code. - if (dr.mShowing[Drawables.TOP] != null) { - canvas.save(); - canvas.translate(scrollX + compoundPaddingLeft - + (hspace - dr.mDrawableWidthTop) / 2, scrollY + mPaddingTop); - dr.mShowing[Drawables.TOP].draw(canvas); - canvas.restore(); - } + int vspace = bottom - top - compoundPaddingBottom - compoundPaddingTop; + int hspace = right - left - compoundPaddingRight - compoundPaddingLeft; - // IMPORTANT: The coordinates computed are also used in invalidateDrawable() - // Make sure to update invalidateDrawable() when changing this code. - if (dr.mShowing[Drawables.BOTTOM] != null) { - canvas.save(); - canvas.translate(scrollX + compoundPaddingLeft - + (hspace - dr.mDrawableWidthBottom) / 2, - scrollY + bottom - top - mPaddingBottom - dr.mDrawableSizeBottom); - dr.mShowing[Drawables.BOTTOM].draw(canvas); - canvas.restore(); - } + // IMPORTANT: The coordinates computed are also used in invalidateDrawable() + // Make sure to update invalidateDrawable() when changing this code. + if (dr.mShowing[Drawables.LEFT] != null) { + canvas.save(); + canvas.translate(scrollX + mPaddingLeft + leftOffset, + scrollY + compoundPaddingTop + (vspace - dr.mDrawableHeightLeft) / 2); + dr.mShowing[Drawables.LEFT].draw(canvas); + canvas.restore(); } - int color = mCurTextColor; + // IMPORTANT: The coordinates computed are also used in invalidateDrawable() + // Make sure to update invalidateDrawable() when changing this code. + if (dr.mShowing[Drawables.RIGHT] != null) { + canvas.save(); + canvas.translate(scrollX + right - left - mPaddingRight + - dr.mDrawableSizeRight - rightOffset, + scrollY + compoundPaddingTop + (vspace - dr.mDrawableHeightRight) / 2); + dr.mShowing[Drawables.RIGHT].draw(canvas); + canvas.restore(); + } - if (mLayout == null) { - assumeLayout(); + // IMPORTANT: The coordinates computed are also used in invalidateDrawable() + // Make sure to update invalidateDrawable() when changing this code. + if (dr.mShowing[Drawables.TOP] != null) { + canvas.save(); + canvas.translate(scrollX + compoundPaddingLeft + + (hspace - dr.mDrawableWidthTop) / 2, scrollY + mPaddingTop); + dr.mShowing[Drawables.TOP].draw(canvas); + canvas.restore(); } - Layout layout = mLayout; + // IMPORTANT: The coordinates computed are also used in invalidateDrawable() + // Make sure to update invalidateDrawable() when changing this code. + if (dr.mShowing[Drawables.BOTTOM] != null) { + canvas.save(); + canvas.translate(scrollX + compoundPaddingLeft + + (hspace - dr.mDrawableWidthBottom) / 2, + scrollY + bottom - top - mPaddingBottom - dr.mDrawableSizeBottom); + dr.mShowing[Drawables.BOTTOM].draw(canvas); + canvas.restore(); + } + } - if (mHint != null && !mHideHint && mText.length() == 0) { - if (mHintTextColor != null) { - color = mCurHintTextColor; - } + int color = mCurTextColor; - layout = mHintLayout; - } + if (mLayout == null) { + assumeLayout(); + } - mTextPaint.setColor(color); - mTextPaint.drawableState = getDrawableState(); + Layout layout = mLayout; - canvas.save(); - /* Would be faster if we didn't have to do this. Can we chop the - (displayable) text so that we don't need to do this ever? - */ + if (mHint != null && !mHideHint && mText.length() == 0) { + if (mHintTextColor != null) { + color = mCurHintTextColor; + } - int extendedPaddingTop = getExtendedPaddingTop(); - int extendedPaddingBottom = getExtendedPaddingBottom(); + layout = mHintLayout; + } - final int vspace = mBottom - mTop - compoundPaddingBottom - compoundPaddingTop; - final int maxScrollY = mLayout.getHeight() - vspace; + mTextPaint.setColor(color); + mTextPaint.drawableState = getDrawableState(); - float clipLeft = compoundPaddingLeft + scrollX; - float clipTop = (scrollY == 0) ? 0 : extendedPaddingTop + scrollY; - float clipRight = right - left - getCompoundPaddingRight() + scrollX; - float clipBottom = bottom - top + scrollY - - ((scrollY == maxScrollY) ? 0 : extendedPaddingBottom); + canvas.save(); + /* Would be faster if we didn't have to do this. Can we chop the + (displayable) text so that we don't need to do this ever? + */ - if (mShadowRadius != 0) { - clipLeft += Math.min(0, mShadowDx - mShadowRadius); - clipRight += Math.max(0, mShadowDx + mShadowRadius); + int extendedPaddingTop = getExtendedPaddingTop(); + int extendedPaddingBottom = getExtendedPaddingBottom(); - clipTop += Math.min(0, mShadowDy - mShadowRadius); - clipBottom += Math.max(0, mShadowDy + mShadowRadius); - } + final int vspace = mBottom - mTop - compoundPaddingBottom - compoundPaddingTop; + final int maxScrollY = mLayout.getHeight() - vspace; - canvas.clipRect(clipLeft, clipTop, clipRight, clipBottom); + float clipLeft = compoundPaddingLeft + scrollX; + float clipTop = (scrollY == 0) ? 0 : extendedPaddingTop + scrollY; + float clipRight = right - left - getCompoundPaddingRight() + scrollX; + float clipBottom = bottom - top + scrollY + - ((scrollY == maxScrollY) ? 0 : extendedPaddingBottom); - int voffsetText = 0; - int voffsetCursor = 0; + if (mShadowRadius != 0) { + clipLeft += Math.min(0, mShadowDx - mShadowRadius); + clipRight += Math.max(0, mShadowDx + mShadowRadius); - // translate in by our padding - /* shortcircuit calling getVerticaOffset() */ - if ((mGravity & Gravity.VERTICAL_GRAVITY_MASK) != Gravity.TOP) { - voffsetText = getVerticalOffset(false); - voffsetCursor = getVerticalOffset(true); - } - canvas.translate(compoundPaddingLeft, extendedPaddingTop + voffsetText); - - final int layoutDirection = getLayoutDirection(); - final int absoluteGravity = Gravity.getAbsoluteGravity(mGravity, layoutDirection); - if (isMarqueeFadeEnabled()) { - if (!mSingleLine && getLineCount() == 1 && canMarquee() - && (absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK) != Gravity.LEFT) { - final int width = mRight - mLeft; - final int padding = getCompoundPaddingLeft() + getCompoundPaddingRight(); - final float dx = mLayout.getLineRight(0) - (width - padding); - canvas.translate(layout.getParagraphDirection(0) * dx, 0.0f); - } + clipTop += Math.min(0, mShadowDy - mShadowRadius); + clipBottom += Math.max(0, mShadowDy + mShadowRadius); + } - if (mMarquee != null && mMarquee.isRunning()) { - final float dx = -mMarquee.getScroll(); - canvas.translate(layout.getParagraphDirection(0) * dx, 0.0f); - } - } + canvas.clipRect(clipLeft, clipTop, clipRight, clipBottom); - final int cursorOffsetVertical = voffsetCursor - voffsetText; + int voffsetText = 0; + int voffsetCursor = 0; - maybeUpdateHighlightPaths(); - // If there is a gesture preview highlight, then the selection or cursor is not drawn. - Path highlight = hasGesturePreviewHighlight() ? null : getUpdatedHighlightPath(); - if (mEditor != null) { - mEditor.onDraw(canvas, layout, mHighlightPaths, mHighlightPaints, highlight, - mHighlightPaint, cursorOffsetVertical); - } else { - layout.draw(canvas, mHighlightPaths, mHighlightPaints, highlight, mHighlightPaint, - cursorOffsetVertical); + // translate in by our padding + /* shortcircuit calling getVerticaOffset() */ + if ((mGravity & Gravity.VERTICAL_GRAVITY_MASK) != Gravity.TOP) { + voffsetText = getVerticalOffset(false); + voffsetCursor = getVerticalOffset(true); + } + canvas.translate(compoundPaddingLeft, extendedPaddingTop + voffsetText); + + final int layoutDirection = getLayoutDirection(); + final int absoluteGravity = Gravity.getAbsoluteGravity(mGravity, layoutDirection); + if (isMarqueeFadeEnabled()) { + if (!mSingleLine && getLineCount() == 1 && canMarquee() + && (absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK) != Gravity.LEFT) { + final int width = mRight - mLeft; + final int padding = getCompoundPaddingLeft() + getCompoundPaddingRight(); + final float dx = mLayout.getLineRight(0) - (width - padding); + canvas.translate(layout.getParagraphDirection(0) * dx, 0.0f); } - if (mMarquee != null && mMarquee.shouldDrawGhost()) { - final float dx = mMarquee.getGhostOffset(); + if (mMarquee != null && mMarquee.isRunning()) { + final float dx = -mMarquee.getScroll(); canvas.translate(layout.getParagraphDirection(0) * dx, 0.0f); - layout.draw(canvas, mHighlightPaths, mHighlightPaints, highlight, mHighlightPaint, - cursorOffsetVertical); } + } + + final int cursorOffsetVertical = voffsetCursor - voffsetText; + + maybeUpdateHighlightPaths(); + // If there is a gesture preview highlight, then the selection or cursor is not drawn. + Path highlight = hasGesturePreviewHighlight() ? null : getUpdatedHighlightPath(); + if (mEditor != null) { + mEditor.onDraw(canvas, layout, mHighlightPaths, mHighlightPaints, highlight, + mHighlightPaint, cursorOffsetVertical); + } else { + layout.draw(canvas, mHighlightPaths, mHighlightPaints, highlight, mHighlightPaint, + cursorOffsetVertical); + } - canvas.restore(); - } finally { - Trace.traceEnd(Trace.TRACE_TAG_VIEW); + if (mMarquee != null && mMarquee.shouldDrawGhost()) { + final float dx = mMarquee.getGhostOffset(); + canvas.translate(layout.getParagraphDirection(0) * dx, 0.0f); + layout.draw(canvas, mHighlightPaths, mHighlightPaints, highlight, mHighlightPaint, + cursorOffsetVertical); } + + canvas.restore(); } @Override @@ -11260,201 +11254,192 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - Trace.traceBegin(Trace.TRACE_TAG_VIEW, "TextView.onMeasure"); - try { - int widthMode = MeasureSpec.getMode(widthMeasureSpec); - int heightMode = MeasureSpec.getMode(heightMeasureSpec); - int widthSize = MeasureSpec.getSize(widthMeasureSpec); - int heightSize = MeasureSpec.getSize(heightMeasureSpec); + int widthMode = MeasureSpec.getMode(widthMeasureSpec); + int heightMode = MeasureSpec.getMode(heightMeasureSpec); + int widthSize = MeasureSpec.getSize(widthMeasureSpec); + int heightSize = MeasureSpec.getSize(heightMeasureSpec); - int width; - int height; + int width; + int height; - BoringLayout.Metrics boring = UNKNOWN_BORING; - BoringLayout.Metrics hintBoring = UNKNOWN_BORING; + BoringLayout.Metrics boring = UNKNOWN_BORING; + BoringLayout.Metrics hintBoring = UNKNOWN_BORING; - if (mTextDir == null) { - mTextDir = getTextDirectionHeuristic(); + if (mTextDir == null) { + mTextDir = getTextDirectionHeuristic(); + } + + int des = -1; + boolean fromexisting = false; + final float widthLimit = (widthMode == MeasureSpec.AT_MOST) + ? (float) widthSize : Float.MAX_VALUE; + + if (widthMode == MeasureSpec.EXACTLY) { + // Parent has told us how big to be. So be it. + width = widthSize; + } else { + if (mLayout != null && mEllipsize == null) { + des = desired(mLayout, mUseBoundsForWidth); } - int des = -1; - boolean fromexisting = false; - final float widthLimit = (widthMode == MeasureSpec.AT_MOST) - ? (float) widthSize : Float.MAX_VALUE; + if (des < 0) { + boring = BoringLayout.isBoring(mTransformed, mTextPaint, mTextDir, + isFallbackLineSpacingForBoringLayout(), getResolvedMinimumFontMetrics(), + mBoring); + if (boring != null) { + mBoring = boring; + } + } else { + fromexisting = true; + } - if (widthMode == MeasureSpec.EXACTLY) { - // Parent has told us how big to be. So be it. - width = widthSize; + if (boring == null || boring == UNKNOWN_BORING) { + if (des < 0) { + des = (int) Math.ceil(Layout.getDesiredWidthWithLimit(mTransformed, 0, + mTransformed.length(), mTextPaint, mTextDir, widthLimit, + mUseBoundsForWidth)); + } + width = des; } else { - if (mLayout != null && mEllipsize == null) { - des = desired(mLayout, mUseBoundsForWidth); + if (mUseBoundsForWidth) { + RectF bbox = boring.getDrawingBoundingBox(); + float rightMax = Math.max(bbox.right, boring.width); + float leftMin = Math.min(bbox.left, 0); + width = Math.max(boring.width, (int) Math.ceil(rightMax - leftMin)); + } else { + width = boring.width; } + } - if (des < 0) { - boring = BoringLayout.isBoring(mTransformed, mTextPaint, mTextDir, + final Drawables dr = mDrawables; + if (dr != null) { + width = Math.max(width, dr.mDrawableWidthTop); + width = Math.max(width, dr.mDrawableWidthBottom); + } + + if (mHint != null) { + int hintDes = -1; + int hintWidth; + + if (mHintLayout != null && mEllipsize == null) { + hintDes = desired(mHintLayout, mUseBoundsForWidth); + } + + if (hintDes < 0) { + hintBoring = BoringLayout.isBoring(mHint, mTextPaint, mTextDir, isFallbackLineSpacingForBoringLayout(), getResolvedMinimumFontMetrics(), - mBoring); - if (boring != null) { - mBoring = boring; + mHintBoring); + if (hintBoring != null) { + mHintBoring = hintBoring; } - } else { - fromexisting = true; } - if (boring == null || boring == UNKNOWN_BORING) { - if (des < 0) { - des = (int) Math.ceil(Layout.getDesiredWidthWithLimit(mTransformed, 0, - mTransformed.length(), mTextPaint, mTextDir, widthLimit, + if (hintBoring == null || hintBoring == UNKNOWN_BORING) { + if (hintDes < 0) { + hintDes = (int) Math.ceil(Layout.getDesiredWidthWithLimit(mHint, 0, + mHint.length(), mTextPaint, mTextDir, widthLimit, mUseBoundsForWidth)); } - width = des; + hintWidth = hintDes; } else { - if (mUseBoundsForWidth) { - RectF bbox = boring.getDrawingBoundingBox(); - float rightMax = Math.max(bbox.right, boring.width); - float leftMin = Math.min(bbox.left, 0); - width = Math.max(boring.width, (int) Math.ceil(rightMax - leftMin)); - } else { - width = boring.width; - } + hintWidth = hintBoring.width; } - final Drawables dr = mDrawables; - if (dr != null) { - width = Math.max(width, dr.mDrawableWidthTop); - width = Math.max(width, dr.mDrawableWidthBottom); + if (hintWidth > width) { + width = hintWidth; } + } - if (mHint != null) { - int hintDes = -1; - int hintWidth; - - if (mHintLayout != null && mEllipsize == null) { - hintDes = desired(mHintLayout, mUseBoundsForWidth); - } + width += getCompoundPaddingLeft() + getCompoundPaddingRight(); - if (hintDes < 0) { - hintBoring = BoringLayout.isBoring(mHint, mTextPaint, mTextDir, - isFallbackLineSpacingForBoringLayout(), - getResolvedMinimumFontMetrics(), - mHintBoring); - if (hintBoring != null) { - mHintBoring = hintBoring; - } - } - - if (hintBoring == null || hintBoring == UNKNOWN_BORING) { - if (hintDes < 0) { - hintDes = (int) Math.ceil(Layout.getDesiredWidthWithLimit(mHint, 0, - mHint.length(), mTextPaint, mTextDir, widthLimit, - mUseBoundsForWidth)); - } - hintWidth = hintDes; - } else { - hintWidth = hintBoring.width; - } + if (mMaxWidthMode == EMS) { + width = Math.min(width, mMaxWidth * getLineHeight()); + } else { + width = Math.min(width, mMaxWidth); + } - if (hintWidth > width) { - width = hintWidth; - } - } + if (mMinWidthMode == EMS) { + width = Math.max(width, mMinWidth * getLineHeight()); + } else { + width = Math.max(width, mMinWidth); + } - width += getCompoundPaddingLeft() + getCompoundPaddingRight(); + // Check against our minimum width + width = Math.max(width, getSuggestedMinimumWidth()); - if (mMaxWidthMode == EMS) { - width = Math.min(width, mMaxWidth * getLineHeight()); - } else { - width = Math.min(width, mMaxWidth); - } + if (widthMode == MeasureSpec.AT_MOST) { + width = Math.min(widthSize, width); + } + } - if (mMinWidthMode == EMS) { - width = Math.max(width, mMinWidth * getLineHeight()); - } else { - width = Math.max(width, mMinWidth); - } + int want = width - getCompoundPaddingLeft() - getCompoundPaddingRight(); + int unpaddedWidth = want; - // Check against our minimum width - width = Math.max(width, getSuggestedMinimumWidth()); + if (mHorizontallyScrolling) want = VERY_WIDE; - if (widthMode == MeasureSpec.AT_MOST) { - width = Math.min(widthSize, width); - } - } + int hintWant = want; + int hintWidth = (mHintLayout == null) ? hintWant : mHintLayout.getWidth(); - int want = width - getCompoundPaddingLeft() - getCompoundPaddingRight(); - int unpaddedWidth = want; + if (mLayout == null) { + makeNewLayout(want, hintWant, boring, hintBoring, + width - getCompoundPaddingLeft() - getCompoundPaddingRight(), false); + } else { + final boolean layoutChanged = (mLayout.getWidth() != want) || (hintWidth != hintWant) + || (mLayout.getEllipsizedWidth() + != width - getCompoundPaddingLeft() - getCompoundPaddingRight()); - if (mHorizontallyScrolling) want = VERY_WIDE; + final boolean widthChanged = (mHint == null) && (mEllipsize == null) + && (want > mLayout.getWidth()) + && (mLayout instanceof BoringLayout + || (fromexisting && des >= 0 && des <= want)); - int hintWant = want; - int hintWidth = (mHintLayout == null) ? hintWant : mHintLayout.getWidth(); + final boolean maximumChanged = (mMaxMode != mOldMaxMode) || (mMaximum != mOldMaximum); - if (mLayout == null) { - makeNewLayout(want, hintWant, boring, hintBoring, - width - getCompoundPaddingLeft() - getCompoundPaddingRight(), false); - } else { - final boolean layoutChanged = - (mLayout.getWidth() != want) || (hintWidth != hintWant) - || (mLayout.getEllipsizedWidth() - != width - getCompoundPaddingLeft() - getCompoundPaddingRight()); - - final boolean widthChanged = (mHint == null) && (mEllipsize == null) - && (want > mLayout.getWidth()) - && (mLayout instanceof BoringLayout - || (fromexisting && des >= 0 && des <= want)); - - final boolean maximumChanged = - (mMaxMode != mOldMaxMode) || (mMaximum != mOldMaximum); - - if (layoutChanged || maximumChanged) { - if (!maximumChanged && widthChanged) { - mLayout.increaseWidthTo(want); - } else { - makeNewLayout(want, hintWant, boring, hintBoring, - width - getCompoundPaddingLeft() - getCompoundPaddingRight(), - false); - } + if (layoutChanged || maximumChanged) { + if (!maximumChanged && widthChanged) { + mLayout.increaseWidthTo(want); } else { - // Nothing has changed + makeNewLayout(want, hintWant, boring, hintBoring, + width - getCompoundPaddingLeft() - getCompoundPaddingRight(), false); } - } - - if (heightMode == MeasureSpec.EXACTLY) { - // Parent has told us how big to be. So be it. - height = heightSize; - mDesiredHeightAtMeasure = -1; } else { - int desired = getDesiredHeight(); + // Nothing has changed + } + } - height = desired; - mDesiredHeightAtMeasure = desired; + if (heightMode == MeasureSpec.EXACTLY) { + // Parent has told us how big to be. So be it. + height = heightSize; + mDesiredHeightAtMeasure = -1; + } else { + int desired = getDesiredHeight(); - if (heightMode == MeasureSpec.AT_MOST) { - height = Math.min(desired, heightSize); - } - } + height = desired; + mDesiredHeightAtMeasure = desired; - int unpaddedHeight = height - getCompoundPaddingTop() - getCompoundPaddingBottom(); - if (mMaxMode == LINES && mLayout.getLineCount() > mMaximum) { - unpaddedHeight = Math.min(unpaddedHeight, mLayout.getLineTop(mMaximum)); + if (heightMode == MeasureSpec.AT_MOST) { + height = Math.min(desired, heightSize); } + } - /* - * We didn't let makeNewLayout() register to bring the cursor into view, - * so do it here if there is any possibility that it is needed. - */ - if (mMovement != null - || mLayout.getWidth() > unpaddedWidth - || mLayout.getHeight() > unpaddedHeight) { - registerForPreDraw(); - } else { - scrollTo(0, 0); - } + int unpaddedHeight = height - getCompoundPaddingTop() - getCompoundPaddingBottom(); + if (mMaxMode == LINES && mLayout.getLineCount() > mMaximum) { + unpaddedHeight = Math.min(unpaddedHeight, mLayout.getLineTop(mMaximum)); + } - setMeasuredDimension(width, height); - } finally { - Trace.traceEnd(Trace.TRACE_TAG_VIEW); + /* + * We didn't let makeNewLayout() register to bring the cursor into view, + * so do it here if there is any possibility that it is needed. + */ + if (mMovement != null + || mLayout.getWidth() > unpaddedWidth + || mLayout.getHeight() > unpaddedHeight) { + registerForPreDraw(); + } else { + scrollTo(0, 0); } + + setMeasuredDimension(width, height); } /** diff --git a/core/java/android/window/DesktopModeFlags.java b/core/java/android/window/DesktopModeFlags.java index 7a01ad340c561be0b4d07c84716e4e0b1f0ab731..289c5cf4bf85031ab31b6b585acf8f7d6391225d 100644 --- a/core/java/android/window/DesktopModeFlags.java +++ b/core/java/android/window/DesktopModeFlags.java @@ -68,7 +68,8 @@ public enum DesktopModeFlags { Flags::enableDesktopWindowingTaskbarRunningApps, true), // TODO: b/369763947 - remove this once ENABLE_DESKTOP_WINDOWING_ENTER_TRANSITIONS is ramped up ENABLE_DESKTOP_WINDOWING_TRANSITIONS(Flags::enableDesktopWindowingTransitions, false), - ENABLE_DESKTOP_WINDOWING_ENTER_TRANSITIONS(Flags::enableDesktopWindowingTransitions, false), + ENABLE_DESKTOP_WINDOWING_ENTER_TRANSITIONS( + Flags::enableDesktopWindowingEnterTransitions, false), ENABLE_DESKTOP_WINDOWING_EXIT_TRANSITIONS(Flags::enableDesktopWindowingExitTransitions, false), ENABLE_WINDOWING_TRANSITION_HANDLERS_OBSERVERS( Flags::enableWindowingTransitionHandlersObservers, false), @@ -77,7 +78,15 @@ public enum DesktopModeFlags { ENABLE_DESKTOP_APP_LAUNCH_TRANSITIONS( Flags::enableDesktopAppLaunchTransitions, false), ENABLE_DESKTOP_WINDOWING_PERSISTENCE(Flags::enableDesktopWindowingPersistence, false), - ENABLE_HANDLE_INPUT_FIX(Flags::enableHandleInputFix, true); + ENABLE_HANDLE_INPUT_FIX(Flags::enableHandleInputFix, true), + ENABLE_DESKTOP_WINDOWING_ENTER_TRANSITIONS_BUGFIX( + Flags::enableDesktopWindowingEnterTransitionBugfix, false), + ENABLE_DESKTOP_WINDOWING_EXIT_TRANSITIONS_BUGFIX( + Flags::enableDesktopWindowingExitTransitionsBugfix, false), + ENABLE_DESKTOP_APP_LAUNCH_ALTTAB_TRANSITIONS_BUGFIX( + Flags::enableDesktopAppLaunchAlttabTransitionsBugfix, false), + ENABLE_DESKTOP_APP_LAUNCH_TRANSITIONS_BUGFIX( + Flags::enableDesktopAppLaunchTransitionsBugfix, false); private static final String TAG = "DesktopModeFlagsUtil"; // Function called to obtain aconfig flag value. diff --git a/core/java/android/window/KeyguardState.java b/core/java/android/window/KeyguardState.java index 6584d30cdaedefbe9c754a58a0267a9dd1308382..159275abb9ef0c1f11d6b9f5fb2be540c3b85e26 100644 --- a/core/java/android/window/KeyguardState.java +++ b/core/java/android/window/KeyguardState.java @@ -30,28 +30,23 @@ import java.util.Objects; */ public final class KeyguardState implements Parcelable { - private final int mDisplayId; - private final boolean mKeyguardShowing; private final boolean mAodShowing; - private KeyguardState(int displayId, boolean keyguardShowing, boolean aodShowing) { - mDisplayId = displayId; + private KeyguardState(boolean keyguardShowing, boolean aodShowing) { mKeyguardShowing = keyguardShowing; mAodShowing = aodShowing; } private KeyguardState(Parcel in) { - mDisplayId = in.readInt(); mKeyguardShowing = in.readBoolean(); mAodShowing = in.readBoolean(); } @Override public void writeToParcel(@NonNull Parcel dest, int flags) { - dest.writeInt(mDisplayId); dest.writeBoolean(mKeyguardShowing); dest.writeBoolean(mAodShowing); } @@ -70,13 +65,6 @@ public final class KeyguardState implements Parcelable { } }; - /** - * Gets the display id of this {@link KeyguardState}. - */ - public int getDisplayId() { - return mDisplayId; - } - /** Returns the keyguard showing value. */ public boolean getKeyguardShowing() { return mKeyguardShowing; @@ -89,15 +77,14 @@ public final class KeyguardState implements Parcelable { @Override public String toString() { - return "KeyguardState{ displayId=" + mDisplayId - + ", keyguardShowing=" + mKeyguardShowing + return "KeyguardState{ keyguardShowing=" + mKeyguardShowing + ", aodShowing=" + mAodShowing + '}'; } @Override public int hashCode() { - return Objects.hash(mDisplayId, mKeyguardShowing, mAodShowing); + return Objects.hash(mKeyguardShowing, mAodShowing); } @Override @@ -105,8 +92,7 @@ public final class KeyguardState implements Parcelable { if (!(obj instanceof KeyguardState other)) { return false; } - return mDisplayId == other.mDisplayId - && mKeyguardShowing == other.mKeyguardShowing + return mKeyguardShowing == other.mKeyguardShowing && mAodShowing == other.mAodShowing; } @@ -117,18 +103,11 @@ public final class KeyguardState implements Parcelable { /** Builder to construct the {@link KeyguardState}. */ public static final class Builder { - - private final int mDisplayId; - private boolean mKeyguardShowing; private boolean mAodShowing; - /** - * @param displayId the display of this {@link KeyguardState}. - */ - public Builder(int displayId) { - mDisplayId = displayId; + public Builder() { } /** @@ -154,7 +133,7 @@ public final class KeyguardState implements Parcelable { */ @NonNull public KeyguardState build() { - return new KeyguardState(mDisplayId, mKeyguardShowing, mAodShowing); + return new KeyguardState(mKeyguardShowing, mAodShowing); } } } diff --git a/core/java/android/window/flags/large_screen_experiences_app_compat.aconfig b/core/java/android/window/flags/large_screen_experiences_app_compat.aconfig index 7ad14b0c9fe806d5e497f77cab2106d18ccb27f9..801698caff0e57722460a81d1d8834f1ebfded49 100644 --- a/core/java/android/window/flags/large_screen_experiences_app_compat.aconfig +++ b/core/java/android/window/flags/large_screen_experiences_app_compat.aconfig @@ -111,6 +111,18 @@ flag { bug: "353697519" } +flag { + name: "app_compat_async_relayout" + namespace: "large_screen_experiences_app_compat" + description: "Whether we use the SurfaceViewHost overload to apply a change in /n" + "position and size in a Transaction provided by a callback invoked /n" + "after the View relayout." + bug: "322463856" + metadata { + purpose: PURPOSE_BUGFIX + } +} + flag { name: "app_compat_refactoring" namespace: "large_screen_experiences_app_compat" diff --git a/core/java/android/window/flags/lse_desktop_experience.aconfig b/core/java/android/window/flags/lse_desktop_experience.aconfig index 8019e6791cf1628c9097b07f6d8a71ec42bea9f0..4fb5fa70c0830e6442f60cdd4e0e3ac09916de64 100644 --- a/core/java/android/window/flags/lse_desktop_experience.aconfig +++ b/core/java/android/window/flags/lse_desktop_experience.aconfig @@ -58,10 +58,13 @@ flag { } flag { - name: "enable_desktop_windowing_scvh_cache" + name: "enable_desktop_windowing_scvh_cache_bug_fix" namespace: "lse_desktop_experience" description: "Enables a SurfaceControlViewHost cache for window decorations" - bug: "345146928" + bug: "360452034" + metadata { + purpose: PURPOSE_BUGFIX + } } flag { @@ -241,13 +244,6 @@ flag { bug: "316006079" } -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" @@ -301,6 +297,14 @@ flag { namespace: "lse_desktop_experience" description: "Enables desktop windowing app-to-web education" bug: "348205896" + is_exported: true +} + +flag { + name: "enable_desktop_windowing_app_to_web_education_integration" + namespace: "lse_desktop_experience" + description: "Enables desktop windowing App-to-Web education and integrates new APIs" + bug: "380272815" } flag { diff --git a/core/java/android/window/flags/responsible_apis.aconfig b/core/java/android/window/flags/responsible_apis.aconfig index b2f125dd2821b19f955552f45d1448a850103539..d5ba32cafebdacbfe4f4278ff606c3a0b2518059 100644 --- a/core/java/android/window/flags/responsible_apis.aconfig +++ b/core/java/android/window/flags/responsible_apis.aconfig @@ -48,6 +48,7 @@ flag { namespace: "responsible_apis" description: "Introduce additional start modes." bug: "352182359" + is_exported: true } flag { @@ -55,6 +56,7 @@ flag { namespace: "responsible_apis" description: "Add options parameter to IntentSender.sendIntent." bug: "339720406" + is_exported: true } flag { @@ -63,6 +65,7 @@ flag { description: "Strict mode flag" bug: "324089586" is_fixed_read_only: true + is_exported: true } flag { diff --git a/core/java/android/window/flags/wallpaper_manager.aconfig b/core/java/android/window/flags/wallpaper_manager.aconfig index efacc346ac0abdc8237f911c1df05eaa484754af..1ddfe878dfd83bf8af0811d81a8224e0e3368ca1 100644 --- a/core/java/android/window/flags/wallpaper_manager.aconfig +++ b/core/java/android/window/flags/wallpaper_manager.aconfig @@ -14,6 +14,7 @@ flag { namespace: "systemui" description: "Support storing different wallpaper crops for different display dimensions. Only effective after rebooting." bug: "281648899" + is_exported: true } flag { diff --git a/core/java/android/window/flags/windowing_frontend.aconfig b/core/java/android/window/flags/windowing_frontend.aconfig index ebbe4830009c49655dc5e69c7993cd1fb4767899..0b034b61c72e9e9f2c03989acfea56614bdbda3e 100644 --- a/core/java/android/window/flags/windowing_frontend.aconfig +++ b/core/java/android/window/flags/windowing_frontend.aconfig @@ -368,6 +368,7 @@ flag { description: "PRIORITY_SYSTEM_NAVIGATION_OBSERVER predictive back API extension" is_fixed_read_only: true bug: "362938401" + is_exported: true } flag { @@ -376,6 +377,7 @@ flag { description: "expose timestamp in BackEvent (API extension)" is_fixed_read_only: true bug: "362938401" + is_exported: true } flag { @@ -384,6 +386,7 @@ flag { description: "EDGE_NONE swipeEdge option in BackEvent" is_fixed_read_only: true bug: "362938401" + is_exported: true } flag { @@ -422,6 +425,7 @@ flag { description: "Provide pre-make predictive back API extension" is_fixed_read_only: true bug: "362938401" + is_exported: true } flag { diff --git a/core/java/android/window/flags/windowing_sdk.aconfig b/core/java/android/window/flags/windowing_sdk.aconfig index b7012b68d459c48e1b3ef8f682df6c2f85558de6..81734a3e2115c14de52a782bd59d4185db3d98bf 100644 --- a/core/java/android/window/flags/windowing_sdk.aconfig +++ b/core/java/android/window/flags/windowing_sdk.aconfig @@ -100,6 +100,7 @@ flag { name: "touch_pass_through_opt_in" description: "Requires apps to opt-in to overlay pass through touches and provide APIs to opt-in" bug: "358129114" + is_exported: true } flag { diff --git a/core/java/com/android/internal/accessibility/AccessibilityShortcutController.java b/core/java/com/android/internal/accessibility/AccessibilityShortcutController.java index e8831ec2743ea3778555e8f3c8d9d5c735eefad8..e2be1f57b1fba2556f5276418a828ce44871cf35 100644 --- a/core/java/com/android/internal/accessibility/AccessibilityShortcutController.java +++ b/core/java/com/android/internal/accessibility/AccessibilityShortcutController.java @@ -360,43 +360,44 @@ public class AccessibilityShortcutController { // Avoid non-a11y users accidentally turning shortcut on without reading this carefully. // Put "don't turn on" as the primary action. - final AlertDialog alertDialog = mFrameworkObjectProvider.getAlertDialogBuilder( - // Use SystemUI context so we pick up any theme set in a vendor overlay - mFrameworkObjectProvider.getSystemUiContext()) - .setTitle(getShortcutWarningTitle(targets)) - .setMessage(getShortcutWarningMessage(targets)) - .setCancelable(false) - .setNegativeButton(R.string.accessibility_shortcut_on, - (DialogInterface d, int which) -> enableDefaultHardwareShortcut(userId)) - .setPositiveButton(R.string.accessibility_shortcut_off, - (DialogInterface d, int which) -> { - Set targetServices = - ShortcutUtils.getShortcutTargetsFromSettings( - mContext, - HARDWARE, + final AlertDialog alertDialog = + mFrameworkObjectProvider + .getAlertDialogBuilder( + // Use SystemUI context so we pick up any theme set in a vendor + // overlay + mFrameworkObjectProvider.getSystemUiContext()) + .setTitle(getShortcutWarningTitle(targets)) + .setMessage(getShortcutWarningMessage(targets)) + .setCancelable(false) + .setNegativeButton( + R.string.accessibility_shortcut_on, + (DialogInterface d, int which) -> + enableDefaultHardwareShortcut(userId)) + .setPositiveButton( + R.string.accessibility_shortcut_off, + (DialogInterface d, int which) -> { + Set targetServices = + ShortcutUtils.getShortcutTargetsFromSettings( + mContext, HARDWARE, userId); + am.enableShortcutsForTargets( + false, HARDWARE, targetServices, userId); + // If canceled, treat as if the dialog has never been shown + Settings.Secure.putIntForUser( + mContext.getContentResolver(), + Settings.Secure.ACCESSIBILITY_SHORTCUT_DIALOG_SHOWN, + DialogStatus.NOT_SHOWN, userId); - if (Flags.migrateEnableShortcuts()) { - am.enableShortcutsForTargets( - false, HARDWARE, targetServices, userId); - } else { - Settings.Secure.putStringForUser(mContext.getContentResolver(), - Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE, "", - userId); - ShortcutUtils.updateInvisibleToggleAccessibilityServiceEnableState( - mContext, targetServices, userId); - } - // If canceled, treat as if the dialog has never been shown - Settings.Secure.putIntForUser(mContext.getContentResolver(), - Settings.Secure.ACCESSIBILITY_SHORTCUT_DIALOG_SHOWN, - DialogStatus.NOT_SHOWN, userId); - }) - .setOnCancelListener((DialogInterface d) -> { - // If canceled, treat as if the dialog has never been shown - Settings.Secure.putIntForUser(mContext.getContentResolver(), - Settings.Secure.ACCESSIBILITY_SHORTCUT_DIALOG_SHOWN, - DialogStatus.NOT_SHOWN, userId); - }) - .create(); + }) + .setOnCancelListener( + (DialogInterface d) -> { + // If canceled, treat as if the dialog has never been shown + Settings.Secure.putIntForUser( + mContext.getContentResolver(), + Settings.Secure.ACCESSIBILITY_SHORTCUT_DIALOG_SHOWN, + DialogStatus.NOT_SHOWN, + userId); + }) + .create(); return alertDialog; } @@ -531,14 +532,8 @@ public class AccessibilityShortcutController { // Default service is invalid, so nothing we can do here. return; } - if (Flags.migrateEnableShortcuts()) { - accessibilityManager.enableShortcutsForTargets(true, HARDWARE, - Set.of(defaultServiceComponent.flattenToString()), userId); - } else { - Settings.Secure.putStringForUser(mContext.getContentResolver(), - Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE, - defaultServiceComponent.flattenToString(), userId); - } + accessibilityManager.enableShortcutsForTargets(true, HARDWARE, + Set.of(defaultServiceComponent.flattenToString()), userId); } private boolean performTtsPrompt(AlertDialog alertDialog) { diff --git a/core/java/com/android/internal/accessibility/dialog/AccessibilityTarget.java b/core/java/com/android/internal/accessibility/dialog/AccessibilityTarget.java index a753110edd5185e7b22dd68c344b89bfe13c25e3..f0582d063c71c538a00592e34c65fef86c9f15a0 100644 --- a/core/java/com/android/internal/accessibility/dialog/AccessibilityTarget.java +++ b/core/java/com/android/internal/accessibility/dialog/AccessibilityTarget.java @@ -19,8 +19,6 @@ package com.android.internal.accessibility.dialog; import static com.android.internal.accessibility.common.ShortcutConstants.UserShortcutType.GESTURE; import static com.android.internal.accessibility.common.ShortcutConstants.UserShortcutType.HARDWARE; import static com.android.internal.accessibility.common.ShortcutConstants.UserShortcutType.SOFTWARE; -import static com.android.internal.accessibility.util.ShortcutUtils.optInValueToSettings; -import static com.android.internal.accessibility.util.ShortcutUtils.optOutValueFromSettings; import android.annotation.NonNull; import android.annotation.Nullable; @@ -31,7 +29,6 @@ import android.graphics.drawable.Drawable; import android.os.UserHandle; import android.view.View; import android.view.accessibility.AccessibilityManager; -import android.view.accessibility.Flags; import com.android.internal.accessibility.common.ShortcutConstants; import com.android.internal.accessibility.common.ShortcutConstants.AccessibilityFragmentType; @@ -118,18 +115,9 @@ public abstract class AccessibilityTarget implements TargetOperations, OnTargetS @Override public void onCheckedChanged(boolean isChecked) { setShortcutEnabled(isChecked); - if (Flags.migrateEnableShortcuts()) { - final AccessibilityManager am = - getContext().getSystemService(AccessibilityManager.class); - am.enableShortcutsForTargets( - isChecked, getShortcutType(), Set.of(mId), UserHandle.myUserId()); - } else { - if (isChecked) { - optInValueToSettings(getContext(), getShortcutType(), getId()); - } else { - optOutValueFromSettings(getContext(), getShortcutType(), getId()); - } - } + final AccessibilityManager am = getContext().getSystemService(AccessibilityManager.class); + am.enableShortcutsForTargets( + isChecked, getShortcutType(), Set.of(mId), UserHandle.myUserId()); } public void setStateDescription(CharSequence stateDescription) { diff --git a/core/java/com/android/internal/app/AlertController.java b/core/java/com/android/internal/app/AlertController.java index f690bd3477f07089f035d3b10a6aff3b433087cc..92f9e6014107f5c61d461320cadaedd45d2a1708 100644 --- a/core/java/com/android/internal/app/AlertController.java +++ b/core/java/com/android/internal/app/AlertController.java @@ -20,9 +20,13 @@ import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; import android.annotation.Nullable; import android.app.AlertDialog; +import android.app.compat.CompatChanges; +import android.compat.annotation.ChangeId; +import android.compat.annotation.EnabledSince; import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; import android.content.DialogInterface; +import android.content.pm.PackageManager; import android.content.res.TypedArray; import android.database.Cursor; import android.graphics.drawable.Drawable; @@ -58,6 +62,7 @@ import android.widget.ListView; import android.widget.ScrollView; import android.widget.SimpleCursorAdapter; import android.widget.TextView; +import android.widget.flags.Flags; import com.android.internal.R; @@ -66,6 +71,12 @@ import java.lang.ref.WeakReference; public class AlertController { public static final int MICRO = 1; + private static boolean sUseWearMaterial3Style; + + @ChangeId + @EnabledSince(targetSdkVersion = 36) + private static final long WEAR_MATERIAL3_ALERTDIALOG = 379365266L; + private final Context mContext; private final DialogInterface mDialogInterface; protected final Window mWindow; @@ -210,7 +221,8 @@ public class AlertController { mHandler = new ButtonHandler(di); final TypedArray a = context.obtainStyledAttributes(null, - R.styleable.AlertDialog, R.attr.alertDialogStyle, 0); + R.styleable.AlertDialog, getAlertDialogDefStyleAttr(context), + getAlertDialogDefStyleRes()); mAlertDialogLayout = a.getResourceId( R.styleable.AlertDialog_layout, R.layout.alert_dialog); @@ -236,6 +248,28 @@ public class AlertController { window.requestFeature(Window.FEATURE_NO_TITLE); } + private int getAlertDialogDefStyleAttr(Context context) { + sUseWearMaterial3Style = useWearMaterial3Style(context); + if (sUseWearMaterial3Style) { + return 0; + } + return R.attr.alertDialogStyle; + } + + private int getAlertDialogDefStyleRes() { + if (sUseWearMaterial3Style) { + return com.android.internal.R.style.AlertDialog_DeviceDefault_WearMaterial3; + } + return 0; + } + + private static boolean useWearMaterial3Style(Context context) { + return Flags.useWearMaterial3Ui() + && CompatChanges.isChangeEnabled(WEAR_MATERIAL3_ALERTDIALOG) + && context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH) + && context.getThemeResId() == com.android.internal.R.style.Theme_DeviceDefault; + } + static boolean canTextInput(View v) { if (v.onCheckIsTextEditor()) { return true; diff --git a/core/java/com/android/internal/inputmethod/SoftInputShowHideReason.java b/core/java/com/android/internal/inputmethod/SoftInputShowHideReason.java index eb6a81031321bf5690be8e2ffae7408090257003..429a6a267bb1abe33cc57a6e27c85a90b3a0eed9 100644 --- a/core/java/com/android/internal/inputmethod/SoftInputShowHideReason.java +++ b/core/java/com/android/internal/inputmethod/SoftInputShowHideReason.java @@ -89,6 +89,8 @@ import java.lang.annotation.Retention; SoftInputShowHideReason.SHOW_SOFT_INPUT_IME_TOGGLE_SOFT_INPUT, SoftInputShowHideReason.SHOW_SOFT_INPUT_IMM_DEPRECATION, SoftInputShowHideReason.CONTROL_WINDOW_INSETS_ANIMATION, + SoftInputShowHideReason.SHOW_INPUT_TARGET_CHANGED, + SoftInputShowHideReason.HIDE_INPUT_TARGET_CHANGED, }) public @interface SoftInputShowHideReason { /** Default, undefined reason. */ @@ -336,6 +338,18 @@ public @interface SoftInputShowHideReason { */ int HIDE_WINDOW_LEGACY_DIRECT = ImeProtoEnums.REASON_HIDE_WINDOW_LEGACY_DIRECT; + /** + * Show soft input because the input target changed + * {@link com.android.server.wm.ImeInsetsSourceProvider#onInputTargetChanged}. + */ + int SHOW_INPUT_TARGET_CHANGED = ImeProtoEnums.REASON_SHOW_INPUT_TARGET_CHANGED; + + /** + * Hide soft input because the input target changed by + * {@link com.android.server.wm.ImeInsetsSourceProvider#onInputTargetChanged}. + */ + int HIDE_INPUT_TARGET_CHANGED = ImeProtoEnums.REASON_HIDE_INPUT_TARGET_CHANGED; + /** * Show / Hide soft input by * {@link android.inputmethodservice.InputMethodService#resetStateForNewConfiguration}. diff --git a/core/java/com/android/internal/jank/FrameTracker.java b/core/java/com/android/internal/jank/FrameTracker.java index 2834e68833160ebc90a9f6203d5a90a67250088e..454323b603331ddb0d71f3ca65106843645417db 100644 --- a/core/java/com/android/internal/jank/FrameTracker.java +++ b/core/java/com/android/internal/jank/FrameTracker.java @@ -685,14 +685,6 @@ public class FrameTracker implements HardwareRendererObserver.OnFrameMetricsAvai } } - ThreadedRendererWrapper getThreadedRenderer() { - return mRendererWrapper; - } - - ViewRootWrapper getViewRoot() { - return mViewRoot; - } - private boolean shouldTriggerPerfetto(int missedFramesCount, int maxFrameTimeNanos) { boolean overMissedFramesThreshold = mTraceThresholdMissedFrames != -1 && missedFramesCount >= mTraceThresholdMissedFrames; diff --git a/core/java/com/android/internal/jank/InteractionJankMonitor.java b/core/java/com/android/internal/jank/InteractionJankMonitor.java index ef08e49ce6d9bd1985991d64708019719fef4fcd..26ff43009ef7bb44ec39e9bd65cc0093a5ef32e6 100644 --- a/core/java/com/android/internal/jank/InteractionJankMonitor.java +++ b/core/java/com/android/internal/jank/InteractionJankMonitor.java @@ -31,6 +31,7 @@ import android.annotation.RequiresPermission; import android.annotation.UiThread; import android.annotation.WorkerThread; import android.app.ActivityThread; +import android.app.Application; import android.content.Context; import android.graphics.Color; import android.os.Build; @@ -184,10 +185,12 @@ public class InteractionJankMonitor { @GuardedBy("mLock") private final SparseArray mRunningTrackers = new SparseArray<>(); private final Handler mWorker; + private final Application mCurrentApplication; private final DisplayResolutionTracker mDisplayResolutionTracker; private final Object mLock = new Object(); private @ColorInt int mDebugBgColor = Color.CYAN; private double mDebugYOffset = 0.1; + @GuardedBy("mLock") private InteractionMonitorDebugOverlay mDebugOverlay; private volatile boolean mEnabled = DEFAULT_ENABLED; @@ -216,13 +219,15 @@ public class InteractionJankMonitor { mWorker = worker.getThreadHandler(); mDisplayResolutionTracker = new DisplayResolutionTracker(mWorker); - final Context context = ActivityThread.currentApplication(); - if (context == null || context.checkCallingOrSelfPermission(READ_DEVICE_CONFIG) != PERMISSION_GRANTED) { + mCurrentApplication = ActivityThread.currentApplication(); + if (mCurrentApplication == null || mCurrentApplication.checkCallingOrSelfPermission( + READ_DEVICE_CONFIG) != PERMISSION_GRANTED) { Log.w(TAG, "Initializing without READ_DEVICE_CONFIG permission." + " enabled=" + mEnabled + ", interval=" + mSamplingInterval + ", missedFrameThreshold=" + mTraceThresholdMissedFrames + ", frameTimeThreshold=" + mTraceThresholdFrameTimeMillis - + ", package=" + (context == null ? "null" : context.getPackageName())); + + ", package=" + (mCurrentApplication == null ? "null" + : mCurrentApplication.getPackageName())); return; } @@ -234,8 +239,8 @@ public class InteractionJankMonitor { new HandlerExecutor(mWorker), this::updateProperties); } catch (SecurityException ex) { Log.d(TAG, "Can't get properties: READ_DEVICE_CONFIG granted=" - + context.checkCallingOrSelfPermission(READ_DEVICE_CONFIG) - + ", package=" + context.getPackageName()); + + mCurrentApplication.checkCallingOrSelfPermission(READ_DEVICE_CONFIG) + + ", package=" + mCurrentApplication.getPackageName()); } }); } @@ -405,7 +410,11 @@ public class InteractionJankMonitor { RunningTracker tracker = putTrackerIfNoCurrent(cujType, () -> new RunningTracker( - conf, createFrameTracker(conf), () -> cancel(cujType, REASON_CANCEL_TIMEOUT))); + conf, createFrameTracker(conf), () -> { + Log.w(TAG, "CUJ cancelled due to timeout, CUJ=" + + Cuj.getNameOfCuj(cujType)); + cancel(cujType, REASON_CANCEL_TIMEOUT); + })); if (tracker == null) { return false; } @@ -534,7 +543,7 @@ public class InteractionJankMonitor { mRunningTrackers.put(cuj, tracker); if (mDebugOverlay != null) { - mDebugOverlay.onTrackerAdded(cuj, tracker); + mDebugOverlay.onTrackerAdded(cuj, tracker.mTracker.hashCode()); } return tracker; @@ -569,7 +578,7 @@ public class InteractionJankMonitor { running.mConfig.getHandler().removeCallbacks(running.mTimeoutAction); mRunningTrackers.remove(cuj); if (mDebugOverlay != null) { - mDebugOverlay.onTrackerRemoved(cuj, reason, mRunningTrackers); + mDebugOverlay.onTrackerRemoved(cuj, reason, tracker.hashCode()); } return false; } @@ -592,14 +601,18 @@ public class InteractionJankMonitor { mEnabled = properties.getBoolean(property, DEFAULT_ENABLED); case SETTINGS_DEBUG_OVERLAY_ENABLED_KEY -> { // Never allow the debug overlay to be used on user builds - boolean debugOverlayEnabled = Build.IS_DEBUGGABLE - && properties.getBoolean(property, DEFAULT_DEBUG_OVERLAY_ENABLED); - if (debugOverlayEnabled && mDebugOverlay == null) { - mDebugOverlay = new InteractionMonitorDebugOverlay( - mLock, mDebugBgColor, mDebugYOffset); - } else if (!debugOverlayEnabled && mDebugOverlay != null) { - mDebugOverlay.dispose(); - mDebugOverlay = null; + if (Build.IS_USER) break; + boolean debugOverlayEnabled = properties.getBoolean(property, + DEFAULT_DEBUG_OVERLAY_ENABLED); + synchronized (mLock) { + if (debugOverlayEnabled && mDebugOverlay == null) { + // Use the worker thread as the UI thread for the debug overlay: + mDebugOverlay = new InteractionMonitorDebugOverlay( + mCurrentApplication, mWorker, mDebugBgColor, mDebugYOffset); + } else if (!debugOverlayEnabled && mDebugOverlay != null) { + mDebugOverlay.dispose(); + mDebugOverlay = null; + } } } default -> Log.w(TAG, "Got a change event for an unknown property: " diff --git a/core/java/com/android/internal/jank/InteractionMonitorDebugOverlay.java b/core/java/com/android/internal/jank/InteractionMonitorDebugOverlay.java index d9cac12c33725e7a150f9e8530caf24e7e7317c2..97f8879d1ff54346598d211364b4a2e293485bcb 100644 --- a/core/java/com/android/internal/jank/InteractionMonitorDebugOverlay.java +++ b/core/java/com/android/internal/jank/InteractionMonitorDebugOverlay.java @@ -16,26 +16,39 @@ package com.android.internal.jank; +import static android.view.Display.DEFAULT_DISPLAY; +import static android.view.Gravity.CENTER; +import static android.view.View.INVISIBLE; +import static android.view.View.VISIBLE; +import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS; +import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY; + import static com.android.internal.jank.FrameTracker.REASON_END_NORMAL; +import android.annotation.AnyThread; import android.annotation.ColorInt; +import android.annotation.NonNull; import android.annotation.UiThread; -import android.app.ActivityThread; +import android.app.Application; import android.content.Context; +import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; -import android.graphics.RecordingCanvas; +import android.graphics.PixelFormat; import android.graphics.Rect; +import android.hardware.display.DisplayManager; import android.os.Handler; import android.os.Trace; +import android.util.DisplayMetrics; import android.util.Log; -import android.util.SparseArray; -import android.util.SparseIntArray; -import android.view.WindowCallbacks; +import android.view.Display; +import android.view.View; +import android.view.WindowManager; -import com.android.internal.annotations.GuardedBy; import com.android.internal.jank.FrameTracker.Reasons; +import java.util.ArrayList; + /** * An overlay that uses WindowCallbacks to draw the names of all running CUJs to the window * associated with one of the CUJs being tracked. There's no guarantee which window it will @@ -50,236 +63,261 @@ import com.android.internal.jank.FrameTracker.Reasons; *
      • Grey text indicates the CUJ ended normally and is no longer running *
      • Red text with a strikethrough indicates the CUJ was canceled or ended abnormally *
      + * * @hide */ -class InteractionMonitorDebugOverlay implements WindowCallbacks { +class InteractionMonitorDebugOverlay { private static final String TAG = "InteractionMonitorDebug"; private static final int REASON_STILL_RUNNING = -1000; - private final Object mLock; + private static final long HIDE_OVERLAY_DELAY = 2000L; // Sparse array where the key in the CUJ and the value is the session status, or null if // it's currently running - @GuardedBy("mLock") - private final SparseIntArray mRunningCujs = new SparseIntArray(); - private Handler mHandler = null; - private FrameTracker.ViewRootWrapper mViewRoot = null; - private final Paint mDebugPaint; - private final Paint.FontMetrics mDebugFontMetrics; - // Used to display the overlay in a different color and position for different processes. - // Otherwise, two overlays will overlap and be difficult to read. - private final int mBgColor; - private final double mYOffset; - private final String mPackageName; - private static final String TRACK_NAME = "InteractionJankMonitor"; - - InteractionMonitorDebugOverlay(Object lock, @ColorInt int bgColor, double yOffset) { - mLock = lock; - mBgColor = bgColor; - mYOffset = yOffset; - mDebugPaint = new Paint(); - mDebugPaint.setAntiAlias(false); - mDebugFontMetrics = new Paint.FontMetrics(); - final Context context = ActivityThread.currentApplication(); - mPackageName = context == null ? "null" : context.getPackageName(); - } + private final Application mCurrentApplication; + private final Handler mUiThread; + private final DebugOverlayView mDebugOverlayView; + private final WindowManager mWindowManager; + private final ArrayList mRunningCujs = new ArrayList<>(); - @UiThread - void dispose() { - if (mViewRoot != null && mHandler != null) { - mHandler.runWithScissors(() -> mViewRoot.removeWindowCallbacks(this), - InteractionJankMonitor.EXECUTOR_TASK_TIMEOUT); - forceRedraw(); + InteractionMonitorDebugOverlay(@NonNull Application currentApplication, + @NonNull @UiThread Handler uiThread, @ColorInt int bgColor, double yOffset) { + mCurrentApplication = currentApplication; + mUiThread = uiThread; + final Display display = mCurrentApplication.getSystemService( + DisplayManager.class).getDisplay(DEFAULT_DISPLAY); + final Context windowContext = mCurrentApplication.createDisplayContext( + display).createWindowContext(TYPE_SYSTEM_OVERLAY, null /* options */); + mWindowManager = windowContext.getSystemService(WindowManager.class); + + final Rect size = mWindowManager.getCurrentWindowMetrics().getBounds(); + + final WindowManager.LayoutParams lp = new WindowManager.LayoutParams( + WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY, + WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE + | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL + | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH + | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN + | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE, PixelFormat.TRANSLUCENT); + lp.privateFlags |= WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS + | WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION; + + lp.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS; + lp.setFitInsetsTypes(0 /* types */); + lp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_COLOR_SPACE_AGNOSTIC; + + lp.width = size.width(); + lp.height = size.height(); + lp.gravity = CENTER; + lp.setTitle("InteractionMonitorDebugOverlay"); + + if (!mUiThread.getLooper().isCurrentThread()) { + Log.e(TAG, "InteractionMonitorDebugOverlay must be constructed on " + + "InteractionJankMonitor's worker thread"); } - mHandler = null; - mViewRoot = null; - Trace.asyncTraceForTrackEnd(Trace.TRACE_TAG_APP, TRACK_NAME, 0); + mDebugOverlayView = new DebugOverlayView(mCurrentApplication, bgColor, yOffset); + mWindowManager.addView(mDebugOverlayView, lp); } - @UiThread - private boolean attachViewRootIfNeeded(InteractionJankMonitor.RunningTracker tracker) { - FrameTracker.ViewRootWrapper viewRoot = tracker.mTracker.getViewRoot(); - if (mViewRoot == null && viewRoot != null) { - // Add a trace marker so we can identify traces that were captured while the debug - // overlay was enabled. Traces that use the debug overlay should NOT be used for - // performance analysis. - Trace.asyncTraceForTrackBegin(Trace.TRACE_TAG_APP, TRACK_NAME, "DEBUG_OVERLAY_DRAW", 0); - mHandler = tracker.mConfig.getHandler(); - mViewRoot = viewRoot; - mHandler.runWithScissors(() -> viewRoot.addWindowCallbacks(this), - InteractionJankMonitor.EXECUTOR_TASK_TIMEOUT); - forceRedraw(); - return true; + private final Runnable mHideOverlayRunnable = new Runnable() { + @Override + public void run() { + mRunningCujs.clear(); + mDebugOverlayView.setVisibility(INVISIBLE); } - return false; + }; + + @AnyThread + void onTrackerAdded(@Cuj.CujType int addedCuj, int cookie) { + mUiThread.removeCallbacks(mHideOverlayRunnable); + mUiThread.post(() -> { + String cujName = Cuj.getNameOfCuj(addedCuj); + Log.i(TAG, cujName + " started (cookie=" + cookie + ")"); + mRunningCujs.add(new TrackerState(addedCuj, cookie)); + mDebugOverlayView.setVisibility(VISIBLE); + mDebugOverlayView.invalidate(); + }); } - @GuardedBy("mLock") - private float getWidthOfLongestCujName(int cujFontSize) { - mDebugPaint.setTextSize(cujFontSize); - float maxLength = 0; - for (int i = 0; i < mRunningCujs.size(); i++) { - String cujName = Cuj.getNameOfCuj(mRunningCujs.keyAt(i)); - float textLength = mDebugPaint.measureText(cujName); - if (textLength > maxLength) { - maxLength = textLength; + @AnyThread + void onTrackerRemoved(@Cuj.CujType int removedCuj, @Reasons int reason, int cookie) { + mUiThread.post(() -> { + TrackerState foundTracker = null; + boolean allTrackersEnded = true; + for (int i = 0; i < mRunningCujs.size(); i++) { + TrackerState tracker = mRunningCujs.get(i); + if (tracker.mCuj == removedCuj && tracker.mCookie == cookie) { + foundTracker = tracker; + } else { + // If none of the trackers have REASON_STILL_RUNNING status, then + // all CUJs have ended + allTrackersEnded = allTrackersEnded && tracker.mState != REASON_STILL_RUNNING; + } } - } - return maxLength; - } - private float getTextHeight(int textSize) { - mDebugPaint.setTextSize(textSize); - mDebugPaint.getFontMetrics(mDebugFontMetrics); - return mDebugFontMetrics.descent - mDebugFontMetrics.ascent; + if (foundTracker != null) { + foundTracker.mState = reason; + } + + String cujName = Cuj.getNameOfCuj(removedCuj); + Log.i(TAG, cujName + (reason == REASON_END_NORMAL ? " ended" : " cancelled") + + " (cookie=" + cookie + ")"); + + if (allTrackersEnded) { + Log.i(TAG, "All CUJs ended"); + mUiThread.postDelayed(mHideOverlayRunnable, HIDE_OVERLAY_DELAY); + } + mDebugOverlayView.invalidate(); + }); } - private int dipToPx(int dip) { - if (mViewRoot != null) { - return mViewRoot.dipToPx(dip); - } else { - return dip; - } + @AnyThread + void dispose() { + mUiThread.post(() -> { + mWindowManager.removeView(mDebugOverlayView); + }); } - @UiThread - private void forceRedraw() { - if (mViewRoot != null && mHandler != null) { - mHandler.runWithScissors(() -> { - mViewRoot.requestInvalidateRootRenderNode(); - mViewRoot.getView().invalidate(); - }, InteractionJankMonitor.EXECUTOR_TASK_TIMEOUT); + @AnyThread + private static class TrackerState { + final int mCookie; + final int mCuj; + int mState; + + private TrackerState(int cuj, int cookie) { + mCuj = cuj; + mCookie = cookie; + // Use REASON_STILL_RUNNING (not technically one of the '@Reasons') to indicate the CUJ + // is still running + mState = REASON_STILL_RUNNING; } } @UiThread - void onTrackerRemoved(@Cuj.CujType int removedCuj, @Reasons int reason, - SparseArray runningTrackers) { - synchronized (mLock) { - mRunningCujs.put(removedCuj, reason); - boolean isLoggable = Log.isLoggable(TAG, Log.DEBUG); - if (isLoggable) { - String cujName = Cuj.getNameOfCuj(removedCuj); - Log.d(TAG, cujName + (reason == REASON_END_NORMAL ? " ended" : " cancelled")); - } - // If REASON_STILL_RUNNING is not in mRunningCujs, then all CUJs have ended - if (mRunningCujs.indexOfValue(REASON_STILL_RUNNING) < 0) { - if (isLoggable) Log.d(TAG, "All CUJs ended"); - mRunningCujs.clear(); - dispose(); - } else { - boolean needsNewViewRoot = true; - if (mViewRoot != null) { - // Check to see if this viewroot is still associated with one of the running - // trackers - for (int i = 0; i < runningTrackers.size(); i++) { - if (mViewRoot.equals( - runningTrackers.valueAt(i).mTracker.getViewRoot())) { - needsNewViewRoot = false; - break; - } - } - } - if (needsNewViewRoot) { - dispose(); - for (int i = 0; i < runningTrackers.size(); i++) { - if (attachViewRootIfNeeded(runningTrackers.valueAt(i))) { - break; - } - } - } else { - forceRedraw(); - } - } + private class DebugOverlayView extends View { + private static final String TRACK_NAME = "InteractionJankMonitor"; + + // Used to display the overlay in a different color and position for different processes. + // Otherwise, two overlays will overlap and be difficult to read. + private final int mBgColor; + private final double mYOffset; + + private final float mDensity; + private final Paint mDebugPaint; + private final Paint.FontMetrics mDebugFontMetrics; + private final String mPackageNameText; + + final int mPadding; + final int mPackageNameFontSize; + final int mCujFontSize; + final float mCujNameTextHeight; + final float mCujStatusWidth; + final float mPackageNameTextHeight; + final float mPackageNameWidth; + + private DebugOverlayView(Context context, @ColorInt int bgColor, double yOffset) { + super(context); + setVisibility(INVISIBLE); + mBgColor = bgColor; + mYOffset = yOffset; + final DisplayMetrics displayMetrics = getContext().getResources().getDisplayMetrics(); + mDensity = displayMetrics.density; + mDebugPaint = new Paint(); + mDebugPaint.setAntiAlias(false); + mDebugFontMetrics = new Paint.FontMetrics(); + mPackageNameText = "package:" + mCurrentApplication.getPackageName(); + mPadding = dipToPx(5); + mPackageNameFontSize = dipToPx(12); + mCujFontSize = dipToPx(18); + mCujNameTextHeight = getTextHeight(mCujFontSize); + mCujStatusWidth = mCujNameTextHeight * 1.2f; + mPackageNameTextHeight = getTextHeight(mPackageNameFontSize); + mPackageNameWidth = getWidthOfText(mPackageNameText, mPackageNameFontSize); } - } - @UiThread - void onTrackerAdded(@Cuj.CujType int addedCuj, InteractionJankMonitor.RunningTracker tracker) { - if (Log.isLoggable(TAG, Log.DEBUG)) { - String cujName = Cuj.getNameOfCuj(addedCuj); - Log.d(TAG, cujName + " started"); + private int dipToPx(int dip) { + return (int) (mDensity * dip + 0.5f); } - synchronized (mLock) { - // Use REASON_STILL_RUNNING (not technically one of the '@Reasons') to indicate the CUJ - // is still running - mRunningCujs.put(addedCuj, REASON_STILL_RUNNING); - attachViewRootIfNeeded(tracker); - forceRedraw(); + + private float getTextHeight(int textSize) { + mDebugPaint.setTextSize(textSize); + mDebugPaint.getFontMetrics(mDebugFontMetrics); + return mDebugFontMetrics.descent - mDebugFontMetrics.ascent; } - } - @Override - public void onWindowSizeIsChanging(Rect newBounds, boolean fullscreen, - Rect systemInsets, Rect stableInsets) { - } + private float getWidthOfText(String text, int fontSize) { + mDebugPaint.setTextSize(fontSize); + return mDebugPaint.measureText(text); + } - @Override - public void onWindowDragResizeStart(Rect initialBounds, boolean fullscreen, - Rect systemInsets, Rect stableInsets) { - } + private float getWidthOfLongestCujName(int cujFontSize) { + mDebugPaint.setTextSize(cujFontSize); + float maxLength = 0; + for (int i = 0; i < mRunningCujs.size(); i++) { + String cujName = Cuj.getNameOfCuj(mRunningCujs.get(i).mCuj); + float textLength = mDebugPaint.measureText(cujName); + if (textLength > maxLength) { + maxLength = textLength; + } + } + return maxLength; + } - @Override - public void onWindowDragResizeEnd() { - } + @Override + protected void onDraw(@NonNull Canvas canvas) { + super.onDraw(canvas); - @Override - public boolean onContentDrawn(int offsetX, int offsetY, int sizeX, int sizeY) { - return false; - } + // Add a trace marker so we can identify traces that were captured while the debug + // overlay was enabled. Traces that use the debug overlay should NOT be used for + // performance analysis. + Trace.asyncTraceForTrackBegin(Trace.TRACE_TAG_APP, TRACK_NAME, "DEBUG_OVERLAY_DRAW", 0); - @Override - public void onRequestDraw(boolean reportNextDraw) { - } + final int h = getHeight(); + final int w = getWidth(); + final int dy = (int) (h * mYOffset); - @Override - public void onPostDraw(RecordingCanvas canvas) { - final int padding = dipToPx(5); - final int h = canvas.getHeight(); - final int w = canvas.getWidth(); - // Draw sysui CUjs near the bottom of the screen so they don't overlap with the shade, - // and draw launcher CUJs near the top of the screen so they don't overlap with gestures - final int dy = (int) (h * mYOffset); - int packageNameFontSize = dipToPx(12); - int cujFontSize = dipToPx(18); - final float cujNameTextHeight = getTextHeight(cujFontSize); - final float packageNameTextHeight = getTextHeight(packageNameFontSize); - - synchronized (mLock) { - float maxLength = getWidthOfLongestCujName(cujFontSize); + float maxLength = Math.max(mPackageNameWidth, getWidthOfLongestCujName(mCujFontSize)) + + mCujStatusWidth; final int dx = (int) ((w - maxLength) / 2f); canvas.translate(dx, dy); // Draw background rectangle for displaying the text showing the CUJ name mDebugPaint.setColor(mBgColor); - canvas.drawRect( - -padding * 2, // more padding on top so we can draw the package name - -padding, - padding * 2 + maxLength, - padding * 2 + packageNameTextHeight + cujNameTextHeight * mRunningCujs.size(), - mDebugPaint); - mDebugPaint.setTextSize(packageNameFontSize); + canvas.drawRect(-mPadding * 2, // more padding on top so we can draw the package name + -mPadding, mPadding * 2 + maxLength, mPadding * 2 + mPackageNameTextHeight + + mCujNameTextHeight * mRunningCujs.size(), mDebugPaint); + mDebugPaint.setTextSize(mPackageNameFontSize); mDebugPaint.setColor(Color.BLACK); mDebugPaint.setStrikeThruText(false); - canvas.translate(0, packageNameTextHeight); - canvas.drawText("package:" + mPackageName, 0, 0, mDebugPaint); - mDebugPaint.setTextSize(cujFontSize); + canvas.translate(0, mPackageNameTextHeight); + canvas.drawText(mPackageNameText, 0, 0, mDebugPaint); + mDebugPaint.setTextSize(mCujFontSize); // Draw text for CUJ names for (int i = 0; i < mRunningCujs.size(); i++) { - int status = mRunningCujs.valueAt(i); - if (status == REASON_STILL_RUNNING) { - mDebugPaint.setColor(Color.BLACK); - mDebugPaint.setStrikeThruText(false); - } else if (status == REASON_END_NORMAL) { - mDebugPaint.setColor(Color.GRAY); - mDebugPaint.setStrikeThruText(false); - } else { - // Cancelled, or otherwise ended for a bad reason - mDebugPaint.setColor(Color.RED); - mDebugPaint.setStrikeThruText(true); - } - String cujName = Cuj.getNameOfCuj(mRunningCujs.keyAt(i)); - canvas.translate(0, cujNameTextHeight); - canvas.drawText(cujName, 0, 0, mDebugPaint); + TrackerState tracker = mRunningCujs.get(i); + int status = tracker.mState; + String statusText = switch (status) { + case REASON_STILL_RUNNING -> { + mDebugPaint.setColor(Color.BLACK); + mDebugPaint.setStrikeThruText(false); + yield "☐"; // BALLOT BOX + } + case REASON_END_NORMAL -> { + mDebugPaint.setColor(Color.GRAY); + mDebugPaint.setStrikeThruText(false); + yield "✅"; // WHITE HEAVY CHECK MARK + } + default -> { + // Cancelled, or otherwise ended for a bad reason + mDebugPaint.setColor(Color.RED); + mDebugPaint.setStrikeThruText(true); + yield "❌"; // CROSS MARK + } + }; + String cujName = Cuj.getNameOfCuj(tracker.mCuj); + canvas.translate(0, mCujNameTextHeight); + canvas.drawText(statusText, 0, 0, mDebugPaint); + canvas.drawText(cujName, mCujStatusWidth, 0, mDebugPaint); } + Trace.asyncTraceForTrackEnd(Trace.TRACE_TAG_APP, TRACK_NAME, 0); } } } diff --git a/core/java/com/android/internal/os/Zygote.java b/core/java/com/android/internal/os/Zygote.java index fafa08536d6c35c6b3d19a6fda1a040971968559..cd17ed89058a1072618fcedda21623d27247fa81 100644 --- a/core/java/com/android/internal/os/Zygote.java +++ b/core/java/com/android/internal/os/Zygote.java @@ -201,6 +201,9 @@ public final class Zygote { */ public static final int DEBUG_ENABLE_PTRACE = 1 << 25; + /** Load 4KB ELF files on 16KB device using appcompat mode */ + public static final int ENABLE_PAGE_SIZE_APP_COMPAT = 1 << 26; + /** No external storage should be mounted. */ public static final int MOUNT_EXTERNAL_NONE = IVold.REMOUNT_MODE_NONE; /** Default external storage should be mounted. */ diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java index e402ddfc637ae8fb78954b46d6da8cfc58f4906b..e60879e02b4b4cff8ba83c6ba4e9564794d761b4 100644 --- a/core/java/com/android/internal/os/ZygoteInit.java +++ b/core/java/com/android/internal/os/ZygoteInit.java @@ -19,6 +19,8 @@ package com.android.internal.os; import static android.system.OsConstants.S_IRWXG; import static android.system.OsConstants.S_IRWXO; +import static android.net.http.Flags.preloadHttpengineInZygote; + import static com.android.internal.util.FrameworkStatsLog.BOOT_TIME_EVENT_ELAPSED_TIME__EVENT__SECONDARY_ZYGOTE_INIT_START; import static com.android.internal.util.FrameworkStatsLog.BOOT_TIME_EVENT_ELAPSED_TIME__EVENT__ZYGOTE_INIT_START; @@ -27,6 +29,7 @@ import android.compat.annotation.UnsupportedAppUsage; import android.content.pm.SharedLibraryInfo; import android.content.res.Resources; import android.os.Build; +import android.net.http.HttpEngine; import android.os.Environment; import android.os.IInstalld; import android.os.Process; @@ -144,6 +147,23 @@ public class ZygoteInit { Trace.traceEnd(Trace.TRACE_TAG_DALVIK); preloadSharedLibraries(); preloadTextResources(); + + // TODO: remove the try/catch and the flag read as soon as the flag is ramped and 25Q2 + // starts building from source. + if (preloadHttpengineInZygote()) { + try { + HttpEngine.preload(); + } catch (NoSuchMethodError e){ + // The flag protecting this API is not an exported + // flag because ZygoteInit happens before the + // system service has initialized the flag which means + // that we can't query the real value of the flag + // from the tethering module. In order to avoid crashing + // in the case where we have (new zygote, old tethering). + // we catch the NoSuchMethodError and just log. + Log.d(TAG, "HttpEngine.preload() threw " + e); + } + } // Ask the WebViewFactory to do any initialization that must run in the zygote process, // for memory sharing purposes. WebViewFactory.prepareWebViewInZygote(); 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 0f93e6e8109bf0e4dfcc7810e57798af4cb7e7fe..c160b42f8b6bb563a3f639a123488dcd059bb523 100644 --- a/core/java/com/android/internal/pm/pkg/parsing/ParsingPackageUtils.java +++ b/core/java/com/android/internal/pm/pkg/parsing/ParsingPackageUtils.java @@ -29,6 +29,7 @@ import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_UNEXPECTED_ import static android.os.Build.VERSION_CODES.DONUT; import static android.os.Build.VERSION_CODES.O; import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER; +import static android.sdk.Flags.majorMinorVersioningScheme; import static com.android.internal.pm.pkg.parsing.ParsingUtils.parseKnownActivityEmbeddingCerts; @@ -1689,6 +1690,21 @@ public class ParsingPackageUtils { targetCode = minCode; } + if (majorMinorVersioningScheme()) { + val = sa.peekValue(R.styleable.AndroidManifestUsesSdk_minSdkVersionFull); + if (val != null) { + if (val.type == TypedValue.TYPE_STRING && val.string != null) { + String minSdkVersionFullString = val.string.toString(); + ParseResult minSdkVersionFullResult = + FrameworkParsingPackageUtils.verifyMinSdkVersionFull( + minSdkVersionFullString, Build.VERSION.SDK_INT_FULL, input); + if (minSdkVersionFullResult.isError()) { + return input.error(minSdkVersionFullResult); + } + } + } + } + if (isApkInApex) { val = sa.peekValue(R.styleable.AndroidManifestUsesSdk_maxSdkVersion); if (val != null) { diff --git a/core/java/com/android/internal/widget/ConversationLayout.java b/core/java/com/android/internal/widget/ConversationLayout.java index 2bfbf843b2aba764432f210b28121aa9e1af3d54..4b90420a75eecdaefccc2e0a98958aaaf69ea3ee 100644 --- a/core/java/com/android/internal/widget/ConversationLayout.java +++ b/core/java/com/android/internal/widget/ConversationLayout.java @@ -16,6 +16,7 @@ package com.android.internal.widget; +import static android.app.Flags.notificationsRedesignTemplates; import static android.widget.flags.Flags.conversationLayoutUseMaximumChildHeight; import static com.android.internal.widget.MessagingGroup.IMAGE_DISPLAY_LOCATION_EXTERNAL; @@ -692,7 +693,7 @@ public class ConversationLayout extends FrameLayout } private void updateActionListPadding() { - if (mActions != null) { + if (!notificationsRedesignTemplates() && mActions != null) { mActions.setCollapsibleIndentDimen(R.dimen.call_notification_collapsible_indent); } } diff --git a/core/java/com/android/internal/widget/MessagingGroup.java b/core/java/com/android/internal/widget/MessagingGroup.java index 97a2d3beda90143d9bc508bf7646599e1e331ca4..4305ba753e46e656c8f4484fe8276ab5eabae46c 100644 --- a/core/java/com/android/internal/widget/MessagingGroup.java +++ b/core/java/com/android/internal/widget/MessagingGroup.java @@ -261,7 +261,7 @@ public class MessagingGroup extends NotificationOptimizedLinearLayout implements MessagingGroup createdGroup = sInstancePool.acquire(); if (createdGroup == null) { createdGroup = (MessagingGroup) LayoutInflater.from(layout.getContext()).inflate( - R.layout.notification_template_messaging_group, layout, + getMessagingGroupLayoutResource(), layout, false); createdGroup.addOnLayoutChangeListener(MessagingLayout.MESSAGING_PROPERTY_ANIMATOR); } @@ -269,6 +269,14 @@ public class MessagingGroup extends NotificationOptimizedLinearLayout implements return createdGroup; } + private static int getMessagingGroupLayoutResource() { + if (Flags.notificationsRedesignTemplates()) { + return R.layout.notification_2025_messaging_group; + } else { + return R.layout.notification_template_messaging_group; + } + } + public void removeMessage(MessagingMessage messagingMessage, ArrayList toRecycle) { View view = messagingMessage.getView(); diff --git a/core/java/com/android/internal/widget/NotificationActionListLayout.java b/core/java/com/android/internal/widget/NotificationActionListLayout.java index 301dc392c125e5c19935a420a324fd3c0af75797..cac2024f548d365d0d0c764e3a846b286bb34971 100644 --- a/core/java/com/android/internal/widget/NotificationActionListLayout.java +++ b/core/java/com/android/internal/widget/NotificationActionListLayout.java @@ -20,6 +20,7 @@ import static android.app.Notification.CallStyle.DEBUG_NEW_ACTION_LAYOUT; import static android.app.Flags.evenlyDividedCallStyleActionLayout; import android.annotation.DimenRes; +import android.app.Flags; import android.app.Notification; import android.content.Context; import android.content.res.TypedArray; @@ -58,7 +59,7 @@ public class NotificationActionListLayout extends LinearLayout { private int mEmphasizedPaddingBottom; private int mEmphasizedHeight; private int mRegularHeight; - @DimenRes private int mCollapsibleIndentDimen = R.dimen.notification_actions_padding_start; + @DimenRes private int mCollapsibleIndentDimen; int mNumNotGoneChildren; int mNumPriorityChildren; @@ -73,6 +74,10 @@ public class NotificationActionListLayout extends LinearLayout { public NotificationActionListLayout(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); + mCollapsibleIndentDimen = Flags.notificationsRedesignTemplates() + ? R.dimen.notification_2025_actions_margin_start + : R.dimen.notification_actions_padding_start; + int[] attrIds = { android.R.attr.gravity }; TypedArray ta = context.obtainStyledAttributes(attrs, attrIds, defStyleAttr, defStyleRes); mGravity = ta.getInt(0, 0); diff --git a/core/java/com/android/internal/widget/remotecompose/core/Operation.java b/core/java/com/android/internal/widget/remotecompose/core/Operation.java index 102003e2e371f84a95d7f0921c8c0f052b8eae85..6f6a0a89296455849f86877430976ba1ad573fa3 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/Operation.java +++ b/core/java/com/android/internal/widget/remotecompose/core/Operation.java @@ -18,19 +18,19 @@ package com.android.internal.widget.remotecompose.core; import android.annotation.NonNull; /** Base interface for RemoteCompose operations */ -public interface Operation { +public abstract class Operation { /** add the operation to the buffer */ - void write(@NonNull WireBuffer buffer); + public abstract void write(@NonNull WireBuffer buffer); /** * paint an operation * * @param context the paint context used to paint the operation */ - void apply(@NonNull RemoteContext context); + public abstract void apply(@NonNull RemoteContext context); /** Debug utility to display an operation + indentation */ @NonNull - String deepToString(@NonNull String indent); + public abstract String deepToString(@NonNull String indent); } diff --git a/core/java/com/android/internal/widget/remotecompose/core/OperationInterface.java b/core/java/com/android/internal/widget/remotecompose/core/OperationInterface.java new file mode 100644 index 0000000000000000000000000000000000000000..741303a40bc918973cc906b5639025c755bcd58e --- /dev/null +++ b/core/java/com/android/internal/widget/remotecompose/core/OperationInterface.java @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.internal.widget.remotecompose.core; + +import android.annotation.NonNull; + +/** Base interface for RemoteCompose operations */ +public interface OperationInterface { + + /** add the operation to the buffer */ + void write(@NonNull WireBuffer buffer); + + /** + * paint an operation + * + * @param context the paint context used to paint the operation + */ + void apply(@NonNull RemoteContext context); + + /** Debug utility to display an operation + indentation */ + @NonNull + String deepToString(@NonNull String indent); +} diff --git a/core/java/com/android/internal/widget/remotecompose/core/Operations.java b/core/java/com/android/internal/widget/remotecompose/core/Operations.java index 687a99baff83c5b0334157697204e9ff2ce24a54..006fe3afb4d81d45feabc1e518bfa186cd8ffa6a 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/Operations.java +++ b/core/java/com/android/internal/widget/remotecompose/core/Operations.java @@ -55,7 +55,10 @@ import com.android.internal.widget.remotecompose.core.operations.MatrixSkew; import com.android.internal.widget.remotecompose.core.operations.MatrixTranslate; import com.android.internal.widget.remotecompose.core.operations.NamedVariable; import com.android.internal.widget.remotecompose.core.operations.PaintData; +import com.android.internal.widget.remotecompose.core.operations.PathAppend; +import com.android.internal.widget.remotecompose.core.operations.PathCreate; import com.android.internal.widget.remotecompose.core.operations.PathData; +import com.android.internal.widget.remotecompose.core.operations.PathTween; import com.android.internal.widget.remotecompose.core.operations.RootContentBehavior; import com.android.internal.widget.remotecompose.core.operations.RootContentDescription; import com.android.internal.widget.remotecompose.core.operations.ShaderData; @@ -178,6 +181,9 @@ public class Operations { public static final int TEXT_MEASURE = 155; public static final int TEXT_LENGTH = 156; public static final int TOUCH_EXPRESSION = 157; + public static final int PATH_TWEEN = 158; + public static final int PATH_CREATE = 159; + public static final int PATH_ADD = 160; ///////////////////////////////////////// ====================== @@ -353,5 +359,8 @@ public class Operations { map.put(TEXT_MEASURE, TextMeasure::read); map.put(TEXT_LENGTH, TextLength::read); map.put(TOUCH_EXPRESSION, TouchExpression::read); + map.put(PATH_TWEEN, PathTween::read); + map.put(PATH_CREATE, PathCreate::read); + map.put(PATH_ADD, PathAppend::read); } } diff --git a/core/java/com/android/internal/widget/remotecompose/core/PaintContext.java b/core/java/com/android/internal/widget/remotecompose/core/PaintContext.java index 38b08e9b0ab352de1c62b77a29bde19847354a29..7ecd11826303e9e8fa41c89f59a61319cba44403 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/PaintContext.java +++ b/core/java/com/android/internal/widget/remotecompose/core/PaintContext.java @@ -157,6 +157,8 @@ public abstract class PaintContext { public abstract void drawTweenPath( int path1Id, int path2Id, float tween, float start, float stop); + public abstract void tweenPath(int out, int path1, int path2, float tween); + /** * This applies changes to the current paint * diff --git a/core/java/com/android/internal/widget/remotecompose/core/PaintOperation.java b/core/java/com/android/internal/widget/remotecompose/core/PaintOperation.java index 9999182b53fc8bb85bdb7b61996d2044f7fae56f..cfdd52212b03c9521f04005c3ec6446b057f8430 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/PaintOperation.java +++ b/core/java/com/android/internal/widget/remotecompose/core/PaintOperation.java @@ -21,7 +21,7 @@ import android.annotation.NonNull; * PaintOperation interface, used for operations aimed at painting (while any operation _can_ paint, * this make it a little more explicit) */ -public abstract class PaintOperation implements Operation { +public abstract class PaintOperation extends Operation { @Override public void apply(@NonNull RemoteContext context) { diff --git a/core/java/com/android/internal/widget/remotecompose/core/RemoteComposeBuffer.java b/core/java/com/android/internal/widget/remotecompose/core/RemoteComposeBuffer.java index c05079e3450524fc9032a549690772ede6818abf..3a5d68db8a3787f2c8b3e8453f297c07d348c594 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/RemoteComposeBuffer.java +++ b/core/java/com/android/internal/widget/remotecompose/core/RemoteComposeBuffer.java @@ -59,7 +59,10 @@ import com.android.internal.widget.remotecompose.core.operations.MatrixSkew; import com.android.internal.widget.remotecompose.core.operations.MatrixTranslate; import com.android.internal.widget.remotecompose.core.operations.NamedVariable; import com.android.internal.widget.remotecompose.core.operations.PaintData; +import com.android.internal.widget.remotecompose.core.operations.PathAppend; +import com.android.internal.widget.remotecompose.core.operations.PathCreate; import com.android.internal.widget.remotecompose.core.operations.PathData; +import com.android.internal.widget.remotecompose.core.operations.PathTween; import com.android.internal.widget.remotecompose.core.operations.RootContentBehavior; import com.android.internal.widget.remotecompose.core.operations.RootContentDescription; import com.android.internal.widget.remotecompose.core.operations.TextData; @@ -643,6 +646,37 @@ public class RemoteComposeBuffer { addDrawPath(id); } + /** + * interpolate the two paths to produce a 3rd + * + * @param pid1 the first path + * @param pid2 the second path + * @param tween path is the path1+(pat2-path1)*tween + * @return id of the tweened path + */ + public int pathTween(int pid1, int pid2, float tween) { + int out = mRemoteComposeState.nextId(); + PathTween.apply(mBuffer, out, pid1, pid2, tween); + return out; + } + + /** + * Create a path with an initial moveTo + * + * @param x x coordinate of the moveto + * @param y y coordinate of the moveto + * @return id of the created path + */ + public int pathCreate(float x, float y) { + int out = mRemoteComposeState.nextId(); + PathCreate.apply(mBuffer, out, x, y); + return out; + } + + public void pathAppend(int id, float... path) { + PathAppend.apply(mBuffer, id, path); + } + /** * Draw the specified path * @@ -1153,6 +1187,16 @@ public class RemoteComposeBuffer { return Utils.asNan(id); } + /** + * Reserve a float and returns a NaN number pointing to that float + * + * @return the nan id of float + */ + public float reserveFloatVariable() { + int id = mRemoteComposeState.cacheFloat(0f); + return Utils.asNan(id); + } + /** * Add a Integer return an id number pointing to that float. * @@ -1651,8 +1695,8 @@ public class RemoteComposeBuffer { */ public void addModifierScroll(int direction, float positionId, int notches) { // TODO: add support for non-notch behaviors etc. - float max = this.addFloat(0f); - float notchMax = this.addFloat(0f); + float max = this.reserveFloatVariable(); + float notchMax = this.reserveFloatVariable(); float touchExpressionDirection = direction != 0 ? RemoteContext.FLOAT_TOUCH_POS_X : RemoteContext.FLOAT_TOUCH_POS_Y; this.addTouchExpression( @@ -1807,8 +1851,8 @@ public class RemoteComposeBuffer { ClipRectModifierOperation.apply(mBuffer); } - public void addLoopStart(float count, float from, float step, int indexId) { - LoopOperation.apply(mBuffer, count, from, step, indexId); + public void addLoopStart(int indexId, float from, float step, float until) { + LoopOperation.apply(mBuffer, indexId, from, step, until); } public void addLoopEnd() { diff --git a/core/java/com/android/internal/widget/remotecompose/core/RemoteComposeOperation.java b/core/java/com/android/internal/widget/remotecompose/core/RemoteComposeOperation.java index e60695fc4a06a6c05d637c32e88c00942a18a959..97487e6d27149906d0da34eb010b8632c02b1464 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/RemoteComposeOperation.java +++ b/core/java/com/android/internal/widget/remotecompose/core/RemoteComposeOperation.java @@ -15,4 +15,4 @@ */ package com.android.internal.widget.remotecompose.core; -public interface RemoteComposeOperation extends Operation {} +public interface RemoteComposeOperation {} diff --git a/core/java/com/android/internal/widget/remotecompose/core/RemoteComposeState.java b/core/java/com/android/internal/widget/remotecompose/core/RemoteComposeState.java index a903e6ee1f27878f495b010ad94b0c3800646091..f5f9e214723b8785f332763069a2fd2997244e70 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/RemoteComposeState.java +++ b/core/java/com/android/internal/widget/remotecompose/core/RemoteComposeState.java @@ -131,6 +131,16 @@ public class RemoteComposeState implements CollectionsAccess { } } + private final IntMap mPathData = new IntMap<>(); + + public void putPathData(int id, float[] data) { + mPathData.put(id, data); + } + + public float[] getPathData(int id) { + return mPathData.get(id); + } + /** * Adds a data Override. * diff --git a/core/java/com/android/internal/widget/remotecompose/core/RemoteContext.java b/core/java/com/android/internal/widget/remotecompose/core/RemoteContext.java index 26305bf124f7f01bae3d42bd63a807085a90b92b..6eb8463ab308aa25f1340f322210b74fba7f4491 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/RemoteContext.java +++ b/core/java/com/android/internal/widget/remotecompose/core/RemoteContext.java @@ -93,11 +93,19 @@ public abstract class RemoteContext { /** * Load a path under an id. Paths can be use in clip drawPath and drawTweenPath * - * @param instanceId - * @param floatPath + * @param instanceId the id to save this path under + * @param floatPath the path as a float array */ public abstract void loadPathData(int instanceId, @NonNull float[] floatPath); + /** + * Load a path under an id. Paths can be use in clip drawPath and drawTweenPath + * + * @param instanceId + * @return the a + */ + public abstract @Nullable float[] getPathData(int instanceId); + /** * Associate a name with a give id. * diff --git a/core/java/com/android/internal/widget/remotecompose/core/WireBuffer.java b/core/java/com/android/internal/widget/remotecompose/core/WireBuffer.java index a64b706fea3bef35a67c026ea7fc72d71dcdec98..2f1502cd59c7bb81ca348da76b7000892977dbba 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/WireBuffer.java +++ b/core/java/com/android/internal/widget/remotecompose/core/WireBuffer.java @@ -28,11 +28,17 @@ public class WireBuffer { int mStartingIndex = 0; int mSize = 0; + /** + * Create a wire buffer + * + * @param size the initial size of the buffer + */ public WireBuffer(int size) { mMaxSize = size; mBuffer = new byte[mMaxSize]; } + /** Create a wire buffer of default size */ public WireBuffer() { this(BUFFER_SIZE); } @@ -44,37 +50,74 @@ public class WireBuffer { } } + /** + * get the wire buffer's underlying byte array. Note the array will be bigger that the used + * portion + * + * @return byte array of the wire buffer + */ public @NonNull byte[] getBuffer() { return mBuffer; } + /** + * The current mix size of the buffer + * + * @return max size + */ public int getMax_size() { return mMaxSize; } + /** + * The current point in the buffer which will be written to + * + * @return index pointing into the buffer + */ public int getIndex() { return mIndex; } + /** + * The size of the buffer + * + * @return the size of the buffer + */ public int getSize() { return mSize; } + /** + * Reposition the pointer + * + * @param index the new position of the index + */ public void setIndex(int index) { this.mIndex = index; } + /** + * Write a byte representing the command into the buffer + * + * @param type the command id + */ public void start(int type) { mStartingIndex = mIndex; writeByte(type); } + /** + * Unused Todo remove? + * + * @param type the type of object to write + */ public void startWithSize(int type) { mStartingIndex = mIndex; writeByte(type); mIndex += 4; // skip ahead for the future size } + /** Unused Todo remove? */ public void endWithSize() { int size = mIndex - mStartingIndex; int currentIndex = mIndex; @@ -97,10 +140,20 @@ public class WireBuffer { } } + /** + * return the size of the buffer todo rename to getSize + * + * @return the size of the buffer + */ public int size() { return mSize; } + /** + * Bytes available + * + * @return the size - index + */ public boolean available() { return mSize - mIndex > 0; } @@ -109,28 +162,53 @@ public class WireBuffer { // Read values /////////////////////////////////////////////////////////////////////////// + /** + * read the operation type (reads a single byte) + * + * @return the byte cast to an integer + */ public int readOperationType() { return readByte(); } + /** + * Read a boolean (stored as a byte 1 = true) + * + * @return boolean of the byte + */ public boolean readBoolean() { byte value = mBuffer[mIndex]; mIndex++; return (value == 1); } + /** + * read a single byte byte + * + * @return byte from 0..255 as an Integer + */ public int readByte() { int value = 0xFF & mBuffer[mIndex]; mIndex++; return value; } + /** + * read a short [byte n] << 8 | [byte n+1]; index increast by 2 + * + * @return return a short cast as an integer + */ public int readShort() { int v1 = (mBuffer[mIndex++] & 0xFF) << 8; int v2 = (mBuffer[mIndex++] & 0xFF) << 0; return v1 + v2; } + /** + * Read an integer without incrementing the index + * + * @return the integer + */ public int peekInt() { int tmp = mIndex; int v1 = (mBuffer[tmp++] & 0xFF) << 24; @@ -140,6 +218,11 @@ public class WireBuffer { return v1 + v2 + v3 + v4; } + /** + * Read an integer. index increased by 4 + * + * @return integer + */ public int readInt() { int v1 = (mBuffer[mIndex++] & 0xFF) << 24; int v2 = (mBuffer[mIndex++] & 0xFF) << 16; @@ -148,6 +231,11 @@ public class WireBuffer { return v1 + v2 + v3 + v4; } + /** + * Read a long index is increased by 8 + * + * @return long + */ public long readLong() { long v1 = (mBuffer[mIndex++] & 0xFFL) << 56; long v2 = (mBuffer[mIndex++] & 0xFFL) << 48; @@ -160,14 +248,30 @@ public class WireBuffer { return v1 + v2 + v3 + v4 + v5 + v6 + v7 + v8; } + /** + * Read a 32 bit float IEEE standard index is increased by 4 + * + * @return the float + */ public float readFloat() { return java.lang.Float.intBitsToFloat(readInt()); } + /** + * Read a 64 bit double index is increased by 8 + * + * @return double + */ public double readDouble() { return java.lang.Double.longBitsToDouble(readLong()); } + /** + * Read a byte buffer bytes are encoded as 4 byte length followed by length bytes index is + * increased by 4 + number of bytes + * + * @return byte array + */ public @NonNull byte[] readBuffer() { int count = readInt(); byte[] b = Arrays.copyOfRange(mBuffer, mIndex, mIndex + count); @@ -175,6 +279,13 @@ public class WireBuffer { return b; } + /** + * Read a byte buffer limited to max size. bytes are encoded as 4 byte length followed by length + * bytes index is increased by 4 + number of bytes Throw an exception if the read excedes the + * max size. This is the preferred form of read buffer. + * + * @return byte array + */ public @NonNull byte[] readBuffer(int maxSize) { int count = readInt(); if (count < 0 || count > maxSize) { @@ -186,12 +297,23 @@ public class WireBuffer { return b; } + /** + * Read a string encoded in UTF8 The buffer is red with readBuffer and converted to a String + * + * @return unicode string + */ @NonNull public String readUTF8() { byte[] stringBuffer = readBuffer(); return new String(stringBuffer); } + /** + * Read a string encoded in UTF8 The buffer is red with readBuffer and converted to a String + * This is the preferred readUTF8 because it catches errors + * + * @return unicode string + */ @NonNull public String readUTF8(int maxSize) { byte[] stringBuffer = readBuffer(maxSize); @@ -202,18 +324,33 @@ public class WireBuffer { // Write values /////////////////////////////////////////////////////////////////////////// + /** + * Write a boolean value. (written as a byte 1=true) + * + * @param value value to write + */ public void writeBoolean(boolean value) { resize(1); mBuffer[mIndex++] = (byte) (value ? 1 : 0); mSize++; } + /** + * Write a byte value + * + * @param value value to write + */ public void writeByte(int value) { resize(1); mBuffer[mIndex++] = (byte) value; mSize++; } + /** + * Write a short value + * + * @param value value to write + */ public void writeShort(int value) { int need = 2; resize(need); @@ -222,6 +359,11 @@ public class WireBuffer { mSize += need; } + /** + * Write a int (4 byte) value + * + * @param value value to write + */ public void writeInt(int value) { int need = 4; resize(need); @@ -232,6 +374,11 @@ public class WireBuffer { mSize += need; } + /** + * Write a long (8 byte) value + * + * @param value value to write + */ public void writeLong(long value) { int need = 8; resize(need); @@ -246,14 +393,29 @@ public class WireBuffer { mSize += need; } + /** + * Write a 32 bit IEEE float value + * + * @param value value to write + */ public void writeFloat(float value) { writeInt(Float.floatToRawIntBits(value)); } + /** + * Write a 64 bit IEEE double value + * + * @param value value to write + */ public void writeDouble(double value) { writeLong(Double.doubleToRawLongBits(value)); } + /** + * Write a buffer The buffer length is first written followed by the bytes + * + * @param b array of bytes write + */ public void writeBuffer(@NonNull byte[] b) { resize(b.length + 4); writeInt(b.length); @@ -263,6 +425,11 @@ public class WireBuffer { mSize += b.length; } + /** + * Write a string is encoded as UTF8 + * + * @param content the string to write + */ public void writeUTF8(@NonNull String content) { byte[] buffer = content.getBytes(); writeBuffer(buffer); diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/BitmapData.java b/core/java/com/android/internal/widget/remotecompose/core/operations/BitmapData.java index 948007699b80804eab84f65a5109b238b43df1b7..27ba6528a703b94934348171bb04ccda8f9ebd24 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/BitmapData.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/BitmapData.java @@ -36,7 +36,7 @@ import java.util.List; * Operation to deal with bitmap data On getting an Image during a draw call the bitmap is * compressed and saved in playback the image is decompressed */ -public class BitmapData implements Operation, SerializableToString { +public class BitmapData extends Operation implements SerializableToString { private static final int OP_CODE = Operations.DATA_BITMAP; private static final String CLASS_NAME = "BitmapData"; int mImageId; @@ -85,6 +85,11 @@ public class BitmapData implements Operation, SerializableToString { return CLASS_NAME; } + /** + * The OP_CODE for this command + * + * @return the opcode + */ public static int id() { return OP_CODE; } @@ -119,6 +124,12 @@ public class BitmapData implements Operation, SerializableToString { buffer.writeBuffer(bitmap); } + /** + * Read this operation and add it to the list of operations + * + * @param buffer the buffer to read + * @param operations the list of operations that will be added to + */ public static void read(@NonNull WireBuffer buffer, @NonNull List operations) { int imageId = buffer.readInt(); int width = buffer.readInt(); @@ -133,6 +144,11 @@ public class BitmapData implements Operation, SerializableToString { operations.add(new BitmapData(imageId, width, height, bitmap)); } + /** + * Populate the documentation with a description of this operation + * + * @param doc to append the description to. + */ public static void documentation(@NonNull DocumentationBuilder doc) { doc.operation("Data Operations", OP_CODE, CLASS_NAME) .description("Bitmap data") diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/ClickArea.java b/core/java/com/android/internal/widget/remotecompose/core/operations/ClickArea.java index 310b194ec4860b6943ed40f140d96e4ec88887ac..5e5e5653053fc5eecc192f8644869cc844f950eb 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/ClickArea.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/ClickArea.java @@ -28,7 +28,7 @@ import com.android.internal.widget.remotecompose.core.documentation.DocumentedOp import java.util.List; /** Add a click area to the document */ -public class ClickArea implements RemoteComposeOperation { +public class ClickArea extends Operation implements RemoteComposeOperation { private static final int OP_CODE = Operations.CLICK_AREA; private static final String CLASS_NAME = "ClickArea"; int mId; @@ -118,6 +118,11 @@ public class ClickArea implements RemoteComposeOperation { return CLASS_NAME; } + /** + * The OP_CODE for this command + * + * @return the opcode + */ public static int id() { return OP_CODE; } @@ -141,6 +146,12 @@ public class ClickArea implements RemoteComposeOperation { buffer.writeInt(metadata); } + /** + * Read this operation and add it to the list of operations + * + * @param buffer the buffer to read + * @param operations the list of operations that will be added to + */ public static void read(@NonNull WireBuffer buffer, @NonNull List operations) { int id = buffer.readInt(); int contentDescription = buffer.readInt(); @@ -154,6 +165,11 @@ public class ClickArea implements RemoteComposeOperation { operations.add(clickArea); } + /** + * Populate the documentation with a description of this operation + * + * @param doc to append the description to. + */ public static void documentation(@NonNull DocumentationBuilder doc) { doc.operation("Canvas Operations", OP_CODE, CLASS_NAME) .description("Define a region you can click on") diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/ClipPath.java b/core/java/com/android/internal/widget/remotecompose/core/operations/ClipPath.java index db93829586bbda7e478a9bf5e60c39925bad7f80..2fe56d3ec935a0510d2e95eaaac16a3f50b439f7 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/ClipPath.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/ClipPath.java @@ -69,6 +69,12 @@ public class ClipPath extends PaintOperation { return "ClipPath " + mId + ";"; } + /** + * Read this operation and add it to the list of operations + * + * @param buffer the buffer to read + * @param operations the list of operations that will be added to + */ public static void read(@NonNull WireBuffer buffer, @NonNull List operations) { int pack = buffer.readInt(); int id = pack & 0xFFFFF; @@ -82,6 +88,11 @@ public class ClipPath extends PaintOperation { return CLASS_NAME; } + /** + * The OP_CODE for this command + * + * @return the opcode + */ public static int id() { return OP_CODE; } @@ -91,6 +102,11 @@ public class ClipPath extends PaintOperation { buffer.writeInt(id); } + /** + * Populate the documentation with a description of this operation + * + * @param doc to append the description to. + */ public static void documentation(@NonNull DocumentationBuilder doc) { doc.operation("Canvas Operations", OP_CODE, CLASS_NAME) .description("Intersect the current clip with the path") diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/ClipRect.java b/core/java/com/android/internal/widget/remotecompose/core/operations/ClipRect.java index df54fb1ed834d5235583ff19a9769ff77e9670ef..defa656b44e6c79c8a6d6314d57ba34486d2fa66 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/ClipRect.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/ClipRect.java @@ -31,11 +31,22 @@ public class ClipRect extends DrawBase4 { public static final int OP_CODE = Operations.CLIP_RECT; public static final String CLASS_NAME = "ClipRect"; + /** + * Read this operation and add it to the list of operations + * + * @param buffer the buffer to read + * @param operations the list of operations that will be added to + */ public static void read(@NonNull WireBuffer buffer, @NonNull List operations) { Maker m = ClipRect::new; read(m, buffer, operations); } + /** + * The OP_CODE for this command + * + * @return the opcode + */ public static int id() { return OP_CODE; } @@ -50,6 +61,11 @@ public class ClipRect extends DrawBase4 { apply(buffer, v1, v2, v3, v4); } + /** + * Populate the documentation with a description of this operation + * + * @param doc to append the description to. + */ public static void documentation(@NonNull DocumentationBuilder doc) { doc.operation("Expressions Operations", OP_CODE, CLASS_NAME) .description("Intersect the current clip with rectangle") diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/ColorConstant.java b/core/java/com/android/internal/widget/remotecompose/core/operations/ColorConstant.java index 34e93f590dbe30fe52c1e40cc81f49937526f16d..d86576dd99f239a8a5778c6b599b9494b12b0934 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/ColorConstant.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/ColorConstant.java @@ -29,12 +29,22 @@ import com.android.internal.widget.remotecompose.core.documentation.DocumentedOp import java.util.List; /** Operation that defines a simple Color based on ID Mainly for colors in theming. */ -public class ColorConstant implements Operation { +public class ColorConstant extends Operation { private static final int OP_CODE = Operations.COLOR_CONSTANT; private static final String CLASS_NAME = "ColorConstant"; + + /** the id of the color */ public int mColorId; + + /** the color value (AARRGGBB) */ public int mColor; + /** + * Creat a color constant + * + * @param colorId id of color + * @param color AARRGGBB value + */ public ColorConstant(int colorId, int color) { this.mColorId = colorId; this.mColor = color; @@ -56,6 +66,11 @@ public class ColorConstant implements Operation { return CLASS_NAME; } + /** + * The OP_CODE for this command + * + * @return the opcode + */ public static int id() { return OP_CODE; } @@ -73,12 +88,23 @@ public class ColorConstant implements Operation { buffer.writeInt(color); } + /** + * Read this operation and add it to the list of operations + * + * @param buffer the buffer to read + * @param operations the list of operations that will be added to + */ public static void read(@NonNull WireBuffer buffer, @NonNull List operations) { int colorId = buffer.readInt(); int color = buffer.readInt(); operations.add(new ColorConstant(colorId, color)); } + /** + * Populate the documentation with a description of this operation + * + * @param doc to append the description to. + */ public static void documentation(@NonNull DocumentationBuilder doc) { doc.operation("Expressions Operations", OP_CODE, CLASS_NAME) .description("Define a Color") diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/ColorExpression.java b/core/java/com/android/internal/widget/remotecompose/core/operations/ColorExpression.java index c947d1139a2ebe9b48a7bf50200010dcc1bf7eb4..66f128f8f478bc283be5a7d07df3a5a9a67593bf 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/ColorExpression.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/ColorExpression.java @@ -34,7 +34,7 @@ import java.util.List; * Operation to Colors Color modes mMode = 0 two colors and a tween mMode = 1 color1 is a colorID. * mMode = 2 color2 is a colorID. mMode = 3 color1 & color2 are ids mMode = 4 H S V mode */ -public class ColorExpression implements Operation, VariableSupport { +public class ColorExpression extends Operation implements VariableSupport { private static final int OP_CODE = Operations.COLOR_EXPRESSIONS; private static final String CLASS_NAME = "ColorExpression"; public int mId; @@ -204,6 +204,11 @@ public class ColorExpression implements Operation, VariableSupport { return CLASS_NAME; } + /** + * The OP_CODE for this command + * + * @return the opcode + */ public static int id() { return OP_CODE; } @@ -228,6 +233,12 @@ public class ColorExpression implements Operation, VariableSupport { buffer.writeFloat(tween); } + /** + * Read this operation and add it to the list of operations + * + * @param buffer the buffer to read + * @param operations the list of operations that will be added to + */ public static void read(@NonNull WireBuffer buffer, @NonNull List operations) { int id = buffer.readInt(); int mode = buffer.readInt(); @@ -238,6 +249,11 @@ public class ColorExpression implements Operation, VariableSupport { operations.add(new ColorExpression(id, mode, color1, color2, tween)); } + /** + * Populate the documentation with a description of this operation + * + * @param doc to append the description to. + */ public static void documentation(@NonNull DocumentationBuilder doc) { doc.operation("Expressions Operations", OP_CODE, CLASS_NAME) .description("A Color defined by an expression") diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/ComponentValue.java b/core/java/com/android/internal/widget/remotecompose/core/operations/ComponentValue.java index b0ccd1871fd2197a1de8d6438eab65c885bc0625..19c219bc0121aef8fcdc11b8072c29dc4b5db23a 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/ComponentValue.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/ComponentValue.java @@ -30,7 +30,7 @@ import com.android.internal.widget.remotecompose.core.operations.utilities.Strin import java.util.List; -public class ComponentValue implements Operation, SerializableToString { +public class ComponentValue extends Operation implements SerializableToString { public static final int OP_CODE = Operations.COMPONENT_VALUE; public static final String CLASS_NAME = "ComponentValue"; @@ -41,6 +41,11 @@ public class ComponentValue implements Operation, SerializableToString { private int mComponentID = -1; private int mValueId = -1; + /** + * The OP_CODE for this command + * + * @return the opcode + */ public static int id() { return OP_CODE; } @@ -78,6 +83,12 @@ public class ComponentValue implements Operation, SerializableToString { // Nothing } + /** + * Read this operation and add it to the list of operations + * + * @param buffer the buffer to read + * @param operations the list of operations that will be added to + */ public static void read(@NonNull WireBuffer buffer, @NonNull List operations) { int type = buffer.readInt(); int componentId = buffer.readInt(); @@ -86,6 +97,11 @@ public class ComponentValue implements Operation, SerializableToString { operations.add(op); } + /** + * Populate the documentation with a description of this operation + * + * @param doc to append the description to. + */ public static void documentation(@NonNull DocumentationBuilder doc) { doc.operation("Expressions Operations", OP_CODE, CLASS_NAME) .description("Encode a component-related value (eg its width, height etc.)") diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/DataListFloat.java b/core/java/com/android/internal/widget/remotecompose/core/operations/DataListFloat.java index bfaf139da21baa5b24d999e5d3cb98b66c98e2cb..ac6271c6328e98fd9a6f62dadf886719a9509e90 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/DataListFloat.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/DataListFloat.java @@ -32,7 +32,7 @@ import com.android.internal.widget.remotecompose.core.operations.utilities.Array import java.util.Arrays; import java.util.List; -public class DataListFloat implements VariableSupport, ArrayAccess, Operation { +public class DataListFloat extends Operation implements VariableSupport, ArrayAccess { private static final int OP_CODE = Operations.FLOAT_LIST; private static final String CLASS_NAME = "IdListData"; private final int mId; @@ -79,6 +79,12 @@ public class DataListFloat implements VariableSupport, ArrayAccess, Operation { } } + /** + * Read this operation and add it to the list of operations + * + * @param buffer the buffer to read + * @param operations the list of operations that will be added to + */ public static void read(@NonNull WireBuffer buffer, @NonNull List operations) { int id = buffer.readInt(); int len = buffer.readInt(); @@ -93,6 +99,11 @@ public class DataListFloat implements VariableSupport, ArrayAccess, Operation { operations.add(data); } + /** + * Populate the documentation with a description of this operation + * + * @param doc to append the description to. + */ public static void documentation(@NonNull DocumentationBuilder doc) { doc.operation("Data Operations", OP_CODE, CLASS_NAME) .description("a list of Floats") diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/DataListIds.java b/core/java/com/android/internal/widget/remotecompose/core/operations/DataListIds.java index 9b286b94d553ec6a755254143bb00634767b1aae..47cbff36d4925e6d89afc739b61ab40c5b81a724 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/DataListIds.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/DataListIds.java @@ -33,7 +33,7 @@ import com.android.internal.widget.remotecompose.core.operations.utilities.Array import java.util.Arrays; import java.util.List; -public class DataListIds implements VariableSupport, ArrayAccess, Operation { +public class DataListIds extends Operation implements VariableSupport, ArrayAccess { private static final int OP_CODE = Operations.ID_LIST; private static final String CLASS_NAME = "IdListData"; private final int mId; @@ -71,6 +71,12 @@ public class DataListIds implements VariableSupport, ArrayAccess, Operation { } } + /** + * Read this operation and add it to the list of operations + * + * @param buffer the buffer to read + * @param operations the list of operations that will be added to + */ public static void read(@NonNull WireBuffer buffer, @NonNull List operations) { int id = buffer.readInt(); int len = buffer.readInt(); @@ -85,6 +91,11 @@ public class DataListIds implements VariableSupport, ArrayAccess, Operation { operations.add(data); } + /** + * Populate the documentation with a description of this operation + * + * @param doc to append the description to. + */ public static void documentation(@NonNull DocumentationBuilder doc) { doc.operation("Data Operations", OP_CODE, CLASS_NAME) .description("a list of id's") diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/DataMapIds.java b/core/java/com/android/internal/widget/remotecompose/core/operations/DataMapIds.java index 643afc85e69f5bc4e66ee9c121897307c5ca6b2c..e888074cda746e0cd28c14b073bd556849612e43 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/DataMapIds.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/DataMapIds.java @@ -31,7 +31,7 @@ import com.android.internal.widget.remotecompose.core.operations.utilities.DataM import java.util.List; /** This is a map of strings to type & Id */ -public class DataMapIds implements Operation { +public class DataMapIds extends Operation { private static final int OP_CODE = Operations.ID_MAP; private static final String CLASS_NAME = "DataMapIds"; int mId; @@ -105,6 +105,12 @@ public class DataMapIds implements Operation { } } + /** + * Read this operation and add it to the list of operations + * + * @param buffer the buffer to read + * @param operations the list of operations that will be added to + */ public static void read(@NonNull WireBuffer buffer, @NonNull List operations) { int id = buffer.readInt(); int len = buffer.readInt(); diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/DataMapLookup.java b/core/java/com/android/internal/widget/remotecompose/core/operations/DataMapLookup.java index eae532c1434417971816739d4ca88d9974c15dad..9af2343a5fa46fcdb1e4479e1c7dbfc134c13056 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/DataMapLookup.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/DataMapLookup.java @@ -31,7 +31,7 @@ import com.android.internal.widget.remotecompose.core.types.LongConstant; import java.util.List; /** This can lookup in a map given a string writing the results to an id. */ -public class DataMapLookup implements Operation { +public class DataMapLookup extends Operation { private static final int OP_CODE = Operations.DATA_MAP_LOOKUP; private static final String CLASS_NAME = "DataMapLookup"; public int mId; @@ -109,12 +109,17 @@ public class DataMapLookup implements Operation { operations.add(new DataMapLookup(id, mapId, stringId)); } + /** + * Populate the documentation with a description of this operation + * + * @param doc to append the description to. + */ public static void documentation(@NonNull DocumentationBuilder doc) { doc.operation("Expressions Operations", OP_CODE, CLASS_NAME) - .description("A float and its associated id") + .description("Look up a value in a data map") .field(INT, "id", "id of float") .field(INT, "dataMapId", "32-bit float value") - .field(INT, "value", "32-bit float value"); + .field(INT, "stringId", "32-bit float value"); } @Override diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawArc.java b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawArc.java index 629f78647079760946d234c08805e31e79a0aa4b..3f95f02747f900687f5f74eb6d1f31d040d795be 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawArc.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawArc.java @@ -30,11 +30,22 @@ public class DrawArc extends DrawBase6 { public static final int OP_CODE = Operations.DRAW_ARC; private static final String CLASS_NAME = "DrawArc"; + /** + * Read this operation and add it to the list of operations + * + * @param buffer the buffer to read + * @param operations the list of operations that will be added to + */ public static void read(@NonNull WireBuffer buffer, @NonNull List operations) { Maker m = DrawArc::new; read(m, buffer, operations); } + /** + * The OP_CODE for this command + * + * @return the opcode + */ public static int id() { return OP_CODE; } @@ -79,6 +90,11 @@ public class DrawArc extends DrawBase6 { apply(buffer, v1, v2, v3, v4, v5, v6); } + /** + * Populate the documentation with a description of this operation + * + * @param doc to append the description to. + */ public static void documentation(@NonNull DocumentationBuilder doc) { doc.operation("Canvas Operations", OP_CODE, CLASS_NAME) .description( diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawBitmap.java b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawBitmap.java index 9c23c95599533e99ee8681c69e655c796b33700a..69f5cc52a78af8e4b8215328f75fce76c430c493 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawBitmap.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawBitmap.java @@ -100,15 +100,21 @@ public class DrawBitmap extends PaintOperation implements VariableSupport { + ";"; } + /** + * Read this operation and add it to the list of operations + * + * @param buffer the buffer to read + * @param operations the list of operations that will be added to + */ public static void read(@NonNull WireBuffer buffer, @NonNull List operations) { int id = buffer.readInt(); float sLeft = buffer.readFloat(); float srcTop = buffer.readFloat(); float srcRight = buffer.readFloat(); float srcBottom = buffer.readFloat(); - int discriptionId = buffer.readInt(); + int descriptionId = buffer.readInt(); - DrawBitmap op = new DrawBitmap(id, sLeft, srcTop, srcRight, srcBottom, discriptionId); + DrawBitmap op = new DrawBitmap(id, sLeft, srcTop, srcRight, srcBottom, descriptionId); operations.add(op); } @@ -117,6 +123,11 @@ public class DrawBitmap extends PaintOperation implements VariableSupport { return CLASS_NAME; } + /** + * The OP_CODE for this command + * + * @return the opcode + */ public static int id() { return OP_CODE; } @@ -138,6 +149,11 @@ public class DrawBitmap extends PaintOperation implements VariableSupport { buffer.writeInt(descriptionId); } + /** + * Populate the documentation with a description of this operation + * + * @param doc to append the description to. + */ public static void documentation(@NonNull DocumentationBuilder doc) { doc.operation("Draw Operations", OP_CODE, CLASS_NAME) .description("Draw a bitmap") diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawBitmapInt.java b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawBitmapInt.java index da9fe247bced4a62b6017e4d777fa0c51a48fad8..66646d7c2faa50214e614f3f4ff7871290703c6c 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawBitmapInt.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawBitmapInt.java @@ -111,6 +111,11 @@ public class DrawBitmapInt extends PaintOperation { return CLASS_NAME; } + /** + * The OP_CODE for this command + * + * @return the opcode + */ public static int id() { return OP_CODE; } @@ -140,6 +145,12 @@ public class DrawBitmapInt extends PaintOperation { buffer.writeInt(cdId); } + /** + * Read this operation and add it to the list of operations + * + * @param buffer the buffer to read + * @param operations the list of operations that will be added to + */ public static void read(@NonNull WireBuffer buffer, @NonNull List operations) { int imageId = buffer.readInt(); int sLeft = buffer.readInt(); diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawBitmapScaled.java b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawBitmapScaled.java index e9f81d52d67fa5bb246fa07da5100910e7d37414..170148608ab357e6e78e2055167108c8e3e2b1c6 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawBitmapScaled.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawBitmapScaled.java @@ -196,6 +196,11 @@ public class DrawBitmapScaled extends PaintOperation implements VariableSupport return CLASS_NAME; } + /** + * The OP_CODE for this command + * + * @return the opcode + */ public static int id() { return OP_CODE; } @@ -232,6 +237,12 @@ public class DrawBitmapScaled extends PaintOperation implements VariableSupport buffer.writeInt(cdId); } + /** + * Read this operation and add it to the list of operations + * + * @param buffer the buffer to read + * @param operations the list of operations that will be added to + */ public static void read(@NonNull WireBuffer buffer, @NonNull List operations) { int imageId = buffer.readInt(); @@ -265,6 +276,11 @@ public class DrawBitmapScaled extends PaintOperation implements VariableSupport operations.add(op); } + /** + * Populate the documentation with a description of this operation + * + * @param doc to append the description to. + */ public static void documentation(@NonNull DocumentationBuilder doc) { doc.operation("Draw Operations", OP_CODE, CLASS_NAME) .description("Draw a bitmap using integer coordinates") diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawCircle.java b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawCircle.java index 11bd49a4a6514fa04e02f4591dac02dea6552437..e6aecdbf8bbe4d723806b8e467c434d4830e532d 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawCircle.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawCircle.java @@ -30,11 +30,22 @@ public class DrawCircle extends DrawBase3 { private static final int OP_CODE = Operations.DRAW_CIRCLE; private static final String CLASS_NAME = "DrawCircle"; + /** + * Read this operation and add it to the list of operations + * + * @param buffer the buffer to read + * @param operations the list of operations that will be added to + */ public static void read(@NonNull WireBuffer buffer, @NonNull List operations) { Maker m = DrawCircle::new; read(m, buffer, operations); } + /** + * The OP_CODE for this command + * + * @return the opcode + */ public static int id() { return OP_CODE; } @@ -44,6 +55,11 @@ public class DrawCircle extends DrawBase3 { return CLASS_NAME; } + /** + * Populate the documentation with a description of this operation + * + * @param doc to append the description to. + */ public static void documentation(@NonNull DocumentationBuilder doc) { doc.operation("Canvas Operations", OP_CODE, CLASS_NAME) .description("Draw a Circle") diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawLine.java b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawLine.java index 7310a9defba64bcb2884055a0272ac5c012b22f1..04f32642d5fa85ef41798c38679cc715c4675531 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawLine.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawLine.java @@ -32,11 +32,22 @@ public class DrawLine extends DrawBase4 implements SerializableToString { private static final int OP_CODE = Operations.DRAW_LINE; private static final String CLASS_NAME = "DrawLine"; + /** + * Read this operation and add it to the list of operations + * + * @param buffer the buffer to read + * @param operations the list of operations that will be added to + */ public static void read(@NonNull WireBuffer buffer, @NonNull List operations) { Maker m = DrawLine::new; read(m, buffer, operations); } + /** + * The OP_CODE for this command + * + * @return the opcode + */ public static int id() { return OP_CODE; } @@ -46,6 +57,11 @@ public class DrawLine extends DrawBase4 implements SerializableToString { return CLASS_NAME; } + /** + * Populate the documentation with a description of this operation + * + * @param doc to append the description to. + */ public static void documentation(@NonNull DocumentationBuilder doc) { doc.operation("Canvas Operations", OP_CODE, CLASS_NAME) .description("Draw a line segment") diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawOval.java b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawOval.java index aa5116e950c591f46e456f257b98e6df382ae8fb..0a50042b11c7f1033c8ccd1436908500425fb30c 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawOval.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawOval.java @@ -30,11 +30,22 @@ public class DrawOval extends DrawBase4 { private static final int OP_CODE = Operations.DRAW_OVAL; private static final String CLASS_NAME = "DrawOval"; + /** + * Read this operation and add it to the list of operations + * + * @param buffer the buffer to read + * @param operations the list of operations that will be added to + */ public static void read(@NonNull WireBuffer buffer, @NonNull List operations) { Maker m = DrawOval::new; read(m, buffer, operations); } + /** + * The OP_CODE for this command + * + * @return the opcode + */ public static int id() { return OP_CODE; } @@ -44,6 +55,11 @@ public class DrawOval extends DrawBase4 { return CLASS_NAME; } + /** + * Populate the documentation with a description of this operation + * + * @param doc to append the description to. + */ public static void documentation(@NonNull DocumentationBuilder doc) { doc.operation("Canvas Operations", OP_CODE, CLASS_NAME) .description("Draw the specified oval") diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawPath.java b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawPath.java index d35094b0b3511a5a8f90c019c946d48abf6f6071..41b8243f070f94813717d8e9bac47b4f3383ffd4 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawPath.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawPath.java @@ -50,6 +50,12 @@ public class DrawPath extends PaintOperation { return "DrawPath " + "[" + mId + "]" + ", " + mStart + ", " + mEnd; } + /** + * Read this operation and add it to the list of operations + * + * @param buffer the buffer to read + * @param operations the list of operations that will be added to + */ public static void read(@NonNull WireBuffer buffer, @NonNull List operations) { int id = buffer.readInt(); DrawPath op = new DrawPath(id); @@ -61,6 +67,11 @@ public class DrawPath extends PaintOperation { return CLASS_NAME; } + /** + * The OP_CODE for this command + * + * @return the opcode + */ public static int id() { return Operations.DRAW_PATH; } @@ -70,6 +81,11 @@ public class DrawPath extends PaintOperation { buffer.writeInt(id); } + /** + * Populate the documentation with a description of this operation + * + * @param doc to append the description to. + */ public static void documentation(@NonNull DocumentationBuilder doc) { doc.operation("Draw Operations", OP_CODE, CLASS_NAME) .description("Draw a bitmap using integer coordinates") diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawRect.java b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawRect.java index db7633cbe3355f6f974e2211106932bf94b55958..7e22550d654465eac50693e47fa8fbfa7f247923 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawRect.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawRect.java @@ -31,11 +31,22 @@ public class DrawRect extends DrawBase4 { private static final int OP_CODE = Operations.DRAW_RECT; private static final String CLASS_NAME = "DrawRect"; + /** + * Read this operation and add it to the list of operations + * + * @param buffer the buffer to read + * @param operations the list of operations that will be added to + */ public static void read(@NonNull WireBuffer buffer, @NonNull List operations) { Maker m = DrawRect::new; read(m, buffer, operations); } + /** + * The OP_CODE for this command + * + * @return the opcode + */ public static int id() { return OP_CODE; } @@ -45,6 +56,11 @@ public class DrawRect extends DrawBase4 { return CLASS_NAME; } + /** + * Populate the documentation with a description of this operation + * + * @param doc to append the description to. + */ public static void documentation(@NonNull DocumentationBuilder doc) { doc.operation("Canvas Operations", OP_CODE, CLASS_NAME) .description("Draw the specified rectangle") diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawRoundRect.java b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawRoundRect.java index c306e2b5f0411c53ada979b6a70800639d0554e8..a41e46e035065e8558d15079311b138205f3e2af 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawRoundRect.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawRoundRect.java @@ -31,11 +31,22 @@ public class DrawRoundRect extends DrawBase6 { private static final int OP_CODE = Operations.DRAW_ROUND_RECT; private static final String CLASS_NAME = "DrawRoundRect"; + /** + * Read this operation and add it to the list of operations + * + * @param buffer the buffer to read + * @param operations the list of operations that will be added to + */ public static void read(@NonNull WireBuffer buffer, @NonNull List operations) { Maker m = DrawRoundRect::new; read(m, buffer, operations); } + /** + * The OP_CODE for this command + * + * @return the opcode + */ public static int id() { return OP_CODE; } @@ -80,6 +91,11 @@ public class DrawRoundRect extends DrawBase6 { apply(buffer, v1, v2, v3, v4, v5, v6); } + /** + * Populate the documentation with a description of this operation + * + * @param doc to append the description to. + */ public static void documentation(@NonNull DocumentationBuilder doc) { doc.operation("Canvas Operations", OP_CODE, CLASS_NAME) .description("Draw the specified round-rect") diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawSector.java b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawSector.java index 3b60df7d529e2cd12e6d302f37a97c2bf4dcdc67..7616df09b6cc03106fac085d0d0e9c2312bbceb9 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawSector.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawSector.java @@ -30,11 +30,22 @@ public class DrawSector extends DrawBase6 { public static final int OP_CODE = Operations.DRAW_SECTOR; private static final String CLASS_NAME = "DrawSector"; + /** + * Read this operation and add it to the list of operations + * + * @param buffer the buffer to read + * @param operations the list of operations that will be added to + */ public static void read(@NonNull WireBuffer buffer, @NonNull List operations) { Maker m = DrawSector::new; read(m, buffer, operations); } + /** + * The OP_CODE for this command + * + * @return the opcode + */ public static int id() { return OP_CODE; } @@ -79,6 +90,11 @@ public class DrawSector extends DrawBase6 { apply(buffer, v1, v2, v3, v4, v5, v6); } + /** + * Populate the documentation with a description of this operation + * + * @param doc to append the description to. + */ public static void documentation(@NonNull DocumentationBuilder doc) { doc.operation("Canvas Operations", OP_CODE, CLASS_NAME) .description( diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawText.java b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawText.java index 9c587aba3f7bcc6ac9761556a398b0c8239fb65d..2c5d790b2f2a1563131bb1f5b19b97958a391db5 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawText.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawText.java @@ -101,6 +101,12 @@ public class DrawText extends PaintOperation implements VariableSupport { + floatToString(mY, mOutY); } + /** + * Read this operation and add it to the list of operations + * + * @param buffer the buffer to read + * @param operations the list of operations that will be added to + */ public static void read(@NonNull WireBuffer buffer, @NonNull List operations) { int text = buffer.readInt(); int start = buffer.readInt(); @@ -120,6 +126,11 @@ public class DrawText extends PaintOperation implements VariableSupport { return CLASS_NAME; } + /** + * The OP_CODE for this command + * + * @return the opcode + */ public static int id() { return OP_CODE; } @@ -158,6 +169,11 @@ public class DrawText extends PaintOperation implements VariableSupport { buffer.writeBoolean(rtl); } + /** + * Populate the documentation with a description of this operation + * + * @param doc to append the description to. + */ public static void documentation(@NonNull DocumentationBuilder doc) { doc.operation("Draw Operations", id(), CLASS_NAME) .description("Draw a run of text, all in a single direction") diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawTextAnchored.java b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawTextAnchored.java index 8b7018191f4de0cf000b31fe6df736f792bdf986..7de52b8e5f3e9dd4955ccf973144e8ba077027a2 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawTextAnchored.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawTextAnchored.java @@ -111,6 +111,12 @@ public class DrawTextAnchored extends PaintOperation implements VariableSupport return Float.toString(v); } + /** + * Read this operation and add it to the list of operations + * + * @param buffer the buffer to read + * @param operations the list of operations that will be added to + */ public static void read(@NonNull WireBuffer buffer, @NonNull List operations) { int textID = buffer.readInt(); float x = buffer.readFloat(); @@ -129,6 +135,11 @@ public class DrawTextAnchored extends PaintOperation implements VariableSupport return CLASS_NAME; } + /** + * The OP_CODE for this command + * + * @return the opcode + */ public static int id() { return OP_CODE; } @@ -161,6 +172,11 @@ public class DrawTextAnchored extends PaintOperation implements VariableSupport buffer.writeInt(flags); } + /** + * Populate the documentation with a description of this operation + * + * @param doc to append the description to. + */ public static void documentation(@NonNull DocumentationBuilder doc) { doc.operation("Draw Operations", OP_CODE, CLASS_NAME) .description("Draw text centered about an anchor point") diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawTextOnPath.java b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawTextOnPath.java index e90122bb95accf781f28aa272511cdb5c5bc14f6..18d9fdf1b671b775584662e1d88ef24583ede619 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawTextOnPath.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawTextOnPath.java @@ -83,6 +83,12 @@ public class DrawTextOnPath extends PaintOperation implements VariableSupport { + Utils.floatToString(mVOffset, mOutVOffset); } + /** + * Read this operation and add it to the list of operations + * + * @param buffer the buffer to read + * @param operations the list of operations that will be added to + */ public static void read(@NonNull WireBuffer buffer, @NonNull List operations) { int textId = buffer.readInt(); int pathId = buffer.readInt(); @@ -97,6 +103,11 @@ public class DrawTextOnPath extends PaintOperation implements VariableSupport { return "DrawTextOnPath"; } + /** + * The OP_CODE for this command + * + * @return the opcode + */ public static int id() { return Operations.DRAW_TEXT_ON_PATH; } @@ -110,6 +121,11 @@ public class DrawTextOnPath extends PaintOperation implements VariableSupport { buffer.writeFloat(hOffset); } + /** + * Populate the documentation with a description of this operation + * + * @param doc to append the description to. + */ public static void documentation(@NonNull DocumentationBuilder doc) { doc.operation("Draw Operations", OP_CODE, CLASS_NAME) .description("Draw text along path object") diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawTweenPath.java b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawTweenPath.java index 0aaaf42ba838b7b5ba52879ceb4b234d02cd29af..b83e4c2191b2d1cedc7f3cfe2c90fd8781aa021d 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/DrawTweenPath.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/DrawTweenPath.java @@ -92,6 +92,12 @@ public class DrawTweenPath extends PaintOperation implements VariableSupport { + floatToString(mStop, mOutStop); } + /** + * Read this operation and add it to the list of operations + * + * @param buffer the buffer to read + * @param operations the list of operations that will be added to + */ public static void read(@NonNull WireBuffer buffer, @NonNull List operations) { int path1Id = buffer.readInt(); int path2Id = buffer.readInt(); @@ -107,6 +113,11 @@ public class DrawTweenPath extends PaintOperation implements VariableSupport { return "DrawTweenPath"; } + /** + * The OP_CODE for this command + * + * @return the opcode + */ public static int id() { return Operations.DRAW_TWEEN_PATH; } @@ -126,6 +137,11 @@ public class DrawTweenPath extends PaintOperation implements VariableSupport { buffer.writeFloat(stop); } + /** + * Populate the documentation with a description of this operation + * + * @param doc to append the description to. + */ public static void documentation(@NonNull DocumentationBuilder doc) { doc.operation("Draw Operations", OP_CODE, CLASS_NAME) .description("Draw text along path object") diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/FloatConstant.java b/core/java/com/android/internal/widget/remotecompose/core/operations/FloatConstant.java index 17aaf3bb9cd8cc8d247fc32baac6dff8f229293f..7dd435a5c5b1d2d82191734ae1d8cccfe7d60bbb 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/FloatConstant.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/FloatConstant.java @@ -29,7 +29,7 @@ import com.android.internal.widget.remotecompose.core.documentation.DocumentedOp import java.util.List; /** Operation to deal with Text data */ -public class FloatConstant implements com.android.internal.widget.remotecompose.core.Operation { +public class FloatConstant extends Operation { private static final int OP_CODE = Operations.DATA_FLOAT; private static final String CLASS_NAME = "FloatConstant"; public int mTextId; @@ -56,6 +56,11 @@ public class FloatConstant implements com.android.internal.widget.remotecompose. return CLASS_NAME; } + /** + * The OP_CODE for this command + * + * @return the opcode + */ public static int id() { return OP_CODE; } @@ -73,6 +78,12 @@ public class FloatConstant implements com.android.internal.widget.remotecompose. buffer.writeFloat(value); } + /** + * Read this operation and add it to the list of operations + * + * @param buffer the buffer to read + * @param operations the list of operations that will be added to + */ public static void read(@NonNull WireBuffer buffer, @NonNull List operations) { int textId = buffer.readInt(); @@ -80,6 +91,11 @@ public class FloatConstant implements com.android.internal.widget.remotecompose. operations.add(new FloatConstant(textId, value)); } + /** + * Populate the documentation with a description of this operation + * + * @param doc to append the description to. + */ public static void documentation(@NonNull DocumentationBuilder doc) { doc.operation("Expressions Operations", OP_CODE, CLASS_NAME) .description("A float and its associated id") diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/FloatExpression.java b/core/java/com/android/internal/widget/remotecompose/core/operations/FloatExpression.java index eef9746ffaf698be0720d130b0d8b3789ee89777..3d92e129a2367a6e29a6b7dac32ae118a2332530 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/FloatExpression.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/FloatExpression.java @@ -42,7 +42,7 @@ import java.util.List; * like injecting the width of the component int draw rect As well as supporting generalized * animation floats. The floats represent a RPN style calculator */ -public class FloatExpression implements Operation, VariableSupport { +public class FloatExpression extends Operation implements VariableSupport { private static final int OP_CODE = Operations.ANIMATED_FLOAT; private static final String CLASS_NAME = "FloatExpression"; public int mId; @@ -146,16 +146,19 @@ public class FloatExpression implements Operation, VariableSupport { if (Float.isNaN(mLastChange)) { mLastChange = t; } - if (mFloatAnimation != null) { + if (mFloatAnimation != null && !Float.isNaN(mLastCalculatedValue)) { float f = mFloatAnimation.get(t - mLastChange); context.loadFloat(mId, f); } else if (mSpring != null) { float f = mSpring.get(t - mLastChange); context.loadFloat(mId, f); } else { - context.loadFloat( - mId, - mExp.eval(context.getCollectionsAccess(), mPreCalcValue, mPreCalcValue.length)); + float v = + mExp.eval(context.getCollectionsAccess(), mPreCalcValue, mPreCalcValue.length); + if (mFloatAnimation != null) { + mFloatAnimation.setTargetValue(v); + } + context.loadFloat(mId, v); } } @@ -207,6 +210,11 @@ public class FloatExpression implements Operation, VariableSupport { return CLASS_NAME; } + /** + * The OP_CODE for this command + * + * @return the opcode + */ public static int id() { return OP_CODE; } @@ -243,12 +251,18 @@ public class FloatExpression implements Operation, VariableSupport { } } + /** + * Read this operation and add it to the list of operations + * + * @param buffer the buffer to read + * @param operations the list of operations that will be added to + */ public static void read(@NonNull WireBuffer buffer, @NonNull List operations) { int id = buffer.readInt(); int len = buffer.readInt(); int valueLen = len & 0xFFFF; if (valueLen > MAX_EXPRESSION_SIZE) { - throw new RuntimeException("Float expression to long"); + throw new RuntimeException("Float expression too long"); } int animLen = (len >> 16) & 0xFFFF; float[] values = new float[valueLen]; @@ -268,6 +282,11 @@ public class FloatExpression implements Operation, VariableSupport { operations.add(new FloatExpression(id, values, animation)); } + /** + * Populate the documentation with a description of this operation + * + * @param doc to append the description to. + */ public static void documentation(@NonNull DocumentationBuilder doc) { doc.operation("Expressions Operations", OP_CODE, CLASS_NAME) .description("A Float expression") diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/Header.java b/core/java/com/android/internal/widget/remotecompose/core/operations/Header.java index 009aa0339625e697480f07e6f0862ef7de94991e..04e4346cf05d60f3e15cbb96ebdf8e1529beafb6 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/Header.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/Header.java @@ -35,7 +35,7 @@ import java.util.List; *

      It encodes the version of the document (following semantic versioning) as well as the * dimensions of the document in pixels. */ -public class Header implements RemoteComposeOperation { +public class Header extends Operation implements RemoteComposeOperation { private static final int OP_CODE = Operations.HEADER; private static final String CLASS_NAME = "Header"; public static final int MAJOR_VERSION = 0; @@ -120,6 +120,11 @@ public class Header implements RemoteComposeOperation { return CLASS_NAME; } + /** + * The OP_CODE for this command + * + * @return the opcode + */ public static int id() { return OP_CODE; } @@ -136,6 +141,12 @@ public class Header implements RemoteComposeOperation { buffer.writeLong(capabilities); } + /** + * Read this operation and add it to the list of operations + * + * @param buffer the buffer to read + * @param operations the list of operations that will be added to + */ public static void read(@NonNull WireBuffer buffer, @NonNull List operations) { int majorVersion = buffer.readInt(); int minorVersion = buffer.readInt(); @@ -157,6 +168,11 @@ public class Header implements RemoteComposeOperation { operations.add(header); } + /** + * Populate the documentation with a description of this operation + * + * @param doc to append the description to. + */ public static void documentation(@NonNull DocumentationBuilder doc) { doc.operation("Protocol Operations", OP_CODE, CLASS_NAME) .description( diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/IntegerExpression.java b/core/java/com/android/internal/widget/remotecompose/core/operations/IntegerExpression.java index c49f74de789335cfbc75a8fb6ba09723bf859b35..67274af7c28330e56f980f467196f9fb24546fa0 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/IntegerExpression.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/IntegerExpression.java @@ -38,7 +38,7 @@ import java.util.List; * like injecting the width of the component int draw rect As well as supporting generalized * animation floats. The floats represent a RPN style calculator */ -public class IntegerExpression implements Operation, VariableSupport { +public class IntegerExpression extends Operation implements VariableSupport { private static final int OP_CODE = Operations.INTEGER_EXPRESSION; private static final String CLASS_NAME = "IntegerExpression"; public int mId; @@ -141,6 +141,11 @@ public class IntegerExpression implements Operation, VariableSupport { return CLASS_NAME; } + /** + * The OP_CODE for this command + * + * @return the opcode + */ public static int id() { return OP_CODE; } @@ -163,6 +168,12 @@ public class IntegerExpression implements Operation, VariableSupport { } } + /** + * Read this operation and add it to the list of operations + * + * @param buffer the buffer to read + * @param operations the list of operations that will be added to + */ public static void read(@NonNull WireBuffer buffer, @NonNull List operations) { int id = buffer.readInt(); int mask = buffer.readInt(); @@ -178,6 +189,11 @@ public class IntegerExpression implements Operation, VariableSupport { operations.add(new IntegerExpression(id, mask, values)); } + /** + * Populate the documentation with a description of this operation + * + * @param doc to append the description to. + */ public static void documentation(@NonNull DocumentationBuilder doc) { doc.operation("Data Operations", OP_CODE, CLASS_NAME) .description("Expression that computes an integer") diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/MatrixRestore.java b/core/java/com/android/internal/widget/remotecompose/core/operations/MatrixRestore.java index 4e7ee4d135ee2e33c0b77fce167cbcc0d36db5fd..aed597ae74940b389ca841196d4066b3f5affd41 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/MatrixRestore.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/MatrixRestore.java @@ -37,6 +37,12 @@ public class MatrixRestore extends PaintOperation { apply(buffer); } + /** + * Read this operation and add it to the list of operations + * + * @param buffer the buffer to read + * @param operations the list of operations that will be added to + */ public static void read(@NonNull WireBuffer buffer, @NonNull List operations) { MatrixRestore op = new MatrixRestore(); operations.add(op); @@ -53,6 +59,11 @@ public class MatrixRestore extends PaintOperation { return CLASS_NAME; } + /** + * The OP_CODE for this command + * + * @return the opcode + */ public static int id() { return OP_CODE; } @@ -61,6 +72,11 @@ public class MatrixRestore extends PaintOperation { buffer.start(OP_CODE); } + /** + * Populate the documentation with a description of this operation + * + * @param doc to append the description to. + */ public static void documentation(@NonNull DocumentationBuilder doc) { doc.operation("Canvas Operations", OP_CODE, CLASS_NAME) .description("Restore the matrix and clip"); diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/MatrixRotate.java b/core/java/com/android/internal/widget/remotecompose/core/operations/MatrixRotate.java index 438a2aad648a4c8db971097d85947a86f2409c24..fece143ebfa15365d5b8419061d0307448b6f5a0 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/MatrixRotate.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/MatrixRotate.java @@ -30,6 +30,12 @@ public class MatrixRotate extends DrawBase3 { public static final int OP_CODE = Operations.MATRIX_ROTATE; private static final String CLASS_NAME = "MatrixRotate"; + /** + * Read this operation and add it to the list of operations + * + * @param buffer the buffer to read + * @param operations the list of operations that will be added to + */ public static void read(@NonNull WireBuffer buffer, @NonNull List operations) { Maker m = new Maker() { @@ -42,6 +48,11 @@ public class MatrixRotate extends DrawBase3 { read(m, buffer, operations); } + /** + * The OP_CODE for this command + * + * @return the opcode + */ public static int id() { return OP_CODE; } @@ -51,6 +62,11 @@ public class MatrixRotate extends DrawBase3 { return CLASS_NAME; } + /** + * Populate the documentation with a description of this operation + * + * @param doc to append the description to. + */ public static void documentation(@NonNull DocumentationBuilder doc) { doc.operation("Canvas Operations", OP_CODE, CLASS_NAME) .description("apply rotation to matrix") diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/MatrixSave.java b/core/java/com/android/internal/widget/remotecompose/core/operations/MatrixSave.java index 09f54a52e6a3c4bfe5090182a521657d915a2d8c..7eb7b3ffaf34a1b8edad1df6f07113e3e2370a78 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/MatrixSave.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/MatrixSave.java @@ -41,6 +41,12 @@ public class MatrixSave extends PaintOperation { return "MatrixSave;"; } + /** + * Read this operation and add it to the list of operations + * + * @param buffer the buffer to read + * @param operations the list of operations that will be added to + */ public static void read(@NonNull WireBuffer buffer, @NonNull List operations) { MatrixSave op = new MatrixSave(); operations.add(op); @@ -51,6 +57,11 @@ public class MatrixSave extends PaintOperation { return CLASS_NAME; } + /** + * The OP_CODE for this command + * + * @return the opcode + */ public static int id() { return OP_CODE; } @@ -59,6 +70,11 @@ public class MatrixSave extends PaintOperation { buffer.start(Operations.MATRIX_SAVE); } + /** + * Populate the documentation with a description of this operation + * + * @param doc to append the description to. + */ public static void documentation(@NonNull DocumentationBuilder doc) { doc.operation("Canvas Operations", OP_CODE, CLASS_NAME) .description("Save the matrix and clip to a stack"); diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/MatrixScale.java b/core/java/com/android/internal/widget/remotecompose/core/operations/MatrixScale.java index 6304584999778536c455c1aca76d2004b3cf82ca..49bdd1b06eedbe6dc42105d2780cf561e77df6a6 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/MatrixScale.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/MatrixScale.java @@ -30,11 +30,22 @@ public class MatrixScale extends DrawBase4 { public static final int OP_CODE = Operations.MATRIX_SCALE; public static final String CLASS_NAME = "MatrixScale"; + /** + * Read this operation and add it to the list of operations + * + * @param buffer the buffer to read + * @param operations the list of operations that will be added to + */ public static void read(@NonNull WireBuffer buffer, @NonNull List operations) { Maker m = MatrixScale::new; read(m, buffer, operations); } + /** + * The OP_CODE for this command + * + * @return the opcode + */ public static int id() { return OP_CODE; } @@ -49,9 +60,14 @@ public class MatrixScale extends DrawBase4 { apply(buffer, v1, v2, v3, v4); } + /** + * Populate the documentation with a description of this operation + * + * @param doc to append the description to. + */ public static void documentation(@NonNull DocumentationBuilder doc) { doc.operation("Canvas Operations", OP_CODE, CLASS_NAME) - .description("Draw the specified Oval") + .description("Scale the following draw commands") .field(DocumentedOperation.FLOAT, "scaleX", "The amount to scale in X") .field(DocumentedOperation.FLOAT, "scaleY", "The amount to scale in Y") .field(DocumentedOperation.FLOAT, "pivotX", "The x-coordinate for the pivot point") diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/MatrixSkew.java b/core/java/com/android/internal/widget/remotecompose/core/operations/MatrixSkew.java index 675cf0de47438964ab9d83f4c769e893d74bb20b..54b6fd1fa9ae370b7c2771cb1c1380fb44763a8e 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/MatrixSkew.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/MatrixSkew.java @@ -31,11 +31,22 @@ public class MatrixSkew extends DrawBase2 { public static final int OP_CODE = Operations.MATRIX_SKEW; public static final String CLASS_NAME = "MatrixSkew"; + /** + * Read this operation and add it to the list of operations + * + * @param buffer the buffer to read + * @param operations the list of operations that will be added to + */ public static void read(@NonNull WireBuffer buffer, @NonNull List operations) { Maker m = MatrixSkew::new; read(m, buffer, operations); } + /** + * The OP_CODE for this command + * + * @return the opcode + */ public static int id() { return OP_CODE; } @@ -50,6 +61,11 @@ public class MatrixSkew extends DrawBase2 { apply(buffer, v1, v2); } + /** + * Populate the documentation with a description of this operation + * + * @param doc to append the description to. + */ public static void documentation(@NonNull DocumentationBuilder doc) { doc.operation("Canvas Operations", OP_CODE, CLASS_NAME) .description("Current matrix with the specified skew.") diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/MatrixTranslate.java b/core/java/com/android/internal/widget/remotecompose/core/operations/MatrixTranslate.java index b0a7d352dfe3904b66af8844606754add5af26d8..b57d83b770b2c0b5fd8340323ec6133842e0d45c 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/MatrixTranslate.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/MatrixTranslate.java @@ -30,11 +30,22 @@ public class MatrixTranslate extends DrawBase2 { public static final int OP_CODE = Operations.MATRIX_TRANSLATE; public static final String CLASS_NAME = "MatrixTranslate"; + /** + * Read this operation and add it to the list of operations + * + * @param buffer the buffer to read + * @param operations the list of operations that will be added to + */ public static void read(@NonNull WireBuffer buffer, @NonNull List operations) { Maker m = MatrixTranslate::new; read(m, buffer, operations); } + /** + * The OP_CODE for this command + * + * @return the opcode + */ public static int id() { return OP_CODE; } @@ -49,6 +60,11 @@ public class MatrixTranslate extends DrawBase2 { apply(buffer, v1, v2); } + /** + * Populate the documentation with a description of this operation + * + * @param doc to append the description to. + */ public static void documentation(@NonNull DocumentationBuilder doc) { doc.operation("Canvas Operations", OP_CODE, "MatrixTranslate") .description("Preconcat the current matrix with the specified translation") diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/NamedVariable.java b/core/java/com/android/internal/widget/remotecompose/core/operations/NamedVariable.java index 5ca91af91f8649f98d28403a5daedd1d0514f7db..3c82f2b27ca68e97bb39ba4a0c9f439da4ec9983 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/NamedVariable.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/NamedVariable.java @@ -30,7 +30,7 @@ import com.android.internal.widget.remotecompose.core.documentation.DocumentedOp import java.util.List; /** Operation to deal with Text data */ -public class NamedVariable implements Operation { +public class NamedVariable extends Operation { private static final int OP_CODE = Operations.NAMED_VARIABLE; private static final String CLASS_NAME = "NamedVariable"; public final int mVarId; @@ -69,6 +69,11 @@ public class NamedVariable implements Operation { return CLASS_NAME; } + /** + * The OP_CODE for this command + * + * @return the opcode + */ public static int id() { return OP_CODE; } @@ -89,6 +94,12 @@ public class NamedVariable implements Operation { buffer.writeUTF8(text); } + /** + * Read this operation and add it to the list of operations + * + * @param buffer the buffer to read + * @param operations the list of operations that will be added to + */ public static void read(@NonNull WireBuffer buffer, @NonNull List operations) { int varId = buffer.readInt(); int varType = buffer.readInt(); @@ -96,6 +107,11 @@ public class NamedVariable implements Operation { operations.add(new NamedVariable(varId, varType, text)); } + /** + * Populate the documentation with a description of this operation + * + * @param doc to append the description to. + */ public static void documentation(@NonNull DocumentationBuilder doc) { doc.operation("Data Operations", OP_CODE, CLASS_NAME) .description("Add a string name for an ID") diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/PaintData.java b/core/java/com/android/internal/widget/remotecompose/core/operations/PaintData.java index b24df8a6a91eb7e08ed03f178e03ff6d5962d8ba..3c0a842371c7c8af741f24314a2d29da8630b44d 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/PaintData.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/PaintData.java @@ -66,6 +66,11 @@ public class PaintData extends PaintOperation implements VariableSupport { return CLASS_NAME; } + /** + * The OP_CODE for this command + * + * @return the opcode + */ public static int id() { return OP_CODE; } @@ -75,6 +80,12 @@ public class PaintData extends PaintOperation implements VariableSupport { paintBundle.writeBundle(buffer); } + /** + * Read this operation and add it to the list of operations + * + * @param buffer the buffer to read + * @param operations the list of operations that will be added to + */ public static void read(@NonNull WireBuffer buffer, @NonNull List operations) { PaintData data = new PaintData(); data.mPaintData.readBundle(buffer); diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/PathAppend.java b/core/java/com/android/internal/widget/remotecompose/core/operations/PathAppend.java new file mode 100644 index 0000000000000000000000000000000000000000..2b00001a521e0e9b5c3447f6f42b74cc67ef9981 --- /dev/null +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/PathAppend.java @@ -0,0 +1,230 @@ +/* + * 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.internal.widget.remotecompose.core.operations; + +import static com.android.internal.widget.remotecompose.core.documentation.DocumentedOperation.FLOAT_ARRAY; +import static com.android.internal.widget.remotecompose.core.documentation.DocumentedOperation.INT; + +import android.annotation.NonNull; +import android.annotation.Nullable; + +import com.android.internal.widget.remotecompose.core.Operation; +import com.android.internal.widget.remotecompose.core.Operations; +import com.android.internal.widget.remotecompose.core.PaintContext; +import com.android.internal.widget.remotecompose.core.PaintOperation; +import com.android.internal.widget.remotecompose.core.RemoteContext; +import com.android.internal.widget.remotecompose.core.VariableSupport; +import com.android.internal.widget.remotecompose.core.WireBuffer; +import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder; +import com.android.internal.widget.remotecompose.core.documentation.DocumentedOperation; + +import java.util.Arrays; +import java.util.List; + +public class PathAppend extends PaintOperation implements VariableSupport { + private static final int OP_CODE = Operations.PATH_ADD; + private static final String CLASS_NAME = "PathAppend"; + int mInstanceId; + float[] mFloatPath; + float[] mOutputPath; + + PathAppend(int instanceId, float[] floatPath) { + mInstanceId = instanceId; + mFloatPath = floatPath; + mOutputPath = Arrays.copyOf(mFloatPath, mFloatPath.length); + } + + @Override + public void updateVariables(@NonNull RemoteContext context) { + for (int i = 0; i < mFloatPath.length; i++) { + float v = mFloatPath[i]; + if (Utils.isVariable(v)) { + mOutputPath[i] = Float.isNaN(v) ? context.getFloat(Utils.idFromNan(v)) : v; + } else { + mOutputPath[i] = v; + } + } + } + + @Override + public void registerListening(@NonNull RemoteContext context) { + for (float v : mFloatPath) { + if (Float.isNaN(v)) { + context.listensTo(Utils.idFromNan(v), this); + } + } + } + + @Override + public void write(@NonNull WireBuffer buffer) { + apply(buffer, mInstanceId, mOutputPath); + } + + @NonNull + @Override + public String deepToString(String indent) { + return PathData.pathString(mFloatPath); + } + + @NonNull + @Override + public String toString() { + return "PathAppend[" + mInstanceId + "] += " + "\"" + pathString(mOutputPath) + "\""; + } + + /** + * public float[] getFloatPath(PaintContext context) { float[] ret = mRetFloats; // Assume + * retFloats is declared elsewhere if (ret == null) { return mFloatPath; // Assume floatPath is + * declared elsewhere } float[] localRef = mRef; // Assume ref is of type Float[] if (localRef + * == null) { for (int i = 0; i < mFloatPath.length; i++) { ret[i] = mFloatPath[i]; } } else { + * for (int i = 0; i < mFloatPath.length; i++) { float lr = localRef[i]; if (Float.isNaN(lr)) { + * ret[i] = Utils.getActualValue(lr); } else { ret[i] = mFloatPath[i]; } } } return ret; } + */ + public static final int MOVE = 10; + + public static final int LINE = 11; + public static final int QUADRATIC = 12; + public static final int CONIC = 13; + public static final int CUBIC = 14; + public static final int CLOSE = 15; + public static final int DONE = 16; + public static final float MOVE_NAN = Utils.asNan(MOVE); + public static final float LINE_NAN = Utils.asNan(LINE); + public static final float QUADRATIC_NAN = Utils.asNan(QUADRATIC); + public static final float CONIC_NAN = Utils.asNan(CONIC); + public static final float CUBIC_NAN = Utils.asNan(CUBIC); + public static final float CLOSE_NAN = Utils.asNan(CLOSE); + public static final float DONE_NAN = Utils.asNan(DONE); + + @NonNull + public static String name() { + return CLASS_NAME; + } + + /** + * The OP_CODE for this command + * + * @return the opcode + */ + public static int id() { + return OP_CODE; + } + + public static void apply(@NonNull WireBuffer buffer, int id, @NonNull float[] data) { + buffer.start(OP_CODE); + buffer.writeInt(id); + buffer.writeInt(data.length); + for (float datum : data) { + buffer.writeFloat(datum); + } + } + + /** + * Read this operation and add it to the list of operations + * + * @param buffer the buffer to read + * @param operations the list of operations that will be added to + */ + public static void read(@NonNull WireBuffer buffer, @NonNull List operations) { + int id = buffer.readInt(); + int len = buffer.readInt(); + float[] data = new float[len]; + for (int i = 0; i < data.length; i++) { + data[i] = buffer.readFloat(); + } + operations.add(new PathAppend(id, data)); + } + + /** + * Populate the documentation with a description of this operation + * + * @param doc to append the description to. + */ + public static void documentation(@NonNull DocumentationBuilder doc) { + doc.operation("Data Operations", OP_CODE, CLASS_NAME) + .description("Append to a Path") + .field(DocumentedOperation.INT, "id", "id string") + .field(INT, "length", "id string") + .field(FLOAT_ARRAY, "pathData", "length", "path encoded as floats"); + } + + @Override + public void paint(PaintContext context) {} + + @Override + public void apply(@NonNull RemoteContext context) { + updateVariables(context); + float[] data = context.getPathData(mInstanceId); + float[] out = mOutputPath; + if (data != null) { + out = new float[data.length + mOutputPath.length]; + + for (int i = 0; i < data.length; i++) { + out[i] = data[i]; + } + for (int i = 0; i < mOutputPath.length; i++) { + out[i + data.length] = mOutputPath[i]; + } + } else { + System.out.println(">>>>>>>>>>> DATA IS NULL"); + } + context.loadPathData(mInstanceId, out); + } + + @NonNull + public static String pathString(@Nullable float[] path) { + if (path == null) { + return "null"; + } + StringBuilder str = new StringBuilder(); + for (int i = 0; i < path.length; i++) { + if (Float.isNaN(path[i])) { + int id = Utils.idFromNan(path[i]); // Assume idFromNan is defined elsewhere + if (id <= DONE) { // Assume DONE is a constant + switch (id) { + case MOVE: + str.append("M"); + break; + case LINE: + str.append("L"); + break; + case QUADRATIC: + str.append("Q"); + break; + case CONIC: + str.append("R"); + break; + case CUBIC: + str.append("C"); + break; + case CLOSE: + str.append("Z"); + break; + case DONE: + str.append("."); + break; + default: + str.append("[" + id + "]"); + break; + } + } else { + str.append("(" + id + ")"); + } + } + } + return str.toString(); + } +} diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/PathCreate.java b/core/java/com/android/internal/widget/remotecompose/core/operations/PathCreate.java new file mode 100644 index 0000000000000000000000000000000000000000..b62f36b8db5f2d2fd07ed7b55d00f9d15d0804c7 --- /dev/null +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/PathCreate.java @@ -0,0 +1,206 @@ +/* + * 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.internal.widget.remotecompose.core.operations; + +import static com.android.internal.widget.remotecompose.core.documentation.DocumentedOperation.FLOAT; + +import android.annotation.NonNull; +import android.annotation.Nullable; + +import com.android.internal.widget.remotecompose.core.Operation; +import com.android.internal.widget.remotecompose.core.Operations; +import com.android.internal.widget.remotecompose.core.PaintContext; +import com.android.internal.widget.remotecompose.core.PaintOperation; +import com.android.internal.widget.remotecompose.core.RemoteContext; +import com.android.internal.widget.remotecompose.core.VariableSupport; +import com.android.internal.widget.remotecompose.core.WireBuffer; +import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder; +import com.android.internal.widget.remotecompose.core.documentation.DocumentedOperation; + +import java.util.Arrays; +import java.util.List; + +public class PathCreate extends PaintOperation implements VariableSupport { + private static final int OP_CODE = Operations.PATH_CREATE; + private static final String CLASS_NAME = "PathCreate"; + int mInstanceId; + float[] mFloatPath; + float[] mOutputPath; + + PathCreate(int instanceId, float startX, float startY) { + mInstanceId = instanceId; + mFloatPath = new float[] {PathData.MOVE_NAN, startX, startY}; + mOutputPath = Arrays.copyOf(mFloatPath, mFloatPath.length); + } + + @Override + public void updateVariables(@NonNull RemoteContext context) { + for (int i = 0; i < mFloatPath.length; i++) { + float v = mFloatPath[i]; + if (Utils.isVariable(v)) { + mOutputPath[i] = Float.isNaN(v) ? context.getFloat(Utils.idFromNan(v)) : v; + } else { + mOutputPath[i] = v; + } + } + } + + @Override + public void registerListening(@NonNull RemoteContext context) { + for (float v : mFloatPath) { + if (Float.isNaN(v)) { + context.listensTo(Utils.idFromNan(v), this); + } + } + } + + @Override + public void write(@NonNull WireBuffer buffer) { + apply(buffer, mInstanceId, mFloatPath[1], mFloatPath[2]); + } + + @NonNull + @Override + public String deepToString(String indent) { + return pathString(mFloatPath); + } + + @NonNull + @Override + public String toString() { + return "PathCreate[" + mInstanceId + "] = " + "\"" + deepToString(" ") + "\""; + } + + public static final int MOVE = 10; + public static final int LINE = 11; + public static final int QUADRATIC = 12; + public static final int CONIC = 13; + public static final int CUBIC = 14; + public static final int CLOSE = 15; + public static final int DONE = 16; + public static final float MOVE_NAN = Utils.asNan(MOVE); + public static final float LINE_NAN = Utils.asNan(LINE); + public static final float QUADRATIC_NAN = Utils.asNan(QUADRATIC); + public static final float CONIC_NAN = Utils.asNan(CONIC); + public static final float CUBIC_NAN = Utils.asNan(CUBIC); + public static final float CLOSE_NAN = Utils.asNan(CLOSE); + public static final float DONE_NAN = Utils.asNan(DONE); + + @NonNull + public static String name() { + return CLASS_NAME; + } + + /** + * The OP_CODE for this command + * + * @return the opcode + */ + public static int id() { + return OP_CODE; + } + + public static void apply(@NonNull WireBuffer buffer, int id, float startX, float startY) { + buffer.start(OP_CODE); + buffer.writeInt(id); + buffer.writeFloat(startX); + buffer.writeFloat(startY); + } + + /** + * Read this operation and add it to the list of operations + * + * @param buffer the buffer to read + * @param operations the list of operations that will be added to + */ + public static void read(@NonNull WireBuffer buffer, @NonNull List operations) { + + int id = buffer.readInt(); + float startX = buffer.readFloat(); + float startY = buffer.readFloat(); + operations.add(new PathCreate(id, startX, startY)); + } + + /** + * Populate the documentation with a description of this operation + * + * @param doc to append the description to. + */ + public static void documentation(@NonNull DocumentationBuilder doc) { + doc.operation("Data Operations", OP_CODE, CLASS_NAME) + .description("Encode a Path ") + .field(DocumentedOperation.INT, "id", "id of path") + .field(FLOAT, "startX", "initial start x") + .field(FLOAT, "startX", "initial start y"); + } + + @NonNull + public static String pathString(@Nullable float[] path) { + if (path == null) { + return "null"; + } + StringBuilder str = new StringBuilder(); + for (int i = 0; i < path.length; i++) { + if (i != 0) { + str.append(" "); + } + if (Float.isNaN(path[i])) { + int id = Utils.idFromNan(path[i]); // Assume idFromNan is defined elsewhere + if (id <= DONE) { // Assume DONE is a constant + switch (id) { + case MOVE: + str.append("M"); + break; + case LINE: + str.append("L"); + break; + case QUADRATIC: + str.append("Q"); + break; + case CONIC: + str.append("R"); + break; + case CUBIC: + str.append("C"); + break; + case CLOSE: + str.append("Z"); + break; + case DONE: + str.append("."); + break; + default: + str.append("[" + id + "]"); + break; + } + } else { + str.append("(" + id + ")"); + } + } else { + str.append(path[i]); + } + } + return str.toString(); + } + + @Override + public void paint(PaintContext context) {} + + @Override + public void apply(@NonNull RemoteContext context) { + context.loadPathData(mInstanceId, mOutputPath); + } +} diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/PathData.java b/core/java/com/android/internal/widget/remotecompose/core/operations/PathData.java index 509f362c02ed54aa4861f7e1571ca3390d636258..4ec5436c8689ec6e3f3f27e478bb6b9609ec306b 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/PathData.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/PathData.java @@ -32,7 +32,7 @@ import com.android.internal.widget.remotecompose.core.documentation.DocumentedOp import java.util.Arrays; import java.util.List; -public class PathData implements Operation, VariableSupport { +public class PathData extends Operation implements VariableSupport { private static final int OP_CODE = Operations.DATA_PATH; private static final String CLASS_NAME = "PathData"; int mInstanceId; @@ -112,6 +112,11 @@ public class PathData implements Operation, VariableSupport { return CLASS_NAME; } + /** + * The OP_CODE for this command + * + * @return the opcode + */ public static int id() { return OP_CODE; } @@ -125,6 +130,12 @@ public class PathData implements Operation, VariableSupport { } } + /** + * Read this operation and add it to the list of operations + * + * @param buffer the buffer to read + * @param operations the list of operations that will be added to + */ public static void read(@NonNull WireBuffer buffer, @NonNull List operations) { int imageId = buffer.readInt(); int len = buffer.readInt(); @@ -135,6 +146,11 @@ public class PathData implements Operation, VariableSupport { operations.add(new PathData(imageId, data)); } + /** + * Populate the documentation with a description of this operation + * + * @param doc to append the description to. + */ public static void documentation(@NonNull DocumentationBuilder doc) { doc.operation("Data Operations", OP_CODE, CLASS_NAME) .description("Encode a Path ") @@ -143,6 +159,12 @@ public class PathData implements Operation, VariableSupport { .field(FLOAT_ARRAY, "pathData", "length", "path encoded as floats"); } + /** + * Render a path as a string + * + * @param path path as a array of floats + * @return string describing the path + */ @NonNull public static String pathString(@Nullable float[] path) { if (path == null) { diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/PathTween.java b/core/java/com/android/internal/widget/remotecompose/core/operations/PathTween.java new file mode 100644 index 0000000000000000000000000000000000000000..a6fa680f647a5a05d9f3ad5142a0e22276a43ad6 --- /dev/null +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/PathTween.java @@ -0,0 +1,153 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.internal.widget.remotecompose.core.operations; + +import static com.android.internal.widget.remotecompose.core.documentation.DocumentedOperation.INT; +import static com.android.internal.widget.remotecompose.core.operations.Utils.floatToString; + +import android.annotation.NonNull; + +import com.android.internal.widget.remotecompose.core.Operation; +import com.android.internal.widget.remotecompose.core.Operations; +import com.android.internal.widget.remotecompose.core.PaintContext; +import com.android.internal.widget.remotecompose.core.PaintOperation; +import com.android.internal.widget.remotecompose.core.RemoteContext; +import com.android.internal.widget.remotecompose.core.VariableSupport; +import com.android.internal.widget.remotecompose.core.WireBuffer; +import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder; +import com.android.internal.widget.remotecompose.core.documentation.DocumentedOperation; + +import java.util.List; + +/** Operation to deal with Path data */ +public class PathTween extends PaintOperation implements VariableSupport { + private static final int OP_CODE = Operations.PATH_TWEEN; + private static final String CLASS_NAME = "PathTween"; + public int mOutId; + public int mPathId1; + public int mPathId2; + public float mTween; + public float mTweenOut; + + public PathTween(int outId, int pathId1, int pathId2, float tween) { + this.mOutId = outId; + this.mPathId1 = pathId1; + this.mPathId2 = pathId2; + this.mTween = tween; + this.mTweenOut = mTween; + } + + @Override + public void updateVariables(@NonNull RemoteContext context) { + mTweenOut = Float.isNaN(mTween) ? context.getFloat(Utils.idFromNan(mTween)) : mTween; + } + + @Override + public void registerListening(@NonNull RemoteContext context) { + if (Float.isNaN(mTween)) { + context.listensTo(Utils.idFromNan(mTween), this); + } + } + + @Override + public void write(@NonNull WireBuffer buffer) { + apply(buffer, mOutId, mPathId1, mPathId2, mTween); + } + + @NonNull + @Override + public String toString() { + return "PathTween[" + + mOutId + + "] = [" + + mPathId1 + + " ] + [ " + + mPathId2 + + "], " + + floatToString(mTween, mTweenOut); + } + + @NonNull + public static String name() { + return CLASS_NAME; + } + + /** + * The OP_CODE for this command + * + * @return the opcode + */ + public static int id() { + return OP_CODE; + } + + /** + * Writes out the operation to the buffer + * + * @param buffer buffer to write to + * @param outId id of the path + * @param pathId1 source path 1 + * @param pathId2 source path 2 + * @param tween interpolate between two paths + */ + public static void apply( + @NonNull WireBuffer buffer, int outId, int pathId1, int pathId2, float tween) { + buffer.start(OP_CODE); + buffer.writeInt(outId); + buffer.writeInt(pathId1); + buffer.writeInt(pathId2); + buffer.writeFloat(tween); + } + + /** + * Read this operation and add it to the list of operations + * + * @param buffer the buffer to read + * @param operations the list of operations that will be added to + */ + public static void read(@NonNull WireBuffer buffer, @NonNull List operations) { + int outId1 = buffer.readInt(); + int pathId1 = buffer.readInt(); + int pathId2 = buffer.readInt(); + float tween = buffer.readFloat(); + + operations.add(new PathTween(outId1, pathId1, pathId2, tween)); + } + + /** + * Populate the documentation with a description of this operation + * + * @param doc to append the description to. + */ + public static void documentation(@NonNull DocumentationBuilder doc) { + doc.operation("Data Operations", OP_CODE, CLASS_NAME) + .description("Merge two string into one") + .field(DocumentedOperation.INT, "pathId", "id of the path") + .field(INT, "srcPathId1", "id of the path") + .field(INT, "srcPathId1", "x Shift of the path"); + } + + @NonNull + @Override + public String deepToString(String indent) { + return indent + toString(); + } + + @Override + public void paint(PaintContext context) { + context.tweenPath(mOutId, mPathId1, mPathId2, mTweenOut); + } +} diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/RootContentBehavior.java b/core/java/com/android/internal/widget/remotecompose/core/operations/RootContentBehavior.java index 849412618c2ccbe587d6e7a51c9b5376d483dba3..aaa717629c2ef70f183790444b0a9ad656ea1d1e 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/RootContentBehavior.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/RootContentBehavior.java @@ -33,7 +33,7 @@ import java.util.List; *

      It encodes the version of the document (following semantic versioning) as well as the * dimensions of the document in pixels. */ -public class RootContentBehavior implements RemoteComposeOperation { +public class RootContentBehavior extends Operation implements RemoteComposeOperation { private static final int OP_CODE = Operations.ROOT_CONTENT_BEHAVIOR; private static final String CLASS_NAME = "RootContentBehavior"; int mScroll = NONE; @@ -205,6 +205,11 @@ public class RootContentBehavior implements RemoteComposeOperation { return CLASS_NAME; } + /** + * The OP_CODE for this command + * + * @return the opcode + */ public static int id() { return OP_CODE; } @@ -218,6 +223,12 @@ public class RootContentBehavior implements RemoteComposeOperation { buffer.writeInt(mode); } + /** + * Read this operation and add it to the list of operations + * + * @param buffer the buffer to read + * @param operations the list of operations that will be added to + */ public static void read(@NonNull WireBuffer buffer, @NonNull List operations) { int scroll = buffer.readInt(); int alignment = buffer.readInt(); diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/RootContentDescription.java b/core/java/com/android/internal/widget/remotecompose/core/operations/RootContentDescription.java index 109945f21ec5263fd503826d624a496df93ddaaa..e92daa384dc3dbce33e7b120b15de7297c0459be 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/RootContentDescription.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/RootContentDescription.java @@ -28,7 +28,7 @@ import com.android.internal.widget.remotecompose.core.documentation.DocumentedOp import java.util.List; /** Describe a content description for the document */ -public class RootContentDescription implements RemoteComposeOperation { +public class RootContentDescription extends Operation implements RemoteComposeOperation { private static final int OP_CODE = Operations.ROOT_CONTENT_DESCRIPTION; private static final String CLASS_NAME = "RootContentDescription"; int mContentDescription; @@ -69,6 +69,11 @@ public class RootContentDescription implements RemoteComposeOperation { return CLASS_NAME; } + /** + * The OP_CODE for this command + * + * @return the opcode + */ public static int id() { return OP_CODE; } @@ -78,12 +83,23 @@ public class RootContentDescription implements RemoteComposeOperation { buffer.writeInt(contentDescription); } + /** + * Read this operation and add it to the list of operations + * + * @param buffer the buffer to read + * @param operations the list of operations that will be added to + */ public static void read(@NonNull WireBuffer buffer, @NonNull List operations) { int contentDescription = buffer.readInt(); RootContentDescription header = new RootContentDescription(contentDescription); operations.add(header); } + /** + * Populate the documentation with a description of this operation + * + * @param doc to append the description to. + */ public static void documentation(@NonNull DocumentationBuilder doc) { doc.operation("Protocol Operations", OP_CODE, CLASS_NAME) .description("Content description of root") diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/ShaderData.java b/core/java/com/android/internal/widget/remotecompose/core/operations/ShaderData.java index e967ff4f4ff4edfa9bbb08cb33f0e0f72befeb6a..e2502feb2bb154b6568f1fa0144f9d8a48fe6e6a 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/ShaderData.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/ShaderData.java @@ -41,7 +41,7 @@ import java.util.List; * Operation to deal with bitmap data On getting an Image during a draw call the bitmap is * compressed and saved in playback the image is decompressed */ -public class ShaderData implements Operation, VariableSupport { +public class ShaderData extends Operation implements VariableSupport { private static final int OP_CODE = Operations.DATA_SHADER; private static final String CLASS_NAME = "ShaderData"; int mShaderTextId; // the actual text of a shader @@ -203,6 +203,11 @@ public class ShaderData implements Operation, VariableSupport { return CLASS_NAME; } + /** + * The OP_CODE for this command + * + * @return the opcode + */ public static int id() { return OP_CODE; } @@ -266,6 +271,12 @@ public class ShaderData implements Operation, VariableSupport { } } + /** + * Read this operation and add it to the list of operations + * + * @param buffer the buffer to read + * @param operations the list of operations that will be added to + */ public static void read(@NonNull WireBuffer buffer, @NonNull List operations) { int shaderID = buffer.readInt(); int shaderTextId = buffer.readInt(); @@ -318,6 +329,11 @@ public class ShaderData implements Operation, VariableSupport { operations.add(new ShaderData(shaderID, shaderTextId, floatMap, intMap, bitmapMap)); } + /** + * Populate the documentation with a description of this operation + * + * @param doc to append the description to. + */ public static void documentation(@NonNull DocumentationBuilder doc) { doc.operation("Data Operations", OP_CODE, CLASS_NAME) .description("Shader") diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/TextData.java b/core/java/com/android/internal/widget/remotecompose/core/operations/TextData.java index ade008e3bdb4c0925c8f7652d3bf68767d4347f3..3f679bf4758247b8a3a38d689b1f3350f716f1ff 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/TextData.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/TextData.java @@ -31,7 +31,7 @@ import com.android.internal.widget.remotecompose.core.operations.utilities.Strin import java.util.List; /** Operation to deal with Text data */ -public class TextData implements Operation, SerializableToString { +public class TextData extends Operation implements SerializableToString { private static final int OP_CODE = Operations.DATA_TEXT; private static final String CLASS_NAME = "TextData"; public final int mTextId; @@ -59,6 +59,11 @@ public class TextData implements Operation, SerializableToString { return CLASS_NAME; } + /** + * The OP_CODE for this command + * + * @return the opcode + */ public static int id() { return OP_CODE; } @@ -69,6 +74,12 @@ public class TextData implements Operation, SerializableToString { buffer.writeUTF8(text); } + /** + * Read this operation and add it to the list of operations + * + * @param buffer the buffer to read + * @param operations the list of operations that will be added to + */ public static void read(@NonNull WireBuffer buffer, @NonNull List operations) { int textId = buffer.readInt(); @@ -76,6 +87,11 @@ public class TextData implements Operation, SerializableToString { operations.add(new TextData(textId, text)); } + /** + * Populate the documentation with a description of this operation + * + * @param doc to append the description to. + */ public static void documentation(@NonNull DocumentationBuilder doc) { doc.operation("Data Operations", OP_CODE, CLASS_NAME) .description("Encode a string ") diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/TextFromFloat.java b/core/java/com/android/internal/widget/remotecompose/core/operations/TextFromFloat.java index 865ee81f2725f08fd450e8f532edf9b61b80e6aa..4d01e0c3cbe4247eaf77a161361b12838aaa7083 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/TextFromFloat.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/TextFromFloat.java @@ -36,7 +36,7 @@ import java.util.List; * [command][textID][before,after][flags] before and after define number of digits before and after * the decimal point */ -public class TextFromFloat implements Operation, VariableSupport { +public class TextFromFloat extends Operation implements VariableSupport { private static final int OP_CODE = Operations.TEXT_FROM_FLOAT; private static final String CLASS_NAME = "TextFromFloat"; public int mTextId; @@ -127,6 +127,11 @@ public class TextFromFloat implements Operation, VariableSupport { return CLASS_NAME; } + /** + * The OP_CODE for this command + * + * @return the opcode + */ public static int id() { return OP_CODE; } @@ -155,6 +160,12 @@ public class TextFromFloat implements Operation, VariableSupport { buffer.writeInt(flags); } + /** + * Read this operation and add it to the list of operations + * + * @param buffer the buffer to read + * @param operations the list of operations that will be added to + */ public static void read(@NonNull WireBuffer buffer, @NonNull List operations) { int textId = buffer.readInt(); float value = buffer.readFloat(); @@ -166,6 +177,11 @@ public class TextFromFloat implements Operation, VariableSupport { operations.add(new TextFromFloat(textId, value, pre, post, flags)); } + /** + * Populate the documentation with a description of this operation + * + * @param doc to append the description to. + */ public static void documentation(@NonNull DocumentationBuilder doc) { doc.operation("Expressions Operations", OP_CODE, CLASS_NAME) .description("Draw text along path object") diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/TextLength.java b/core/java/com/android/internal/widget/remotecompose/core/operations/TextLength.java index 6ff687b7494e35ffc8b3c1d4bfa32166be4ac0b2..37ea567f5913c849932fc5ff35a12459524ef554 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/TextLength.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/TextLength.java @@ -28,7 +28,7 @@ import com.android.internal.widget.remotecompose.core.documentation.Documentatio import java.util.List; /** Operation to measure the length of the text */ -public class TextLength implements Operation { +public class TextLength extends Operation { private static final int OP_CODE = Operations.TEXT_LENGTH; private static final String CLASS_NAME = "TextLength"; public int mLengthId; @@ -54,6 +54,11 @@ public class TextLength implements Operation { return CLASS_NAME; } + /** + * The OP_CODE for this command + * + * @return the opcode + */ public static int id() { return OP_CODE; } @@ -71,12 +76,23 @@ public class TextLength implements Operation { buffer.writeInt(textId); } + /** + * Read this operation and add it to the list of operations + * + * @param buffer the buffer to read + * @param operations the list of operations that will be added to + */ public static void read(@NonNull WireBuffer buffer, @NonNull List operations) { int lengthId = buffer.readInt(); int textId = buffer.readInt(); operations.add(new TextLength(lengthId, textId)); } + /** + * Populate the documentation with a description of this operation + * + * @param doc to append the description to. + */ public static void documentation(@NonNull DocumentationBuilder doc) { doc.operation("Expressions Operations", OP_CODE, CLASS_NAME) .description("get the length of the text and store in float table") diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/TextLookup.java b/core/java/com/android/internal/widget/remotecompose/core/operations/TextLookup.java index cc812a8e160ea967f890466b6c0d10b0a510d995..3ec6f019c3585777f4af97e53470f1584bc0730e 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/TextLookup.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/TextLookup.java @@ -34,7 +34,7 @@ import java.util.List; * [command][textID][before,after][flags] before and after define number of digits before and after * the decimal point */ -public class TextLookup implements Operation, VariableSupport { +public class TextLookup extends Operation implements VariableSupport { private static final int OP_CODE = Operations.TEXT_LOOKUP; private static final String CLASS_NAME = "TextFromFloat"; public int mTextId; @@ -84,6 +84,11 @@ public class TextLookup implements Operation, VariableSupport { return CLASS_NAME; } + /** + * The OP_CODE for this command + * + * @return the opcode + */ public static int id() { return OP_CODE; } @@ -103,6 +108,12 @@ public class TextLookup implements Operation, VariableSupport { buffer.writeFloat(index); } + /** + * Read this operation and add it to the list of operations + * + * @param buffer the buffer to read + * @param operations the list of operations that will be added to + */ public static void read(@NonNull WireBuffer buffer, @NonNull List operations) { int textId = buffer.readInt(); int dataSetId = buffer.readInt(); @@ -110,6 +121,11 @@ public class TextLookup implements Operation, VariableSupport { operations.add(new TextLookup(textId, dataSetId, index)); } + /** + * Populate the documentation with a description of this operation + * + * @param doc to append the description to. + */ public static void documentation(@NonNull DocumentationBuilder doc) { doc.operation("Expressions Operations", OP_CODE, CLASS_NAME) .description("Look an array and turn into a text object") diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/TextLookupInt.java b/core/java/com/android/internal/widget/remotecompose/core/operations/TextLookupInt.java index 74be698872fa86515081a68edeca8c07c82d7d5f..9c0ee535f62a1604224208fe1924ed574aa0ca87 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/TextLookupInt.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/TextLookupInt.java @@ -30,7 +30,7 @@ import com.android.internal.widget.remotecompose.core.documentation.DocumentedOp import java.util.List; /** Operation convert int index of a list to text */ -public class TextLookupInt implements Operation, VariableSupport { +public class TextLookupInt extends Operation implements VariableSupport { private static final int OP_CODE = Operations.TEXT_LOOKUP_INT; private static final String CLASS_NAME = "TextFromINT"; public int mTextId; @@ -77,6 +77,11 @@ public class TextLookupInt implements Operation, VariableSupport { return CLASS_NAME; } + /** + * The OP_CODE for this command + * + * @return the opcode + */ public static int id() { return OP_CODE; } @@ -96,6 +101,12 @@ public class TextLookupInt implements Operation, VariableSupport { buffer.writeInt(indexId); } + /** + * Read this operation and add it to the list of operations + * + * @param buffer the buffer to read + * @param operations the list of operations that will be added to + */ public static void read(@NonNull WireBuffer buffer, @NonNull List operations) { int textId = buffer.readInt(); int dataSetId = buffer.readInt(); @@ -103,6 +114,11 @@ public class TextLookupInt implements Operation, VariableSupport { operations.add(new TextLookupInt(textId, dataSetId, indexId)); } + /** + * Populate the documentation with a description of this operation + * + * @param doc to append the description to. + */ public static void documentation(@NonNull DocumentationBuilder doc) { doc.operation("Expressions Operations", OP_CODE, CLASS_NAME) .description("Look up an array and turn into a text object") diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/TextMeasure.java b/core/java/com/android/internal/widget/remotecompose/core/operations/TextMeasure.java index 6d48f67ed8c80c66d5f5ce24cce8014a21e3495e..d51b389241266b4aa12fd37a4c337f2208e00097 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/TextMeasure.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/TextMeasure.java @@ -70,6 +70,11 @@ public class TextMeasure extends PaintOperation { return CLASS_NAME; } + /** + * The OP_CODE for this command + * + * @return the opcode + */ public static int id() { return OP_CODE; } @@ -89,6 +94,12 @@ public class TextMeasure extends PaintOperation { buffer.writeInt(type); } + /** + * Read this operation and add it to the list of operations + * + * @param buffer the buffer to read + * @param operations the list of operations that will be added to + */ public static void read(@NonNull WireBuffer buffer, @NonNull List operations) { int id = buffer.readInt(); int textId = buffer.readInt(); @@ -96,9 +107,14 @@ public class TextMeasure extends PaintOperation { operations.add(new TextMeasure(id, textId, type)); } + /** + * Populate the documentation with a description of this operation + * + * @param doc to append the description to. + */ public static void documentation(@NonNull DocumentationBuilder doc) { doc.operation("Expressions Operations", OP_CODE, CLASS_NAME) - .description("A float and its associated id") + .description("Measure text") .field(INT, "id", "id of float result of the measure") .field(INT, "textId", "id of text") .field(INT, "type", "type: measure 0=width,1=height"); diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/TextMerge.java b/core/java/com/android/internal/widget/remotecompose/core/operations/TextMerge.java index ecd5baaf0dd2b8af133efd92022d17420f34621b..5b0c38fe996b49ce7a490345ca4e58ee82b11ee4 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/TextMerge.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/TextMerge.java @@ -29,7 +29,7 @@ import com.android.internal.widget.remotecompose.core.documentation.DocumentedOp import java.util.List; /** Operation to deal with Text data */ -public class TextMerge implements Operation { +public class TextMerge extends Operation { private static final int OP_CODE = Operations.TEXT_MERGE; private static final String CLASS_NAME = "TextMerge"; public int mTextId; @@ -58,6 +58,11 @@ public class TextMerge implements Operation { return CLASS_NAME; } + /** + * The OP_CODE for this command + * + * @return the opcode + */ public static int id() { return OP_CODE; } @@ -77,6 +82,12 @@ public class TextMerge implements Operation { buffer.writeInt(srcId2); } + /** + * Read this operation and add it to the list of operations + * + * @param buffer the buffer to read + * @param operations the list of operations that will be added to + */ public static void read(@NonNull WireBuffer buffer, @NonNull List operations) { int textId = buffer.readInt(); int srcId1 = buffer.readInt(); @@ -85,6 +96,11 @@ public class TextMerge implements Operation { operations.add(new TextMerge(textId, srcId1, srcId2)); } + /** + * Populate the documentation with a description of this operation + * + * @param doc to append the description to. + */ public static void documentation(@NonNull DocumentationBuilder doc) { doc.operation("Data Operations", OP_CODE, CLASS_NAME) .description("Merge two string into one") diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/Theme.java b/core/java/com/android/internal/widget/remotecompose/core/operations/Theme.java index d265070a50bfcf742886e005ff62229b04b3fa67..e329c38daf20af490edf0689a9920aca02ab3975 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/Theme.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/Theme.java @@ -33,7 +33,7 @@ import java.util.List; * "tag" the subsequent operations to a given theme. On playback, we can then filter operations * depending on the chosen theme. */ -public class Theme implements RemoteComposeOperation { +public class Theme extends Operation implements RemoteComposeOperation { private static final int OP_CODE = Operations.THEME; private static final String CLASS_NAME = "Theme"; int mTheme; @@ -77,6 +77,11 @@ public class Theme implements RemoteComposeOperation { return CLASS_NAME; } + /** + * The OP_CODE for this command + * + * @return the opcode + */ public static int id() { return OP_CODE; } @@ -86,11 +91,22 @@ public class Theme implements RemoteComposeOperation { buffer.writeInt(theme); } + /** + * Read this operation and add it to the list of operations + * + * @param buffer the buffer to read + * @param operations the list of operations that will be added to + */ public static void read(@NonNull WireBuffer buffer, @NonNull List operations) { int theme = buffer.readInt(); operations.add(new Theme(theme)); } + /** + * Populate the documentation with a description of this operation + * + * @param doc to append the description to. + */ public static void documentation(@NonNull DocumentationBuilder doc) { doc.operation("Protocol Operations", OP_CODE, CLASS_NAME) .description("Set a theme") diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/TouchExpression.java b/core/java/com/android/internal/widget/remotecompose/core/operations/TouchExpression.java index 1bb7b2a183a2e468e1852e9ea7083891c73f823f..e2e20bc5e57f51fec3ae3e54f1dc6929fc8f92f2 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/TouchExpression.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/TouchExpression.java @@ -42,12 +42,12 @@ import java.util.List; * touch behaviours. Including animating to Notched, positions. and tweaking the dynamics of the * animation. */ -public class TouchExpression implements Operation, VariableSupport, TouchListener { +public class TouchExpression extends Operation implements VariableSupport, TouchListener { private static final int OP_CODE = Operations.TOUCH_EXPRESSION; private static final String CLASS_NAME = "TouchExpression"; private float mDefValue; private float mOutDefValue; - public int mId; + private int mId; public float[] mSrcExp; int mMode = 1; // 0 = delta, 1 = absolute float mMax = 1; @@ -56,11 +56,14 @@ public class TouchExpression implements Operation, VariableSupport, TouchListene float mOutMin = 1; float mValue = 0; boolean mUnmodified = true; - public float[] mPreCalcValue; + private float[] mPreCalcValue; private float mLastChange = Float.NaN; private float mLastCalculatedValue = Float.NaN; AnimatedFloatExpression mExp = new AnimatedFloatExpression(); + + /** The maximum number of floats in the expression */ public static final int MAX_EXPRESSION_SIZE = 32; + private VelocityEasing mEasyTouch = new VelocityEasing(); private boolean mEasingToStop = false; private float mTouchUpTime = 0; @@ -495,6 +498,11 @@ public class TouchExpression implements Operation, VariableSupport, TouchListene return CLASS_NAME; } + /** + * The OP_CODE for this command + * + * @return the opcode + */ public static int id() { return OP_CODE; } @@ -505,6 +513,14 @@ public class TouchExpression implements Operation, VariableSupport, TouchListene * @param buffer The buffer to write to * @param id the id of the resulting float * @param value the float expression array + * @param min the minimum allowed value + * @param max the maximum allowed value + * @param velocityId the velocity id + * @param touchEffects the type touch effect + * @param exp the expression the maps touch drags to movement + * @param touchMode the touch mode e.g. notch modes + * @param touchSpec the spec of the touch modes + * @param easingSpec the spec of when the object comes to an easing */ public static void apply( WireBuffer buffer, @@ -549,7 +565,13 @@ public class TouchExpression implements Operation, VariableSupport, TouchListene } } - public static void read(WireBuffer buffer, List operations) { + /** + * Read this operation and add it to the list of operations + * + * @param buffer the buffer to read + * @param operations the list of operations that will be added to + */ + public static void read(@NonNull WireBuffer buffer, @NonNull List operations) { int id = buffer.readInt(); float startValue = buffer.readFloat(); float min = buffer.readFloat(); @@ -594,6 +616,11 @@ public class TouchExpression implements Operation, VariableSupport, TouchListene easingData)); } + /** + * Populate the documentation with a description of this operation + * + * @param doc to append the description to. + */ public static void documentation(DocumentationBuilder doc) { doc.operation("Expressions Operations", OP_CODE, CLASS_NAME) .description("A Float expression") diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/Utils.java b/core/java/com/android/internal/widget/remotecompose/core/operations/Utils.java index baca3e0dc99af5204572222cef13ff5cec737f2c..de43b90840cc3157f99accbce9ae430adef72bbd 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/Utils.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/Utils.java @@ -19,34 +19,60 @@ import android.annotation.NonNull; /** Utilities to be used across all core operations */ public class Utils { + /** + * Convert an integer id into a float + * + * @param v the integer id to convert + * @return the id as an float + */ public static float asNan(int v) { return Float.intBitsToFloat(v | -0x800000); } + /** + * convert a float into an integer id + * + * @param value the float id to convert + * @return the id as an integer + */ public static int idFromNan(float value) { int b = Float.floatToRawIntBits(value); return b & 0x3FFFFF; } + /** + * convert a long into an ID + * + * @param v the long to convert + * @return the id still as a long + */ public static long idFromLong(long v) { return v - 0x100000000L; } + /** + * convert a float id and turn it into a string + * + * @param value float to convert + * @return string form of an id + */ @NonNull public static String idStringFromNan(float value) { int b = Float.floatToRawIntBits(value) & 0x3FFFFF; return idString(b); } + /** + * print an id as a string + * + * @param b the id + * @return the id as a string + */ @NonNull public static String idString(int b) { return (b > 0xFFFFF) ? "A_" + (b & 0xFFFFF) : "" + b; } - public static float getActualValue(float lr) { - return 0; - } - /** * trim a string to n characters if needing to trim end in "..." * diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/ActionOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/ActionOperation.java index 7f1d101cff16fca67dad5a456fc7884b76ae5e44..0f840597e3c6d67faa51a43947ef216c2b0f13d4 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/ActionOperation.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/ActionOperation.java @@ -18,12 +18,11 @@ package com.android.internal.widget.remotecompose.core.operations.layout; import android.annotation.NonNull; import com.android.internal.widget.remotecompose.core.CoreDocument; -import com.android.internal.widget.remotecompose.core.Operation; import com.android.internal.widget.remotecompose.core.RemoteContext; import com.android.internal.widget.remotecompose.core.operations.utilities.StringSerializer; /** Operations representing actions on the document */ -public interface ActionOperation extends Operation { +public interface ActionOperation { void serializeToString(int indent, @NonNull StringSerializer serializer); void runAction( diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/CanvasContent.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/CanvasContent.java index aa8f758071416e90ea27973f2849d11fc2f7691f..121b18014a21805142fb6dd42c6bb22b51e3878a 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/CanvasContent.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/CanvasContent.java @@ -46,6 +46,11 @@ public class CanvasContent extends Component implements ComponentStartOperation return "CanvasContent"; } + /** + * The OP_CODE for this command + * + * @return the opcode + */ public static int id() { return Operations.LAYOUT_CANVAS_CONTENT; } @@ -61,6 +66,12 @@ public class CanvasContent extends Component implements ComponentStartOperation buffer.writeInt(componentId); } + /** + * Read this operation and add it to the list of operations + * + * @param buffer the buffer to read + * @param operations the list of operations that will be added to + */ public static void read(@NonNull WireBuffer buffer, @NonNull List operations) { int componentId = buffer.readInt(); operations.add(new CanvasContent(componentId, 0, 0, 0, 0, null, -1)); diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/ClickModifierOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/ClickModifierOperation.java index f44e20ddcdac63a0bd032071bb056fb3323b6356..34c42494d964b470e152d21c092ece9a9a223576 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/ClickModifierOperation.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/ClickModifierOperation.java @@ -182,6 +182,12 @@ public class ClickModifierOperation extends PaintOperation buffer.start(OP_CODE); } + /** + * Read this operation and add it to the list of operations + * + * @param buffer the buffer to read + * @param operations the list of operations that will be added to + */ public static void read(@NonNull WireBuffer buffer, @NonNull List operations) { operations.add(new ClickModifierOperation()); } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/Component.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/Component.java index fbfc796e092a05f75e2f3248852ee43f17d661e3..faa259f6b8351b09301d46141a4ba63442c7869f 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/Component.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/Component.java @@ -26,7 +26,6 @@ import com.android.internal.widget.remotecompose.core.RemoteContext; import com.android.internal.widget.remotecompose.core.SerializableToString; import com.android.internal.widget.remotecompose.core.VariableSupport; import com.android.internal.widget.remotecompose.core.WireBuffer; -import com.android.internal.widget.remotecompose.core.operations.BitmapData; import com.android.internal.widget.remotecompose.core.operations.ComponentValue; import com.android.internal.widget.remotecompose.core.operations.TextData; import com.android.internal.widget.remotecompose.core.operations.layout.animation.AnimateMeasure; @@ -468,11 +467,6 @@ public class Component extends PaintOperation implements Measurable, Serializabl value[0] += mX; value[1] += mY; if (mParent != null) { - if (mParent instanceof LayoutComponent) { - LayoutComponent parent = (LayoutComponent) mParent; - value[0] += parent.getMarginLeft() + parent.getPaddingLeft(); - value[1] += parent.getMarginTop() + parent.getPaddingTop(); - } mParent.getLocationInWindow(value); } } @@ -658,12 +652,7 @@ public class Component extends PaintOperation implements Measurable, Serializabl debugBox(this, context); } for (Operation op : mList) { - if (op instanceof BitmapData) { - ((BitmapData) op).apply(context.getContext()); - } - if (op instanceof PaintOperation) { - ((PaintOperation) op).paint(context); - } + op.apply(context.getContext()); } context.restore(); context.getContext().mLastComponent = prev; @@ -701,7 +690,7 @@ public class Component extends PaintOperation implements Measurable, Serializabl if (applyAnimationAsNeeded(context)) { return; } - if (mVisibility == Visibility.GONE) { + if (mVisibility == Visibility.GONE || mVisibility == Visibility.INVISIBLE) { return; } paintingComponent(context); diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/ComponentEnd.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/ComponentEnd.java index 476b73c8fe7d6674e576e7411458c5b3aa3aa312..396644c45fa4ca938f4abe792c400016c6fe2d7a 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/ComponentEnd.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/ComponentEnd.java @@ -25,7 +25,7 @@ import com.android.internal.widget.remotecompose.core.documentation.Documentatio import java.util.List; -public class ComponentEnd implements Operation { +public class ComponentEnd extends Operation { @Override public void write(@NonNull WireBuffer buffer) { @@ -54,6 +54,11 @@ public class ComponentEnd implements Operation { return "ComponentEnd"; } + /** + * The OP_CODE for this command + * + * @return the opcode + */ public static int id() { return Operations.COMPONENT_END; } @@ -66,6 +71,12 @@ public class ComponentEnd implements Operation { return 1 + 4 + 4 + 4; } + /** + * Read this operation and add it to the list of operations + * + * @param buffer the buffer to read + * @param operations the list of operations that will be added to + */ public static void read(@NonNull WireBuffer buffer, @NonNull List operations) { operations.add(new ComponentEnd()); } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/ComponentStart.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/ComponentStart.java index def9f780ba7f2c827a7ccb6e6d344bb594273ecf..a85ae270ffb126dbbfc2bfc7f637127d76a355db 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/ComponentStart.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/ComponentStart.java @@ -28,7 +28,7 @@ import com.android.internal.widget.remotecompose.core.documentation.Documentatio import java.util.List; -public class ComponentStart implements ComponentStartOperation { +public class ComponentStart extends Operation implements ComponentStartOperation { int mType = DEFAULT; float mX; @@ -162,6 +162,11 @@ public class ComponentStart implements ComponentStartOperation { return "ComponentStart"; } + /** + * The OP_CODE for this command + * + * @return the opcode + */ public static int id() { return Operations.COMPONENT_START; } @@ -179,6 +184,12 @@ public class ComponentStart implements ComponentStartOperation { return 1 + 4 + 4 + 4; } + /** + * Read this operation and add it to the list of operations + * + * @param buffer the buffer to read + * @param operations the list of operations that will be added to + */ public static void read(@NonNull WireBuffer buffer, @NonNull List operations) { int type = buffer.readInt(); int componentId = buffer.readInt(); diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/ComponentStartOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/ComponentStartOperation.java index abf2356a3e49d3df83c383575437669a980308ad..a257d466839c100fb0b8fdb4d8e16c25dde4bcf2 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/ComponentStartOperation.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/ComponentStartOperation.java @@ -15,6 +15,4 @@ */ package com.android.internal.widget.remotecompose.core.operations.layout; -import com.android.internal.widget.remotecompose.core.Operation; - -public interface ComponentStartOperation extends Operation {} +public interface ComponentStartOperation {} diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/LayoutComponent.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/LayoutComponent.java index 0041582f718939f48f399a8ac7419d4470988d12..7b0e4a2e262705927ac854b4f3e3120fa6e6f6c9 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/LayoutComponent.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/LayoutComponent.java @@ -19,8 +19,10 @@ import android.annotation.NonNull; import android.annotation.Nullable; import com.android.internal.widget.remotecompose.core.Operation; +import com.android.internal.widget.remotecompose.core.OperationInterface; import com.android.internal.widget.remotecompose.core.PaintContext; import com.android.internal.widget.remotecompose.core.operations.BitmapData; +import com.android.internal.widget.remotecompose.core.operations.FloatExpression; import com.android.internal.widget.remotecompose.core.operations.MatrixRestore; import com.android.internal.widget.remotecompose.core.operations.MatrixSave; import com.android.internal.widget.remotecompose.core.operations.MatrixTranslate; @@ -47,12 +49,6 @@ public class LayoutComponent extends Component { @Nullable protected ZIndexModifierOperation mZIndexModifier = null; @Nullable protected GraphicsLayerModifierOperation mGraphicsLayerModifier = null; - // Margins - protected float mMarginLeft = 0f; - protected float mMarginRight = 0f; - protected float mMarginTop = 0f; - protected float mMarginBottom = 0f; - protected float mPaddingLeft = 0f; protected float mPaddingRight = 0f; protected float mPaddingTop = 0f; @@ -76,22 +72,6 @@ public class LayoutComponent extends Component { super(parent, componentId, animationId, x, y, width, height); } - public float getMarginLeft() { - return mMarginLeft; - } - - public float getMarginRight() { - return mMarginRight; - } - - public float getMarginTop() { - return mMarginTop; - } - - public float getMarginBottom() { - return mMarginBottom; - } - public float getPaddingLeft() { return mPaddingLeft; } @@ -133,8 +113,7 @@ public class LayoutComponent extends Component { public void inflate() { ArrayList data = new ArrayList<>(); - ArrayList touchExpressions = new ArrayList<>(); - ArrayList paintData = new ArrayList<>(); + ArrayList supportedOperations = new ArrayList<>(); for (Operation op : mList) { if (op instanceof LayoutComponentContent) { @@ -179,10 +158,10 @@ public class LayoutComponent extends Component { mComponentModifiers.add((ModifierOperation) op); } else if (op instanceof TextData) { data.add((TextData) op); - } else if (op instanceof TouchExpression) { - touchExpressions.add((TouchExpression) op); - } else if (op instanceof PaintData) { - paintData.add((PaintData) op); + } else if (op instanceof TouchExpression + || (op instanceof PaintData) + || (op instanceof FloatExpression)) { + supportedOperations.add(op); } else { // nothing } @@ -190,8 +169,7 @@ public class LayoutComponent extends Component { mList.clear(); mList.addAll(data); - mList.addAll(touchExpressions); - mList.addAll(paintData); + mList.addAll(supportedOperations); mList.add(mComponentModifiers); for (Component c : mChildrenComponents) { c.mParent = this; @@ -203,10 +181,6 @@ public class LayoutComponent extends Component { mX = 0f; mY = 0f; - mMarginLeft = 0f; - mMarginTop = 0f; - mMarginRight = 0f; - mMarginBottom = 0f; mPaddingLeft = 0f; mPaddingTop = 0f; mPaddingRight = 0f; @@ -214,7 +188,7 @@ public class LayoutComponent extends Component { boolean applyHorizontalMargin = true; boolean applyVerticalMargin = true; - for (Operation op : mComponentModifiers.getList()) { + for (OperationInterface op : mComponentModifiers.getList()) { if (op instanceof PaddingModifierOperation) { // We are accumulating padding modifiers to compute the margin // until we hit a dimension; the computed padding for the @@ -223,31 +197,17 @@ public class LayoutComponent extends Component { float right = ((PaddingModifierOperation) op).getRight(); float top = ((PaddingModifierOperation) op).getTop(); float bottom = ((PaddingModifierOperation) op).getBottom(); - if (applyHorizontalMargin) { - mMarginLeft += left; - mMarginRight += right; - } - if (applyVerticalMargin) { - mMarginTop += top; - mMarginBottom += bottom; - } mPaddingLeft += left; mPaddingTop += top; mPaddingRight += right; mPaddingBottom += bottom; - } - if (op instanceof WidthModifierOperation && mWidthModifier == null) { + } else if (op instanceof WidthModifierOperation && mWidthModifier == null) { mWidthModifier = (WidthModifierOperation) op; - applyHorizontalMargin = false; - } - if (op instanceof HeightModifierOperation && mHeightModifier == null) { + } else if (op instanceof HeightModifierOperation && mHeightModifier == null) { mHeightModifier = (HeightModifierOperation) op; - applyVerticalMargin = false; - } - if (op instanceof ZIndexModifierOperation) { + } else if (op instanceof ZIndexModifierOperation) { mZIndexModifier = (ZIndexModifierOperation) op; - } - if (op instanceof GraphicsLayerModifierOperation) { + } else if (op instanceof GraphicsLayerModifierOperation) { mGraphicsLayerModifier = (GraphicsLayerModifierOperation) op; } } @@ -339,7 +299,7 @@ public class LayoutComponent extends Component { float s = 0f; float e = 0f; float w = 0f; - for (Operation c : mComponentModifiers.getList()) { + for (OperationInterface c : mComponentModifiers.getList()) { if (c instanceof WidthModifierOperation) { WidthModifierOperation o = (WidthModifierOperation) c; if (o.getType() == DimensionModifierOperation.Type.EXACT @@ -366,7 +326,7 @@ public class LayoutComponent extends Component { public float computeModifierDefinedPaddingWidth(@NonNull float[] padding) { float s = 0f; float e = 0f; - for (Operation c : mComponentModifiers.getList()) { + for (OperationInterface c : mComponentModifiers.getList()) { if (c instanceof PaddingModifierOperation) { PaddingModifierOperation pop = (PaddingModifierOperation) c; s += pop.getLeft(); @@ -383,7 +343,7 @@ public class LayoutComponent extends Component { float t = 0f; float b = 0f; float h = 0f; - for (Operation c : mComponentModifiers.getList()) { + for (OperationInterface c : mComponentModifiers.getList()) { if (c instanceof HeightModifierOperation) { HeightModifierOperation o = (HeightModifierOperation) c; if (o.getType() == DimensionModifierOperation.Type.EXACT @@ -410,7 +370,7 @@ public class LayoutComponent extends Component { public float computeModifierDefinedPaddingHeight(@NonNull float[] padding) { float t = 0f; float b = 0f; - for (Operation c : mComponentModifiers.getList()) { + for (OperationInterface c : mComponentModifiers.getList()) { if (c instanceof PaddingModifierOperation) { PaddingModifierOperation pop = (PaddingModifierOperation) c; t += pop.getTop(); diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/LayoutComponentContent.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/LayoutComponentContent.java index 7eea885f6b6d2c2b1d51ebd7e87b47c47b5b69f3..20e4688aaa323132a97b5edc8cda4ef084763dc9 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/LayoutComponentContent.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/LayoutComponentContent.java @@ -46,6 +46,11 @@ public class LayoutComponentContent extends Component implements ComponentStartO return "LayoutContent"; } + /** + * The OP_CODE for this command + * + * @return the opcode + */ public static int id() { return Operations.LAYOUT_CONTENT; } @@ -61,6 +66,12 @@ public class LayoutComponentContent extends Component implements ComponentStartO buffer.writeInt(componentId); } + /** + * Read this operation and add it to the list of operations + * + * @param buffer the buffer to read + * @param operations the list of operations that will be added to + */ public static void read(@NonNull WireBuffer buffer, @NonNull List operations) { int componentId = buffer.readInt(); operations.add(new LayoutComponentContent(componentId, 0, 0, 0, 0, null, -1)); diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/LoopEnd.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/LoopEnd.java index 71de2857258b803810b005376368a4ee6a4b9e18..d88f711c62c6e4c07141ccdc13c46b6c26a4169d 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/LoopEnd.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/LoopEnd.java @@ -25,7 +25,7 @@ import com.android.internal.widget.remotecompose.core.documentation.Documentatio import java.util.List; -public class LoopEnd implements Operation { +public class LoopEnd extends Operation { @Override public void write(@NonNull WireBuffer buffer) { @@ -54,6 +54,11 @@ public class LoopEnd implements Operation { return "LoopEnd"; } + /** + * The OP_CODE for this command + * + * @return the opcode + */ public static int id() { return Operations.LOOP_END; } @@ -62,6 +67,12 @@ public class LoopEnd implements Operation { buffer.start(id()); } + /** + * Read this operation and add it to the list of operations + * + * @param buffer the buffer to read + * @param operations the list of operations that will be added to + */ public static void read(@NonNull WireBuffer buffer, @NonNull List operations) { operations.add(new LoopEnd()); } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/LoopOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/LoopOperation.java index d88382dde7e04d587d939f7a930150b9a35508ff..83a2f0e1ffa367aadedbbd2593412db4f86cef66 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/LoopOperation.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/LoopOperation.java @@ -21,31 +21,57 @@ import com.android.internal.widget.remotecompose.core.Operation; import com.android.internal.widget.remotecompose.core.Operations; import com.android.internal.widget.remotecompose.core.PaintContext; import com.android.internal.widget.remotecompose.core.PaintOperation; +import com.android.internal.widget.remotecompose.core.RemoteContext; import com.android.internal.widget.remotecompose.core.VariableSupport; import com.android.internal.widget.remotecompose.core.WireBuffer; import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder; +import com.android.internal.widget.remotecompose.core.documentation.DocumentedOperation; +import com.android.internal.widget.remotecompose.core.operations.Utils; import java.util.ArrayList; import java.util.List; /** Represents a loop of operations */ -public class LoopOperation extends PaintOperation { +public class LoopOperation extends PaintOperation implements VariableSupport { private static final int OP_CODE = Operations.LOOP_START; @NonNull public ArrayList mList = new ArrayList<>(); int mIndexVariableId; - float mUntil = 12; - float mFrom = 0; - float mStep = 1; + float mUntil; + float mFrom; + float mStep; + float mUntilOut; + float mFromOut; + float mStepOut; public LoopOperation(int count, int indexId) { mUntil = count; mIndexVariableId = indexId; } - public LoopOperation(float count, float from, float step, int indexId) { - mUntil = count; + @Override + public void registerListening(RemoteContext context) { + if (Float.isNaN(mUntil)) { + context.listensTo(Utils.idFromNan(mUntil), this); + } + if (Float.isNaN(mFrom)) { + context.listensTo(Utils.idFromNan(mFrom), this); + } + if (Float.isNaN(mStep)) { + context.listensTo(Utils.idFromNan(mStep), this); + } + } + + @Override + public void updateVariables(RemoteContext context) { + mUntilOut = Float.isNaN(mUntil) ? context.getFloat(Utils.idFromNan(mUntil)) : mUntil; + mFromOut = Float.isNaN(mFrom) ? context.getFloat(Utils.idFromNan(mFrom)) : mFrom; + mStepOut = Float.isNaN(mStep) ? context.getFloat(Utils.idFromNan(mStep)) : mStep; + } + + public LoopOperation(int indexId, float from, float step, float until) { + mUntil = until; mFrom = from; mStep = step; mIndexVariableId = indexId; @@ -58,13 +84,19 @@ public class LoopOperation extends PaintOperation { @Override public void write(@NonNull WireBuffer buffer) { - apply(buffer, mUntil, mFrom, mStep, mIndexVariableId); + apply(buffer, mIndexVariableId, mFrom, mStep, mUntil); } @NonNull @Override public String toString() { - return "LoopOperation"; + StringBuilder builder = new StringBuilder("LoopOperation\n"); + for (Operation operation : mList) { + builder.append(" "); + builder.append(operation); + builder.append("\n"); + } + return builder.toString(); } @NonNull @@ -76,13 +108,13 @@ public class LoopOperation extends PaintOperation { @Override public void paint(@NonNull PaintContext context) { if (mIndexVariableId == 0) { - for (float i = mFrom; i < mUntil; i += mStep) { + for (float i = mFromOut; i < mUntilOut; i += mStepOut) { for (Operation op : mList) { op.apply(context.getContext()); } } } else { - for (float i = mFrom; i < mUntil; i += mStep) { + for (float i = mFromOut; i < mUntilOut; i += mStepOut) { context.getContext().loadFloat(mIndexVariableId, i); for (Operation op : mList) { if (op instanceof VariableSupport) { @@ -100,24 +132,34 @@ public class LoopOperation extends PaintOperation { } public static void apply( - @NonNull WireBuffer buffer, float count, float from, float step, int indexId) { + @NonNull WireBuffer buffer, int indexId, float from, float step, float until) { buffer.start(OP_CODE); - buffer.writeFloat(count); + buffer.writeInt(indexId); buffer.writeFloat(from); buffer.writeFloat(step); - buffer.writeInt(indexId); + buffer.writeFloat(until); } + /** + * Read this operation and add it to the list of operations + * + * @param buffer the buffer to read + * @param operations the list of operations that will be added to + */ public static void read(@NonNull WireBuffer buffer, @NonNull List operations) { - float count = buffer.readFloat(); + int indexId = buffer.readInt(); float from = buffer.readFloat(); float step = buffer.readFloat(); - int indexId = buffer.readInt(); - operations.add(new LoopOperation(count, from, step, indexId)); + float until = buffer.readFloat(); + operations.add(new LoopOperation(indexId, from, step, until)); } public static void documentation(@NonNull DocumentationBuilder doc) { doc.operation("Operations", OP_CODE, name()) - .description("Loop. This operation execute" + " a list of action in a loop"); + .description("Loop. This operation execute" + " a list of action in a loop") + .field(DocumentedOperation.INT, "id", "if not 0 write value") + .field(DocumentedOperation.FLOAT, "from", "values starts at") + .field(DocumentedOperation.FLOAT, "step", "value step") + .field(DocumentedOperation.FLOAT, "until", "stops less than or equal"); } } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/OperationsListEnd.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/OperationsListEnd.java index ca79003448e73235d3e310500a975b92521ae6f1..99b7e68786fb8c5d1825a440dba51ba9a7e4ab4d 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/OperationsListEnd.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/OperationsListEnd.java @@ -25,7 +25,7 @@ import com.android.internal.widget.remotecompose.core.documentation.Documentatio import java.util.List; -public class OperationsListEnd implements Operation { +public class OperationsListEnd extends Operation { @Override public void write(@NonNull WireBuffer buffer) { @@ -54,6 +54,11 @@ public class OperationsListEnd implements Operation { return "ListEnd"; } + /** + * The OP_CODE for this command + * + * @return the opcode + */ public static int id() { return Operations.OPERATIONS_LIST_END; } @@ -62,6 +67,12 @@ public class OperationsListEnd implements Operation { buffer.start(id()); } + /** + * Read this operation and add it to the list of operations + * + * @param buffer the buffer to read + * @param operations the list of operations that will be added to + */ public static void read(@NonNull WireBuffer buffer, @NonNull List operations) { operations.add(new OperationsListEnd()); } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/RootLayoutComponent.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/RootLayoutComponent.java index 85c71537540c3ad3255678e52ddda2456500263a..fd1628729dd41a6fe7f1679828a4e263c119d95b 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/RootLayoutComponent.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/RootLayoutComponent.java @@ -197,6 +197,11 @@ public class RootLayoutComponent extends Component implements ComponentStartOper return "RootLayout"; } + /** + * The OP_CODE for this command + * + * @return the opcode + */ public static int id() { return Operations.LAYOUT_ROOT; } @@ -206,6 +211,12 @@ public class RootLayoutComponent extends Component implements ComponentStartOper buffer.writeInt(componentId); } + /** + * Read this operation and add it to the list of operations + * + * @param buffer the buffer to read + * @param operations the list of operations that will be added to + */ public static void read(@NonNull WireBuffer buffer, @NonNull List operations) { int componentId = buffer.readInt(); operations.add(new RootLayoutComponent(componentId, 0, 0, 0, 0, null, -1)); diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/TouchCancelModifierOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/TouchCancelModifierOperation.java index 0316f96bfc3e3146160f30263c62fc096b7d70a8..3185bb5f0f72e12f71355c95e467ee722e4a2927 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/TouchCancelModifierOperation.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/TouchCancelModifierOperation.java @@ -84,6 +84,12 @@ public class TouchCancelModifierOperation extends ListActionsOperation implement buffer.start(OP_CODE); } + /** + * Read this operation and add it to the list of operations + * + * @param buffer the buffer to read + * @param operations the list of operations that will be added to + */ public static void read(WireBuffer buffer, List operations) { operations.add(new TouchCancelModifierOperation()); } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/animation/AnimationSpec.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/animation/AnimationSpec.java index 6fb70598571172c533ef7d8c124789a8b20eb4fc..b230b09112b29f5a6a1c40878b9720f9a9f1d2bc 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/animation/AnimationSpec.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/animation/AnimationSpec.java @@ -29,7 +29,7 @@ import com.android.internal.widget.remotecompose.core.operations.utilities.easin import java.util.List; /** Basic component animation spec */ -public class AnimationSpec implements Operation { +public class AnimationSpec extends Operation { int mAnimationId = -1; int mMotionDuration = 300; int mMotionEasingType = GeneralEasing.CUBIC_STANDARD; @@ -142,6 +142,11 @@ public class AnimationSpec implements Operation { return "AnimationSpec"; } + /** + * The OP_CODE for this command + * + * @return the opcode + */ public static int id() { return Operations.ANIMATION_SPEC; } @@ -193,6 +198,12 @@ public class AnimationSpec implements Operation { buffer.writeInt(animationToInt(exitAnimation)); } + /** + * Read this operation and add it to the list of operations + * + * @param buffer the buffer to read + * @param operations the list of operations that will be added to + */ public static void read(@NonNull WireBuffer buffer, @NonNull List operations) { int animationId = buffer.readInt(); int motionDuration = buffer.readInt(); diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/BoxLayout.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/BoxLayout.java index 47a9421879002fae6468e1195b601a7e30dd535a..01cd7ccd0b947b7cd9619f91d5cb2ff809e8cb26 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/BoxLayout.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/BoxLayout.java @@ -108,6 +108,8 @@ public class BoxLayout extends LayoutManager implements ComponentStartOperation @NonNull PaintContext context, float maxWidth, float maxHeight, + boolean horizontalWrap, + boolean verticalWrap, @NonNull MeasurePass measure, @NonNull Size size) { for (Component c : mChildrenComponents) { @@ -175,6 +177,11 @@ public class BoxLayout extends LayoutManager implements ComponentStartOperation return "BoxLayout"; } + /** + * The OP_CODE for this command + * + * @return the opcode + */ public static int id() { return Operations.LAYOUT_BOX; } @@ -192,6 +199,12 @@ public class BoxLayout extends LayoutManager implements ComponentStartOperation buffer.writeInt(verticalPositioning); } + /** + * Read this operation and add it to the list of operations + * + * @param buffer the buffer to read + * @param operations the list of operations that will be added to + */ public static void read(@NonNull WireBuffer buffer, @NonNull List operations) { int componentId = buffer.readInt(); int animationId = buffer.readInt(); diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/CanvasLayout.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/CanvasLayout.java index 476b1a666fe98f2c1c592ecd968e8db3412e8622..665db263767486fbc758d29ac6249f283b3e268d 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/CanvasLayout.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/CanvasLayout.java @@ -77,6 +77,11 @@ public class CanvasLayout extends BoxLayout { return "CanvasLayout"; } + /** + * The OP_CODE for this command + * + * @return the opcode + */ public static int id() { return Operations.LAYOUT_CANVAS; } @@ -87,6 +92,12 @@ public class CanvasLayout extends BoxLayout { buffer.writeInt(animationId); } + /** + * Read this operation and add it to the list of operations + * + * @param buffer the buffer to read + * @param operations the list of operations that will be added to + */ public static void read(@NonNull WireBuffer buffer, @NonNull List operations) { int componentId = buffer.readInt(); int animationId = buffer.readInt(); diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/ColumnLayout.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/ColumnLayout.java index 68e18c699539ad60bdcb3776b73280d0a45e802b..5b9ee0ff511fe2ad70c3487f97a1daad089f6ce8 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/ColumnLayout.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/ColumnLayout.java @@ -125,17 +125,21 @@ public class ColumnLayout extends LayoutManager implements ComponentStartOperati @NonNull PaintContext context, float maxWidth, float maxHeight, + boolean horizontalWrap, + boolean verticalWrap, @NonNull MeasurePass measure, @NonNull Size size) { DebugLog.s(() -> "COMPUTE WRAP SIZE in " + this + " (" + mComponentId + ")"); int visibleChildrens = 0; + float currentMaxHeight = maxHeight; for (Component c : mChildrenComponents) { - c.measure(context, 0f, maxWidth, 0f, maxHeight, measure); + c.measure(context, 0f, maxWidth, 0f, currentMaxHeight, measure); ComponentMeasure m = measure.get(c); if (m.getVisibility() != Visibility.GONE) { size.setWidth(Math.max(size.getWidth(), m.getW())); size.setHeight(size.getHeight() + m.getH()); visibleChildrens++; + currentMaxHeight -= m.getH(); } } if (!mChildrenComponents.isEmpty()) { @@ -342,6 +346,11 @@ public class ColumnLayout extends LayoutManager implements ComponentStartOperati return "ColumnLayout"; } + /** + * The OP_CODE for this command + * + * @return the opcode + */ public static int id() { return Operations.LAYOUT_COLUMN; } @@ -361,6 +370,12 @@ public class ColumnLayout extends LayoutManager implements ComponentStartOperati buffer.writeFloat(spacedBy); } + /** + * Read this operation and add it to the list of operations + * + * @param buffer the buffer to read + * @param operations the list of operations that will be added to + */ public static void read(@NonNull WireBuffer buffer, @NonNull List operations) { int componentId = buffer.readInt(); int animationId = buffer.readInt(); diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/LayoutManager.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/LayoutManager.java index 3b5aaf38fb5b3b5fb94b5195e761a1bf4b02ab90..6a15b7f1b17858ea27bc2849142ec37d4a08912f 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/LayoutManager.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/LayoutManager.java @@ -53,6 +53,8 @@ public abstract class LayoutManager extends LayoutComponent implements Measurabl @NonNull PaintContext context, float maxWidth, float maxHeight, + boolean horizontalWrap, + boolean verticalWrap, @NonNull MeasurePass measure, @NonNull Size size) { // nothing here @@ -129,42 +131,67 @@ public abstract class LayoutManager extends LayoutComponent implements Measurabl float maxHeight, @NonNull MeasurePass measure) { boolean hasWrap = true; - float measuredWidth = - Math.min(maxWidth, computeModifierDefinedWidth() - mMarginLeft - mMarginRight); - float measuredHeight = - Math.min(maxHeight, computeModifierDefinedHeight() - mMarginTop - mMarginBottom); - float insetMaxWidth = maxWidth - mMarginLeft - mMarginRight; - float insetMaxHeight = maxHeight - mMarginTop - mMarginBottom; + + float measuredWidth = Math.min(maxWidth, computeModifierDefinedWidth()); + float measuredHeight = Math.min(maxHeight, computeModifierDefinedHeight()); + float insetMaxWidth = maxWidth - mPaddingLeft - mPaddingRight; + float insetMaxHeight = maxHeight - mPaddingTop - mPaddingBottom; + if (mWidthModifier.isIntrinsicMin()) { maxWidth = intrinsicWidth(); } if (mHeightModifier.isIntrinsicMin()) { maxHeight = intrinsicHeight(); } - if (mWidthModifier.isWrap() || mHeightModifier.isWrap()) { // TODO: potential npe -- bbade@ + + boolean hasHorizontalWrap = mWidthModifier.isWrap(); + boolean hasVerticalWrap = mHeightModifier.isWrap(); + if (hasHorizontalWrap || hasVerticalWrap) { // TODO: potential npe -- bbade@ mCachedWrapSize.setWidth(0f); mCachedWrapSize.setHeight(0f); - computeWrapSize(context, maxWidth, maxHeight, measure, mCachedWrapSize); + float wrapMaxWidth = insetMaxWidth; + float wrapMaxHeight = insetMaxHeight; + if (hasHorizontalWrap) { + wrapMaxWidth = insetMaxWidth - mPaddingLeft - mPaddingRight; + } + if (hasVerticalWrap) { + wrapMaxHeight = insetMaxHeight - mPaddingTop - mPaddingBottom; + } + computeWrapSize( + context, + wrapMaxWidth, + wrapMaxHeight, + mWidthModifier.isWrap(), + mHeightModifier.isWrap(), + measure, + mCachedWrapSize); measuredWidth = mCachedWrapSize.getWidth(); + if (hasHorizontalWrap) { + measuredWidth += mPaddingLeft + mPaddingRight; + } measuredHeight = mCachedWrapSize.getHeight(); + if (hasVerticalWrap) { + measuredHeight += mPaddingTop + mPaddingBottom; + } } else { hasWrap = false; } + if (isInHorizontalFill()) { - measuredWidth = insetMaxWidth; + measuredWidth = maxWidth; } else if (mWidthModifier.hasWeight()) { measuredWidth = Math.max(measuredWidth, computeModifierDefinedWidth()); } else { measuredWidth = Math.max(measuredWidth, minWidth); - measuredWidth = Math.min(measuredWidth, insetMaxWidth); + measuredWidth = Math.min(measuredWidth, maxWidth); } if (isInVerticalFill()) { // todo: potential npe -- bbade@ - measuredHeight = insetMaxHeight; + measuredHeight = maxHeight; } else if (mHeightModifier.hasWeight()) { measuredHeight = Math.max(measuredHeight, computeModifierDefinedHeight()); } else { measuredHeight = Math.max(measuredHeight, minHeight); - measuredHeight = Math.min(measuredHeight, insetMaxHeight); + measuredHeight = Math.min(measuredHeight, maxHeight); } if (minWidth == maxWidth) { measuredWidth = maxWidth; @@ -172,20 +199,27 @@ public abstract class LayoutManager extends LayoutComponent implements Measurabl if (minHeight == maxHeight) { measuredHeight = maxHeight; } - measuredWidth = Math.min(measuredWidth, insetMaxWidth); - measuredHeight = Math.min(measuredHeight, insetMaxHeight); + if (!hasWrap) { if (hasHorizontalScroll()) { mCachedWrapSize.setWidth(0f); mCachedWrapSize.setHeight(0f); - computeWrapSize(context, Float.MAX_VALUE, maxHeight, measure, mCachedWrapSize); + computeWrapSize( + context, + Float.MAX_VALUE, + maxHeight, + false, + false, + measure, + mCachedWrapSize); float w = mCachedWrapSize.getWidth(); computeSize(context, 0f, w, 0, measuredHeight, measure); mComponentModifiers.setHorizontalScrollDimension(measuredWidth, w); } else if (hasVerticalScroll()) { mCachedWrapSize.setWidth(0f); mCachedWrapSize.setHeight(0f); - computeWrapSize(context, maxWidth, Float.MAX_VALUE, measure, mCachedWrapSize); + computeWrapSize( + context, maxWidth, Float.MAX_VALUE, false, false, measure, mCachedWrapSize); float h = mCachedWrapSize.getHeight(); computeSize(context, 0f, measuredWidth, 0, h, measure); mComponentModifiers.setVerticalScrollDimension(measuredHeight, h); @@ -202,9 +236,6 @@ public abstract class LayoutManager extends LayoutComponent implements Measurabl cm.setH(measuredHeight); } - measuredWidth += mMarginLeft + mMarginRight; - measuredHeight += mMarginTop + mMarginBottom; - ComponentMeasure m = measure.get(this); m.setW(measuredWidth); m.setH(measuredHeight); diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/RowLayout.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/RowLayout.java index 0ce634f9c1ab69202c156aaaabac69b83dcdd774..0ec820b859649de9781a56c61dbe7cd1d08df039 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/RowLayout.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/RowLayout.java @@ -123,21 +123,25 @@ public class RowLayout extends LayoutManager implements ComponentStartOperation @NonNull PaintContext context, float maxWidth, float maxHeight, + boolean horizontalWrap, + boolean verticalWrap, @NonNull MeasurePass measure, @NonNull Size size) { DebugLog.s(() -> "COMPUTE WRAP SIZE in " + this + " (" + mComponentId + ")"); - // int visibleChildrens = 0; + int visibleChildrens = 0; + float currentMaxWidth = maxWidth; for (Component c : mChildrenComponents) { - c.measure(context, 0f, maxWidth, 0f, maxHeight, measure); + c.measure(context, 0f, currentMaxWidth, 0f, maxHeight, measure); ComponentMeasure m = measure.get(c); if (m.getVisibility() != Visibility.GONE) { size.setWidth(size.getWidth() + m.getW()); size.setHeight(Math.max(size.getHeight(), m.getH())); - // visibleChildrens++; + visibleChildrens++; + currentMaxWidth -= m.getW(); } } if (!mChildrenComponents.isEmpty()) { - size.setWidth(size.getWidth() + (mSpacedBy * (mChildrenComponents.size() - 1))); + size.setWidth(size.getWidth() + (mSpacedBy * (visibleChildrens - 1))); } DebugLog.e(); } @@ -345,6 +349,11 @@ public class RowLayout extends LayoutManager implements ComponentStartOperation return "RowLayout"; } + /** + * The OP_CODE for this command + * + * @return the opcode + */ public static int id() { return Operations.LAYOUT_ROW; } @@ -364,6 +373,12 @@ public class RowLayout extends LayoutManager implements ComponentStartOperation buffer.writeFloat(spacedBy); } + /** + * Read this operation and add it to the list of operations + * + * @param buffer the buffer to read + * @param operations the list of operations that will be added to + */ public static void read(@NonNull WireBuffer buffer, @NonNull List operations) { int componentId = buffer.readInt(); int animationId = buffer.readInt(); diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/StateLayout.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/StateLayout.java index 73a104bcafa67935bab1511e1dc51ecbefec45b1..61a3ec964142d6dfbc46bb3b6569e7ba34029027 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/StateLayout.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/StateLayout.java @@ -159,10 +159,13 @@ public class StateLayout extends LayoutManager implements ComponentStartOperatio @NonNull PaintContext context, float maxWidth, float maxHeight, + boolean horizontalWrap, + boolean verticalWrap, @NonNull MeasurePass measure, @NonNull Size size) { LayoutManager layout = getLayout(currentLayoutIndex); - layout.computeWrapSize(context, maxWidth, maxHeight, measure, size); + layout.computeWrapSize( + context, maxWidth, maxHeight, horizontalWrap, verticalWrap, measure, size); } @Override @@ -442,11 +445,7 @@ public class StateLayout extends LayoutManager implements ComponentStartOperatio int id = c.getPaintId(); for (int i = 0; i < idIndex; i++) { if (cacheListElementsId[i] == id) { - context.translate( - previousLayout.getMarginLeft(), previousLayout.getMarginTop()); c.paint(context); - context.translate( - -currentLayout.getMarginLeft(), -currentLayout.getMarginTop()); break; } } @@ -472,16 +471,10 @@ public class StateLayout extends LayoutManager implements ComponentStartOperatio // and fade in the new one Component previousComponent = stateComponents[previousLayoutIndex]; if (previousComponent != null && component != previousComponent) { - context.translate( - currentLayout.getMarginLeft(), currentLayout.getMarginTop()); previousComponent.paint(context); - context.translate( - -currentLayout.getMarginLeft(), -currentLayout.getMarginTop()); } } - context.translate(currentLayout.getMarginLeft(), currentLayout.getMarginTop()); component.paint(context); - context.translate(-currentLayout.getMarginLeft(), -currentLayout.getMarginTop()); } else if (op instanceof PaintOperation) { ((PaintOperation) op).paint(context); } @@ -563,6 +556,12 @@ public class StateLayout extends LayoutManager implements ComponentStartOperatio buffer.writeInt(indexId); } + /** + * Read this operation and add it to the list of operations + * + * @param buffer the buffer to read + * @param operations the list of operations that will be added to + */ public static void read(@NonNull WireBuffer buffer, @NonNull List operations) { int componentId = buffer.readInt(); int animationId = buffer.readInt(); diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/TextLayout.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/TextLayout.java index a527e5ad40777fca20f1c40e6f41cd595da31f83..8e7f538d000489e7a35d943e530ea28828b37603 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/TextLayout.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/managers/TextLayout.java @@ -52,8 +52,8 @@ public class TextLayout extends LayoutManager implements ComponentStartOperation private int mType = -1; private float mTextX; private float mTextY; - private float mTextW; - private float mTextH; + private float mTextW = -1; + private float mTextH = -1; @Nullable private String mCachedString = ""; @@ -66,7 +66,11 @@ public class TextLayout extends LayoutManager implements ComponentStartOperation @Override public void updateVariables(@NonNull RemoteContext context) { - mCachedString = context.getText(mTextId); + String cachedString = context.getText(mTextId); + if (cachedString != null && cachedString.equalsIgnoreCase(mCachedString)) { + return; + } + mCachedString = cachedString; if (mType == -1) { if (mFontFamilyId != -1) { String fontFamily = context.getText(mFontFamilyId); @@ -86,8 +90,9 @@ public class TextLayout extends LayoutManager implements ComponentStartOperation mType = 0; } } - mNeedsMeasure = true; - needsRepaint(); + mTextW = -1; + mTextH = -1; + invalidateMeasure(); } public TextLayout( @@ -168,7 +173,14 @@ public class TextLayout extends LayoutManager implements ComponentStartOperation return; } int length = mCachedString.length(); - context.drawTextRun(mTextId, 0, length, 0, 0, mTextX, mTextY, false); + if (mTextW > mWidth) { + context.save(); + context.translate(getScrollX(), getScrollY()); + context.drawTextRun(mTextId, 0, length, 0, 0, mTextX, mTextY, false); + context.restore(); + } else { + context.drawTextRun(mTextId, 0, length, 0, 0, mTextX, mTextY, false); + } if (DEBUG) { mPaint.setStyle(PaintBundle.STYLE_FILL_AND_STROKE); mPaint.setColor(1f, 1F, 1F, 1F); @@ -246,6 +258,8 @@ public class TextLayout extends LayoutManager implements ComponentStartOperation @NonNull PaintContext context, float maxWidth, float maxHeight, + boolean horizontalWrap, + boolean verticalWrap, @NonNull MeasurePass measure, @NonNull Size size) { context.savePaint(); @@ -262,9 +276,9 @@ public class TextLayout extends LayoutManager implements ComponentStartOperation context.restorePaint(); float w = bounds[2] - bounds[0]; float h = bounds[3] - bounds[1]; - size.setWidth(w); + size.setWidth(Math.min(maxWidth, w)); mTextX = -bounds[0]; - size.setHeight(h); + size.setHeight(Math.min(maxHeight, h)); mTextY = -bounds[1]; mTextW = w; mTextH = h; @@ -285,6 +299,11 @@ public class TextLayout extends LayoutManager implements ComponentStartOperation return "TextLayout"; } + /** + * The OP_CODE for this command + * + * @return the opcode + */ public static int id() { return Operations.LAYOUT_TEXT; } @@ -312,6 +331,12 @@ public class TextLayout extends LayoutManager implements ComponentStartOperation buffer.writeInt(textAlign); } + /** + * Read this operation and add it to the list of operations + * + * @param buffer the buffer to read + * @param operations the list of operations that will be added to + */ public static void read(@NonNull WireBuffer buffer, @NonNull List operations) { int componentId = buffer.readInt(); int animationId = buffer.readInt(); diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/BackgroundModifierOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/BackgroundModifierOperation.java index 71d2ba6edf21a39ee979ae745e5c3f991d560488..5df16c5bc03a11443805a03fb9a27e59c1e7c189 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/BackgroundModifierOperation.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/BackgroundModifierOperation.java @@ -114,6 +114,11 @@ public class BackgroundModifierOperation extends DecoratorModifierOperation { return CLASS_NAME; } + /** + * The OP_CODE for this command + * + * @return the opcode + */ public static int id() { return OP_CODE; } @@ -142,6 +147,12 @@ public class BackgroundModifierOperation extends DecoratorModifierOperation { buffer.writeInt(shapeType); } + /** + * Read this operation and add it to the list of operations + * + * @param buffer the buffer to read + * @param operations the list of operations that will be added to + */ public static void read(@NonNull WireBuffer buffer, @NonNull List operations) { float x = buffer.readFloat(); float y = buffer.readFloat(); diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/BorderModifierOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/BorderModifierOperation.java index 0707cd62767802a8e0b4d4da011508f98679e26c..bfadd2f1ef9ce1062bd6f792538f72a15d0c8d7e 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/BorderModifierOperation.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/BorderModifierOperation.java @@ -160,6 +160,11 @@ public class BorderModifierOperation extends DecoratorModifierOperation { return CLASS_NAME; } + /** + * The OP_CODE for this command + * + * @return the opcode + */ public static int id() { return OP_CODE; } @@ -192,6 +197,12 @@ public class BorderModifierOperation extends DecoratorModifierOperation { buffer.writeInt(shapeType); } + /** + * Read this operation and add it to the list of operations + * + * @param buffer the buffer to read + * @param operations the list of operations that will be added to + */ public static void read(@NonNull WireBuffer buffer, @NonNull List operations) { float x = buffer.readFloat(); float y = buffer.readFloat(); diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ClipRectModifierOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ClipRectModifierOperation.java index e05b02781e10283c7a81ba3367f572b9e8dff0e8..d0af872acc532e7c527a0c8999c2309bad5bb522 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ClipRectModifierOperation.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ClipRectModifierOperation.java @@ -60,6 +60,11 @@ public class ClipRectModifierOperation extends DecoratorModifierOperation { return CLASS_NAME; } + /** + * The OP_CODE for this command + * + * @return the opcode + */ public static int id() { return OP_CODE; } @@ -68,6 +73,12 @@ public class ClipRectModifierOperation extends DecoratorModifierOperation { buffer.start(OP_CODE); } + /** + * Read this operation and add it to the list of operations + * + * @param buffer the buffer to read + * @param operations the list of operations that will be added to + */ public static void read(@NonNull WireBuffer buffer, @NonNull List operations) { operations.add(new ClipRectModifierOperation()); } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ComponentVisibilityOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ComponentVisibilityOperation.java index 471db0bedb1198e7bdedff8a706f858221209043..1e6ccfcb5d342bd8df865cdc24f7a102ef0c4377 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ComponentVisibilityOperation.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ComponentVisibilityOperation.java @@ -34,7 +34,7 @@ import com.android.internal.widget.remotecompose.core.operations.utilities.Strin import java.util.List; /** Allows setting visibility on a component */ -public class ComponentVisibilityOperation +public class ComponentVisibilityOperation extends Operation implements ModifierOperation, VariableSupport, DecoratorComponent { private static final int OP_CODE = Operations.MODIFIER_VISIBILITY; @@ -79,6 +79,12 @@ public class ComponentVisibilityOperation buffer.writeInt(valueId); } + /** + * Read this operation and add it to the list of operations + * + * @param buffer the buffer to read + * @param operations the list of operations that will be added to + */ public static void read(@NonNull WireBuffer buffer, @NonNull List operations) { int valueId = buffer.readInt(); operations.add(new ComponentVisibilityOperation(valueId)); diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/DimensionModifierOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/DimensionModifierOperation.java index b9324f0320d36392e30b24b73c7715f5044a80a8..b11deae3d1967b6a8577388f5d491f401cc9a223 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/DimensionModifierOperation.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/DimensionModifierOperation.java @@ -17,13 +17,15 @@ package com.android.internal.widget.remotecompose.core.operations.layout.modifie import android.annotation.NonNull; +import com.android.internal.widget.remotecompose.core.Operation; import com.android.internal.widget.remotecompose.core.RemoteContext; import com.android.internal.widget.remotecompose.core.VariableSupport; import com.android.internal.widget.remotecompose.core.operations.Utils; import com.android.internal.widget.remotecompose.core.operations.utilities.StringSerializer; /** Base class for dimension modifiers */ -public abstract class DimensionModifierOperation implements ModifierOperation, VariableSupport { +public abstract class DimensionModifierOperation extends Operation + implements ModifierOperation, VariableSupport { public enum Type { EXACT, diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/GraphicsLayerModifierOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/GraphicsLayerModifierOperation.java index 571e554b9c71136ab44ef3c1dcb9cc18b992bd67..4252309b7e4c4f87e012a450479e33192bc46d99 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/GraphicsLayerModifierOperation.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/GraphicsLayerModifierOperation.java @@ -206,6 +206,11 @@ public class GraphicsLayerModifierOperation extends DecoratorModifierOperation { return CLASS_NAME; } + /** + * The OP_CODE for this command + * + * @return the opcode + */ public static int id() { return OP_CODE; } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/HeightModifierOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/HeightModifierOperation.java index 7bb4a756afa577d39933a0d2895aa4af8f65800e..692b5269954abbd0117592720333a4e7539fdbce 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/HeightModifierOperation.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/HeightModifierOperation.java @@ -37,6 +37,11 @@ public class HeightModifierOperation extends DimensionModifierOperation { return CLASS_NAME; } + /** + * The OP_CODE for this command + * + * @return the opcode + */ public static int id() { return OP_CODE; } @@ -47,6 +52,12 @@ public class HeightModifierOperation extends DimensionModifierOperation { buffer.writeFloat(value); } + /** + * Read this operation and add it to the list of operations + * + * @param buffer the buffer to read + * @param operations the list of operations that will be added to + */ public static void read(@NonNull WireBuffer buffer, @NonNull List operations) { Type type = Type.fromInt(buffer.readInt()); float value = buffer.readFloat(); diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/HostActionOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/HostActionOperation.java index d239bc85744634f61e948fcb67b57bc54f9a034f..333e281d4abbcd4ba80e4ebce28f97ae4110a700 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/HostActionOperation.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/HostActionOperation.java @@ -32,7 +32,7 @@ import com.android.internal.widget.remotecompose.core.operations.utilities.Strin import java.util.List; /** Capture a host action information. This can be triggered on eg. a click. */ -public class HostActionOperation implements ActionOperation { +public class HostActionOperation extends Operation implements ActionOperation { private static final int OP_CODE = Operations.HOST_ACTION; int mActionId = -1; @@ -88,6 +88,12 @@ public class HostActionOperation implements ActionOperation { buffer.writeInt(actionId); } + /** + * Read this operation and add it to the list of operations + * + * @param buffer the buffer to read + * @param operations the list of operations that will be added to + */ public static void read(@NonNull WireBuffer buffer, @NonNull List operations) { int actionId = buffer.readInt(); operations.add(new HostActionOperation(actionId)); diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/HostNamedActionOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/HostNamedActionOperation.java index 3268e5efd4492f976e9928495aec24e524a469ed..f9a4270905a16ca4334aa70a0374d4cc434e483f 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/HostNamedActionOperation.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/HostNamedActionOperation.java @@ -32,7 +32,7 @@ import com.android.internal.widget.remotecompose.core.operations.utilities.Strin import java.util.List; /** Capture a host action information. This can be triggered on eg. a click. */ -public class HostNamedActionOperation implements ActionOperation { +public class HostNamedActionOperation extends Operation implements ActionOperation { private static final int OP_CODE = Operations.HOST_NAMED_ACTION; public static final int FLOAT_TYPE = 0; @@ -112,6 +112,12 @@ public class HostNamedActionOperation implements ActionOperation { buffer.writeInt(valueId); } + /** + * Read this operation and add it to the list of operations + * + * @param buffer the buffer to read + * @param operations the list of operations that will be added to + */ public static void read(@NonNull WireBuffer buffer, @NonNull List operations) { int textId = buffer.readInt(); int type = buffer.readInt(); diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ModifierOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ModifierOperation.java index 8f08f1417add3cf44e5800c17cb2f4092d07df7a..f8926fef56faf932c45a579e22fc2f0be00b7d87 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ModifierOperation.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ModifierOperation.java @@ -17,10 +17,10 @@ package com.android.internal.widget.remotecompose.core.operations.layout.modifie import android.annotation.NonNull; -import com.android.internal.widget.remotecompose.core.Operation; +import com.android.internal.widget.remotecompose.core.OperationInterface; import com.android.internal.widget.remotecompose.core.operations.utilities.StringSerializer; /** Represents a modifier */ -public interface ModifierOperation extends Operation { +public interface ModifierOperation extends OperationInterface { void serializeToString(int indent, @NonNull StringSerializer serializer); } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/OffsetModifierOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/OffsetModifierOperation.java index 8c07059369ab39d090d922e21e6f677deaef60db..69c4e9a8e42377772ab44ce1eb3813ae7c7f2efe 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/OffsetModifierOperation.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/OffsetModifierOperation.java @@ -94,6 +94,11 @@ public class OffsetModifierOperation extends DecoratorModifierOperation { return CLASS_NAME; } + /** + * The OP_CODE for this command + * + * @return the opcode + */ public static int id() { return OP_CODE; } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/PaddingModifierOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/PaddingModifierOperation.java index 2b6621e4fd58dcb05744c09d9d18df7d18c26c13..545df64ab154dfc294ed2b9a69d6f4db3d4d49fa 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/PaddingModifierOperation.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/PaddingModifierOperation.java @@ -32,7 +32,7 @@ import java.util.List; * Represents a padding modifier. Padding modifiers can be chained and will impact following * modifiers. */ -public class PaddingModifierOperation implements ModifierOperation { +public class PaddingModifierOperation extends Operation implements ModifierOperation { private static final int OP_CODE = Operations.MODIFIER_PADDING; public static final String CLASS_NAME = "PaddingModifierOperation"; float mLeft; @@ -118,6 +118,11 @@ public class PaddingModifierOperation implements ModifierOperation { return CLASS_NAME; } + /** + * The OP_CODE for this command + * + * @return the opcode + */ public static int id() { return Operations.MODIFIER_PADDING; } @@ -131,6 +136,12 @@ public class PaddingModifierOperation implements ModifierOperation { buffer.writeFloat(bottom); } + /** + * Read this operation and add it to the list of operations + * + * @param buffer the buffer to read + * @param operations the list of operations that will be added to + */ public static void read(@NonNull WireBuffer buffer, @NonNull List operations) { float left = buffer.readFloat(); float top = buffer.readFloat(); diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/RoundedClipRectModifierOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/RoundedClipRectModifierOperation.java index 3fefc58172709d2ebcefa08825b64aad1efef268..681501d9cdf9566a10efb937372d6ab79bd7b187 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/RoundedClipRectModifierOperation.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/RoundedClipRectModifierOperation.java @@ -37,11 +37,22 @@ public class RoundedClipRectModifierOperation extends DrawBase4 public static final int OP_CODE = Operations.MODIFIER_ROUNDED_CLIP_RECT; public static final String CLASS_NAME = "RoundedClipRectModifierOperation"; + /** + * Read this operation and add it to the list of operations + * + * @param buffer the buffer to read + * @param operations the list of operations that will be added to + */ public static void read(@NonNull WireBuffer buffer, @NonNull List operations) { Maker m = RoundedClipRectModifierOperation::new; read(m, buffer, operations); } + /** + * The OP_CODE for this command + * + * @return the opcode + */ public static int id() { return OP_CODE; } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ScrollModifierOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ScrollModifierOperation.java index 8dcfed999c5c5bd82e4110934ea95424d9937490..0b6632057bd2d77ae987bcbe0b821a3953c113f3 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ScrollModifierOperation.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ScrollModifierOperation.java @@ -134,6 +134,11 @@ public class ScrollModifierOperation extends DecoratorModifierOperation implemen return CLASS_NAME; } + /** + * The OP_CODE for this command + * + * @return the opcode + */ public static int id() { return OP_CODE; } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ValueFloatChangeActionOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ValueFloatChangeActionOperation.java index a97fcffdf75cedcaa3a3e3c1945c549dca7282c8..b96d3cc4bbc06e39f415fe74e9cd348134cbb254 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ValueFloatChangeActionOperation.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ValueFloatChangeActionOperation.java @@ -33,7 +33,7 @@ import com.android.internal.widget.remotecompose.core.operations.utilities.Strin import java.util.List; /** Apply a value change on an float variable. */ -public class ValueFloatChangeActionOperation implements ActionOperation { +public class ValueFloatChangeActionOperation extends Operation implements ActionOperation { private static final int OP_CODE = Operations.VALUE_FLOAT_CHANGE_ACTION; int mTargetValueId = -1; diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ValueFloatExpressionChangeActionOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ValueFloatExpressionChangeActionOperation.java index 41586b4939a6140ada63df8ae1a221ff514ea26a..d81b7ffd1ef90825baa3c1157a0efdb1855b6a84 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ValueFloatExpressionChangeActionOperation.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ValueFloatExpressionChangeActionOperation.java @@ -32,7 +32,8 @@ import com.android.internal.widget.remotecompose.core.operations.utilities.Strin import java.util.List; /** Apply a value change on an integer variable. */ -public class ValueFloatExpressionChangeActionOperation implements ActionOperation { +public class ValueFloatExpressionChangeActionOperation extends Operation + implements ActionOperation { private static final int OP_CODE = Operations.VALUE_FLOAT_EXPRESSION_CHANGE_ACTION; int mTargetValueId = -1; @@ -88,6 +89,12 @@ public class ValueFloatExpressionChangeActionOperation implements ActionOperatio buffer.writeInt(value); } + /** + * Read this operation and add it to the list of operations + * + * @param buffer the buffer to read + * @param operations the list of operations that will be added to + */ public static void read(@NonNull WireBuffer buffer, @NonNull List operations) { int valueId = buffer.readInt(); int value = buffer.readInt(); diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ValueIntegerChangeActionOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ValueIntegerChangeActionOperation.java index c2cd2ab32bb7da60dffd0549d48a9351b1beb4cf..fb13b42dbd2184b0fb42c72614bd1d8c3029400a 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ValueIntegerChangeActionOperation.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ValueIntegerChangeActionOperation.java @@ -32,7 +32,7 @@ import com.android.internal.widget.remotecompose.core.operations.utilities.Strin import java.util.List; /** Apply a value change on an integer variable. */ -public class ValueIntegerChangeActionOperation implements ActionOperation { +public class ValueIntegerChangeActionOperation extends Operation implements ActionOperation { private static final int OP_CODE = Operations.VALUE_INTEGER_CHANGE_ACTION; int mTargetValueId = -1; @@ -87,6 +87,12 @@ public class ValueIntegerChangeActionOperation implements ActionOperation { buffer.writeInt(value); } + /** + * Read this operation and add it to the list of operations + * + * @param buffer the buffer to read + * @param operations the list of operations that will be added to + */ public static void read(@NonNull WireBuffer buffer, @NonNull List operations) { int valueId = buffer.readInt(); int value = buffer.readInt(); diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ValueIntegerExpressionChangeActionOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ValueIntegerExpressionChangeActionOperation.java index 43fbb8546b9d137ac43d14bfe5f3612815b31692..0fe88ad165a910643e1e6defd1ac7caf71089b6b 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ValueIntegerExpressionChangeActionOperation.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ValueIntegerExpressionChangeActionOperation.java @@ -32,7 +32,8 @@ import com.android.internal.widget.remotecompose.core.operations.utilities.Strin import java.util.List; /** Apply a value change on an integer variable. */ -public class ValueIntegerExpressionChangeActionOperation implements ActionOperation { +public class ValueIntegerExpressionChangeActionOperation extends Operation + implements ActionOperation { private static final int OP_CODE = Operations.VALUE_INTEGER_EXPRESSION_CHANGE_ACTION; long mTargetValueId = -1; @@ -88,6 +89,12 @@ public class ValueIntegerExpressionChangeActionOperation implements ActionOperat buffer.writeLong(value); } + /** + * Read this operation and add it to the list of operations + * + * @param buffer the buffer to read + * @param operations the list of operations that will be added to + */ public static void read(@NonNull WireBuffer buffer, @NonNull List operations) { long valueId = buffer.readLong(); long value = buffer.readLong(); diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ValueStringChangeActionOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ValueStringChangeActionOperation.java index 1107889faaab77fec396ebe2038ba5026aac345e..a8d3b87f04b4f0eeb02879888a0cb0de57d142ef 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ValueStringChangeActionOperation.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ValueStringChangeActionOperation.java @@ -32,7 +32,7 @@ import com.android.internal.widget.remotecompose.core.operations.utilities.Strin import java.util.List; /** Apply a value change on a string variable. */ -public class ValueStringChangeActionOperation implements ActionOperation { +public class ValueStringChangeActionOperation extends Operation implements ActionOperation { private static final int OP_CODE = Operations.VALUE_STRING_CHANGE_ACTION; int mTargetValueId = -1; @@ -91,6 +91,12 @@ public class ValueStringChangeActionOperation implements ActionOperation { buffer.writeInt(value); } + /** + * Read this operation and add it to the list of operations + * + * @param buffer the buffer to read + * @param operations the list of operations that will be added to + */ public static void read(@NonNull WireBuffer buffer, @NonNull List operations) { int valueId = buffer.readInt(); int value = buffer.readInt(); diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/WidthModifierOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/WidthModifierOperation.java index 3c757a893a57089f7f33c2d860f22c5b9d262824..f6d743f599d3de0f51ad1d0f0e3f40c943bc3cc5 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/WidthModifierOperation.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/WidthModifierOperation.java @@ -37,6 +37,11 @@ public class WidthModifierOperation extends DimensionModifierOperation { return CLASS_NAME; } + /** + * The OP_CODE for this command + * + * @return the opcode + */ public static int id() { return OP_CODE; } @@ -47,6 +52,12 @@ public class WidthModifierOperation extends DimensionModifierOperation { buffer.writeFloat(value); } + /** + * Read this operation and add it to the list of operations + * + * @param buffer the buffer to read + * @param operations the list of operations that will be added to + */ public static void read(@NonNull WireBuffer buffer, @NonNull List operations) { Type type = Type.fromInt(buffer.readInt()); float value = buffer.readFloat(); diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ZIndexModifierOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ZIndexModifierOperation.java index 82c8f343565e1f94e6ef410c9cfe0a7b291bbd80..96ed2cda3e106a6a10f26afdfb0e20ed51c1b8d9 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ZIndexModifierOperation.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/modifiers/ZIndexModifierOperation.java @@ -83,6 +83,11 @@ public class ZIndexModifierOperation extends DecoratorModifierOperation { return CLASS_NAME; } + /** + * The OP_CODE for this command + * + * @return the opcode + */ public static int id() { return OP_CODE; } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/paint/PaintBundle.java b/core/java/com/android/internal/widget/remotecompose/core/operations/paint/PaintBundle.java index 07cf7627e24d0a00a342f9edf14f46987114bafb..95434696abdc8f518b70f51e245f802267ba731f 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/paint/PaintBundle.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/paint/PaintBundle.java @@ -498,6 +498,11 @@ public class PaintBundle { return ret; } + /** + * Write a bundle of paint changes to the buffer + * + * @param buffer bundle to write + */ public void writeBundle(@NonNull WireBuffer buffer) { buffer.writeInt(mPos); for (int index = 0; index < mPos; index++) { @@ -505,6 +510,11 @@ public class PaintBundle { } } + /** + * This will read the paint bundle off the wire buffer + * + * @param buffer the buffer to read + */ public void readBundle(@NonNull WireBuffer buffer) { int len = buffer.readInt(); if (len <= 0 || len > 1024) { @@ -587,6 +597,9 @@ public class PaintBundle { public static final int RADIAL_GRADIENT = 1; public static final int SWEEP_GRADIENT = 2; + private int mLastShaderSet = -1; + private boolean mColorFilterSet = false; + /** * sets a shader that draws a linear gradient along a line. * @@ -722,12 +735,14 @@ public class PaintBundle { mArray[mPos] = COLOR_FILTER_ID | (mode << 16); mPos++; mArray[mPos++] = color; + mColorFilterSet = true; } /** This sets the color filter to null */ public void clearColorFilter() { mArray[mPos] = CLEAR_COLOR_FILTER; mPos++; + mColorFilterSet = false; } /** @@ -843,6 +858,7 @@ public class PaintBundle { * @param shaderId */ public void setShader(int shaderId) { + mLastShaderSet = shaderId; mArray[mPos] = SHADER; mPos++; mArray[mPos] = shaderId; @@ -909,11 +925,23 @@ public class PaintBundle { mPos++; } + /** + * clear a series of paint parameters. Currently not used + * + * @param mask bit pattern of the attributes to clear + */ public void clear(long mask) { // unused for now } + /** Reset the content of the paint bundle so that it can be reused */ public void reset() { mPos = 0; + if (mColorFilterSet) { + clearColorFilter(); + } + if (mLastShaderSet != -1 && mLastShaderSet != 0) { + setShader(0); + } } public static @NonNull String blendModeString(int mode) { diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/AnimatedFloatExpression.java b/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/AnimatedFloatExpression.java index e5633c70faee3f91839d590147955e7e13dc143a..a56874781e4a42382bdb9a9d0f028be4a4743896 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/AnimatedFloatExpression.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/AnimatedFloatExpression.java @@ -18,7 +18,6 @@ package com.android.internal.widget.remotecompose.core.operations.utilities; import android.annotation.NonNull; import android.annotation.Nullable; -import com.android.internal.widget.remotecompose.core.operations.Utils; import com.android.internal.widget.remotecompose.core.operations.utilities.easing.MonotonicSpline; /** high performance floating point expression evaluator used in animation */ @@ -141,7 +140,7 @@ public class AnimatedFloatExpression { for (int i = 0; i < mStack.length; i++) { float v = mStack[i]; if (Float.isNaN(v)) { - sp = mOps[fromNaN(v) - OFFSET].eval(sp); + sp = opEval(sp, fromNaN(v)); } else { mStack[++sp] = v; } @@ -170,7 +169,7 @@ public class AnimatedFloatExpression { if (Float.isNaN(v)) { int id = fromNaN(v); if ((id & NanMap.ID_REGION_MASK) != NanMap.ID_REGION_ARRAY) { - sp = mOps[id - OFFSET].eval(sp); + sp = opEval(sp, id); } else { mStack[++sp] = v; } @@ -199,7 +198,7 @@ public class AnimatedFloatExpression { if (Float.isNaN(v)) { int id = fromNaN(v); if ((id & NanMap.ID_REGION_MASK) != NanMap.ID_REGION_ARRAY) { - sp = mOps[id - OFFSET].eval(sp); + sp = opEval(sp, id); } else { mStack[++sp] = v; } @@ -228,10 +227,11 @@ public class AnimatedFloatExpression { mStack = mLocalStack; mVar = var; int sp = -1; + for (int i = 0; i < len; i++) { float v = mStack[i]; if (Float.isNaN(v)) { - sp = mOps[fromNaN(v) - OFFSET].eval(sp); + sp = opEval(sp, fromNaN(v)); } else { mStack[++sp] = v; } @@ -250,9 +250,10 @@ public class AnimatedFloatExpression { mStack = exp; mVar = var; int sp = -1; + for (float v : exp) { if (Float.isNaN(v)) { - sp = mOps[fromNaN(v) - OFFSET].eval(sp); + sp = opEval(sp, fromNaN(v)); } else { System.out.print(" " + v); mStack[++sp] = v; @@ -261,294 +262,6 @@ public class AnimatedFloatExpression { return mStack[sp]; } - @NonNull Op[] mOps; - - { - Op mADD = - (sp) -> { // ADD - mStack[sp - 1] = mStack[sp - 1] + mStack[sp]; - return sp - 1; - }; - Op mSUB = - (sp) -> { // SUB - mStack[sp - 1] = mStack[sp - 1] - mStack[sp]; - return sp - 1; - }; - Op mMUL = - (sp) -> { // MUL - mStack[sp - 1] = mStack[sp - 1] * mStack[sp]; - return sp - 1; - }; - Op mDIV = - (sp) -> { // DIV - mStack[sp - 1] = mStack[sp - 1] / mStack[sp]; - return sp - 1; - }; - Op mMOD = - (sp) -> { // MOD - mStack[sp - 1] = mStack[sp - 1] % mStack[sp]; - return sp - 1; - }; - Op mMIN = - (sp) -> { // MIN - mStack[sp - 1] = (float) Math.min(mStack[sp - 1], mStack[sp]); - return sp - 1; - }; - Op mMAX = - (sp) -> { // MAX - mStack[sp - 1] = (float) Math.max(mStack[sp - 1], mStack[sp]); - return sp - 1; - }; - Op mPOW = - (sp) -> { // POW - mStack[sp - 1] = (float) Math.pow(mStack[sp - 1], mStack[sp]); - return sp - 1; - }; - Op mSQRT = - (sp) -> { // SQRT - mStack[sp] = (float) Math.sqrt(mStack[sp]); - return sp; - }; - Op mABS = - (sp) -> { // ABS - mStack[sp] = (float) Math.abs(mStack[sp]); - return sp; - }; - Op mSIGN = - (sp) -> { // SIGN - mStack[sp] = (float) Math.signum(mStack[sp]); - return sp; - }; - Op mCOPY_SIGN = - (sp) -> { // copySign - mStack[sp - 1] = (float) Math.copySign(mStack[sp - 1], mStack[sp]); - return sp - 1; - }; - Op mEXP = - (sp) -> { // EXP - mStack[sp] = (float) Math.exp(mStack[sp]); - return sp; - }; - Op mFLOOR = - (sp) -> { // FLOOR - mStack[sp] = (float) Math.floor(mStack[sp]); - return sp; - }; - Op mLOG = - (sp) -> { // LOG - mStack[sp] = (float) Math.log10(mStack[sp]); - return sp; - }; - Op mLN = - (sp) -> { // LN - mStack[sp] = (float) Math.log(mStack[sp]); - return sp; - }; - Op mROUND = - (sp) -> { // ROUND - mStack[sp] = (float) Math.round(mStack[sp]); - return sp; - }; - Op mSIN = - (sp) -> { // SIN - mStack[sp] = (float) Math.sin(mStack[sp]); - return sp; - }; - Op mCOS = - (sp) -> { // COS - mStack[sp] = (float) Math.cos(mStack[sp]); - return sp; - }; - Op mTAN = - (sp) -> { // TAN - mStack[sp] = (float) Math.tan(mStack[sp]); - return sp; - }; - Op mASIN = - (sp) -> { // ASIN - mStack[sp] = (float) Math.asin(mStack[sp]); - return sp; - }; - Op mACOS = - (sp) -> { // ACOS - mStack[sp] = (float) Math.acos(mStack[sp]); - return sp; - }; - Op mATAN = - (sp) -> { // ATAN - mStack[sp] = (float) Math.atan(mStack[sp]); - return sp; - }; - Op mATAN2 = - (sp) -> { // ATAN2 - mStack[sp - 1] = (float) Math.atan2(mStack[sp - 1], mStack[sp]); - return sp - 1; - }; - Op mMAD = - (sp) -> { // MAD - mStack[sp - 2] = mStack[sp] + mStack[sp - 1] * mStack[sp - 2]; - return sp - 2; - }; - Op mTERNARY_CONDITIONAL = - (sp) -> { // TERNARY_CONDITIONAL - mStack[sp - 2] = (mStack[sp] > 0) ? mStack[sp - 1] : mStack[sp - 2]; - return sp - 2; - }; - Op mCLAMP = - (sp) -> { // CLAMP (min, max, value) - mStack[sp - 2] = Math.min(Math.max(mStack[sp - 2], mStack[sp]), mStack[sp - 1]); - return sp - 2; - }; - Op mCBRT = - (sp) -> { // CBRT is cube root - mStack[sp] = (float) Math.pow(mStack[sp], 1 / 3.); - return sp; - }; - Op mDEG = - (sp) -> { // DEG - mStack[sp] = mStack[sp] * FP_TO_RAD; - return sp; - }; - Op mRAD = - (sp) -> { // RAD - mStack[sp] = mStack[sp] * FP_TO_DEG; - return sp; - }; - Op mCEIL = - (sp) -> { // CEIL - mStack[sp] = (float) Math.ceil(mStack[sp]); - return sp; - }; - Op mA_DEREF = - (sp) -> { // A_DEREF - Utils.log(" \n >>> DREF " + Integer.toHexString(fromNaN(mStack[sp - 1]))); - Utils.log(" >>> DREF " + mStack[sp] + " " + mStack[sp - 1]); - int id = fromNaN(mStack[sp - 1]); - mStack[sp - 1] = mCollectionsAccess.getFloatValue(id, (int) mStack[sp]); - return sp - 1; - }; - Op mA_MAX = - (sp) -> { // A_MAX - int id = fromNaN(mStack[sp]); - float[] array = mCollectionsAccess.getFloats(id); - float max = array[0]; - for (int i = 1; i < array.length; i++) { - max = Math.max(max, array[i]); - } - mStack[sp] = max; - return sp; - }; - Op mA_MIN = - (sp) -> { // A_MIN - int id = fromNaN(mStack[sp]); - float[] array = mCollectionsAccess.getFloats(id); - if (array.length == 0) { - return sp; - } - float min = array[0]; - for (int i = 1; i < array.length; i++) { - min = Math.min(min, array[i]); - } - mStack[sp] = min; - return sp; - }; - Op mA_SUM = - (sp) -> { // A_SUM - int id = fromNaN(mStack[sp]); - float[] array = mCollectionsAccess.getFloats(id); - float sum = 0; - for (int i = 0; i < array.length; i++) { - sum += array[i]; - } - mStack[sp] = sum; - return sp; - }; - Op mA_AVG = - (sp) -> { // A_AVG - int id = fromNaN(mStack[sp]); - float[] array = mCollectionsAccess.getFloats(id); - float sum = 0; - for (int i = 0; i < array.length; i++) { - sum += array[i]; - } - mStack[sp] = sum / array.length; - return sp; - }; - Op mA_LEN = - (sp) -> { // A_LEN - int id = fromNaN(mStack[sp]); - mStack[sp] = mCollectionsAccess.getListLength(id); - return sp; - }; - Op mA_SPLINE = - (sp) -> { // A_SPLINE - int id = fromNaN(mStack[sp - 1]); - mStack[sp - 1] = getSplineValue(id, mStack[sp]); - return sp - 1; - }; - Op mFIRST_VAR = - (sp) -> { // FIRST_VAR - mStack[sp] = mVar[0]; - return sp; - }; - Op mSECOND_VAR = - (sp) -> { // SECOND_VAR - mStack[sp] = mVar[1]; - return sp; - }; - Op mTHIRD_VAR = - (sp) -> { // THIRD_VAR - mStack[sp] = mVar[2]; - return sp; - }; - - Op[] ops = { - null, - mADD, - mSUB, - mMUL, - mDIV, - mMOD, - mMIN, - mMAX, - mPOW, - mSQRT, - mABS, - mSIGN, - mCOPY_SIGN, - mEXP, - mFLOOR, - mLOG, - mLN, - mROUND, - mSIN, - mCOS, - mTAN, - mASIN, - mACOS, - mATAN, - mATAN2, - mMAD, - mTERNARY_CONDITIONAL, - mCLAMP, - mCBRT, - mDEG, - mRAD, - mCEIL, - mA_DEREF, - mA_MAX, - mA_MIN, - mA_SUM, - mA_AVG, - mA_LEN, - mA_SPLINE, - mFIRST_VAR, - mSECOND_VAR, - mTHIRD_VAR, - }; - mOps = ops; - } - static { int k = 0; sNames.put(k++, "NOP"); @@ -765,4 +478,248 @@ public class AnimatedFloatExpression { int b = Float.floatToRawIntBits(v); return b & 0x7FFFFF; } + + // ================= New approach ======== + private static final int OP_ADD = OFFSET + 1; + private static final int OP_SUB = OFFSET + 2; + private static final int OP_MUL = OFFSET + 3; + private static final int OP_DIV = OFFSET + 4; + private static final int OP_MOD = OFFSET + 5; + private static final int OP_MIN = OFFSET + 6; + private static final int OP_MAX = OFFSET + 7; + private static final int OP_POW = OFFSET + 8; + private static final int OP_SQRT = OFFSET + 9; + private static final int OP_ABS = OFFSET + 10; + private static final int OP_SIGN = OFFSET + 11; + private static final int OP_COPY_SIGN = OFFSET + 12; + private static final int OP_EXP = OFFSET + 13; + private static final int OP_FLOOR = OFFSET + 14; + private static final int OP_LOG = OFFSET + 15; + private static final int OP_LN = OFFSET + 16; + private static final int OP_ROUND = OFFSET + 17; + private static final int OP_SIN = OFFSET + 18; + private static final int OP_COS = OFFSET + 19; + private static final int OP_TAN = OFFSET + 20; + private static final int OP_ASIN = OFFSET + 21; + private static final int OP_ACOS = OFFSET + 22; + private static final int OP_ATAN = OFFSET + 23; + private static final int OP_ATAN2 = OFFSET + 24; + private static final int OP_MAD = OFFSET + 25; + private static final int OP_TERNARY_CONDITIONAL = OFFSET + 26; + private static final int OP_CLAMP = OFFSET + 27; + private static final int OP_CBRT = OFFSET + 28; + private static final int OP_DEG = OFFSET + 29; + private static final int OP_RAD = OFFSET + 30; + private static final int OP_CEIL = OFFSET + 31; + private static final int OP_A_DEREF = OFFSET + 32; + private static final int OP_A_MAX = OFFSET + 33; + private static final int OP_A_MIN = OFFSET + 34; + private static final int OP_A_SUM = OFFSET + 35; + private static final int OP_A_AVG = OFFSET + 36; + private static final int OP_A_LEN = OFFSET + 37; + private static final int OP_A_SPLINE = OFFSET + 38; + private static final int OP_FIRST_VAR = OFFSET + 39; + private static final int OP_SECOND_VAR = OFFSET + 40; + private static final int OP_THIRD_VAR = OFFSET + 41; + + int opEval(int sp, int id) { + float[] array; + + switch (id) { + case OP_ADD: + mStack[sp - 1] = mStack[sp - 1] + mStack[sp]; + return sp - 1; + + case OP_SUB: + mStack[sp - 1] = mStack[sp - 1] - mStack[sp]; + return sp - 1; + + case OP_MUL: + mStack[sp - 1] = mStack[sp - 1] * mStack[sp]; + return sp - 1; + + case OP_DIV: + mStack[sp - 1] = mStack[sp - 1] / mStack[sp]; + return sp - 1; + + case OP_MOD: + mStack[sp - 1] = mStack[sp - 1] % mStack[sp]; + return sp - 1; + + case OP_MIN: + mStack[sp - 1] = (float) Math.min(mStack[sp - 1], mStack[sp]); + return sp - 1; + + case OP_MAX: + mStack[sp - 1] = (float) Math.max(mStack[sp - 1], mStack[sp]); + return sp - 1; + + case OP_POW: + mStack[sp - 1] = (float) Math.pow(mStack[sp - 1], mStack[sp]); + return sp - 1; + + case OP_SQRT: + mStack[sp] = (float) Math.sqrt(mStack[sp]); + return sp; + + case OP_ABS: + mStack[sp] = (float) Math.abs(mStack[sp]); + return sp; + + case OP_SIGN: + mStack[sp] = (float) Math.signum(mStack[sp]); + return sp; + + case OP_COPY_SIGN: + mStack[sp - 1] = (float) Math.copySign(mStack[sp - 1], mStack[sp]); + return sp - 1; + + case OP_EXP: + mStack[sp] = (float) Math.exp(mStack[sp]); + return sp; + + case OP_FLOOR: + mStack[sp] = (float) Math.floor(mStack[sp]); + return sp; + + case OP_LOG: + mStack[sp] = (float) Math.log10(mStack[sp]); + return sp; + + case OP_LN: + mStack[sp] = (float) Math.log(mStack[sp]); + return sp; + + case OP_ROUND: + mStack[sp] = (float) Math.round(mStack[sp]); + return sp; + + case OP_SIN: + mStack[sp] = (float) Math.sin(mStack[sp]); + return sp; + + case OP_COS: + mStack[sp] = (float) Math.cos(mStack[sp]); + return sp; + + case OP_TAN: + mStack[sp] = (float) Math.tan(mStack[sp]); + return sp; + + case OP_ASIN: + mStack[sp] = (float) Math.asin(mStack[sp]); + return sp; + + case OP_ACOS: + mStack[sp] = (float) Math.acos(mStack[sp]); + return sp; + + case OP_ATAN: + mStack[sp] = (float) Math.atan(mStack[sp]); + return sp; + + case OP_ATAN2: + mStack[sp - 1] = (float) Math.atan2(mStack[sp - 1], mStack[sp]); + return sp - 1; + + case OP_MAD: + mStack[sp - 2] = mStack[sp] + mStack[sp - 1] * mStack[sp - 2]; + return sp - 2; + + case OP_TERNARY_CONDITIONAL: + mStack[sp - 2] = (mStack[sp] > 0) ? mStack[sp - 1] : mStack[sp - 2]; + return sp - 2; + + case OP_CLAMP: + mStack[sp - 2] = Math.min(Math.max(mStack[sp - 2], mStack[sp]), mStack[sp - 1]); + return sp - 2; + + case OP_CBRT: + mStack[sp] = (float) Math.pow(mStack[sp], 1 / 3.); + return sp; + + case OP_DEG: + mStack[sp] = mStack[sp] * FP_TO_RAD; + return sp; + + case OP_RAD: + mStack[sp] = mStack[sp] * FP_TO_DEG; + return sp; + + case OP_CEIL: + mStack[sp] = (float) Math.ceil(mStack[sp]); + return sp; + + case OP_A_DEREF: + id = fromNaN(mStack[sp - 1]); + mStack[sp - 1] = mCollectionsAccess.getFloatValue(id, (int) mStack[sp]); + return sp - 1; + + case OP_A_MAX: + id = fromNaN(mStack[sp]); + array = mCollectionsAccess.getFloats(id); + float max = array[0]; + for (int i = 1; i < array.length; i++) { + max = Math.max(max, array[i]); + } + mStack[sp] = max; + return sp; + + case OP_A_MIN: + id = fromNaN(mStack[sp]); + array = mCollectionsAccess.getFloats(id); + if (array.length == 0) { + return sp; + } + float min = array[0]; + for (int i = 1; i < array.length; i++) { + min = Math.min(min, array[i]); + } + mStack[sp] = min; + return sp; + + case OP_A_SUM: + id = fromNaN(mStack[sp]); + array = mCollectionsAccess.getFloats(id); + float sum = 0; + for (int i = 0; i < array.length; i++) { + sum += array[i]; + } + mStack[sp] = sum; + return sp; + + case OP_A_AVG: + id = fromNaN(mStack[sp]); + array = mCollectionsAccess.getFloats(id); + sum = 0; + for (int i = 0; i < array.length; i++) { + sum += array[i]; + } + mStack[sp] = sum / array.length; + return sp; + + case OP_A_LEN: + id = fromNaN(mStack[sp]); + mStack[sp] = mCollectionsAccess.getListLength(id); + return sp; + + case OP_A_SPLINE: + id = fromNaN(mStack[sp - 1]); + mStack[sp - 1] = getSplineValue(id, mStack[sp]); + return sp - 1; + + case OP_FIRST_VAR: + mStack[sp] = mVar[0]; + return sp; + + case OP_SECOND_VAR: + mStack[sp] = mVar[1]; + return sp; + + case OP_THIRD_VAR: + mStack[sp] = mVar[2]; + return sp; + } + return sp; + } } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/CollectionsAccess.java b/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/CollectionsAccess.java index 4f1287265d75d572413723d430703102d10b58ff..b92f96f63eb96b49d90cbc26c34723c3f82d4def 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/CollectionsAccess.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/CollectionsAccess.java @@ -24,13 +24,39 @@ import android.annotation.Nullable; public interface CollectionsAccess { float getFloatValue(int id, int index); + /** + * Get the array of float if it is a float array + * + * @param id the id of the float array + * @return + */ @Nullable float[] getFloats(int id); + /** + * Get the number of entries in the list + * + * @param id the id of the list + * @return + */ int getListLength(int id); + /** + * get the id of an entry if the list is a list of id's + * + * @param listId the list id + * @param index the index into the list + * @return + */ int getId(int listId, int index); + /** + * Get the value as an integer + * + * @param listId the list id to access + * @param index the index into the list + * @return + */ default int getIntValue(int listId, int index) { return (int) getFloatValue(listId, index); } diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/IntegerExpressionEvaluator.java b/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/IntegerExpressionEvaluator.java index f73ab39e496efec23cbea8836fa369796e785eb3..0a3351188d9e6b1c1d283a5dbf37c541b0971c93 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/IntegerExpressionEvaluator.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/IntegerExpressionEvaluator.java @@ -82,7 +82,7 @@ public class IntegerExpressionEvaluator { for (int i = 0; i < mStack.length; i++) { int v = mStack[i]; if (((1 << i) & mask) != 0) { - sp = mOps[v - OFFSET].eval(sp); + sp = opEval(sp, v); } else { mStack[++sp] = v; } @@ -107,7 +107,7 @@ public class IntegerExpressionEvaluator { for (int i = 0; i < len; i++) { int v = mStack[i]; if (((1 << i) & mask) != 0) { - sp = mOps[v - OFFSET].eval(sp); + sp = opEval(sp, v); } else { mStack[++sp] = v; } @@ -130,7 +130,7 @@ public class IntegerExpressionEvaluator { for (int i = 0; i < exp.length; i++) { int v = mStack[i]; if (((1 << i) & opMask) != 0) { - sp = mOps[v - OFFSET].eval(sp); + sp = opEval(sp, v); } else { mStack[++sp] = v; } @@ -138,171 +138,140 @@ public class IntegerExpressionEvaluator { return mStack[sp]; } - @NonNull Op[] mOps; - - { - Op mADD = - (sp) -> { // ADD - mStack[sp - 1] = mStack[sp - 1] + mStack[sp]; - return sp - 1; - }; - Op mSUB = - (sp) -> { // SUB - mStack[sp - 1] = mStack[sp - 1] - mStack[sp]; - return sp - 1; - }; - Op mMUL = - (sp) -> { // MUL - mStack[sp - 1] = mStack[sp - 1] * mStack[sp]; - return sp - 1; - }; - Op mDIV = - (sp) -> { // DIV - mStack[sp - 1] = mStack[sp - 1] / mStack[sp]; - return sp - 1; - }; - Op mMOD = - (sp) -> { // MOD - mStack[sp - 1] = mStack[sp - 1] % mStack[sp]; - return sp - 1; - }; - Op mSHL = - (sp) -> { // SHL - mStack[sp - 1] = mStack[sp - 1] << mStack[sp]; - return sp - 1; - }; - Op mSHR = - (sp) -> { // SHR - mStack[sp - 1] = mStack[sp - 1] >> mStack[sp]; - return sp - 1; - }; - Op mUSHR = - (sp) -> { // USHR - mStack[sp - 1] = mStack[sp - 1] >>> mStack[sp]; - return sp - 1; - }; - Op mOR = - (sp) -> { // OR - mStack[sp - 1] = mStack[sp - 1] | mStack[sp]; - return sp - 1; - }; - Op mAND = - (sp) -> { // AND - mStack[sp - 1] = mStack[sp - 1] & mStack[sp]; - return sp - 1; - }; - Op mXOR = - (sp) -> { // XOR - mStack[sp - 1] = mStack[sp - 1] ^ mStack[sp]; - return sp - 1; - }; - Op mCOPY_SIGN = - (sp) -> { // COPY_SIGN copy the sign via bit manipulation - mStack[sp - 1] = (mStack[sp - 1] ^ (mStack[sp] >> 31)) - (mStack[sp] >> 31); - return sp - 1; - }; - Op mMIN = - (sp) -> { // MIN - mStack[sp - 1] = Math.min(mStack[sp - 1], mStack[sp]); - return sp - 1; - }; - Op mMAX = - (sp) -> { // MAX - mStack[sp - 1] = Math.max(mStack[sp - 1], mStack[sp]); - return sp - 1; - }; - Op mNEG = - (sp) -> { // NEG - mStack[sp] = -mStack[sp]; - return sp; - }; - Op mABS = - (sp) -> { // ABS - mStack[sp] = Math.abs(mStack[sp]); - return sp; - }; - Op mINCR = - (sp) -> { // INCR - mStack[sp] = mStack[sp] + 1; - return sp; - }; - Op mDECR = - (sp) -> { // DECR - mStack[sp] = mStack[sp] - 1; - return sp; - }; - Op mNOT = - (sp) -> { // NOT - mStack[sp] = ~mStack[sp]; - return sp; - }; - Op mSIGN = - (sp) -> { // SIGN x<0 = -1,x==0 = 0 , x>0 = 1 - mStack[sp] = (mStack[sp] >> 31) | (-mStack[sp] >>> 31); - return sp; - }; - Op mCLAMP = - (sp) -> { // CLAMP(min,max, val) - mStack[sp - 2] = Math.min(Math.max(mStack[sp - 2], mStack[sp]), mStack[sp - 1]); - return sp - 2; - }; - Op mTERNARY_CONDITIONAL = - (sp) -> { // TERNARY_CONDITIONAL - mStack[sp - 2] = (mStack[sp] > 0) ? mStack[sp - 1] : mStack[sp - 2]; - return sp - 2; - }; - Op mMAD = - (sp) -> { // MAD - mStack[sp - 2] = mStack[sp] + mStack[sp - 1] * mStack[sp - 2]; - return sp - 2; - }; - Op mFIRST_VAR = - (sp) -> { // FIRST_VAR - mStack[sp] = mVar[0]; - return sp; - }; - Op mSECOND_VAR = - (sp) -> { // SECOND_VAR - mStack[sp] = mVar[1]; - return sp; - }; - Op mTHIRD_VAR = - (sp) -> { // THIRD_VAR - mStack[sp] = mVar[2]; - return sp; - }; - - Op[] ops = { - null, - mADD, - mSUB, - mMUL, - mDIV, - mMOD, - mSHL, - mSHR, - mUSHR, - mOR, - mAND, - mXOR, - mCOPY_SIGN, - mMIN, - mMAX, - mNEG, - mABS, - mINCR, - mDECR, - mNOT, - mSIGN, - mCLAMP, - mTERNARY_CONDITIONAL, - mMAD, - mFIRST_VAR, - mSECOND_VAR, - mTHIRD_VAR, - }; - - mOps = ops; + private static final int OP_ADD = OFFSET + 1; + private static final int OP_SUB = OFFSET + 2; + private static final int OP_MUL = OFFSET + 3; + private static final int OP_DIV = OFFSET + 4; + private static final int OP_MOD = OFFSET + 5; + private static final int OP_SHL = OFFSET + 6; + private static final int OP_SHR = OFFSET + 7; + private static final int OP_USHR = OFFSET + 8; + private static final int OP_OR = OFFSET + 9; + private static final int OP_AND = OFFSET + 10; + private static final int OP_XOR = OFFSET + 11; + private static final int OP_COPY_SIGN = OFFSET + 12; + private static final int OP_MIN = OFFSET + 13; + private static final int OP_MAX = OFFSET + 14; + private static final int OP_NEG = OFFSET + 15; + private static final int OP_ABS = OFFSET + 16; + private static final int OP_INCR = OFFSET + 17; + private static final int OP_DECR = OFFSET + 18; + private static final int OP_NOT = OFFSET + 19; + private static final int OP_SIGN = OFFSET + 20; + private static final int OP_CLAMP = OFFSET + 21; + private static final int OP_TERNARY_CONDITIONAL = OFFSET + 22; + private static final int OP_MAD = OFFSET + 23; + private static final int OP_FIRST_VAR = OFFSET + 24; + private static final int OP_SECOND_VAR = OFFSET + 25; + private static final int OP_THIRD_VAR = OFFSET + 26; + + int opEval(int sp, int id) { + switch (id) { + case OP_ADD: // ADD + mStack[sp - 1] = mStack[sp - 1] + mStack[sp]; + return sp - 1; + + case OP_SUB: // SUB + mStack[sp - 1] = mStack[sp - 1] - mStack[sp]; + return sp - 1; + + case OP_MUL: // MUL + mStack[sp - 1] = mStack[sp - 1] * mStack[sp]; + return sp - 1; + + case OP_DIV: // DIV + mStack[sp - 1] = mStack[sp - 1] / mStack[sp]; + return sp - 1; + + case OP_MOD: // MOD + mStack[sp - 1] = mStack[sp - 1] % mStack[sp]; + return sp - 1; + + case OP_SHL: // SHL + mStack[sp - 1] = mStack[sp - 1] << mStack[sp]; + return sp - 1; + + case OP_SHR: // SHR + mStack[sp - 1] = mStack[sp - 1] >> mStack[sp]; + return sp - 1; + + case OP_USHR: // USHR + mStack[sp - 1] = mStack[sp - 1] >>> mStack[sp]; + return sp - 1; + + case OP_OR: // OR + mStack[sp - 1] = mStack[sp - 1] | mStack[sp]; + return sp - 1; + + case OP_AND: // AND + mStack[sp - 1] = mStack[sp - 1] & mStack[sp]; + return sp - 1; + + case OP_XOR: // XOR + mStack[sp - 1] = mStack[sp - 1] ^ mStack[sp]; + return sp - 1; + + case OP_COPY_SIGN: // COPY_SIGN copy the sign via bit manipulation + mStack[sp - 1] = (mStack[sp - 1] ^ (mStack[sp] >> 31)) - (mStack[sp] >> 31); + return sp - 1; + + case OP_MIN: // MIN + mStack[sp - 1] = Math.min(mStack[sp - 1], mStack[sp]); + return sp - 1; + + case OP_MAX: // MAX + mStack[sp - 1] = Math.max(mStack[sp - 1], mStack[sp]); + return sp - 1; + + case OP_NEG: // NEG + mStack[sp] = -mStack[sp]; + return sp; + + case OP_ABS: // ABS + mStack[sp] = Math.abs(mStack[sp]); + return sp; + + case OP_INCR: // INCR + mStack[sp] = mStack[sp] + 1; + return sp; + + case OP_DECR: // DECR + mStack[sp] = mStack[sp] - 1; + return sp; + + case OP_NOT: // NOT + mStack[sp] = ~mStack[sp]; + return sp; + + case OP_SIGN: // SIGN x<0 = -1,x==0 = 0 , x>0 = 1 + mStack[sp] = (mStack[sp] >> 31) | (-mStack[sp] >>> 31); + return sp; + + case OP_CLAMP: // CLAMP(min,max, val) + mStack[sp - 2] = Math.min(Math.max(mStack[sp - 2], mStack[sp]), mStack[sp - 1]); + return sp - 2; + + case OP_TERNARY_CONDITIONAL: // TERNARY_CONDITIONAL + mStack[sp - 2] = (mStack[sp] > 0) ? mStack[sp - 1] : mStack[sp - 2]; + return sp - 2; + + case OP_MAD: // MAD + mStack[sp - 2] = mStack[sp] + mStack[sp - 1] * mStack[sp - 2]; + return sp - 2; + + case OP_FIRST_VAR: // FIRST_VAR + mStack[sp] = mVar[0]; + return sp; + + case OP_SECOND_VAR: // SECOND_VAR + mStack[sp] = mVar[1]; + return sp; + + case OP_THIRD_VAR: // THIRD_VAR + mStack[sp] = mVar[2]; + return sp; + } + return 0; } static { diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/touch/VelocityEasing.java b/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/touch/VelocityEasing.java index 7e02bc9416a9a35b67d42fc764fe99468fed0250..c7e2442221cd7a724bd7269f088fcb810d7a7bd5 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/touch/VelocityEasing.java +++ b/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/touch/VelocityEasing.java @@ -31,6 +31,11 @@ package com.android.internal.widget.remotecompose.core.operations.utilities.touc * limitations under the License. */ +/** + * This computes an form of easing such that the values constrained to be consistent in velocity The + * easing function is also constrained by the configure To have: a maximum time to stop, a maximum + * velocity, a maximum acceleration + */ public class VelocityEasing { private float mStartPos = 0; private float mStartV = 0; @@ -46,6 +51,11 @@ public class VelocityEasing { private boolean mOneDimension = true; private float mTotalEasingDuration = 0; + /** + * get the duration the easing will take + * + * @return the duration for the easing + */ public float getDuration() { if (mEasing != null) { return mTotalEasingDuration; @@ -53,6 +63,12 @@ public class VelocityEasing { return mDuration; } + /** + * Get the velocity at time t + * + * @param t time in seconds + * @return the velocity units/second + */ public float getV(float t) { if (mEasing == null) { for (int i = 0; i < mNumberOfStages; i++) { @@ -71,6 +87,12 @@ public class VelocityEasing { return (float) getEasingDiff((t - mStage[lastStages].mStartTime)); } + /** + * Get the position t seconds after the configure + * + * @param t time in seconds + * @return the position at time t + */ public float getPos(float t) { if (mEasing == null) { for (int i = 0; i < mNumberOfStages; i++) { @@ -91,6 +113,7 @@ public class VelocityEasing { return ret; } + @Override public String toString() { var s = " "; for (int i = 0; i < mNumberOfStages; i++) { @@ -100,6 +123,17 @@ public class VelocityEasing { return s; } + /** + * Configure the Velocity easing curve The system is in arbitrary units + * + * @param currentPos the current position + * @param destination the destination + * @param currentVelocity the current velocity units/seconds + * @param maxTime the max time to achieve position + * @param maxAcceleration the max acceleration units/s^2 + * @param maxVelocity the maximum velocity + * @param easing End in using this easing curve + */ public void config( float currentPos, float destination, diff --git a/core/java/com/android/internal/widget/remotecompose/core/types/BooleanConstant.java b/core/java/com/android/internal/widget/remotecompose/core/types/BooleanConstant.java index 4af79f3ce4f492f93a176deee2c4369531a2d71d..975213f76bd23e4b76de3ddd80e84c4f981ba81f 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/types/BooleanConstant.java +++ b/core/java/com/android/internal/widget/remotecompose/core/types/BooleanConstant.java @@ -29,7 +29,7 @@ import com.android.internal.widget.remotecompose.core.documentation.DocumentedOp import java.util.List; /** Used to represent a boolean */ -public class BooleanConstant implements Operation { +public class BooleanConstant extends Operation { private static final int OP_CODE = Operations.DATA_BOOLEAN; private boolean mValue = false; private int mId; @@ -73,6 +73,11 @@ public class BooleanConstant implements Operation { return "OrigamiBoolean"; } + /** + * The OP_CODE for this command + * + * @return the opcode + */ public static int id() { return Operations.DATA_BOOLEAN; } @@ -90,6 +95,12 @@ public class BooleanConstant implements Operation { buffer.writeBoolean(value); } + /** + * Read this operation and add it to the list of operations + * + * @param buffer the buffer to read + * @param operations the list of operations that will be added to + */ public static void read(@NonNull WireBuffer buffer, @NonNull List operations) { int id = buffer.readInt(); diff --git a/core/java/com/android/internal/widget/remotecompose/core/types/IntegerConstant.java b/core/java/com/android/internal/widget/remotecompose/core/types/IntegerConstant.java index 613e7328e24ad0125447c0fd29c7f51fa083892a..210a15ac7ca4798076ac1433bf65d3d239e49077 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/types/IntegerConstant.java +++ b/core/java/com/android/internal/widget/remotecompose/core/types/IntegerConstant.java @@ -29,7 +29,7 @@ import com.android.internal.widget.remotecompose.core.documentation.DocumentedOp import java.util.List; /** Represents a single integer typically used for states or named for input into the system */ -public class IntegerConstant implements Operation { +public class IntegerConstant extends Operation { private int mValue = 0; private int mId; @@ -65,6 +65,11 @@ public class IntegerConstant implements Operation { return "IntegerConstant"; } + /** + * The OP_CODE for this command + * + * @return the opcode + */ public static int id() { return Operations.DATA_INT; } @@ -82,6 +87,12 @@ public class IntegerConstant implements Operation { buffer.writeInt(value); } + /** + * Read this operation and add it to the list of operations + * + * @param buffer the buffer to read + * @param operations the list of operations that will be added to + */ public static void read(@NonNull WireBuffer buffer, @NonNull List operations) { int id = buffer.readInt(); diff --git a/core/java/com/android/internal/widget/remotecompose/core/types/LongConstant.java b/core/java/com/android/internal/widget/remotecompose/core/types/LongConstant.java index 745caa384e4c4c2e8596ee4f78364a3ebf47607f..9875c935c112bf5fd6298a8924f16c044479017b 100644 --- a/core/java/com/android/internal/widget/remotecompose/core/types/LongConstant.java +++ b/core/java/com/android/internal/widget/remotecompose/core/types/LongConstant.java @@ -29,7 +29,7 @@ import com.android.internal.widget.remotecompose.core.documentation.DocumentedOp import java.util.List; /** Used to represent a long */ -public class LongConstant implements Operation { +public class LongConstant extends Operation { private static final int OP_CODE = Operations.DATA_LONG; private long mValue; private int mId; @@ -83,6 +83,12 @@ public class LongConstant implements Operation { buffer.writeLong(value); } + /** + * Read this operation and add it to the list of operations + * + * @param buffer the buffer to read + * @param operations the list of operations that will be added to + */ public static void read(@NonNull WireBuffer buffer, @NonNull List operations) { int id = buffer.readInt(); diff --git a/core/java/com/android/internal/widget/remotecompose/player/RemoteComposePlayer.java b/core/java/com/android/internal/widget/remotecompose/player/RemoteComposePlayer.java index 648f7bf06dd4fd7706246850c4484aa29cc79815..19b4b36b504c22abb6e8323e0db1996fa8988915 100644 --- a/core/java/com/android/internal/widget/remotecompose/player/RemoteComposePlayer.java +++ b/core/java/com/android/internal/widget/remotecompose/player/RemoteComposePlayer.java @@ -659,4 +659,14 @@ public class RemoteComposePlayer extends FrameLayout { } mListener = null; } + + /** + * This returns the amount of time in ms the player used to evalueate a pass it is averaged over + * a number of evaluations. + * + * @return time in ms + */ + public float getEvalTime() { + return mInner.getEvalTime(); + } } diff --git a/core/java/com/android/internal/widget/remotecompose/player/platform/AndroidPaintContext.java b/core/java/com/android/internal/widget/remotecompose/player/platform/AndroidPaintContext.java index 3c91cffcec3f0951abe75a758cb61f6a8077eccc..bc7d5e108e1d8ff1155b9efb8aae9a9d9b43dd76 100644 --- a/core/java/com/android/internal/widget/remotecompose/player/platform/AndroidPaintContext.java +++ b/core/java/com/android/internal/widget/remotecompose/player/platform/AndroidPaintContext.java @@ -529,6 +529,7 @@ public class AndroidPaintContext extends PaintContext { @Override public void setImageFilterQuality(int quality) { Utils.log(" quality =" + quality); + mPaint.setFilterBitmap(quality == 1); } @Override @@ -710,21 +711,33 @@ public class AndroidPaintContext extends PaintContext { } } + @Override + public void tweenPath(int out, int path1, int path2, float tween) { + float[] p = getPathArray(path1, path2, tween); + AndroidRemoteContext androidContext = (AndroidRemoteContext) mContext; + androidContext.mRemoteComposeState.putPathData(out, p); + } + @Override public void reset() { mPaint.reset(); } private Path getPath(int path1Id, int path2Id, float tween, float start, float end) { + return getPath(getPathArray(path1Id, path2Id, tween), start, end); + } + + private float[] getPathArray(int path1Id, int path2Id, float tween) { + AndroidRemoteContext androidContext = (AndroidRemoteContext) mContext; if (tween == 0.0f) { - return getPath(path1Id, start, end); + return androidContext.mRemoteComposeState.getPathData(path1Id); } if (tween == 1.0f) { - return getPath(path2Id, start, end); + return androidContext.mRemoteComposeState.getPathData(path2Id); } - AndroidRemoteContext androidContext = (AndroidRemoteContext) mContext; - float[] data1 = (float[]) androidContext.mRemoteComposeState.getFromId(path1Id); - float[] data2 = (float[]) androidContext.mRemoteComposeState.getFromId(path2Id); + + float[] data1 = androidContext.mRemoteComposeState.getPathData(path1Id); + float[] data2 = androidContext.mRemoteComposeState.getPathData(path2Id); float[] tmp = new float[data2.length]; for (int i = 0; i < tmp.length; i++) { if (Float.isNaN(data1[i]) || Float.isNaN(data2[i])) { @@ -733,6 +746,10 @@ public class AndroidPaintContext extends PaintContext { tmp[i] = (data2[i] - data1[i]) * tween + data1[i]; } } + return tmp; + } + + private Path getPath(float[] tmp, float start, float end) { Path path = new Path(); FloatsToPath.genPath(path, tmp, start, end); return path; @@ -741,9 +758,9 @@ public class AndroidPaintContext extends PaintContext { private Path getPath(int id, float start, float end) { AndroidRemoteContext androidContext = (AndroidRemoteContext) mContext; Path path = new Path(); - if (androidContext.mRemoteComposeState.containsId(id)) { - float[] data = (float[]) androidContext.mRemoteComposeState.getFromId(id); - FloatsToPath.genPath(path, data, start, end); + float[] pathData = androidContext.mRemoteComposeState.getPathData(id); + if (pathData != null) { + FloatsToPath.genPath(path, pathData, start, end); } return path; } diff --git a/core/java/com/android/internal/widget/remotecompose/player/platform/AndroidRemoteContext.java b/core/java/com/android/internal/widget/remotecompose/player/platform/AndroidRemoteContext.java index 77c25147b1fd61c6d2f14cdf1043a5233d0383af..0fb0a28da1dbe89f82b541e12a58607f7708388e 100644 --- a/core/java/com/android/internal/widget/remotecompose/player/platform/AndroidRemoteContext.java +++ b/core/java/com/android/internal/widget/remotecompose/player/platform/AndroidRemoteContext.java @@ -60,9 +60,12 @@ class AndroidRemoteContext extends RemoteContext { @Override public void loadPathData(int instanceId, @NonNull float[] floatPath) { - if (!mRemoteComposeState.containsId(instanceId)) { - mRemoteComposeState.cacheData(instanceId, floatPath); - } + mRemoteComposeState.putPathData(instanceId, floatPath); + } + + @Override + public float[] getPathData(int instanceId) { + return mRemoteComposeState.getPathData(instanceId); } static class VarName { @@ -162,7 +165,7 @@ class AndroidRemoteContext extends RemoteContext { * @param type the type of the data 0 = RGBA 8888, 1 = 888, 2 = 8 gray * @param width with of image to be loaded largest dimension is 32767 * @param height height of image to be loaded - * @param bitmap a byte array containing the image information + * @param data a byte array containing the image information * @oaram imageId the id of the image */ @Override diff --git a/core/java/com/android/internal/widget/remotecompose/player/platform/RemoteComposeCanvas.java b/core/java/com/android/internal/widget/remotecompose/player/platform/RemoteComposeCanvas.java index 8f55f8abf713da060a6b1bceb0ab6ec1f2e24789..ecfd13aa66b6d8e3e6658e23b85e15cbc0e2e411 100644 --- a/core/java/com/android/internal/widget/remotecompose/player/platform/RemoteComposeCanvas.java +++ b/core/java/com/android/internal/widget/remotecompose/player/platform/RemoteComposeCanvas.java @@ -349,6 +349,27 @@ public class RemoteComposeCanvas extends FrameLayout implements View.OnAttachSta private int mCount; private long mTime = System.nanoTime(); + private long mDuration; + private boolean mEvalTime = false; + + /** + * This returns the amount of time in ms the player used to evalueate a pass it is averaged over + * a number of evaluations. + * + * @return time in ms + */ + public float getEvalTime() { + if (!mEvalTime) { + mEvalTime = true; + return 0.0f; + } + double avg = mDuration / (double) mCount; + if (mCount > 100) { + mDuration /= 2; + mCount /= 2; + } + return (float) (avg * 1E-6); // ms + } @Override protected void onDraw(Canvas canvas) { @@ -356,6 +377,7 @@ public class RemoteComposeCanvas extends FrameLayout implements View.OnAttachSta if (mDocument == null) { return; } + long start = mEvalTime ? System.nanoTime() : 0; mARContext.setAnimationEnabled(true); mARContext.currentTime = System.currentTimeMillis(); mARContext.setDebug(mDebug); @@ -376,5 +398,9 @@ public class RemoteComposeCanvas extends FrameLayout implements View.OnAttachSta if (mDocument.needsRepaint() > 0) { invalidate(); } + if (mEvalTime) { + mDuration += System.nanoTime() - start; + mCount++; + } } } diff --git a/core/jni/Android.bp b/core/jni/Android.bp index 5c03c5cca66d7d159a572dd62219d69f48fc9940..e22d9587093ba46fe7e2c379752f504af473dbf4 100644 --- a/core/jni/Android.bp +++ b/core/jni/Android.bp @@ -214,6 +214,7 @@ cc_library_shared_for_libandroid_runtime { "android_media_ToneGenerator.cpp", "android_hardware_Camera.cpp", "android_hardware_camera2_CameraMetadata.cpp", + "android_hardware_camera2_CameraDevice.cpp", "android_hardware_camera2_DngCreator.cpp", "android_hardware_camera2_impl_CameraExtensionJpegProcessor.cpp", "android_hardware_camera2_utils_SurfaceUtils.cpp", @@ -304,7 +305,12 @@ cc_library_shared_for_libandroid_runtime { "av-types-aidl-cpp", "android.hardware.camera.device@3.2", "camera_platform_flags_c_lib", + "android.hardware.common.fmq-V1-cpp", + "android.hardware.common-V2-cpp", + "android.hardware.common.fmq-V1-ndk", + "android.hardware.common-V2-ndk", "libandroid_net", + "libfmq", "libbattery", "libnetdutils", "libmemtrack", diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp index 00a62977de43acd4533af87bb6c6dfca1b4ee5a4..ac187b08f0f12e2a5f83582eb3e55db1ab401408 100644 --- a/core/jni/AndroidRuntime.cpp +++ b/core/jni/AndroidRuntime.cpp @@ -77,6 +77,7 @@ extern int register_android_opengl_jni_GLES32(JNIEnv* env); extern int register_android_hardware_Camera(JNIEnv *env); extern int register_android_hardware_camera2_CameraMetadata(JNIEnv *env); +extern int register_android_hardware_camera2_CameraDevice(JNIEnv *env); extern int register_android_hardware_camera2_DngCreator(JNIEnv *env); extern int register_android_hardware_camera2_impl_CameraExtensionJpegProcessor(JNIEnv* env); extern int register_android_hardware_camera2_utils_SurfaceUtils(JNIEnv* env); @@ -1623,6 +1624,7 @@ static const RegJNIRec gRegJNI[] = { REG_JNI(register_com_android_internal_util_VirtualRefBasePtr), REG_JNI(register_android_hardware_Camera), REG_JNI(register_android_hardware_camera2_CameraMetadata), + REG_JNI(register_android_hardware_camera2_CameraDevice), REG_JNI(register_android_hardware_camera2_DngCreator), REG_JNI(register_android_hardware_camera2_impl_CameraExtensionJpegProcessor), REG_JNI(register_android_hardware_camera2_utils_SurfaceUtils), diff --git a/core/jni/android_hardware_camera2_CameraDevice.cpp b/core/jni/android_hardware_camera2_CameraDevice.cpp new file mode 100644 index 0000000000000000000000000000000000000000..493c7073416ced641168a3009726ed39337d87a8 --- /dev/null +++ b/core/jni/android_hardware_camera2_CameraDevice.cpp @@ -0,0 +1,148 @@ +/* +** +** 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. +*/ + +// #define LOG_NDEBUG 0 + +#define ATRACE_TAG ATRACE_TAG_CAMERA + +#include +#define LOG_TAG "CameraDevice-JNI" +#include +#include +#include +#include + +#include "jni.h" +#include +#include "android_os_Parcel.h" +#include "core_jni_helpers.h" +#include +#include +#include +#include +#include +#include + +using namespace android; + +using ::android::AidlMessageQueue; +using ResultMetadataQueue = AidlMessageQueue; + +class FMQReader { + public: + FMQReader(MQDescriptor &resultMQ) { + mCaptureResultMetadataQueue = std::make_shared(resultMQ); + } + std::shared_ptr readOneResultMetadata(long metadataSize); + private: + std::shared_ptr mCaptureResultMetadataQueue = nullptr; +}; + +std::shared_ptr FMQReader::readOneResultMetadata(long metadataSize) { + ATRACE_CALL(); + if (metadataSize == 0) { + return nullptr; + } + auto metadataVec = std::make_unique(metadataSize); + bool read = mCaptureResultMetadataQueue->read(metadataVec.get(), metadataSize); + if (!read) { + ALOGE("%s capture metadata could't be read from fmq", __FUNCTION__); + return nullptr; + } + + // Takes ownership of metadataVec, this doesn't copy + std::shared_ptr retVal = + std::make_shared( + reinterpret_cast(metadataVec.release())); + return retVal; +} + +extern "C" { + +static jlong CameraDevice_createFMQReader(JNIEnv *env, jclass thiz, + jobject resultParcel) { + AParcel *resultAParcel = AParcel_fromJavaParcel(env, resultParcel); + if (resultAParcel == nullptr) { + ALOGE("%s: Error creating result parcel", __FUNCTION__); + return 0; + } + AParcel_setDataPosition(resultAParcel, 0); + + MQDescriptor resultMQ; + if (resultMQ.readFromParcel(resultAParcel) != OK) { + ALOGE("%s: read from result parcel failed", __FUNCTION__); + return 0; + } + return reinterpret_cast(new std::shared_ptr( + new FMQReader(resultMQ))); +} + +static std::shared_ptr* FMQReader_getSharedPtr(jlong fmqReaderLongPtr) { + return reinterpret_cast* >(fmqReaderLongPtr); +} + +static jlong CameraDevice_readResultMetadata(JNIEnv *env, jclass thiz, jlong ptr, + jlong metadataSize) { + ALOGV("%s", __FUNCTION__); + + FMQReader *fmqReader = FMQReader_getSharedPtr(ptr)->get(); + auto metadataSp = fmqReader->readOneResultMetadata(metadataSize); + auto retVal = new std::shared_ptr(metadataSp); + return reinterpret_cast(retVal); +} + +static void CameraDevice_close(JNIEnv *env, jclass thiz, jlong ptr) { + ALOGV("%s", __FUNCTION__); + + auto fmqPtr = FMQReader_getSharedPtr(ptr); + if (fmqPtr != nullptr) { + delete fmqPtr; + } +} + +} + +//------------------------------------------------- +#define CAMERA_DEVICE_CLASS_NAME "android/hardware/camera2/impl/CameraDeviceImpl" +static const JNINativeMethod gCameraDeviceMethods[] = { +// static methods + { "nativeCreateFMQReader", + "(Landroid/os/Parcel;)J", + (void *)CameraDevice_createFMQReader}, + { "nativeReadResultMetadata", + "(JJ)J", + (void *)CameraDevice_readResultMetadata}, + { "nativeClose", + "(J)V", + (void*)CameraDevice_close}, +// instance methods +}; + + +// Get all the required offsets in java class and register native functions +int register_android_hardware_camera2_CameraDevice(JNIEnv *env) +{ + // Register native functions + return RegisterMethodsOrDie(env, + CAMERA_DEVICE_CLASS_NAME, + gCameraDeviceMethods, + NELEM(gCameraDeviceMethods)); +} + +extern "C" { + +} // extern "C" \ No newline at end of file diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp index 284c2997f9a95d08ae23359dcced2f0a6c0f6396..aeaeeca3e8456c4ebb2c965af4c3850be63fb578 100644 --- a/core/jni/com_android_internal_os_Zygote.cpp +++ b/core/jni/com_android_internal_os_Zygote.cpp @@ -89,6 +89,7 @@ #if defined(__BIONIC__) extern "C" void android_reset_stack_guards(); +extern "C" void android_set_16kb_appcompat_mode(bool enable_app_compat); #endif namespace { @@ -350,6 +351,7 @@ enum RuntimeFlags : uint32_t { NATIVE_HEAP_ZERO_INIT_ENABLED = 1 << 23, PROFILEABLE = 1 << 24, DEBUG_ENABLE_PTRACE = 1 << 25, + ENABLE_PAGE_SIZE_APP_COMPAT = 1 << 26, }; enum UnsolicitedZygoteMessageTypes : uint32_t { @@ -2117,6 +2119,12 @@ static void SpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray gids, SetCapabilities(permitted_capabilities, effective_capabilities, permitted_capabilities, fail_fn); + if ((runtime_flags & RuntimeFlags::ENABLE_PAGE_SIZE_APP_COMPAT) != 0) { + android_set_16kb_appcompat_mode(true); + // Now that we've used the flag, clear it so that we don't pass unknown flags to the ART + // runtime. + runtime_flags &= ~RuntimeFlags::ENABLE_PAGE_SIZE_APP_COMPAT; + } __android_log_close(); AStatsSocket_close(); diff --git a/core/proto/android/providers/settings/system.proto b/core/proto/android/providers/settings/system.proto index 16d25657f08e2ebe6fdb1b60e1f59731b9ffa300..e424e82b94cdb90baac971566b23adcb2c337107 100644 --- a/core/proto/android/providers/settings/system.proto +++ b/core/proto/android/providers/settings/system.proto @@ -218,6 +218,7 @@ message SystemSettingsProto { optional SettingProto tap_to_click = 4 [ (android.privacy).dest = DEST_AUTOMATIC ]; optional SettingProto tap_dragging = 5 [ (android.privacy).dest = DEST_AUTOMATIC ]; optional SettingProto three_finger_tap_customization = 6 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto system_gestures = 7 [ (android.privacy).dest = DEST_AUTOMATIC ];; } optional Touchpad touchpad = 36; diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index e2f3d2a32d0bdecceaf8e246f0acdb58cc268327..7d77ff054fe6f07a1e5fe778a1ec7a5108396b2d 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -8696,7 +8696,7 @@ android:featureFlag="android.security.secure_lockdown" /> + + + + + diff --git a/core/res/res/drawable-watch-v36/btn_background_material_outlined.xml b/core/res/res/drawable-watch-v36/btn_background_material_outlined.xml new file mode 100644 index 0000000000000000000000000000000000000000..7bc40604dc25bc8abef51aacfafa137e082309fb --- /dev/null +++ b/core/res/res/drawable-watch-v36/btn_background_material_outlined.xml @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + diff --git a/core/res/res/drawable-watch-v36/btn_background_material_text.xml b/core/res/res/drawable-watch-v36/btn_background_material_text.xml new file mode 100644 index 0000000000000000000000000000000000000000..145685c8095cd5bc51e8d0529d5f2d91e4083ebe --- /dev/null +++ b/core/res/res/drawable-watch-v36/btn_background_material_text.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + diff --git a/core/res/res/drawable-watch-v36/progress_ring_wear_material3.xml b/core/res/res/drawable-watch-v36/progress_ring_wear_material3.xml new file mode 100644 index 0000000000000000000000000000000000000000..5c0e5f606d81eb734fefa88441007d7c20f33e10 --- /dev/null +++ b/core/res/res/drawable-watch-v36/progress_ring_wear_material3.xml @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/core/res/res/layout-round-watch/alert_dialog_title_material.xml b/core/res/res/layout-round-watch/alert_dialog_title_material.xml index dac1e324be81d29c4a922bcf02dd75f1cf9bb565..75fe7601317b590c630f4f23e35acd7ab6b7ab7c 100644 --- a/core/res/res/layout-round-watch/alert_dialog_title_material.xml +++ b/core/res/res/layout-round-watch/alert_dialog_title_material.xml @@ -14,30 +14,34 @@ ~ See the License for the specific language governing permissions and ~ limitations under the License --> - + + - + + - + android:layout_gravity="center_horizontal" + android:layout_marginBottom="8dp" + android:maxHeight="32dp" + android:maxWidth="32dp" + android:src="@null" /> - + + diff --git a/core/res/res/layout-watch-v36/alert_dialog_material.xml b/core/res/res/layout-watch-v36/alert_dialog_material.xml deleted file mode 100644 index 8f754569014216824988eece96f0fae290440a6c..0000000000000000000000000000000000000000 --- a/core/res/res/layout-watch-v36/alert_dialog_material.xml +++ /dev/null @@ -1,113 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - -