Merge "Add OWNERS file for libhostgraphics code" into main
diff --git a/AconfigFlags.bp b/AconfigFlags.bp
index 2846221..bfe188d 100644
--- a/AconfigFlags.bp
+++ b/AconfigFlags.bp
@@ -12,171 +12,108 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-aconfig_srcjars = [
- // !!! KEEP THIS LIST ALPHABETICAL !!!
- ":aconfig_mediacodec_flags_java_lib{.generated_srcjars}",
- ":android.adaptiveauth.flags-aconfig-java{.generated_srcjars}",
- ":android.app.flags-aconfig-java{.generated_srcjars}",
- ":android.app.smartspace.flags-aconfig-java{.generated_srcjars}",
- ":android.app.usage.flags-aconfig-java{.generated_srcjars}",
- ":android.app.wearable.flags-aconfig-java{.generated_srcjars}",
- ":android.appwidget.flags-aconfig-java{.generated_srcjars}",
- ":android.chre.flags-aconfig-java{.generated_srcjars}",
- ":android.companion.flags-aconfig-java{.generated_srcjars}",
- ":android.companion.virtual.flags-aconfig-java{.generated_srcjars}",
- ":android.companion.virtualdevice.flags-aconfig-java{.generated_srcjars}",
- ":android.content.flags-aconfig-java{.generated_srcjars}",
- ":android.content.pm.flags-aconfig-java{.generated_srcjars}",
- ":android.content.res.flags-aconfig-java{.generated_srcjars}",
- ":android.crashrecovery.flags-aconfig-java{.generated_srcjars}",
- ":android.credentials.flags-aconfig-java{.generated_srcjars}",
- ":android.database.sqlite-aconfig-java{.generated_srcjars}",
- ":android.hardware.biometrics.flags-aconfig-java{.generated_srcjars}",
- ":android.hardware.flags-aconfig-java{.generated_srcjars}",
- ":android.hardware.radio.flags-aconfig-java{.generated_srcjars}",
- ":android.hardware.usb.flags-aconfig-java{.generated_srcjars}",
- ":android.location.flags-aconfig-java{.generated_srcjars}",
- ":android.media.codec-aconfig-java{.generated_srcjars}",
- ":android.media.tv.flags-aconfig-java{.generated_srcjars}",
- ":android.multiuser.flags-aconfig-java{.generated_srcjars}",
- ":android.net.platform.flags-aconfig-java{.generated_srcjars}",
- ":android.net.vcn.flags-aconfig-java{.generated_srcjars}",
- ":android.net.wifi.flags-aconfig-java{.generated_srcjars}",
- ":android.nfc.flags-aconfig-java{.generated_srcjars}",
- ":android.os.flags-aconfig-java{.generated_srcjars}",
- ":android.os.vibrator.flags-aconfig-java{.generated_srcjars}",
- ":android.permission.flags-aconfig-java{.generated_srcjars}",
- ":android.provider.flags-aconfig-java{.generated_srcjars}",
- ":android.security.flags-aconfig-java{.generated_srcjars}",
- ":android.server.app.flags-aconfig-java{.generated_srcjars}",
- ":android.service.autofill.flags-aconfig-java{.generated_srcjars}",
- ":android.service.chooser.flags-aconfig-java{.generated_srcjars}",
- ":android.service.controls.flags-aconfig-java{.generated_srcjars}",
- ":android.service.dreams.flags-aconfig-java{.generated_srcjars}",
- ":android.service.notification.flags-aconfig-java{.generated_srcjars}",
- ":android.service.appprediction.flags-aconfig-java{.generated_srcjars}",
- ":android.service.voice.flags-aconfig-java{.generated_srcjars}",
- ":android.speech.flags-aconfig-java{.generated_srcjars}",
- ":android.systemserver.flags-aconfig-java{.generated_srcjars}",
- ":android.tracing.flags-aconfig-java{.generated_srcjars}",
- ":android.view.accessibility.flags-aconfig-java{.generated_srcjars}",
- ":android.view.contentcapture.flags-aconfig-java{.generated_srcjars}",
- ":android.view.contentprotection.flags-aconfig-java{.generated_srcjars}",
- ":android.view.flags-aconfig-java{.generated_srcjars}",
- ":android.view.inputmethod.flags-aconfig-java{.generated_srcjars}",
- ":android.webkit.flags-aconfig-java{.generated_srcjars}",
- ":android.widget.flags-aconfig-java{.generated_srcjars}",
- ":audio-framework-aconfig",
- ":backup_flags_lib{.generated_srcjars}",
- ":camera_platform_flags_core_java_lib{.generated_srcjars}",
- ":com.android.hardware.input-aconfig-java{.generated_srcjars}",
- ":com.android.input.flags-aconfig-java{.generated_srcjars}",
- ":com.android.internal.foldables.flags-aconfig-java{.generated_srcjars}",
- ":com.android.internal.pm.pkg.component.flags-aconfig-java{.generated_srcjars}",
- ":com.android.media.flags.bettertogether-aconfig-java{.generated_srcjars}",
- ":com.android.media.flags.editing-aconfig-java{.generated_srcjars}",
- ":com.android.media.flags.projection-aconfig-java{.generated_srcjars}",
- ":com.android.net.thread.flags-aconfig-java{.generated_srcjars}",
- ":com.android.server.flags.services-aconfig-java{.generated_srcjars}",
- ":com.android.text.flags-aconfig-java{.generated_srcjars}",
- ":com.android.window.flags.window-aconfig-java{.generated_srcjars}",
- ":device_policy_aconfig_flags_lib{.generated_srcjars}",
- ":display_flags_lib{.generated_srcjars}",
- ":framework-jobscheduler-job.flags-aconfig-java{.generated_srcjars}",
- ":framework_graphics_flags_java_lib{.generated_srcjars}",
- ":hwui_flags_java_lib{.generated_srcjars}",
- ":power_flags_lib{.generated_srcjars}",
- ":sdk_sandbox_flags_lib{.generated_srcjars}",
- ":surfaceflinger_flags_java_lib{.generated_srcjars}",
- ":telecom_flags_core_java_lib{.generated_srcjars}",
- ":telephony_flags_core_java_lib{.generated_srcjars}",
- // !!! KEEP THIS LIST ALPHABETICAL !!!
-]
-
-stubs_defaults {
+aconfig_declarations_group {
name: "framework-minus-apex-aconfig-declarations",
- aconfig_declarations: [
- "android.app.flags-aconfig",
- "android.app.smartspace.flags-aconfig",
- "android.app.usage.flags-aconfig",
- "android.appwidget.flags-aconfig",
- "android.companion.flags-aconfig",
- "android.companion.virtual.flags-aconfig",
- "android.content.pm.flags-aconfig",
- "android.content.res.flags-aconfig",
- "android.crashrecovery.flags-aconfig",
- "android.credentials.flags-aconfig",
- "android.database.sqlite-aconfig",
- "android.hardware.biometrics.flags-aconfig",
- "android.hardware.flags-aconfig",
- "android.hardware.radio.flags-aconfig",
- "android.hardware.usb.flags-aconfig",
- "android.location.flags-aconfig",
- "android.media.audio-aconfig",
- "android.media.audiopolicy-aconfig",
- "android.media.midi-aconfig",
- "android.media.tv.flags-aconfig",
- "android.multiuser.flags-aconfig",
- "android.net.platform.flags-aconfig",
- "android.net.vcn.flags-aconfig",
- "android.net.wifi.flags-aconfig",
- "android.nfc.flags-aconfig",
- "android.os.flags-aconfig",
- "android.os.vibrator.flags-aconfig",
- "android.permission.flags-aconfig",
- "android.provider.flags-aconfig",
- "android.security.flags-aconfig",
- "android.server.app.flags-aconfig",
- "android.service.appprediction.flags-aconfig",
- "android.service.autofill.flags-aconfig",
- "android.service.chooser.flags-aconfig",
- "android.service.controls.flags-aconfig",
- "android.service.dreams.flags-aconfig",
- "android.service.notification.flags-aconfig",
- "android.service.voice.flags-aconfig",
- "android.speech.flags-aconfig",
- "android.tracing.flags-aconfig",
- "android.view.accessibility.flags-aconfig",
- "android.view.contentcapture.flags-aconfig",
- "android.view.contentprotection.flags-aconfig",
- "android.view.flags-aconfig",
- "android.view.inputmethod.flags-aconfig",
- "android.webkit.flags-aconfig",
- "android.widget.flags-aconfig",
- "camera_platform_flags",
- "chre_flags",
- "com.android.hardware.input.input-aconfig",
- "com.android.input.flags-aconfig",
- "com.android.media.flags.bettertogether-aconfig",
- "com.android.net.thread.flags-aconfig",
- "com.android.server.flags.services-aconfig",
- "com.android.text.flags-aconfig",
- "com.android.window.flags.window-aconfig",
- "device_policy_aconfig_flags",
- "display_flags",
- "fold_lock_setting_flags",
- "framework-jobscheduler-job.flags-aconfig",
- "framework_graphics_flags",
- "hwui_flags",
- "power_flags",
- "sdk_sandbox_flags",
- "surfaceflinger_flags",
- "telecom_flags",
- "telephony_flags",
+ aconfig_declarations_groups: [
+ "audio-framework-aconfig",
+ ],
+ java_aconfig_libraries: [
+ // !!! KEEP THIS LIST ALPHABETICAL !!!
+ "aconfig_mediacodec_flags_java_lib",
+ "android.adaptiveauth.flags-aconfig-java",
+ "android.app.flags-aconfig-java",
+ "android.app.smartspace.flags-aconfig-java",
+ "android.app.usage.flags-aconfig-java",
+ "android.app.wearable.flags-aconfig-java",
+ "android.appwidget.flags-aconfig-java",
+ "android.chre.flags-aconfig-java",
+ "android.companion.flags-aconfig-java",
+ "android.companion.virtual.flags-aconfig-java",
+ "android.companion.virtualdevice.flags-aconfig-java",
+ "android.content.flags-aconfig-java",
+ "android.content.pm.flags-aconfig-java",
+ "android.content.res.flags-aconfig-java",
+ "android.crashrecovery.flags-aconfig-java",
+ "android.credentials.flags-aconfig-java",
+ "android.database.sqlite-aconfig-java",
+ "android.hardware.biometrics.flags-aconfig-java",
+ "android.hardware.devicestate.feature.flags-aconfig-java",
+ "android.hardware.flags-aconfig-java",
+ "android.hardware.radio.flags-aconfig-java",
+ "android.hardware.usb.flags-aconfig-java",
+ "android.location.flags-aconfig-java",
+ "android.media.codec-aconfig-java",
+ "android.media.tv.flags-aconfig-java",
+ "android.multiuser.flags-aconfig-java",
+ "android.net.platform.flags-aconfig-java",
+ "android.net.vcn.flags-aconfig-java",
+ "android.net.wifi.flags-aconfig-java",
+ "android.nfc.flags-aconfig-java",
+ "android.os.flags-aconfig-java",
+ "android.os.vibrator.flags-aconfig-java",
+ "android.permission.flags-aconfig-java",
+ "android.provider.flags-aconfig-java",
+ "android.security.flags-aconfig-java",
+ "android.server.app.flags-aconfig-java",
+ "android.service.autofill.flags-aconfig-java",
+ "android.service.chooser.flags-aconfig-java",
+ "android.service.controls.flags-aconfig-java",
+ "android.service.dreams.flags-aconfig-java",
+ "android.service.notification.flags-aconfig-java",
+ "android.service.appprediction.flags-aconfig-java",
+ "android.service.voice.flags-aconfig-java",
+ "android.speech.flags-aconfig-java",
+ "android.systemserver.flags-aconfig-java",
+ "android.tracing.flags-aconfig-java",
+ "android.view.accessibility.flags-aconfig-java",
+ "android.view.contentcapture.flags-aconfig-java",
+ "android.view.contentprotection.flags-aconfig-java",
+ "android.view.flags-aconfig-java",
+ "android.view.inputmethod.flags-aconfig-java",
+ "android.webkit.flags-aconfig-java",
+ "android.widget.flags-aconfig-java",
+ "backup_flags_lib",
+ "camera_platform_flags_core_java_lib",
+ "com.android.hardware.input-aconfig-java",
+ "com.android.input.flags-aconfig-java",
+ "com.android.internal.foldables.flags-aconfig-java",
+ "com.android.internal.pm.pkg.component.flags-aconfig-java",
+ "com.android.media.flags.bettertogether-aconfig-java",
+ "com.android.media.flags.editing-aconfig-java",
+ "com.android.media.flags.projection-aconfig-java",
+ "com.android.net.thread.flags-aconfig-java",
+ "com.android.server.flags.services-aconfig-java",
+ "com.android.text.flags-aconfig-java",
+ "com.android.window.flags.window-aconfig-java",
+ "device_policy_aconfig_flags_lib",
+ "display_flags_lib",
+ "framework-jobscheduler-job.flags-aconfig-java",
+ "framework_graphics_flags_java_lib",
+ "hwui_flags_java_lib",
+ "power_flags_lib",
+ "sdk_sandbox_flags_lib",
+ "surfaceflinger_flags_java_lib",
+ "telecom_flags_core_java_lib",
+ "telephony_flags_core_java_lib",
+ // !!! KEEP THIS LIST ALPHABETICAL !!!
],
}
filegroup {
name: "framework-minus-apex-aconfig-srcjars",
- srcs: aconfig_srcjars,
+ srcs: [
+ ":framework-minus-apex-aconfig-declarations{.srcjars}",
+ ],
}
// Aconfig declarations and libraries for the core framework
java_defaults {
name: "framework-minus-apex-aconfig-libraries",
// Add java_aconfig_libraries to here to add them to the core framework
- srcs: aconfig_srcjars,
// Add aconfig-annotations-lib as a dependency for the optimization
+ srcs: [
+ ":framework-minus-apex-aconfig-declarations{.srcjars}",
+ ],
libs: ["aconfig-annotations-lib"],
}
@@ -227,6 +164,19 @@
defaults: ["framework-minus-apex-aconfig-java-defaults"],
}
+// DeviceStateManager
+aconfig_declarations {
+ name: "android.hardware.devicestate.feature.flags-aconfig",
+ package: "android.hardware.devicestate.feature.flags",
+ srcs: ["core/java/android/hardware/devicestate/feature/*.aconfig"],
+}
+
+java_aconfig_library {
+ name: "android.hardware.devicestate.feature.flags-aconfig-java",
+ aconfig_declarations: "android.hardware.devicestate.feature.flags-aconfig",
+ defaults: ["framework-minus-apex-aconfig-java-defaults"],
+}
+
// Input
aconfig_declarations {
name: "com.android.hardware.input.input-aconfig",
diff --git a/api/Android.bp b/api/Android.bp
index 9d2147c..eeb76fb 100644
--- a/api/Android.bp
+++ b/api/Android.bp
@@ -302,7 +302,7 @@
// classpath (or sources) somehow.
stubs_defaults {
name: "android-non-updatable-stubs-defaults",
- defaults: ["framework-minus-apex-aconfig-declarations"],
+ aconfig_declarations: ["framework-minus-apex-aconfig-declarations"],
srcs: [":android-non-updatable-stub-sources"],
sdk_version: "none",
system_modules: "none",
diff --git a/core/api/current.txt b/core/api/current.txt
index 4af2c52..e8a342d 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -24567,6 +24567,7 @@
method @FlaggedApi("com.android.media.flags.enable_screen_off_scanning") @NonNull public android.media.MediaRouter2.ScanToken requestScan(@NonNull android.media.MediaRouter2.ScanRequest);
method public void setOnGetControllerHintsListener(@Nullable android.media.MediaRouter2.OnGetControllerHintsListener);
method public void setRouteListingPreference(@Nullable android.media.RouteListingPreference);
+ method @FlaggedApi("com.android.media.flags.enable_privileged_routing_for_media_routing_control") @RequiresPermission(anyOf={android.Manifest.permission.MEDIA_CONTENT_CONTROL, android.Manifest.permission.MEDIA_ROUTING_CONTROL}) public void setRouteVolume(@NonNull android.media.MediaRoute2Info, int);
method public boolean showSystemOutputSwitcher();
method public void stop();
method public void transferTo(@NonNull android.media.MediaRoute2Info);
@@ -52257,6 +52258,7 @@
method @NonNull public android.view.SurfaceControl.Transaction setCrop(@NonNull android.view.SurfaceControl, @Nullable android.graphics.Rect);
method @NonNull public android.view.SurfaceControl.Transaction setDamageRegion(@NonNull android.view.SurfaceControl, @Nullable android.graphics.Region);
method @NonNull public android.view.SurfaceControl.Transaction setDataSpace(@NonNull android.view.SurfaceControl, int);
+ method @FlaggedApi("com.android.graphics.hwui.flags.limited_hdr") @NonNull public android.view.SurfaceControl.Transaction setDesiredHdrHeadroom(@NonNull android.view.SurfaceControl, @FloatRange(from=0.0f) float);
method @FlaggedApi("com.android.window.flags.sdk_desired_present_time") @NonNull public android.view.SurfaceControl.Transaction setDesiredPresentTimeNanos(long);
method @NonNull public android.view.SurfaceControl.Transaction setExtendedRangeBrightness(@NonNull android.view.SurfaceControl, float, float);
method @NonNull public android.view.SurfaceControl.Transaction setFrameRate(@NonNull android.view.SurfaceControl, @FloatRange(from=0.0) float, int);
@@ -52360,6 +52362,7 @@
method @Nullable public android.os.IBinder getHostToken();
method public android.view.SurfaceControl getSurfaceControl();
method public void setChildSurfacePackage(@NonNull android.view.SurfaceControlViewHost.SurfacePackage);
+ method @FlaggedApi("com.android.graphics.hwui.flags.limited_hdr") public void setDesiredHdrHeadroom(@FloatRange(from=0.0f, to=10000.0) float);
method public void setSecure(boolean);
method public void setSurfaceLifecycle(int);
method public void setZOrderMediaOverlay(boolean);
@@ -60249,6 +60252,7 @@
}
@FlaggedApi("android.appwidget.flags.draw_data_parcel") public static final class RemoteViews.DrawInstructions {
+ method @FlaggedApi("android.appwidget.flags.draw_data_parcel") public static long getSupportedVersion();
}
@FlaggedApi("android.appwidget.flags.draw_data_parcel") public static final class RemoteViews.DrawInstructions.Builder {
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index af5ea21..d8ba84d 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -367,7 +367,7 @@
field public static final String SET_VOLUME_KEY_LONG_PRESS_LISTENER = "android.permission.SET_VOLUME_KEY_LONG_PRESS_LISTENER";
field public static final String SET_WALLPAPER_COMPONENT = "android.permission.SET_WALLPAPER_COMPONENT";
field public static final String SET_WALLPAPER_DIM_AMOUNT = "android.permission.SET_WALLPAPER_DIM_AMOUNT";
- field @FlaggedApi("android.service.chooser.support_nfc_resolver") public static final String SHOW_CUSTOMIZED_RESOLVER = "android.permission.SHOW_CUSTOMIZED_RESOLVER";
+ field @FlaggedApi("android.nfc.enable_nfc_mainline") public static final String SHOW_CUSTOMIZED_RESOLVER = "android.permission.SHOW_CUSTOMIZED_RESOLVER";
field public static final String SHOW_KEYGUARD_MESSAGE = "android.permission.SHOW_KEYGUARD_MESSAGE";
field public static final String SHUTDOWN = "android.permission.SHUTDOWN";
field public static final String SIGNAL_REBOOT_READINESS = "android.permission.SIGNAL_REBOOT_READINESS";
@@ -4827,7 +4827,7 @@
}
@FlaggedApi("com.android.internal.camera.flags.concert_mode") public static interface SessionProcessor.CaptureCallback {
- method @FlaggedApi("com.android.internal.camera.flags.concert_mode") public void onCaptureCompleted(long, int, @NonNull android.hardware.camera2.CaptureResult);
+ method @FlaggedApi("com.android.internal.camera.flags.concert_mode") public void onCaptureCompleted(long, int, @NonNull java.util.Map<android.hardware.camera2.CaptureResult.Key,java.lang.Object>);
method @FlaggedApi("com.android.internal.camera.flags.concert_mode") public void onCaptureFailed(int, int);
method @FlaggedApi("com.android.internal.camera.flags.concert_mode") public void onCaptureProcessStarted(int);
method @FlaggedApi("com.android.internal.camera.flags.concert_mode") public void onCaptureSequenceAborted(int);
@@ -4851,6 +4851,39 @@
}
+package android.hardware.devicestate {
+
+ @FlaggedApi("android.hardware.devicestate.feature.flags.device_state_property_api") public final class DeviceState {
+ method @IntRange(from=0x0) public int getIdentifier();
+ method @NonNull public String getName();
+ method public boolean hasProperties(@NonNull int...);
+ method public boolean hasProperty(int);
+ field public static final int PROPERTY_EMULATED_ONLY = 10; // 0xa
+ field public static final int PROPERTY_EXTENDED_DEVICE_STATE_EXTERNAL_DISPLAY = 15; // 0xf
+ field public static final int PROPERTY_FEATURE_DUAL_DISPLAY_INTERNAL_DEFAULT = 17; // 0x11
+ field public static final int PROPERTY_FEATURE_REAR_DISPLAY = 16; // 0x10
+ field public static final int PROPERTY_FOLDABLE_DISPLAY_CONFIGURATION_INNER_PRIMARY = 12; // 0xc
+ field public static final int PROPERTY_FOLDABLE_DISPLAY_CONFIGURATION_OUTER_PRIMARY = 11; // 0xb
+ field public static final int PROPERTY_FOLDABLE_HARDWARE_CONFIGURATION_FOLD_IN_CLOSED = 1; // 0x1
+ field public static final int PROPERTY_FOLDABLE_HARDWARE_CONFIGURATION_FOLD_IN_HALF_OPEN = 2; // 0x2
+ field public static final int PROPERTY_FOLDABLE_HARDWARE_CONFIGURATION_FOLD_IN_OPEN = 3; // 0x3
+ field public static final int PROPERTY_POWER_CONFIGURATION_TRIGGER_SLEEP = 13; // 0xd
+ field public static final int PROPERTY_POWER_CONFIGURATION_TRIGGER_WAKE = 14; // 0xe
+ }
+
+ @FlaggedApi("android.hardware.devicestate.feature.flags.device_state_property_api") public final class DeviceStateManager {
+ method @NonNull public java.util.List<android.hardware.devicestate.DeviceState> getSupportedDeviceStates();
+ method public void registerCallback(@NonNull java.util.concurrent.Executor, @NonNull android.hardware.devicestate.DeviceStateManager.DeviceStateCallback);
+ method public void unregisterCallback(@NonNull android.hardware.devicestate.DeviceStateManager.DeviceStateCallback);
+ }
+
+ public static interface DeviceStateManager.DeviceStateCallback {
+ method public default void onDeviceStateChanged(@NonNull android.hardware.devicestate.DeviceState);
+ method public default void onSupportedStatesChanged(@NonNull java.util.List<android.hardware.devicestate.DeviceState>);
+ }
+
+}
+
package android.hardware.display {
public final class AmbientBrightnessDayStats implements android.os.Parcelable {
@@ -7125,7 +7158,6 @@
public final class MediaRouter2 {
method @NonNull public java.util.List<android.media.MediaRoute2Info> getAllRoutes();
method @Nullable public String getClientPackageName();
- method @RequiresPermission(android.Manifest.permission.MEDIA_CONTENT_CONTROL) public void setRouteVolume(@NonNull android.media.MediaRoute2Info, int);
method @RequiresPermission(android.Manifest.permission.MEDIA_CONTENT_CONTROL) public void startScan();
method @RequiresPermission(android.Manifest.permission.MEDIA_CONTENT_CONTROL) public void stopScan();
method @RequiresPermission(android.Manifest.permission.MEDIA_CONTENT_CONTROL) public void transfer(@NonNull android.media.MediaRouter2.RoutingController, @NonNull android.media.MediaRoute2Info);
@@ -12329,14 +12361,6 @@
}
-package android.service.chooser {
-
- @FlaggedApi("android.service.chooser.support_nfc_resolver") public class CustomChoosers {
- method @FlaggedApi("android.service.chooser.support_nfc_resolver") @NonNull public static android.content.Intent createNfcResolverIntent(@NonNull android.content.Intent, @Nullable CharSequence, @NonNull java.util.List<android.content.pm.ResolveInfo>);
- }
-
-}
-
package android.service.cloudsearch {
public abstract class CloudSearchService extends android.app.Service {
@@ -13390,43 +13414,6 @@
method @NonNull public android.service.voice.HotwordRejectedResult.Builder setConfidenceLevel(int);
}
- @FlaggedApi("android.service.voice.flags.allow_training_data_egress_from_hds") public final class HotwordTrainingAudio implements android.os.Parcelable {
- method public int describeContents();
- method @NonNull public android.media.AudioFormat getAudioFormat();
- method @NonNull public int getAudioType();
- method @NonNull public byte[] getHotwordAudio();
- method public int getHotwordOffsetMillis();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.service.voice.HotwordTrainingAudio> CREATOR;
- field public static final int HOTWORD_OFFSET_UNSET = -1; // 0xffffffff
- }
-
- @FlaggedApi("android.service.voice.flags.allow_training_data_egress_from_hds") public static final class HotwordTrainingAudio.Builder {
- ctor public HotwordTrainingAudio.Builder(@NonNull byte[], @NonNull android.media.AudioFormat);
- method @NonNull public android.service.voice.HotwordTrainingAudio build();
- method @NonNull public android.service.voice.HotwordTrainingAudio.Builder setAudioFormat(@NonNull android.media.AudioFormat);
- method @NonNull public android.service.voice.HotwordTrainingAudio.Builder setAudioType(@NonNull int);
- method @NonNull public android.service.voice.HotwordTrainingAudio.Builder setHotwordAudio(@NonNull byte[]);
- method @NonNull public android.service.voice.HotwordTrainingAudio.Builder setHotwordOffsetMillis(int);
- }
-
- @FlaggedApi("android.service.voice.flags.allow_training_data_egress_from_hds") public final class HotwordTrainingData implements android.os.Parcelable {
- method public int describeContents();
- method public static int getMaxTrainingDataBytes();
- method public int getTimeoutStage();
- method @NonNull public java.util.List<android.service.voice.HotwordTrainingAudio> getTrainingAudioList();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.service.voice.HotwordTrainingData> CREATOR;
- }
-
- @FlaggedApi("android.service.voice.flags.allow_training_data_egress_from_hds") public static final class HotwordTrainingData.Builder {
- ctor public HotwordTrainingData.Builder();
- method @NonNull public android.service.voice.HotwordTrainingData.Builder addTrainingAudio(@NonNull android.service.voice.HotwordTrainingAudio);
- method @NonNull public android.service.voice.HotwordTrainingData build();
- method @NonNull public android.service.voice.HotwordTrainingData.Builder setTimeoutStage(int);
- method @NonNull public android.service.voice.HotwordTrainingData.Builder setTrainingAudioList(@NonNull java.util.List<android.service.voice.HotwordTrainingAudio>);
- }
-
public interface SandboxedDetectionInitializer {
method public static int getMaxCustomInitializationStatus();
method public void onUpdateState(@Nullable android.os.PersistableBundle, @Nullable android.os.SharedMemory, long, @Nullable java.util.function.IntConsumer);
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index f6366a2..334d9e6 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -1620,22 +1620,26 @@
package android.hardware.devicestate {
- public final class DeviceStateManager {
+ @FlaggedApi("android.hardware.devicestate.feature.flags.device_state_property_api") public final class DeviceState {
+ ctor @Deprecated public DeviceState(@IntRange(from=android.hardware.devicestate.DeviceStateManager.MINIMUM_DEVICE_STATE_IDENTIFIER, to=android.hardware.devicestate.DeviceStateManager.MAXIMUM_DEVICE_STATE_IDENTIFIER) int, @NonNull String, int);
+ ctor public DeviceState(@IntRange(from=android.hardware.devicestate.DeviceStateManager.MINIMUM_DEVICE_STATE_IDENTIFIER, to=android.hardware.devicestate.DeviceStateManager.MAXIMUM_DEVICE_STATE_IDENTIFIER) int, @NonNull String, @NonNull java.util.Set<java.lang.Integer>);
+ field public static final int PROPERTY_POLICY_AVAILABLE_FOR_APP_REQUEST = 8; // 0x8
+ }
+
+ @FlaggedApi("android.hardware.devicestate.feature.flags.device_state_property_api") public final class DeviceStateManager {
method @RequiresPermission(android.Manifest.permission.CONTROL_DEVICE_STATE) public void cancelBaseStateOverride();
method @RequiresPermission(value=android.Manifest.permission.CONTROL_DEVICE_STATE, conditional=true) public void cancelStateRequest();
- method @NonNull public int[] getSupportedStates();
- method public void registerCallback(@NonNull java.util.concurrent.Executor, @NonNull android.hardware.devicestate.DeviceStateManager.DeviceStateCallback);
+ method @Deprecated @NonNull public int[] getSupportedStates();
method @RequiresPermission(android.Manifest.permission.CONTROL_DEVICE_STATE) public void requestBaseStateOverride(@NonNull android.hardware.devicestate.DeviceStateRequest, @Nullable java.util.concurrent.Executor, @Nullable android.hardware.devicestate.DeviceStateRequest.Callback);
method @RequiresPermission(value=android.Manifest.permission.CONTROL_DEVICE_STATE, conditional=true) public void requestState(@NonNull android.hardware.devicestate.DeviceStateRequest, @Nullable java.util.concurrent.Executor, @Nullable android.hardware.devicestate.DeviceStateRequest.Callback);
- method public void unregisterCallback(@NonNull android.hardware.devicestate.DeviceStateManager.DeviceStateCallback);
- field public static final int MAXIMUM_DEVICE_STATE = 255; // 0xff
- field public static final int MINIMUM_DEVICE_STATE = 0; // 0x0
+ field public static final int MAXIMUM_DEVICE_STATE_IDENTIFIER = 10000; // 0x2710
+ field public static final int MINIMUM_DEVICE_STATE_IDENTIFIER = 0; // 0x0
}
public static interface DeviceStateManager.DeviceStateCallback {
- method public default void onBaseStateChanged(int);
- method public void onStateChanged(int);
- method public default void onSupportedStatesChanged(@NonNull int[]);
+ method @Deprecated public default void onBaseStateChanged(int);
+ method @Deprecated public void onStateChanged(int);
+ method @Deprecated public default void onSupportedStatesChanged(@NonNull int[]);
}
public final class DeviceStateRequest {
diff --git a/core/java/android/companion/CompanionDeviceManager.java b/core/java/android/companion/CompanionDeviceManager.java
index d743992..91baa4e 100644
--- a/core/java/android/companion/CompanionDeviceManager.java
+++ b/core/java/android/companion/CompanionDeviceManager.java
@@ -707,7 +707,9 @@
* Only components from the same {@link ComponentName#getPackageName package} as the calling app
* are allowed.
*
- * Your app must have an association with a device before calling this API
+ * Your app must have an association with a device before calling this API.
+ *
+ * Side-loaded apps must allow restricted settings before requesting notification access.
*
* <p>Calling this API requires a uses-feature
* {@link PackageManager#FEATURE_COMPANION_DEVICE_SETUP} declaration in the manifest</p>
@@ -721,6 +723,9 @@
IntentSender intentSender = mService
.requestNotificationAccess(component, mContext.getUserId())
.getIntentSender();
+ if (intentSender == null) {
+ return;
+ }
mContext.startIntentSender(intentSender, null, 0, 0, 0,
ActivityOptions.makeBasic().setPendingIntentBackgroundActivityStartMode(
ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOWED).toBundle());
diff --git a/core/java/android/hardware/camera2/extension/SessionProcessor.java b/core/java/android/hardware/camera2/extension/SessionProcessor.java
index d8594e5..2e428e5 100644
--- a/core/java/android/hardware/camera2/extension/SessionProcessor.java
+++ b/core/java/android/hardware/camera2/extension/SessionProcessor.java
@@ -18,7 +18,6 @@
import android.annotation.FlaggedApi;
import android.annotation.NonNull;
-import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CaptureFailure;
@@ -184,8 +183,8 @@
* capture results. This is the return value of
* either {@link #startRepeating} or {@link
* #startMultiFrameCapture}.
- * @param results The supported capture results. Do note
- * that if results 'android.jpeg.quality' and
+ * @param results Key value map of the supported capture results.
+ * Do note that if results 'android.jpeg.quality' and
* android.jpeg.orientation' are present in the
* process capture input results, then the values
* must also be passed as part of this callback.
@@ -195,7 +194,7 @@
*/
@FlaggedApi(Flags.FLAG_CONCERT_MODE)
void onCaptureCompleted(long shutterTimestamp, int requestId,
- @NonNull CaptureResult results);
+ @NonNull Map<CaptureResult.Key, Object> results);
}
/**
@@ -415,7 +414,7 @@
public int startRepeating(ICaptureCallback callback) throws RemoteException {
return SessionProcessor.this.startRepeating(
new HandlerExecutor(new Handler(Looper.getMainLooper())),
- new CaptureCallbackImpl(callback));
+ new CaptureCallbackImpl(callback, mVendorId));
}
@Override
@@ -428,7 +427,7 @@
throws RemoteException {
return SessionProcessor.this.startMultiFrameCapture(
new HandlerExecutor(new Handler(Looper.getMainLooper())),
- new CaptureCallbackImpl(callback));
+ new CaptureCallbackImpl(callback, mVendorId));
}
@Override
@@ -441,7 +440,7 @@
throws RemoteException {
return SessionProcessor.this.startTrigger(captureRequest,
new HandlerExecutor(new Handler(Looper.getMainLooper())),
- new CaptureCallbackImpl(callback));
+ new CaptureCallbackImpl(callback, mVendorId));
}
@Override
@@ -453,9 +452,11 @@
private static final class CaptureCallbackImpl implements CaptureCallback {
private final ICaptureCallback mCaptureCallback;
+ private long mVendorId = -1;
- CaptureCallbackImpl(@NonNull ICaptureCallback cb) {
+ CaptureCallbackImpl(@NonNull ICaptureCallback cb, long vendorId) {
mCaptureCallback = cb;
+ mVendorId = vendorId;
}
@Override
@@ -505,10 +506,14 @@
@Override
public void onCaptureCompleted(long shutterTimestamp, int requestId,
- @androidx.annotation.NonNull CaptureResult results) {
+ Map<CaptureResult.Key, Object> results) {
+ CameraMetadataNative captureResults = new CameraMetadataNative();
+ captureResults.setVendorId(mVendorId);
+ for (Map.Entry<CaptureResult.Key, Object> entry : results.entrySet()) {
+ captureResults.set(entry.getKey(), entry.getValue());
+ }
try {
- mCaptureCallback.onCaptureCompleted(shutterTimestamp, requestId,
- results.getNativeCopy());
+ mCaptureCallback.onCaptureCompleted(shutterTimestamp, requestId, captureResults);
} catch (RemoteException e) {
Log.e(TAG, "Failed to notify capture complete due to remote exception!");
}
diff --git a/core/java/android/hardware/devicestate/DeviceState.java b/core/java/android/hardware/devicestate/DeviceState.java
index 5a34905..8629354 100644
--- a/core/java/android/hardware/devicestate/DeviceState.java
+++ b/core/java/android/hardware/devicestate/DeviceState.java
@@ -16,18 +16,25 @@
package android.hardware.devicestate;
-import static android.hardware.devicestate.DeviceStateManager.MAXIMUM_DEVICE_STATE;
-import static android.hardware.devicestate.DeviceStateManager.MINIMUM_DEVICE_STATE;
+import static android.hardware.devicestate.DeviceStateManager.MAXIMUM_DEVICE_STATE_IDENTIFIER;
+import static android.hardware.devicestate.DeviceStateManager.MINIMUM_DEVICE_STATE_IDENTIFIER;
+import android.annotation.FlaggedApi;
import android.annotation.IntDef;
import android.annotation.IntRange;
import android.annotation.NonNull;
+import android.annotation.SystemApi;
+import android.annotation.TestApi;
import com.android.internal.util.Preconditions;
+import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.util.Collections;
import java.util.Objects;
+import java.util.Set;
/**
* A state of the device defined by the {@link DeviceStateProvider} and managed by the
@@ -37,21 +44,29 @@
* state of the system. This is useful for variable-state devices, like foldable or rollable
* devices, that can be configured by users into differing hardware states, which each may have a
* different expected use case.
- * @hide
*
+ * @hide
* @see DeviceStateManager
*/
+@SystemApi
+@FlaggedApi(android.hardware.devicestate.feature.flags.Flags.FLAG_DEVICE_STATE_PROPERTY_API)
public final class DeviceState {
/**
* Flag that indicates override requests should be cancelled when this device state becomes the
* base device state.
+ * @hide
+ * @deprecated use {@link #PROPERTY_POLICY_CANCEL_OVERRIDE_REQUESTS}
*/
+ @Deprecated
public static final int FLAG_CANCEL_OVERRIDE_REQUESTS = 1 << 0;
/**
* Flag that indicates this device state is inaccessible for applications to be placed in. This
- * could be a device-state where the {@link DEFAULT_DISPLAY} is not enabled.
+ * could be a device-state where the {@link Display#DEFAULT_DISPLAY} is not enabled.
+ * @hide
+ * @deprecated use {@link #PROPERTY_APP_INACCESSIBLE}
*/
+ @Deprecated
public static final int FLAG_APP_INACCESSIBLE = 1 << 1;
/**
@@ -60,7 +75,10 @@
* through emulation and have no physical configuration to match.
*
* This flag indicates that the corresponding state can only be entered through emulation.
+ * @hide
+ * @deprecated use {@link #PROPERTY_EMULATED_ONLY}
*/
+ @Deprecated
public static final int FLAG_EMULATED_ONLY = 1 << 2;
/**
@@ -68,19 +86,28 @@
* requesting app is no longer on top. The app is considered not on top when (1) the top
* activity in the system is from a different app, (2) the device is in sleep mode, or
* (3) the keyguard shows up.
+ * @hide
+ * @deprecated use {@link #PROPERTY_POLICY_CANCEL_WHEN_REQUESTER_NOT_ON_TOP}
*/
+ @Deprecated
public static final int FLAG_CANCEL_WHEN_REQUESTER_NOT_ON_TOP = 1 << 3;
/**
* This flag indicates that the corresponding state should be disabled when the device is
* overheating and reaching the critical status.
+ * @hide
+ * @deprecated use {@link #PROPERTY_POLICY_UNSUPPORTED_WHEN_THERMAL_STATUS_CRITICAL}
*/
+ @Deprecated
public static final int FLAG_UNSUPPORTED_WHEN_THERMAL_STATUS_CRITICAL = 1 << 4;
/**
* This flag indicates that the corresponding state should be disabled when power save mode
* is enabled.
+ * @hide
+ * @deprecated use {@link #PROPERTY_POLICY_UNSUPPORTED_WHEN_POWER_SAVE_MODE}
*/
+ @Deprecated
public static final int FLAG_UNSUPPORTED_WHEN_POWER_SAVE_MODE = 1 << 5;
/** @hide */
@@ -92,11 +119,157 @@
FLAG_UNSUPPORTED_WHEN_THERMAL_STATUS_CRITICAL,
FLAG_UNSUPPORTED_WHEN_POWER_SAVE_MODE
})
+ @Deprecated
@Retention(RetentionPolicy.SOURCE)
public @interface DeviceStateFlags {}
+ /**
+ * Property that indicates that a fold-in style foldable device is currently in a fully closed
+ * configuration.
+ */
+ public static final int PROPERTY_FOLDABLE_HARDWARE_CONFIGURATION_FOLD_IN_CLOSED = 1;
+
+ /**
+ * Property that indicates that a fold-in style foldable device is currently in a half-opened
+ * configuration. This signifies that the device's hinge is positioned somewhere around 90
+ * degrees. Checking for display configuration properties as well can provide information
+ * on which display is currently active.
+ */
+ public static final int PROPERTY_FOLDABLE_HARDWARE_CONFIGURATION_FOLD_IN_HALF_OPEN = 2;
+
+ /**
+ * Property that indicates that a fold-in style foldable device is currently in a fully open
+ * configuration.
+ */
+ public static final int PROPERTY_FOLDABLE_HARDWARE_CONFIGURATION_FOLD_IN_OPEN = 3;
+
+ /**
+ * Property that indicates override requests should be cancelled when the device is physically
+ * put into this state.
+ * @hide
+ */
+ public static final int PROPERTY_POLICY_CANCEL_OVERRIDE_REQUESTS = 4;
+
+ /**
+ * This property indicates that the corresponding state should be automatically canceled when
+ * the requesting app is no longer on top. The app is considered not on top when (1) the top
+ * activity in the system is from a different app, (2) the device is in sleep mode, or
+ * (3) the keyguard shows up.
+ * @hide
+ */
+ public static final int PROPERTY_POLICY_CANCEL_WHEN_REQUESTER_NOT_ON_TOP = 5;
+
+ /**
+ * This property indicates that the corresponding state should be disabled when the device is
+ * overheating and reaching the critical status.
+ * @hide
+ */
+ public static final int PROPERTY_POLICY_UNSUPPORTED_WHEN_THERMAL_STATUS_CRITICAL = 6;
+
+ /**
+ * This property indicates that the corresponding state should be disabled when power save mode
+ * is enabled.
+ * @hide
+ */
+ public static final int PROPERTY_POLICY_UNSUPPORTED_WHEN_POWER_SAVE_MODE = 7;
+
+ /**
+ * This property denotes that this state is available for applications to request and the system
+ * server should deny any request that comes from a process that does not hold the
+ * CONTROL_DEVICE_STATE permission if it is requesting a state that does not have this property
+ * on it.
+ * @hide
+ */
+ @TestApi
+ public static final int PROPERTY_POLICY_AVAILABLE_FOR_APP_REQUEST = 8;
+
+ /**
+ * Property that indicates this device state is inaccessible for applications to be made
+ * visible to the user. This could be a device-state where the {@link Display#DEFAULT_DISPLAY}
+ * is not enabled.
+ * @hide
+ */
+ public static final int PROPERTY_APP_INACCESSIBLE = 9;
+
+ /**
+ * This property indidcates that this state can only be entered through emulation and has no
+ * physical configuration to match.
+ */
+ public static final int PROPERTY_EMULATED_ONLY = 10;
+
+ /**
+ * Property that indicates that the outer display area of a foldable device is currently the
+ * primary display area.
+ *
+ * Note: This does not necessarily mean that the outer display area is the
+ * @link Display#DEFAULT_DISPLAY}.
+ */
+ public static final int PROPERTY_FOLDABLE_DISPLAY_CONFIGURATION_OUTER_PRIMARY = 11;
+
+ /**
+ * Property that indicates that the inner display area of a foldable device is currently the
+ * primary display area.
+ *
+ * Note: This does not necessarily mean that the inner display area is the
+ * {@link Display#DEFAULT_DISPLAY}.
+ */
+ public static final int PROPERTY_FOLDABLE_DISPLAY_CONFIGURATION_INNER_PRIMARY = 12;
+
+ /**
+ * Property that indicates that this device state will attempt to trigger the device to go to
+ * sleep.
+ */
+ public static final int PROPERTY_POWER_CONFIGURATION_TRIGGER_SLEEP = 13;
+
+ /**
+ * Property that indicates that this device state will attempt to trigger the device to wake up.
+ */
+ public static final int PROPERTY_POWER_CONFIGURATION_TRIGGER_WAKE = 14;
+
+ /**
+ * Property that indicates that an external display has been connected to the device. Specifics
+ * around display mode or properties around the display should be gathered through
+ * {@link android.hardware.display.DisplayManager}
+ */
+ public static final int PROPERTY_EXTENDED_DEVICE_STATE_EXTERNAL_DISPLAY = 15;
+ /**
+ * Property that indicates that this state corresponds to the device state for rear display
+ * mode. This means that the active display is facing the same direction as the rear camera.
+ */
+ public static final int PROPERTY_FEATURE_REAR_DISPLAY = 16;
+
+ /**
+ * Property that indicates that this state corresponds to the device state where both displays
+ * on a foldable are active, with the internal display being the default display.
+ */
+ public static final int PROPERTY_FEATURE_DUAL_DISPLAY_INTERNAL_DEFAULT = 17;
+
+ /** @hide */
+ @IntDef(prefix = {"PROPERTY_"}, flag = true, value = {
+ PROPERTY_FOLDABLE_HARDWARE_CONFIGURATION_FOLD_IN_CLOSED,
+ PROPERTY_FOLDABLE_HARDWARE_CONFIGURATION_FOLD_IN_HALF_OPEN,
+ PROPERTY_FOLDABLE_HARDWARE_CONFIGURATION_FOLD_IN_OPEN,
+ PROPERTY_POLICY_CANCEL_OVERRIDE_REQUESTS,
+ PROPERTY_POLICY_CANCEL_WHEN_REQUESTER_NOT_ON_TOP,
+ PROPERTY_POLICY_UNSUPPORTED_WHEN_THERMAL_STATUS_CRITICAL,
+ PROPERTY_POLICY_UNSUPPORTED_WHEN_POWER_SAVE_MODE,
+ PROPERTY_POLICY_AVAILABLE_FOR_APP_REQUEST,
+ PROPERTY_APP_INACCESSIBLE,
+ PROPERTY_EMULATED_ONLY,
+ PROPERTY_FOLDABLE_DISPLAY_CONFIGURATION_OUTER_PRIMARY,
+ PROPERTY_FOLDABLE_DISPLAY_CONFIGURATION_INNER_PRIMARY,
+ PROPERTY_POWER_CONFIGURATION_TRIGGER_SLEEP,
+ PROPERTY_POWER_CONFIGURATION_TRIGGER_WAKE,
+ PROPERTY_EXTENDED_DEVICE_STATE_EXTERNAL_DISPLAY,
+ PROPERTY_FEATURE_REAR_DISPLAY,
+ PROPERTY_FEATURE_DUAL_DISPLAY_INTERNAL_DEFAULT
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ @Target({ElementType.TYPE_PARAMETER, ElementType.TYPE_USE})
+ public @interface DeviceStateProperties {}
+
/** Unique identifier for the device state. */
- @IntRange(from = MINIMUM_DEVICE_STATE, to = MAXIMUM_DEVICE_STATE)
+ @IntRange(from = MINIMUM_DEVICE_STATE_IDENTIFIER, to = MAXIMUM_DEVICE_STATE_IDENTIFIER)
private final int mIdentifier;
/** String description of the device state. */
@@ -106,20 +279,49 @@
@DeviceStateFlags
private final int mFlags;
+ private final Set<@DeviceStateProperties Integer> mProperties;
+
+ /**
+ * @deprecated Deprecated in favor of {@link #DeviceState(int, String, Set)}
+ * @hide
+ */
+ // TODO(b/325124054): Make non-default and remove deprecated callback methods.
+ @TestApi
+ @Deprecated
public DeviceState(
- @IntRange(from = MINIMUM_DEVICE_STATE, to = MAXIMUM_DEVICE_STATE) int identifier,
+ @IntRange(from = MINIMUM_DEVICE_STATE_IDENTIFIER, to =
+ MAXIMUM_DEVICE_STATE_IDENTIFIER) int identifier,
@NonNull String name,
@DeviceStateFlags int flags) {
- Preconditions.checkArgumentInRange(identifier, MINIMUM_DEVICE_STATE, MAXIMUM_DEVICE_STATE,
+ Preconditions.checkArgumentInRange(identifier, MINIMUM_DEVICE_STATE_IDENTIFIER,
+ MAXIMUM_DEVICE_STATE_IDENTIFIER,
"identifier");
mIdentifier = identifier;
mName = name;
mFlags = flags;
+ mProperties = Collections.emptySet();
+ }
+
+ /** @hide */
+ @TestApi
+ public DeviceState(
+ @IntRange(from = MINIMUM_DEVICE_STATE_IDENTIFIER, to =
+ MAXIMUM_DEVICE_STATE_IDENTIFIER) int identifier,
+ @NonNull String name,
+ @NonNull Set<@DeviceStateProperties Integer> properties) {
+ Preconditions.checkArgumentInRange(identifier, MINIMUM_DEVICE_STATE_IDENTIFIER,
+ MAXIMUM_DEVICE_STATE_IDENTIFIER,
+ "identifier");
+
+ mIdentifier = identifier;
+ mName = name;
+ mProperties = Set.copyOf(properties);
+ mFlags = 0;
}
/** Returns the unique identifier for the device state. */
- @IntRange(from = MINIMUM_DEVICE_STATE, to = MAXIMUM_DEVICE_STATE)
+ @IntRange(from = MINIMUM_DEVICE_STATE_IDENTIFIER)
public int getIdentifier() {
return mIdentifier;
}
@@ -130,6 +332,12 @@
return mName;
}
+ /**
+ * @hide
+ * @deprecated in favor of {@link #hasProperty(int)} method
+ */
+ // TODO(b/325124054): Make non-default and remove deprecated callback methods.
+ @Deprecated
@DeviceStateFlags
public int getFlags() {
return mFlags;
@@ -138,9 +346,9 @@
@Override
public String toString() {
return "DeviceState{" + "identifier=" + mIdentifier + ", name='" + mName + '\''
- + ", app_accessible=" + !hasFlag(FLAG_APP_INACCESSIBLE)
+ + ", app_accessible=" + !hasProperty(PROPERTY_APP_INACCESSIBLE)
+ ", cancel_when_requester_not_on_top="
- + hasFlag(FLAG_CANCEL_WHEN_REQUESTER_NOT_ON_TOP)
+ + hasProperty(PROPERTY_POLICY_CANCEL_WHEN_REQUESTER_NOT_ON_TOP)
+ "}";
}
@@ -151,17 +359,40 @@
DeviceState that = (DeviceState) o;
return mIdentifier == that.mIdentifier
&& Objects.equals(mName, that.mName)
- && mFlags == that.mFlags;
+ && Objects.equals(mProperties, that.mProperties);
}
@Override
public int hashCode() {
- return Objects.hash(mIdentifier, mName, mFlags);
+ return Objects.hash(mIdentifier, mName, mProperties);
}
/** Checks if a specific flag is set
+ * @hide
+ * @deprecated in favor of {@link #hasProperty(int)}
*/
+ // TODO(b/325124054): Make non-default and remove deprecated callback methods.
+ @Deprecated
public boolean hasFlag(int flagToCheckFor) {
return (mFlags & flagToCheckFor) == flagToCheckFor;
}
+
+ /**
+ * Checks if a specific property is set on this state
+ */
+ public boolean hasProperty(@DeviceStateProperties int propertyToCheckFor) {
+ return mProperties.contains(propertyToCheckFor);
+ }
+
+ /**
+ * Checks if a list of properties are all set on this state
+ */
+ public boolean hasProperties(@NonNull @DeviceStateProperties int... properties) {
+ for (int i = 0; i < properties.length; i++) {
+ if (mProperties.contains(properties[i])) {
+ return false;
+ }
+ }
+ return true;
+ }
}
diff --git a/core/java/android/hardware/devicestate/DeviceStateManager.java b/core/java/android/hardware/devicestate/DeviceStateManager.java
index 6a667fe..8b4d43e 100644
--- a/core/java/android/hardware/devicestate/DeviceStateManager.java
+++ b/core/java/android/hardware/devicestate/DeviceStateManager.java
@@ -18,15 +18,19 @@
import android.Manifest;
import android.annotation.CallbackExecutor;
+import android.annotation.FlaggedApi;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
+import android.annotation.SuppressLint;
+import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.annotation.TestApi;
import android.content.Context;
import com.android.internal.util.ArrayUtils;
+import java.util.List;
import java.util.concurrent.Executor;
import java.util.function.Consumer;
@@ -36,7 +40,8 @@
*
* @hide
*/
-@TestApi
+@SystemApi
+@FlaggedApi(android.hardware.devicestate.feature.flags.Flags.FLAG_DEVICE_STATE_PROPERTY_API)
@SystemService(Context.DEVICE_STATE_SERVICE)
public final class DeviceStateManager {
/**
@@ -46,11 +51,19 @@
*/
public static final int INVALID_DEVICE_STATE = -1;
- /** The minimum allowed device state identifier. */
- public static final int MINIMUM_DEVICE_STATE = 0;
+ /**
+ * The minimum allowed device state identifier.
+ * @hide
+ */
+ @TestApi
+ public static final int MINIMUM_DEVICE_STATE_IDENTIFIER = 0;
- /** The maximum allowed device state identifier. */
- public static final int MAXIMUM_DEVICE_STATE = 255;
+ /**
+ * The maximum allowed device state identifier.
+ * @hide
+ */
+ @TestApi
+ public static final int MAXIMUM_DEVICE_STATE_IDENTIFIER = 10000;
/**
* Intent needed to launch the rear display overlay activity from SysUI
@@ -83,13 +96,27 @@
/**
* Returns the list of device states that are supported and can be requested with
* {@link #requestState(DeviceStateRequest, Executor, DeviceStateRequest.Callback)}.
+ * @deprecated use {@link #getSupportedDeviceStates()}
+ * @hide
*/
+ // TODO(b/325124054): Make non-default and remove deprecated callback methods.
+ @TestApi
+ @Deprecated
@NonNull
public int[] getSupportedStates() {
return mGlobal.getSupportedStates();
}
/**
+ * Returns the list of device states that are supported and can be requested with
+ * {@link #requestState(DeviceStateRequest, Executor, DeviceStateRequest.Callback)}.
+ */
+ @NonNull
+ public List<DeviceState> getSupportedDeviceStates() {
+ return mGlobal.getSupportedDeviceStates();
+ }
+
+ /**
* Submits a {@link DeviceStateRequest request} to modify the device state.
* <p>
* By default, the request is kept active until one of the following occurs:
@@ -107,7 +134,10 @@
* the {@link android.Manifest.permission#CONTROL_DEVICE_STATE} permission is held.
*
* @see DeviceStateRequest
+ * @hide
*/
+ @SuppressLint("RequiresPermission") // Lint doesn't handle conditional permission checks today
+ @TestApi
@RequiresPermission(value = android.Manifest.permission.CONTROL_DEVICE_STATE,
conditional = true)
public void requestState(@NonNull DeviceStateRequest request,
@@ -124,7 +154,10 @@
*
* @throws SecurityException if the caller is neither the current top-focused activity nor if
* the {@link android.Manifest.permission#CONTROL_DEVICE_STATE} permission is held.
+ * @hide
*/
+ @SuppressLint("RequiresPermission") // Lint doesn't handle conditional permission checks today
+ @TestApi
@RequiresPermission(value = android.Manifest.permission.CONTROL_DEVICE_STATE,
conditional = true)
public void cancelStateRequest() {
@@ -151,11 +184,11 @@
* emulated override requests take priority.
*
* @throws IllegalArgumentException if the requested state is unsupported.
- * @throws SecurityException if the caller does not hold the
- * {@link android.Manifest.permission#CONTROL_DEVICE_STATE} permission.
*
* @see DeviceStateRequest
+ * @hide
*/
+ @TestApi
@RequiresPermission(android.Manifest.permission.CONTROL_DEVICE_STATE)
public void requestBaseStateOverride(@NonNull DeviceStateRequest request,
@Nullable @CallbackExecutor Executor executor,
@@ -169,9 +202,9 @@
* <p>
* This method is noop if there is no base state request currently active.
*
- * @throws SecurityException if the caller does not hold the
- * {@link android.Manifest.permission#CONTROL_DEVICE_STATE} permission.
+ * @hide
*/
+ @TestApi
@RequiresPermission(Manifest.permission.CONTROL_DEVICE_STATE)
public void cancelBaseStateOverride() {
mGlobal.cancelBaseStateOverride();
@@ -209,10 +242,31 @@
* @param supportedStates the new supported states.
*
* @see DeviceStateManager#getSupportedStates()
+ * @deprecated use {@link #onSupportedStatesChanged(List)}
+ * @hide
*/
+ // TODO(b/325124054): Make non-default and remove deprecated callback methods.
+ @TestApi
+ @Deprecated
default void onSupportedStatesChanged(@NonNull int[] supportedStates) {}
/**
+ * Called in response to a change in the states supported by the device.
+ * <p>
+ * Guaranteed to be called once on registration of the callback with the initial value and
+ * then on every subsequent change in the supported states.
+ *
+ * The supported device states may change due to certain states becoming unavailable
+ * due to device configuration or device conditions such as if the device is too hot or
+ * external monitors have been connected.
+ *
+ * @param supportedStates the new supported states.
+ *
+ * @see DeviceStateManager#getSupportedDeviceStates()
+ */
+ default void onSupportedStatesChanged(@NonNull List<DeviceState> supportedStates) {}
+
+ /**
* Called in response to a change in the base device state.
* <p>
* The base state is the state of the device without considering any requests made through
@@ -224,7 +278,13 @@
* then on every subsequent change in the non-override state.
*
* @param state the new base device state.
+ * @deprecated use {@link #onDeviceStateChanged(DeviceState)} and query for physical
+ * properties that are relevant to your needs.
+ * @hide
*/
+ // TODO(b/325124054): Make non-default and remove deprecated callback methods.
+ @TestApi
+ @Deprecated
default void onBaseStateChanged(int state) {}
/**
@@ -234,8 +294,24 @@
* then on every subsequent change in device state.
*
* @param state the new device state.
+ * @deprecated use {@link #onDeviceStateChanged(DeviceState)}
+ * @hide
*/
+ // TODO(b/325124054): Make non-default and remove deprecated callback methods.
+ @TestApi
+ @Deprecated
void onStateChanged(int state);
+
+ /**
+ * Called in response to device state changes.
+ * <p>
+ * Guaranteed to be called once on registration of the callback with the initial value and
+ * then on every subsequent change in device state.
+ *
+ * @param state the new device state.
+ */
+ // TODO(b/325124054): Make non-default and remove deprecated callback methods.
+ default void onDeviceStateChanged(@NonNull DeviceState state) {}
}
/**
@@ -247,6 +323,7 @@
public static class FoldStateListener implements DeviceStateCallback {
private final int[] mFoldedDeviceStates;
private final Consumer<Boolean> mDelegate;
+ private final android.hardware.devicestate.feature.flags.FeatureFlags mFeatureFlags;
@Nullable
private Boolean lastResult;
@@ -259,11 +336,23 @@
mFoldedDeviceStates = context.getResources().getIntArray(
com.android.internal.R.array.config_foldedDeviceStates);
mDelegate = listener;
+ mFeatureFlags = new android.hardware.devicestate.feature.flags.FeatureFlagsImpl();
}
@Override
- public final void onStateChanged(int state) {
- final boolean folded = ArrayUtils.contains(mFoldedDeviceStates, state);
+ public final void onStateChanged(int state) {}
+
+ @Override
+ public final void onDeviceStateChanged(@NonNull DeviceState deviceState) {
+ final boolean folded;
+ if (mFeatureFlags.deviceStatePropertyApi()) {
+ // TODO(b/325124054): Update when system server refactor is completed
+ folded = deviceState.hasProperty(
+ DeviceState.PROPERTY_FOLDABLE_DISPLAY_CONFIGURATION_OUTER_PRIMARY)
+ || ArrayUtils.contains(mFoldedDeviceStates, deviceState.getIdentifier());
+ } else {
+ folded = ArrayUtils.contains(mFoldedDeviceStates, deviceState.getIdentifier());
+ }
if (lastResult == null || !lastResult.equals(folded)) {
lastResult = folded;
diff --git a/core/java/android/hardware/devicestate/DeviceStateManagerGlobal.java b/core/java/android/hardware/devicestate/DeviceStateManagerGlobal.java
index c379188..6db5aee 100644
--- a/core/java/android/hardware/devicestate/DeviceStateManagerGlobal.java
+++ b/core/java/android/hardware/devicestate/DeviceStateManagerGlobal.java
@@ -19,6 +19,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
+import android.app.ActivityThread;
import android.content.Context;
import android.hardware.devicestate.DeviceStateManager.DeviceStateCallback;
import android.os.Binder;
@@ -32,9 +33,13 @@
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.annotations.VisibleForTesting.Visibility;
+import com.android.internal.util.ArrayUtils;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
import java.util.concurrent.Executor;
/**
@@ -50,12 +55,18 @@
private static final String TAG = "DeviceStateManagerGlobal";
private static final boolean DEBUG = Build.IS_DEBUGGABLE;
+ // TODO(b/325124054): Remove when system server refactor is completed
+ private static int[] sFoldedDeviceStates = new int[0];
+
/**
* Returns an instance of {@link DeviceStateManagerGlobal}. May return {@code null} if a
* connection with the device state service couldn't be established.
*/
@Nullable
public static DeviceStateManagerGlobal getInstance() {
+ // TODO(b/325124054): Remove when system server refactor is completed
+ instantiateFoldedStateArray();
+
synchronized (DeviceStateManagerGlobal.class) {
if (sInstance == null) {
IBinder b = ServiceManager.getService(Context.DEVICE_STATE_SERVICE);
@@ -68,6 +79,16 @@
}
}
+ // TODO(b/325124054): Remove when system server refactor is completed
+ // TODO(b/325330654): Investigate if we need a Context passed in to DSMGlobal
+ private static void instantiateFoldedStateArray() {
+ Context context = ActivityThread.currentApplication();
+ if (context != null) {
+ sFoldedDeviceStates = context.getResources().getIntArray(
+ com.android.internal.R.array.config_foldedDeviceStates);
+ }
+ }
+
private final Object mLock = new Object();
@NonNull
private final IDeviceStateManager mDeviceStateManager;
@@ -116,6 +137,32 @@
}
/**
+ * Returns the {@link List} of supported device states.
+ *
+ * @see DeviceStateManager#getSupportedDeviceStates()
+ */
+ public List<DeviceState> getSupportedDeviceStates() {
+ synchronized (mLock) {
+ final DeviceStateInfo currentInfo;
+ if (mLastReceivedInfo != null) {
+ // If we have mLastReceivedInfo a callback is registered for this instance and it
+ // is receiving the most recent info from the server. Use that info here.
+ currentInfo = mLastReceivedInfo;
+ } else {
+ // If mLastReceivedInfo is null there is no registered callback so we manually
+ // fetch the current info.
+ try {
+ currentInfo = mDeviceStateManager.getDeviceStateInfo();
+ } catch (RemoteException ex) {
+ throw ex.rethrowFromSystemServer();
+ }
+ }
+
+ return createDeviceStateList(currentInfo.supportedStates);
+ }
+ }
+
+ /**
* Submits a {@link DeviceStateRequest request} to modify the device state.
*
* @see DeviceStateManager#requestState(DeviceStateRequest, Executor,
@@ -241,8 +288,10 @@
final int[] supportedStates = Arrays.copyOf(mLastReceivedInfo.supportedStates,
mLastReceivedInfo.supportedStates.length);
wrapper.notifySupportedStatesChanged(supportedStates);
+ wrapper.notifySupportedDeviceStatesChanged(createDeviceStateList(supportedStates));
wrapper.notifyBaseStateChanged(mLastReceivedInfo.baseState);
wrapper.notifyStateChanged(mLastReceivedInfo.currentState);
+ wrapper.notifyDeviceStateChanged(createDeviceState(mLastReceivedInfo.currentState));
}
}
}
@@ -327,6 +376,8 @@
final int[] supportedStates = Arrays.copyOf(info.supportedStates,
info.supportedStates.length);
callbacks.get(i).notifySupportedStatesChanged(supportedStates);
+ callbacks.get(i).notifySupportedDeviceStatesChanged(
+ createDeviceStateList(supportedStates));
}
}
if ((diff & DeviceStateInfo.CHANGED_BASE_STATE) > 0) {
@@ -337,6 +388,7 @@
if ((diff & DeviceStateInfo.CHANGED_CURRENT_STATE) > 0) {
for (int i = 0; i < callbacks.size(); i++) {
callbacks.get(i).notifyStateChanged(info.currentState);
+ callbacks.get(i).notifyDeviceStateChanged(createDeviceState(info.currentState));
}
}
}
@@ -369,6 +421,36 @@
}
}
+ /**
+ * Creates a {@link DeviceState} object from a device state identifier, with the
+ * {@link DeviceState} property that corresponds to what display is primary.
+ *
+ */
+ // TODO(b/325124054): Remove when system server refactor is completed
+ @NonNull
+ private DeviceState createDeviceState(int stateIdentifier) {
+ final Set<@DeviceState.DeviceStateProperties Integer> properties = new HashSet<>();
+ if (ArrayUtils.contains(sFoldedDeviceStates, stateIdentifier)) {
+ properties.add(DeviceState.PROPERTY_FOLDABLE_DISPLAY_CONFIGURATION_OUTER_PRIMARY);
+ } else {
+ properties.add(DeviceState.PROPERTY_FOLDABLE_DISPLAY_CONFIGURATION_INNER_PRIMARY);
+ }
+ return new DeviceState(stateIdentifier, "" /* name */, properties);
+ }
+
+ /**
+ * Creates a list of {@link DeviceState} objects from an array of state identifiers.
+ */
+ // TODO(b/325124054): Remove when system server refactor is completed
+ @NonNull
+ private List<DeviceState> createDeviceStateList(int[] supportedStates) {
+ List<DeviceState> deviceStateList = new ArrayList<>();
+ for (int i = 0; i < supportedStates.length; i++) {
+ deviceStateList.add(createDeviceState(supportedStates[i]));
+ }
+ return deviceStateList;
+ }
+
private final class DeviceStateManagerCallback extends IDeviceStateManagerCallback.Stub {
@Override
public void onDeviceStateInfoChanged(DeviceStateInfo info) {
@@ -403,6 +485,11 @@
mDeviceStateCallback.onSupportedStatesChanged(newSupportedStates));
}
+ void notifySupportedDeviceStatesChanged(List<DeviceState> newSupportedDeviceStates) {
+ mExecutor.execute(() ->
+ mDeviceStateCallback.onSupportedStatesChanged(newSupportedDeviceStates));
+ }
+
void notifyBaseStateChanged(int newBaseState) {
execute("notifyBaseStateChanged",
() -> mDeviceStateCallback.onBaseStateChanged(newBaseState));
@@ -413,6 +500,11 @@
() -> mDeviceStateCallback.onStateChanged(newDeviceState));
}
+ void notifyDeviceStateChanged(DeviceState newDeviceState) {
+ execute("notifyDeviceStateChanged",
+ () -> mDeviceStateCallback.onDeviceStateChanged(newDeviceState));
+ }
+
private void execute(String traceName, Runnable r) {
mExecutor.execute(() -> {
if (DEBUG) {
diff --git a/core/java/android/hardware/devicestate/feature/flags.aconfig b/core/java/android/hardware/devicestate/feature/flags.aconfig
new file mode 100644
index 0000000..73a9e34
--- /dev/null
+++ b/core/java/android/hardware/devicestate/feature/flags.aconfig
@@ -0,0 +1,9 @@
+package: "android.hardware.devicestate.feature.flags"
+
+flag {
+ name: "device_state_property_api"
+ namespace: "windowing_sdk"
+ description: "Updated DeviceState hasProperty API"
+ bug: "293636629"
+ is_fixed_read_only: true
+}
\ No newline at end of file
diff --git a/core/java/android/service/chooser/CustomChoosers.java b/core/java/android/service/chooser/CustomChoosers.java
deleted file mode 100644
index 5b89432..0000000
--- a/core/java/android/service/chooser/CustomChoosers.java
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.service.chooser;
-
-import android.annotation.FlaggedApi;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.SystemApi;
-import android.content.Intent;
-import android.content.pm.ResolveInfo;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Static helper methods that privileged clients can use to initiate Share sessions with extra
- * customization options that aren't usually available in the stock "Resolver/Chooser" flows.
- *
- * @hide
- */
-@FlaggedApi(Flags.FLAG_SUPPORT_NFC_RESOLVER)
-@SystemApi
-public class CustomChoosers {
- /**
- * Intent action to start a Share session with additional customization options. Clients should
- * use the helper methods in this class to configure their customized share intents, and should
- * avoid using this action to construct their own intents directly.
- */
- private static final String ACTION_SHOW_CUSTOMIZED_RESOLVER =
- "android.service.chooser.action.SHOW_CUSTOMIZED_RESOLVER";
-
- /**
- * "Extras" key for an ArrayList of {@link ResolveInfo} records which are to be shown as the
- * targets in the customized share session.
- *
- * @hide
- */
- public static final String EXTRA_RESOLVE_INFOS = "android.service.chooser.extra.RESOLVE_INFOS";
-
- /**
- * Build an {@link Intent} to dispatch a "Chooser flow" that picks a target resolution for the
- * specified {@code target} intent, styling the Chooser UI according to the specified
- * customization parameters.
- *
- * @param target The ambiguous intent that should be resolved to a specific target selected
- * via the Chooser flow.
- * @param title An optional "headline" string to display at the top of the Chooser UI, or null
- * to use the system default.
- * @param resolutionList Explicit resolution info for targets that should be shown in the
- * dispatched Share UI.
- *
- * @hide
- */
- @FlaggedApi(Flags.FLAG_SUPPORT_NFC_RESOLVER)
- @SystemApi
- @NonNull
- public static Intent createNfcResolverIntent(
- @NonNull Intent target,
- @Nullable CharSequence title,
- @NonNull List<ResolveInfo> resolutionList) {
- Intent resolverIntent = new Intent(ACTION_SHOW_CUSTOMIZED_RESOLVER);
- resolverIntent.putExtra(Intent.EXTRA_INTENT, target);
- resolverIntent.putExtra(Intent.EXTRA_TITLE, title);
- resolverIntent.putParcelableArrayListExtra(
- EXTRA_RESOLVE_INFOS, new ArrayList<>(resolutionList));
- return resolverIntent;
- }
-
- private CustomChoosers() {}
-}
diff --git a/core/java/android/service/chooser/flags.aconfig b/core/java/android/service/chooser/flags.aconfig
index add575b..00236df 100644
--- a/core/java/android/service/chooser/flags.aconfig
+++ b/core/java/android/service/chooser/flags.aconfig
@@ -15,13 +15,6 @@
}
flag {
- name: "support_nfc_resolver"
- namespace: "systemui"
- description: "This flag controls the new NFC 'resolver' activity"
- bug: "268089816"
-}
-
-flag {
name: "chooser_payload_toggling"
namespace: "intentresolver"
description: "This flag controls content toggling in Chooser"
diff --git a/core/java/android/service/notification/ZenModeConfig.java b/core/java/android/service/notification/ZenModeConfig.java
index f169ecd..15fb6cc 100644
--- a/core/java/android/service/notification/ZenModeConfig.java
+++ b/core/java/android/service/notification/ZenModeConfig.java
@@ -813,9 +813,9 @@
rt.enabler = parser.getAttributeValue(null, RULE_ATT_ENABLER);
rt.condition = readConditionXml(parser);
- // all default rules and user created rules updated to zenMode important interruptions
- if (rt.zenMode != Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS
+ if (!Flags.modesApi() && rt.zenMode != Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS
&& Condition.isValidId(rt.conditionId, SYSTEM_AUTHORITY)) {
+ // all default rules and user created rules updated to zenMode important interruptions
Slog.i(TAG, "Updating zenMode of automatic rule " + rt.name);
rt.zenMode = Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
}
diff --git a/core/java/android/service/voice/HotwordTrainingAudio.java b/core/java/android/service/voice/HotwordTrainingAudio.java
deleted file mode 100644
index 916fa36b..0000000
--- a/core/java/android/service/voice/HotwordTrainingAudio.java
+++ /dev/null
@@ -1,388 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.service.voice;
-
-import android.annotation.FlaggedApi;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.SuppressLint;
-import android.annotation.SystemApi;
-import android.media.AudioFormat;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.service.voice.flags.Flags;
-
-import com.android.internal.util.DataClass;
-
-import java.util.Objects;
-
-/**
- * Represents audio supporting hotword model training.
- *
- * @hide
- */
-@FlaggedApi(Flags.FLAG_ALLOW_TRAINING_DATA_EGRESS_FROM_HDS)
-@DataClass(
- genConstructor = false,
- genBuilder = true,
- genEqualsHashCode = true,
- genHiddenConstDefs = true,
- genParcelable = true,
- genToString = true
-)
-@SystemApi
-public final class HotwordTrainingAudio implements Parcelable {
- /** Represents unset value for the hotword offset. */
- public static final int HOTWORD_OFFSET_UNSET = -1;
-
- /**
- * Buffer of hotword audio data for training models. The data format is expected to match
- * {@link #getAudioFormat()}.
- */
- @NonNull
- private final byte[] mHotwordAudio;
-
- private String hotwordAudioToString() {
- return "length=" + mHotwordAudio.length;
- }
-
- /**
- * The {@link AudioFormat} of the {@link HotwordTrainingAudio#mHotwordAudio}.
- */
- @NonNull
- private final AudioFormat mAudioFormat;
-
- /**
- * App-defined identifier to distinguish hotword training audio instances.
- * <p> Returns -1 if unset. */
- @NonNull
- private final int mAudioType;
-
- private static int defaultAudioType() {
- return -1;
- }
-
- /**
- * App-defined offset in milliseconds relative to start of
- * {@link HotwordTrainingAudio#mHotwordAudio}. Default value is
- * {@link HotwordTrainingAudio#HOTWORD_OFFSET_UNSET}.
- */
- private int mHotwordOffsetMillis = HOTWORD_OFFSET_UNSET;
-
- @DataClass.Suppress("setHotwordAudio")
- abstract static class BaseBuilder {
-
- /**
- * Buffer of hotword audio data for training models. The data format is expected to match
- * {@link #getAudioFormat()}.
- */
- @SuppressLint("UnflaggedApi")
- public @NonNull HotwordTrainingAudio.Builder setHotwordAudio(@NonNull byte[] value) {
- Objects.requireNonNull(value, "value should not be null");
- final HotwordTrainingAudio.Builder builder = (HotwordTrainingAudio.Builder) this;
- // If the code gen flag in build() is changed, we must update the flag e.g. 0x1 here.
- builder.mBuilderFieldsSet |= 0x1;
- builder.mHotwordAudio = value;
- return builder;
- }
- }
-
-
-
- // Code below generated by codegen v1.0.23.
- //
- // DO NOT MODIFY!
- // CHECKSTYLE:OFF Generated code
- //
- // To regenerate run:
- // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/service/voice/HotwordTrainingAudio.java
- //
- // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
- // Settings > Editor > Code Style > Formatter Control
- //@formatter:off
-
-
- @DataClass.Generated.Member
- /* package-private */ HotwordTrainingAudio(
- @NonNull byte[] hotwordAudio,
- @NonNull AudioFormat audioFormat,
- @NonNull int audioType,
- int hotwordOffsetMillis) {
- this.mHotwordAudio = hotwordAudio;
- com.android.internal.util.AnnotationValidations.validate(
- NonNull.class, null, mHotwordAudio);
- this.mAudioFormat = audioFormat;
- com.android.internal.util.AnnotationValidations.validate(
- NonNull.class, null, mAudioFormat);
- this.mAudioType = audioType;
- com.android.internal.util.AnnotationValidations.validate(
- NonNull.class, null, mAudioType);
- this.mHotwordOffsetMillis = hotwordOffsetMillis;
-
- // onConstructed(); // You can define this method to get a callback
- }
-
- /**
- * Buffer of hotword audio data for training models. The data format is expected to match
- * {@link #getAudioFormat()}.
- */
- @DataClass.Generated.Member
- public @NonNull byte[] getHotwordAudio() {
- return mHotwordAudio;
- }
-
- /**
- * The {@link AudioFormat} of the {@link HotwordTrainingAudio#mHotwordAudio}.
- */
- @DataClass.Generated.Member
- public @NonNull AudioFormat getAudioFormat() {
- return mAudioFormat;
- }
-
- /**
- * App-defined identifier to distinguish hotword training audio instances.
- * <p> Returns -1 if unset.
- */
- @DataClass.Generated.Member
- public @NonNull int getAudioType() {
- return mAudioType;
- }
-
- /**
- * App-defined offset in milliseconds relative to start of
- * {@link HotwordTrainingAudio#mHotwordAudio}. Default value is
- * {@link HotwordTrainingAudio#HOTWORD_OFFSET_UNSET}.
- */
- @DataClass.Generated.Member
- public int getHotwordOffsetMillis() {
- return mHotwordOffsetMillis;
- }
-
- @Override
- @DataClass.Generated.Member
- public String toString() {
- // You can override field toString logic by defining methods like:
- // String fieldNameToString() { ... }
-
- return "HotwordTrainingAudio { " +
- "hotwordAudio = " + hotwordAudioToString() + ", " +
- "audioFormat = " + mAudioFormat + ", " +
- "audioType = " + mAudioType + ", " +
- "hotwordOffsetMillis = " + mHotwordOffsetMillis +
- " }";
- }
-
- @Override
- @DataClass.Generated.Member
- public boolean equals(@Nullable Object o) {
- // You can override field equality logic by defining either of the methods like:
- // boolean fieldNameEquals(HotwordTrainingAudio other) { ... }
- // boolean fieldNameEquals(FieldType otherValue) { ... }
-
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
- @SuppressWarnings("unchecked")
- HotwordTrainingAudio that = (HotwordTrainingAudio) o;
- //noinspection PointlessBooleanExpression
- return true
- && java.util.Arrays.equals(mHotwordAudio, that.mHotwordAudio)
- && Objects.equals(mAudioFormat, that.mAudioFormat)
- && mAudioType == that.mAudioType
- && mHotwordOffsetMillis == that.mHotwordOffsetMillis;
- }
-
- @Override
- @DataClass.Generated.Member
- public int hashCode() {
- // You can override field hashCode logic by defining methods like:
- // int fieldNameHashCode() { ... }
-
- int _hash = 1;
- _hash = 31 * _hash + java.util.Arrays.hashCode(mHotwordAudio);
- _hash = 31 * _hash + Objects.hashCode(mAudioFormat);
- _hash = 31 * _hash + mAudioType;
- _hash = 31 * _hash + mHotwordOffsetMillis;
- return _hash;
- }
-
- @Override
- @DataClass.Generated.Member
- public void writeToParcel(@NonNull Parcel dest, int flags) {
- // You can override field parcelling by defining methods like:
- // void parcelFieldName(Parcel dest, int flags) { ... }
-
- dest.writeByteArray(mHotwordAudio);
- dest.writeTypedObject(mAudioFormat, flags);
- dest.writeInt(mAudioType);
- dest.writeInt(mHotwordOffsetMillis);
- }
-
- @Override
- @DataClass.Generated.Member
- public int describeContents() { return 0; }
-
- /** @hide */
- @SuppressWarnings({"unchecked", "RedundantCast"})
- @DataClass.Generated.Member
- /* package-private */ HotwordTrainingAudio(@NonNull Parcel in) {
- // You can override field unparcelling by defining methods like:
- // static FieldType unparcelFieldName(Parcel in) { ... }
-
- byte[] hotwordAudio = in.createByteArray();
- AudioFormat audioFormat = (AudioFormat) in.readTypedObject(AudioFormat.CREATOR);
- int audioType = in.readInt();
- int hotwordOffsetMillis = in.readInt();
-
- this.mHotwordAudio = hotwordAudio;
- com.android.internal.util.AnnotationValidations.validate(
- NonNull.class, null, mHotwordAudio);
- this.mAudioFormat = audioFormat;
- com.android.internal.util.AnnotationValidations.validate(
- NonNull.class, null, mAudioFormat);
- this.mAudioType = audioType;
- com.android.internal.util.AnnotationValidations.validate(
- NonNull.class, null, mAudioType);
- this.mHotwordOffsetMillis = hotwordOffsetMillis;
-
- // onConstructed(); // You can define this method to get a callback
- }
-
- @DataClass.Generated.Member
- public static final @NonNull Parcelable.Creator<HotwordTrainingAudio> CREATOR
- = new Parcelable.Creator<HotwordTrainingAudio>() {
- @Override
- public HotwordTrainingAudio[] newArray(int size) {
- return new HotwordTrainingAudio[size];
- }
-
- @Override
- public HotwordTrainingAudio createFromParcel(@NonNull Parcel in) {
- return new HotwordTrainingAudio(in);
- }
- };
-
- /**
- * A builder for {@link HotwordTrainingAudio}
- */
- @FlaggedApi(Flags.FLAG_ALLOW_TRAINING_DATA_EGRESS_FROM_HDS)
- @SuppressWarnings("WeakerAccess")
- @DataClass.Generated.Member
- public static final class Builder extends BaseBuilder {
-
- private @NonNull byte[] mHotwordAudio;
- private @NonNull AudioFormat mAudioFormat;
- private @NonNull int mAudioType;
- private int mHotwordOffsetMillis;
-
- private long mBuilderFieldsSet = 0L;
-
- /**
- * Creates a new Builder.
- *
- * @param hotwordAudio
- * Buffer of hotword audio data for training models. The data format is expected to match
- * {@link #getAudioFormat()}.
- * @param audioFormat
- * The {@link AudioFormat} of the {@link HotwordTrainingAudio#mHotwordAudio}.
- */
- public Builder(
- @NonNull byte[] hotwordAudio,
- @NonNull AudioFormat audioFormat) {
- mHotwordAudio = hotwordAudio;
- com.android.internal.util.AnnotationValidations.validate(
- NonNull.class, null, mHotwordAudio);
- mAudioFormat = audioFormat;
- com.android.internal.util.AnnotationValidations.validate(
- NonNull.class, null, mAudioFormat);
- }
-
- /**
- * The {@link AudioFormat} of the {@link HotwordTrainingAudio#mHotwordAudio}.
- */
- @DataClass.Generated.Member
- public @NonNull Builder setAudioFormat(@NonNull AudioFormat value) {
- checkNotUsed();
- mBuilderFieldsSet |= 0x2;
- mAudioFormat = value;
- return this;
- }
-
- /**
- * App-defined identifier to distinguish hotword training audio instances.
- * <p> Returns -1 if unset.
- */
- @DataClass.Generated.Member
- public @NonNull Builder setAudioType(@NonNull int value) {
- checkNotUsed();
- mBuilderFieldsSet |= 0x4;
- mAudioType = value;
- return this;
- }
-
- /**
- * App-defined offset in milliseconds relative to start of
- * {@link HotwordTrainingAudio#mHotwordAudio}. Default value is
- * {@link HotwordTrainingAudio#HOTWORD_OFFSET_UNSET}.
- */
- @DataClass.Generated.Member
- public @NonNull Builder setHotwordOffsetMillis(int value) {
- checkNotUsed();
- mBuilderFieldsSet |= 0x8;
- mHotwordOffsetMillis = value;
- return this;
- }
-
- /** Builds the instance. This builder should not be touched after calling this! */
- public @NonNull HotwordTrainingAudio build() {
- checkNotUsed();
- mBuilderFieldsSet |= 0x10; // Mark builder used
-
- if ((mBuilderFieldsSet & 0x4) == 0) {
- mAudioType = defaultAudioType();
- }
- if ((mBuilderFieldsSet & 0x8) == 0) {
- mHotwordOffsetMillis = HOTWORD_OFFSET_UNSET;
- }
- HotwordTrainingAudio o = new HotwordTrainingAudio(
- mHotwordAudio,
- mAudioFormat,
- mAudioType,
- mHotwordOffsetMillis);
- return o;
- }
-
- private void checkNotUsed() {
- if ((mBuilderFieldsSet & 0x10) != 0) {
- throw new IllegalStateException(
- "This Builder should not be reused. Use a new Builder instance instead");
- }
- }
- }
-
- @DataClass.Generated(
- time = 1697827049629L,
- codegenVersion = "1.0.23",
- sourceFile = "frameworks/base/core/java/android/service/voice/HotwordTrainingAudio.java",
- inputSignatures = "public static final int HOTWORD_OFFSET_UNSET\nprivate final @android.annotation.NonNull byte[] mHotwordAudio\nprivate final @android.annotation.NonNull android.media.AudioFormat mAudioFormat\nprivate final @android.annotation.NonNull int mAudioType\nprivate int mHotwordOffsetMillis\nprivate java.lang.String hotwordAudioToString()\nprivate static int defaultAudioType()\nclass HotwordTrainingAudio extends java.lang.Object implements [android.os.Parcelable]\npublic @android.annotation.SuppressLint @android.annotation.NonNull android.service.voice.HotwordTrainingAudio.Builder setHotwordAudio(byte[])\nclass BaseBuilder extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genConstructor=false, genBuilder=true, genEqualsHashCode=true, genHiddenConstDefs=true, genParcelable=true, genToString=true)\npublic @android.annotation.SuppressLint @android.annotation.NonNull android.service.voice.HotwordTrainingAudio.Builder setHotwordAudio(byte[])\nclass BaseBuilder extends java.lang.Object implements []")
- @Deprecated
- private void __metadata() {}
-
-
- //@formatter:on
- // End of generated code
-
-}
diff --git a/core/java/android/service/voice/HotwordTrainingData.aidl b/core/java/android/service/voice/HotwordTrainingData.aidl
deleted file mode 100644
index 03cc841..0000000
--- a/core/java/android/service/voice/HotwordTrainingData.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.service.voice;
-
-parcelable HotwordTrainingData;
diff --git a/core/java/android/service/voice/HotwordTrainingData.java b/core/java/android/service/voice/HotwordTrainingData.java
deleted file mode 100644
index aa6dab3..0000000
--- a/core/java/android/service/voice/HotwordTrainingData.java
+++ /dev/null
@@ -1,305 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.service.voice;
-
-import android.annotation.FlaggedApi;
-import android.annotation.NonNull;
-import android.annotation.SystemApi;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.service.voice.flags.Flags;
-import android.text.TextUtils;
-
-import com.android.internal.util.DataClass;
-import com.android.internal.util.Preconditions;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-/**
- * Contains training data related to hotword detection service.
- *
- * <p>The constructed object's size must be within
- * {@link HotwordTrainingData#getMaxTrainingDataBytes()} or an
- * {@link IllegalArgumentException} will be thrown on construction. Size of the object is calculated
- * by converting object to a {@link Parcel} and using the {@link Parcel#dataSize()}.
- *
- * @hide
- */
-@DataClass(
- genConstructor = false,
- genBuilder = true,
- genEqualsHashCode = true,
- genHiddenConstDefs = true,
- genParcelable = true,
- genToString = true)
-@SystemApi
-@FlaggedApi(Flags.FLAG_ALLOW_TRAINING_DATA_EGRESS_FROM_HDS)
-public final class HotwordTrainingData implements Parcelable {
- /** Max size for hotword training data in bytes. */
- public static int getMaxTrainingDataBytes() {
- return 1024 * 1024; // 1 MB;
- }
-
- /** The list containing hotword audio that is useful for training. */
- @NonNull
- @DataClass.PluralOf("trainingAudio")
- private final List<HotwordTrainingAudio> mTrainingAudioList;
-
- private static List<HotwordTrainingAudio> defaultTrainingAudioList() {
- return Collections.emptyList();
- }
-
- /** App-defined stage when hotword model timed-out while running.
- * <p> Returns -1 if unset. */
- private final int mTimeoutStage;
-
- private static int defaultTimeoutStage() {
- return -1;
- }
-
- private void onConstructed() {
- // Verify size of object is within limit.
- Parcel parcel = Parcel.obtain();
- parcel.writeValue(this);
- int dataSizeBytes = parcel.dataSize();
- parcel.recycle();
- Preconditions.checkArgument(
- dataSizeBytes < getMaxTrainingDataBytes(),
- TextUtils.formatSimple(
- "Hotword training data of size %s exceeds size limit of %s bytes!",
- dataSizeBytes, getMaxTrainingDataBytes()));
- }
-
-
-
- // Code below generated by codegen v1.0.23.
- //
- // DO NOT MODIFY!
- // CHECKSTYLE:OFF Generated code
- //
- // To regenerate run:
- // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/service/voice/HotwordTrainingData.java
- //
- // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
- // Settings > Editor > Code Style > Formatter Control
- //@formatter:off
-
-
- @DataClass.Generated.Member
- /* package-private */ HotwordTrainingData(
- @NonNull List<HotwordTrainingAudio> trainingAudioList,
- int timeoutStage) {
- this.mTrainingAudioList = trainingAudioList;
- com.android.internal.util.AnnotationValidations.validate(
- NonNull.class, null, mTrainingAudioList);
- this.mTimeoutStage = timeoutStage;
-
- onConstructed();
- }
-
- /**
- * The list containing hotword audio that is useful for training.
- */
- @DataClass.Generated.Member
- public @NonNull List<HotwordTrainingAudio> getTrainingAudioList() {
- return mTrainingAudioList;
- }
-
- /**
- * App-defined stage when hotword model timed-out while running.
- * <p> Returns -1 if unset.
- */
- @DataClass.Generated.Member
- public int getTimeoutStage() {
- return mTimeoutStage;
- }
-
- @Override
- @DataClass.Generated.Member
- public String toString() {
- // You can override field toString logic by defining methods like:
- // String fieldNameToString() { ... }
-
- return "HotwordTrainingData { " +
- "trainingAudioList = " + mTrainingAudioList + ", " +
- "timeoutStage = " + mTimeoutStage +
- " }";
- }
-
- @Override
- @DataClass.Generated.Member
- public boolean equals(@android.annotation.Nullable Object o) {
- // You can override field equality logic by defining either of the methods like:
- // boolean fieldNameEquals(HotwordTrainingData other) { ... }
- // boolean fieldNameEquals(FieldType otherValue) { ... }
-
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
- @SuppressWarnings("unchecked")
- HotwordTrainingData that = (HotwordTrainingData) o;
- //noinspection PointlessBooleanExpression
- return true
- && java.util.Objects.equals(mTrainingAudioList, that.mTrainingAudioList)
- && mTimeoutStage == that.mTimeoutStage;
- }
-
- @Override
- @DataClass.Generated.Member
- public int hashCode() {
- // You can override field hashCode logic by defining methods like:
- // int fieldNameHashCode() { ... }
-
- int _hash = 1;
- _hash = 31 * _hash + java.util.Objects.hashCode(mTrainingAudioList);
- _hash = 31 * _hash + mTimeoutStage;
- return _hash;
- }
-
- @Override
- @DataClass.Generated.Member
- public void writeToParcel(@NonNull Parcel dest, int flags) {
- // You can override field parcelling by defining methods like:
- // void parcelFieldName(Parcel dest, int flags) { ... }
-
- dest.writeParcelableList(mTrainingAudioList, flags);
- dest.writeInt(mTimeoutStage);
- }
-
- @Override
- @DataClass.Generated.Member
- public int describeContents() { return 0; }
-
- /** @hide */
- @SuppressWarnings({"unchecked", "RedundantCast"})
- @DataClass.Generated.Member
- /* package-private */ HotwordTrainingData(@NonNull Parcel in) {
- // You can override field unparcelling by defining methods like:
- // static FieldType unparcelFieldName(Parcel in) { ... }
-
- List<HotwordTrainingAudio> trainingAudioList = new ArrayList<>();
- in.readParcelableList(trainingAudioList, HotwordTrainingAudio.class.getClassLoader());
- int timeoutStage = in.readInt();
-
- this.mTrainingAudioList = trainingAudioList;
- com.android.internal.util.AnnotationValidations.validate(
- NonNull.class, null, mTrainingAudioList);
- this.mTimeoutStage = timeoutStage;
-
- onConstructed();
- }
-
- @DataClass.Generated.Member
- public static final @NonNull Parcelable.Creator<HotwordTrainingData> CREATOR
- = new Parcelable.Creator<HotwordTrainingData>() {
- @Override
- public HotwordTrainingData[] newArray(int size) {
- return new HotwordTrainingData[size];
- }
-
- @Override
- public HotwordTrainingData createFromParcel(@NonNull Parcel in) {
- return new HotwordTrainingData(in);
- }
- };
-
- /**
- * A builder for {@link HotwordTrainingData}
- */
- @FlaggedApi(Flags.FLAG_ALLOW_TRAINING_DATA_EGRESS_FROM_HDS)
- @SuppressWarnings("WeakerAccess")
- @DataClass.Generated.Member
- public static final class Builder {
-
- private @NonNull List<HotwordTrainingAudio> mTrainingAudioList;
- private int mTimeoutStage;
-
- private long mBuilderFieldsSet = 0L;
-
- public Builder() {
- }
-
- /**
- * The list containing hotword audio that is useful for training.
- */
- @DataClass.Generated.Member
- public @NonNull Builder setTrainingAudioList(@NonNull List<HotwordTrainingAudio> value) {
- checkNotUsed();
- mBuilderFieldsSet |= 0x1;
- mTrainingAudioList = value;
- return this;
- }
-
- /** @see #setTrainingAudioList */
- @DataClass.Generated.Member
- public @NonNull Builder addTrainingAudio(@NonNull HotwordTrainingAudio value) {
- if (mTrainingAudioList == null) setTrainingAudioList(new ArrayList<>());
- mTrainingAudioList.add(value);
- return this;
- }
-
- /**
- * App-defined stage when hotword model timed-out while running.
- * <p> Returns -1 if unset.
- */
- @DataClass.Generated.Member
- public @NonNull Builder setTimeoutStage(int value) {
- checkNotUsed();
- mBuilderFieldsSet |= 0x2;
- mTimeoutStage = value;
- return this;
- }
-
- /** Builds the instance. This builder should not be touched after calling this! */
- public @NonNull HotwordTrainingData build() {
- checkNotUsed();
- mBuilderFieldsSet |= 0x4; // Mark builder used
-
- if ((mBuilderFieldsSet & 0x1) == 0) {
- mTrainingAudioList = defaultTrainingAudioList();
- }
- if ((mBuilderFieldsSet & 0x2) == 0) {
- mTimeoutStage = defaultTimeoutStage();
- }
- HotwordTrainingData o = new HotwordTrainingData(
- mTrainingAudioList,
- mTimeoutStage);
- return o;
- }
-
- private void checkNotUsed() {
- if ((mBuilderFieldsSet & 0x4) != 0) {
- throw new IllegalStateException(
- "This Builder should not be reused. Use a new Builder instance instead");
- }
- }
- }
-
- @DataClass.Generated(
- time = 1697826948280L,
- codegenVersion = "1.0.23",
- sourceFile = "frameworks/base/core/java/android/service/voice/HotwordTrainingData.java",
- inputSignatures = "private final @android.annotation.NonNull @com.android.internal.util.DataClass.PluralOf(\"trainingAudio\") java.util.List<android.service.voice.HotwordTrainingAudio> mTrainingAudioList\nprivate final int mTimeoutStage\npublic static int getMaxTrainingDataBytes()\nprivate static java.util.List<android.service.voice.HotwordTrainingAudio> defaultTrainingAudioList()\nprivate static int defaultTimeoutStage()\nprivate void onConstructed()\nclass HotwordTrainingData extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genConstructor=false, genBuilder=true, genEqualsHashCode=true, genHiddenConstDefs=true, genParcelable=true, genToString=true)")
- @Deprecated
- private void __metadata() {}
-
-
- //@formatter:on
- // End of generated code
-
-}
diff --git a/core/java/android/text/MeasuredParagraph.java b/core/java/android/text/MeasuredParagraph.java
index 95d1974..2b6684e 100644
--- a/core/java/android/text/MeasuredParagraph.java
+++ b/core/java/android/text/MeasuredParagraph.java
@@ -237,10 +237,13 @@
// Easy case: If the line instance only contains single directionality run, no need
// to reorder visually.
if (bidi.getRunCount() == 1) {
- if ((bidi.getParaLevel() & 0x01) == 1) {
+ if (bidi.getRunLevel(0) == 1) {
return Layout.DIRS_ALL_RIGHT_TO_LEFT;
- } else {
+ } else if (bidi.getRunLevel(0) == 0) {
return Layout.DIRS_ALL_LEFT_TO_RIGHT;
+ } else {
+ return new Directions(new int[] {
+ 0, bidi.getRunLevel(0) << Layout.RUN_LEVEL_SHIFT | (end - start)});
}
}
diff --git a/core/java/android/view/AttachedSurfaceControl.java b/core/java/android/view/AttachedSurfaceControl.java
index 5ec41591..5406cf5 100644
--- a/core/java/android/view/AttachedSurfaceControl.java
+++ b/core/java/android/view/AttachedSurfaceControl.java
@@ -192,7 +192,7 @@
* {@link WindowManager#registerUnbatchedSurfaceControlInputReceiver(int, InputTransferToken,
* SurfaceControl, Looper, SurfaceControlInputReceiver)}
*
- * @return The SurfaceControlViewHost link token.
+ * @return The {@link InputTransferToken} for the {@link AttachedSurfaceControl}
* @throws IllegalStateException if the {@link AttachedSurfaceControl} was created with no
* registered input
*/
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index 3c0ac06..eff35c0c0 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -224,6 +224,8 @@
@DataSpace.NamedDataSpace int dataSpace);
private static native void nativeSetExtendedRangeBrightness(long transactionObj,
long nativeObject, float currentBufferRatio, float desiredRatio);
+ private static native void nativeSetDesiredHdrHeadroom(long transactionObj,
+ long nativeObject, float desiredRatio);
private static native void nativeSetCachingHint(long transactionObj,
long nativeObject, int cachingHint);
@@ -4148,6 +4150,50 @@
}
/**
+ * Sets the desired hdr headroom for the layer.
+ *
+ * <p>Prefer using this API over {@link #setExtendedRangeBrightness} for formats that
+ *. conform to HDR video standards like HLG or HDR10 which do not communicate a HDR/SDR
+ * ratio as part of generating the buffer.
+ *
+ * @param sc The layer whose desired hdr headroom is being specified
+ *
+ * @param desiredRatio The desired hdr/sdr ratio. This can be used to communicate the max
+ * desired brightness range. This is similar to the "max luminance"
+ * value in other HDR metadata formats, but represented as a ratio of
+ * the target SDR whitepoint to the max display brightness. The system
+ * may not be able to, or may choose not to, deliver the
+ * requested range.
+ *
+ * <p>Default value is 0.0f and indicates that the system will choose
+ * the best headroom for this surface control's content. Typically,
+ * this means that HLG/PQ encoded content will be displayed with some
+ * HDR headroom greater than 1.0.
+ *
+ * <p>When called after {@link #setExtendedRangeBrightness}, the
+ * desiredHeadroom will override the desiredRatio provided by
+ * {@link #setExtendedRangeBrightness}. Conversely, when called
+ * before {@link #setExtendedRangeBrightness}, the desiredRatio provided
+ * by {@link #setExtendedRangeBrightness} will override the
+ * desiredHeadroom.
+ *
+ * <p>Must be finite && >= 1.0f or 0.0f.
+ * @return this
+ * @see #setExtendedRangeBrightness
+ **/
+ @FlaggedApi(com.android.graphics.hwui.flags.Flags.FLAG_LIMITED_HDR)
+ public @NonNull Transaction setDesiredHdrHeadroom(@NonNull SurfaceControl sc,
+ @FloatRange(from = 0.0f) float desiredRatio) {
+ checkPreconditions(sc);
+ if (!Float.isFinite(desiredRatio) || (desiredRatio != 0 && desiredRatio < 1.0f)) {
+ throw new IllegalArgumentException(
+ "desiredRatio must be finite && >= 1.0f or 0; got " + desiredRatio);
+ }
+ nativeSetDesiredHdrHeadroom(mNativeObject, sc.mNativeObject, desiredRatio);
+ return this;
+ }
+
+ /**
* Sets the caching hint for the layer. By default, the caching hint is
* {@link CACHING_ENABLED}.
*
diff --git a/core/java/android/view/SurfaceControlViewHost.java b/core/java/android/view/SurfaceControlViewHost.java
index 06a923a..6f757df 100644
--- a/core/java/android/view/SurfaceControlViewHost.java
+++ b/core/java/android/view/SurfaceControlViewHost.java
@@ -293,6 +293,7 @@
/**
* Gets an {@link InputTransferToken} which can be used to request focus on the embedded
* surface or to transfer touch gesture to the embedded surface.
+ *
* @return the InputTransferToken associated with {@link SurfacePackage} or {@code null} if
* the embedded hasn't set up its view or doesn't have input.
* @see WindowManager#transferTouchGesture(InputTransferToken, InputTransferToken)
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index 9caf7a6..d494e28 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -21,6 +21,8 @@
import static android.view.WindowManagerPolicyConstants.APPLICATION_MEDIA_SUBLAYER;
import static android.view.WindowManagerPolicyConstants.APPLICATION_PANEL_SUBLAYER;
+import android.annotation.FlaggedApi;
+import android.annotation.FloatRange;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -187,6 +189,7 @@
final Rect mScreenRect = new Rect();
private final SurfaceSession mSurfaceSession = new SurfaceSession();
+ private final boolean mLimitedHdrEnabled = Flags.limitedHdr();
SurfaceControl mSurfaceControl;
SurfaceControl mBackgroundControl;
@@ -197,6 +200,9 @@
@SurfaceLifecycleStrategy
private int mSurfaceLifecycleStrategy = SURFACE_LIFECYCLE_DEFAULT;
+ private float mRequestedHdrHeadroom = 0.f;
+ private float mHdrHeadroom = 0.f;
+
/**
* We use this lock to protect access to mSurfaceControl. Both are accessed on the UI
* thread and the render thread via RenderNode.PositionUpdateListener#positionLost.
@@ -821,6 +827,45 @@
updateSurface();
}
+
+ /**
+ * Sets the desired amount of HDR headroom to be used when HDR content is presented on this
+ * SurfaceView.
+ *
+ * <p>By default the system will choose an amount of HDR headroom that is appropriate
+ * for the underlying device capabilities & bit-depth of the panel. However, for some types
+ * of content this can end up being more headroom than necessary or desired. An example
+ * would be a messaging app or gallery thumbnail view where some amount of HDR pop is desired
+ * without overly influencing the perceived brightness of the majority SDR content. This can
+ * also be used to animate in/out of an HDR range for smoother transitions.</p>
+ *
+ * <p>Note: The actual amount of HDR headroom that will be given is subject to a variety
+ * of factors such as ambient conditions, display capabilities, or bit-depth limitations.
+ * See {@link Display#getHdrSdrRatio()} for more information as well as how to query the
+ * current value.</p>
+ *
+ * @param desiredHeadroom The amount of HDR headroom that is desired. Must be >= 1.0 (no HDR)
+ * and <= 10,000.0. Passing 0.0 will reset to the default, automatically
+ * chosen value.
+ * @see Display#getHdrSdrRatio()
+ */
+ @FlaggedApi(com.android.graphics.hwui.flags.Flags.FLAG_LIMITED_HDR)
+ public void setDesiredHdrHeadroom(
+ @FloatRange(from = 0.0f, to = 10000.0) float desiredHeadroom) {
+ if (!Float.isFinite(desiredHeadroom)) {
+ throw new IllegalArgumentException("desiredHeadroom must be finite: "
+ + desiredHeadroom);
+ }
+ if (desiredHeadroom != 0 && (desiredHeadroom < 1.0f || desiredHeadroom > 10000.0f)) {
+ throw new IllegalArgumentException(
+ "desiredHeadroom must be 0.0 or in the range [1.0, 10000.0f], received: "
+ + desiredHeadroom);
+ }
+ mRequestedHdrHeadroom = desiredHeadroom;
+ updateSurface();
+ invalidate();
+ }
+
private void updateOpaqueFlag() {
if (!PixelFormat.formatHasAlpha(mRequestedFormat)) {
mSurfaceFlags |= SurfaceControl.OPAQUE;
@@ -941,6 +986,10 @@
updateBackgroundVisibility(surfaceUpdateTransaction);
updateBackgroundColor(surfaceUpdateTransaction);
+ if (mLimitedHdrEnabled) {
+ surfaceUpdateTransaction.setDesiredHdrHeadroom(
+ mBlastSurfaceControl, mHdrHeadroom);
+ }
if (isAboveParent()) {
float alpha = getAlpha();
surfaceUpdateTransaction.setAlpha(mSurfaceControl, alpha);
@@ -1085,11 +1134,12 @@
final boolean relativeZChanged = mSubLayer != mRequestedSubLayer;
final boolean surfaceLifecycleStrategyChanged =
mSurfaceLifecycleStrategy != mRequestedSurfaceLifecycleStrategy;
+ final boolean hdrHeadroomChanged = mHdrHeadroom != mRequestedHdrHeadroom;
if (creating || formatChanged || sizeChanged || visibleChanged
|| alphaChanged || windowVisibleChanged || positionChanged
|| layoutSizeChanged || hintChanged || relativeZChanged || !mAttachedToWindow
- || surfaceLifecycleStrategyChanged) {
+ || surfaceLifecycleStrategyChanged || hdrHeadroomChanged) {
if (DEBUG) Log.i(TAG, System.identityHashCode(this) + " "
+ "Changes: creating=" + creating
@@ -1117,6 +1167,7 @@
final int previousSurfaceLifecycleStrategy = mSurfaceLifecycleStrategy;
mSurfaceLifecycleStrategy = mRequestedSurfaceLifecycleStrategy;
+ mHdrHeadroom = mRequestedHdrHeadroom;
mScreenRect.left = mWindowSpaceLeft;
mScreenRect.top = mWindowSpaceTop;
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 0e17626..64846d0 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -6184,7 +6184,7 @@
* receive batched input event. For those events that are batched, the invocation will happen
* once per {@link Choreographer} frame, and other input events will be delivered immediately.
* This is different from
- * { #registerUnbatchedSurfaceControlInputReceiver(int, InputTransferToken, SurfaceControl,
+ * {@link #registerUnbatchedSurfaceControlInputReceiver(int, InputTransferToken, SurfaceControl,
* Looper, SurfaceControlInputReceiver)} in that the input events are received batched. The
* caller must invoke {@link #unregisterSurfaceControlInputReceiver(SurfaceControl)} to clean up
* the resources when no longer needing to use the {@link SurfaceControlInputReceiver}
@@ -6253,10 +6253,9 @@
* <p>
* Must be called on the same {@link Looper} thread to which was passed to the
* {@link #registerBatchedSurfaceControlInputReceiver(int, InputTransferToken, SurfaceControl,
- * Choreographer,
- * SurfaceControlInputReceiver)} or
- * {@link #registerUnbatchedSurfaceControlInputReceiver(int, InputTransferToken, SurfaceControl, Looper,
- * SurfaceControlInputReceiver)}
+ * Choreographer, SurfaceControlInputReceiver)} or
+ * {@link #registerUnbatchedSurfaceControlInputReceiver(int, InputTransferToken, SurfaceControl,
+ * Looper, SurfaceControlInputReceiver)}
*
* @param surfaceControl The SurfaceControl to remove and unregister the input channel for.
*/
@@ -6267,12 +6266,12 @@
}
/**
- * Returns the input client token for the {@link SurfaceControl}. This will only return non null
- * if the SurfaceControl was registered for input via
- * { #registerBatchedSurfaceControlInputReceiver(int, IBinder, SurfaceControl, Choreographer,
- * SurfaceControlInputReceiver)} or
- * {@link #registerUnbatchedSurfaceControlInputReceiver(int, InputTransferToken, SurfaceControl, Looper,
- * SurfaceControlInputReceiver)}.
+ * Returns the input client token for the {@link SurfaceControl}. This will only return non
+ * null if the SurfaceControl was registered for input via
+ * {@link #registerBatchedSurfaceControlInputReceiver(int, InputTransferToken, SurfaceControl,
+ * Choreographer, SurfaceControlInputReceiver)} or
+ * {@link #registerUnbatchedSurfaceControlInputReceiver(int, InputTransferToken,
+ * SurfaceControl, Looper, SurfaceControlInputReceiver)}.
* <p>
* This is helpful for testing to ensure the test waits for the layer to be registered with
* SurfaceFlinger and Input before proceeding with the test.
diff --git a/core/java/android/view/WindowManagerGlobal.java b/core/java/android/view/WindowManagerGlobal.java
index 584219a..c6d0454 100644
--- a/core/java/android/view/WindowManagerGlobal.java
+++ b/core/java/android/view/WindowManagerGlobal.java
@@ -898,7 +898,7 @@
return inputTransferToken;
}
- void unregisterSurfaceControlInputReceiver(SurfaceControl surfaceControl) {
+ void unregisterSurfaceControlInputReceiver(@NonNull SurfaceControl surfaceControl) {
SurfaceControlInputReceiverInfo surfaceControlInputReceiverInfo;
synchronized (mSurfaceControlInputReceivers) {
surfaceControlInputReceiverInfo = mSurfaceControlInputReceivers.removeReturnOld(
@@ -920,7 +920,7 @@
surfaceControlInputReceiverInfo.mInputEventReceiver.dispose();
}
- IBinder getSurfaceControlInputClientToken(SurfaceControl surfaceControl) {
+ IBinder getSurfaceControlInputClientToken(@NonNull SurfaceControl surfaceControl) {
SurfaceControlInputReceiverInfo surfaceControlInputReceiverInfo;
synchronized (mSurfaceControlInputReceivers) {
surfaceControlInputReceiverInfo = mSurfaceControlInputReceivers.get(
@@ -934,8 +934,8 @@
return surfaceControlInputReceiverInfo.mClientToken;
}
- boolean transferTouchGesture(InputTransferToken transferFromToken,
- InputTransferToken transferToToken) {
+ boolean transferTouchGesture(@NonNull InputTransferToken transferFromToken,
+ @NonNull InputTransferToken transferToToken) {
try {
return getWindowManagerService().transferTouchGesture(transferFromToken,
transferToToken);
diff --git a/core/java/android/view/WindowManagerImpl.java b/core/java/android/view/WindowManagerImpl.java
index 8972228..df4fed6 100644
--- a/core/java/android/view/WindowManagerImpl.java
+++ b/core/java/android/view/WindowManagerImpl.java
@@ -539,6 +539,10 @@
@NonNull InputTransferToken hostInputTransferToken,
@NonNull SurfaceControl surfaceControl, @NonNull Choreographer choreographer,
@NonNull SurfaceControlInputReceiver receiver) {
+ Objects.requireNonNull(hostInputTransferToken);
+ Objects.requireNonNull(surfaceControl);
+ Objects.requireNonNull(choreographer);
+ Objects.requireNonNull(receiver);
return mGlobal.registerBatchedSurfaceControlInputReceiver(displayId, hostInputTransferToken,
surfaceControl, choreographer, receiver);
}
@@ -549,18 +553,24 @@
@NonNull InputTransferToken hostInputTransferToken,
@NonNull SurfaceControl surfaceControl, @NonNull Looper looper,
@NonNull SurfaceControlInputReceiver receiver) {
+ Objects.requireNonNull(hostInputTransferToken);
+ Objects.requireNonNull(surfaceControl);
+ Objects.requireNonNull(looper);
+ Objects.requireNonNull(receiver);
return mGlobal.registerUnbatchedSurfaceControlInputReceiver(displayId,
hostInputTransferToken, surfaceControl, looper, receiver);
}
@Override
public void unregisterSurfaceControlInputReceiver(@NonNull SurfaceControl surfaceControl) {
+ Objects.requireNonNull(surfaceControl);
mGlobal.unregisterSurfaceControlInputReceiver(surfaceControl);
}
@Override
@Nullable
public IBinder getSurfaceControlInputClientToken(@NonNull SurfaceControl surfaceControl) {
+ Objects.requireNonNull(surfaceControl);
return mGlobal.getSurfaceControlInputClientToken(surfaceControl);
}
diff --git a/core/java/android/view/animation/AnimationUtils.java b/core/java/android/view/animation/AnimationUtils.java
index 57a3b76..8a407c3 100644
--- a/core/java/android/view/animation/AnimationUtils.java
+++ b/core/java/android/view/animation/AnimationUtils.java
@@ -185,7 +185,7 @@
@FlaggedApi(FLAG_EXPECTED_PRESENTATION_TIME_READ_ONLY)
public static long getExpectedPresentationTimeNanos() {
if (!sExpectedPresentationTimeFlagValue) {
- return SystemClock.uptimeMillis();
+ return SystemClock.uptimeMillis() * TimeUtils.NANOS_PER_MS;
}
AnimationState state = sAnimationState.get();
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index 5bf1b5b..13dc4ef 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -112,6 +112,7 @@
import com.android.internal.R;
import com.android.internal.util.Preconditions;
import com.android.internal.widget.IRemoteViewsFactory;
+import com.android.internal.widget.remotecompose.core.operations.Theme;
import com.android.internal.widget.remotecompose.player.RemoteComposeDocument;
import com.android.internal.widget.remotecompose.player.RemoteComposePlayer;
@@ -3902,7 +3903,6 @@
throws ActionException {
if (drawDataParcel() && mInstructions != null
&& root instanceof RemoteComposePlayer player) {
- player.setTag(mInstructions);
final List<byte[]> bytes = mInstructions.mInstructions;
if (bytes.isEmpty()) {
return;
@@ -6082,20 +6082,24 @@
if (applyThemeResId != 0) {
inflationContext = new ContextThemeWrapper(inflationContext, applyThemeResId);
}
+ View v;
// If the RemoteViews contains draw instructions, just use it instead.
if (rv.hasDrawInstructions()) {
- return new RemoteComposePlayer(inflationContext);
- }
- LayoutInflater inflater = LayoutInflater.from(context);
+ final RemoteComposePlayer player = new RemoteComposePlayer(inflationContext);
+ player.setDebug(Build.IS_USERDEBUG || Build.IS_ENG ? 1 : 0);
+ v = player;
+ } else {
+ LayoutInflater inflater = LayoutInflater.from(context);
- // Clone inflater so we load resources from correct context and
- // we don't add a filter to the static version returned by getSystemService.
- inflater = inflater.cloneInContext(inflationContext);
- inflater.setFilter(shouldUseStaticFilter() ? INFLATER_FILTER : this);
- if (mLayoutInflaterFactory2 != null) {
- inflater.setFactory2(mLayoutInflaterFactory2);
+ // Clone inflater so we load resources from correct context and
+ // we don't add a filter to the static version returned by getSystemService.
+ inflater = inflater.cloneInContext(inflationContext);
+ inflater.setFilter(shouldUseStaticFilter() ? INFLATER_FILTER : this);
+ if (mLayoutInflaterFactory2 != null) {
+ inflater.setFactory2(mLayoutInflaterFactory2);
+ }
+ v = inflater.inflate(rv.getLayoutId(), parent, false);
}
- View v = inflater.inflate(rv.getLayoutId(), parent, false);
if (mViewId != View.NO_ID) {
v.setId(mViewId);
v.setTagInternal(R.id.remote_views_override_id, mViewId);
@@ -6441,6 +6445,10 @@
if (params.handler == null) {
params.handler = DEFAULT_INTERACTION_HANDLER;
}
+ if (v instanceof RemoteComposePlayer player) {
+ player.setTheme(v.getResources().getConfiguration().isNightModeActive()
+ ? Theme.DARK : Theme.LIGHT);
+ }
if (mActions != null) {
final int count = mActions.size();
for (int i = 0; i < count; i++) {
@@ -7565,6 +7573,8 @@
@FlaggedApi(FLAG_DRAW_DATA_PARCEL)
public static final class DrawInstructions {
+ private static final long VERSION = 1L;
+
@NonNull
final List<byte[]> mInstructions;
@@ -7599,6 +7609,7 @@
}
return new DrawInstructions(instructions);
}
+
private static void writeToParcel(@Nullable final DrawInstructions drawInstructions,
@NonNull final Parcel dest, final int flags) {
if (drawInstructions == null) {
@@ -7614,6 +7625,14 @@
}
/**
+ * Version number of {@link DrawInstructions} currently supported.
+ */
+ @FlaggedApi(FLAG_DRAW_DATA_PARCEL)
+ public static long getSupportedVersion() {
+ return VERSION;
+ }
+
+ /**
* Builder class for {@link DrawInstructions} objects.
*/
@FlaggedApi(FLAG_DRAW_DATA_PARCEL)
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 9847cb1..1721462 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -5513,6 +5513,7 @@
*
* @attr ref android.R.styleable#TextView_fontVariationSettings
*/
+ @android.view.RemotableViewMethod
public boolean setFontVariationSettings(@Nullable String fontVariationSettings) {
final String existingSettings = mTextPaint.getFontVariationSettings();
if (fontVariationSettings == existingSettings
diff --git a/core/java/com/android/internal/app/NfcResolverActivity.java b/core/java/com/android/internal/app/NfcResolverActivity.java
index 402192a..78427fe 100644
--- a/core/java/com/android/internal/app/NfcResolverActivity.java
+++ b/core/java/com/android/internal/app/NfcResolverActivity.java
@@ -16,25 +16,25 @@
package com.android.internal.app;
-import static android.service.chooser.CustomChoosers.EXTRA_RESOLVE_INFOS;
-import static android.service.chooser.Flags.supportNfcResolver;
+import static android.nfc.Flags.enableNfcMainline;
import android.content.Intent;
import android.content.pm.ResolveInfo;
+import android.nfc.NfcAdapter;
import android.os.Bundle;
import java.util.ArrayList;
/**
* Caller-customizable variant of {@link ResolverActivity} to support the
- * {@link CustomChoosers#showNfcResolver()} API.
+ * NFC resolver intent.
*/
public class NfcResolverActivity extends ResolverActivity {
@Override
@SuppressWarnings("MissingSuperCall") // Called indirectly via `super_onCreate()`.
protected void onCreate(Bundle savedInstanceState) {
- if (!supportNfcResolver()) {
+ if (!enableNfcMainline()) {
super_onCreate(savedInstanceState);
finish();
return;
@@ -43,7 +43,8 @@
Intent intent = getIntent();
Intent target = intent.getParcelableExtra(Intent.EXTRA_INTENT, Intent.class);
ArrayList<ResolveInfo> rList =
- intent.getParcelableArrayListExtra(EXTRA_RESOLVE_INFOS, ResolveInfo.class);
+ intent.getParcelableArrayListExtra(
+ NfcAdapter.EXTRA_RESOLVE_INFOS, ResolveInfo.class);
CharSequence title = intent.getExtras().getCharSequence(
Intent.EXTRA_TITLE,
getResources().getText(com.android.internal.R.string.chooseActivity));
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index 98f409a..6fec527a 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -716,6 +716,13 @@
transaction->setExtendedRangeBrightness(ctrl, currentBufferRatio, desiredRatio);
}
+static void nativeSetDesiredHdrHeadroom(JNIEnv* env, jclass clazz, jlong transactionObj,
+ jlong nativeObject, float desiredRatio) {
+ auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj);
+ SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl*>(nativeObject);
+ transaction->setDesiredHdrHeadroom(ctrl, desiredRatio);
+}
+
static void nativeSetCachingHint(JNIEnv* env, jclass clazz, jlong transactionObj,
jlong nativeObject, jint cachingHint) {
auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj);
@@ -2340,7 +2347,9 @@
(void*)nativeSetDataSpace },
{"nativeSetExtendedRangeBrightness", "(JJFF)V",
(void*)nativeSetExtendedRangeBrightness },
- {"nativeSetCachingHint", "(JJI)V",
+ {"nativeSetDesiredHdrHeadroom", "(JJF)V",
+ (void*)nativeSetDesiredHdrHeadroom },
+ {"nativeSetCachingHint", "(JJI)V",
(void*)nativeSetCachingHint },
{"nativeAddWindowInfosReportedListener", "(JLjava/lang/Runnable;)V",
(void*)nativeAddWindowInfosReportedListener },
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 71f06f1..33af172 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -7696,7 +7696,7 @@
<!-- @SystemApi Allows the holder to launch an Intent Resolver flow with custom presentation
and/or targets.
- @FlaggedApi("android.service.chooser.support_nfc_resolver")
+ @FlaggedApi("android.nfc.enable_nfc_mainline")
@hide -->
<permission android:name="android.permission.SHOW_CUSTOMIZED_RESOLVER"
android:protectionLevel="signature|privileged" />
@@ -8196,8 +8196,8 @@
android:multiprocess="true"
android:permission="android.permission.SHOW_CUSTOMIZED_RESOLVER"
android:exported="true">
- <intent-filter>
- <action android:name="android.service.chooser.action.SHOW_CUSTOMIZED_RESOLVER" />
+ <intent-filter android:priority="100" >
+ <action android:name="android.nfc.action.SHOW_NFC_RESOLVER" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
diff --git a/core/tests/coretests/src/android/widget/RemoteViewsTest.java b/core/tests/coretests/src/android/widget/RemoteViewsTest.java
index 3d5494d..15c9047 100644
--- a/core/tests/coretests/src/android/widget/RemoteViewsTest.java
+++ b/core/tests/coretests/src/android/widget/RemoteViewsTest.java
@@ -16,8 +16,6 @@
package android.widget;
-import static android.appwidget.flags.Flags.drawDataParcel;
-
import static com.android.internal.R.id.pending_intent_tag;
import static org.junit.Assert.assertArrayEquals;
@@ -65,7 +63,6 @@
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
@@ -417,25 +414,6 @@
assertNotNull(view.findViewById(R.id.light_background_text));
}
- @Test
- public void remoteCanvasCanAccessDrawInstructions() {
- if (!drawDataParcel()) {
- return;
- }
- final byte[] bytes = new byte[] {'h', 'e', 'l', 'l', 'o'};
- final RemoteViews.DrawInstructions drawInstructions =
- new RemoteViews.DrawInstructions.Builder(Collections.singletonList(bytes)).build();
- final RemoteViews rv = new RemoteViews(drawInstructions);
- final PendingIntent pi = PendingIntent.getActivity(mContext, 0,
- new Intent(Intent.ACTION_VIEW), PendingIntent.FLAG_IMMUTABLE);
- final Intent i = new Intent().putExtra("TEST", "Success");
- final int viewId = 1;
- rv.setPendingIntentTemplate(viewId, pi);
- rv.setOnClickFillInIntent(viewId, i);
- final View view = rv.apply(mContext, mContainer);
- assertEquals(drawInstructions, view.getTag());
- }
-
private RemoteViews createViewChained(int depth, String... texts) {
RemoteViews result = new RemoteViews(mPackage, R.layout.remote_view_host);
diff --git a/core/tests/devicestatetests/src/android/hardware/devicestate/DeviceStateTest.java b/core/tests/devicestatetests/src/android/hardware/devicestate/DeviceStateTest.java
index 396d403..fb5e512 100644
--- a/core/tests/devicestatetests/src/android/hardware/devicestate/DeviceStateTest.java
+++ b/core/tests/devicestatetests/src/android/hardware/devicestate/DeviceStateTest.java
@@ -16,8 +16,8 @@
package android.hardware.devicestate;
-import static android.hardware.devicestate.DeviceStateManager.MAXIMUM_DEVICE_STATE;
-import static android.hardware.devicestate.DeviceStateManager.MINIMUM_DEVICE_STATE;
+import static android.hardware.devicestate.DeviceStateManager.MAXIMUM_DEVICE_STATE_IDENTIFIER;
+import static android.hardware.devicestate.DeviceStateManager.MINIMUM_DEVICE_STATE_IDENTIFIER;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNull;
@@ -39,18 +39,18 @@
public final class DeviceStateTest {
@Test
public void testConstruct() {
- final DeviceState state = new DeviceState(MINIMUM_DEVICE_STATE /* identifier */,
+ final DeviceState state = new DeviceState(MINIMUM_DEVICE_STATE_IDENTIFIER /* identifier */,
"TEST_CLOSED" /* name */, DeviceState.FLAG_CANCEL_OVERRIDE_REQUESTS /* flags */);
- assertEquals(state.getIdentifier(), MINIMUM_DEVICE_STATE);
+ assertEquals(state.getIdentifier(), MINIMUM_DEVICE_STATE_IDENTIFIER);
assertEquals(state.getName(), "TEST_CLOSED");
assertEquals(state.getFlags(), DeviceState.FLAG_CANCEL_OVERRIDE_REQUESTS);
}
@Test
public void testConstruct_nullName() {
- final DeviceState state = new DeviceState(MAXIMUM_DEVICE_STATE /* identifier */,
+ final DeviceState state = new DeviceState(MAXIMUM_DEVICE_STATE_IDENTIFIER /* identifier */,
null /* name */, 0/* flags */);
- assertEquals(state.getIdentifier(), MAXIMUM_DEVICE_STATE);
+ assertEquals(state.getIdentifier(), MAXIMUM_DEVICE_STATE_IDENTIFIER);
assertNull(state.getName());
assertEquals(state.getFlags(), 0);
}
@@ -58,7 +58,8 @@
@Test
public void testConstruct_tooLargeIdentifier() {
assertThrows(IllegalArgumentException.class, () -> {
- final DeviceState state = new DeviceState(MAXIMUM_DEVICE_STATE + 1 /* identifier */,
+ final DeviceState state = new DeviceState(
+ MAXIMUM_DEVICE_STATE_IDENTIFIER + 1 /* identifier */,
null /* name */, 0 /* flags */);
});
}
@@ -66,7 +67,8 @@
@Test
public void testConstruct_tooSmallIdentifier() {
assertThrows(IllegalArgumentException.class, () -> {
- final DeviceState state = new DeviceState(MINIMUM_DEVICE_STATE - 1 /* identifier */,
+ final DeviceState state = new DeviceState(
+ MINIMUM_DEVICE_STATE_IDENTIFIER - 1 /* identifier */,
null /* name */, 0 /* flags */);
});
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/MultiInstanceHelper.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/common/MultiInstanceHelper.kt
new file mode 100644
index 0000000..4c34971
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/MultiInstanceHelper.kt
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.wm.shell.common
+
+import android.app.PendingIntent
+import android.content.ComponentName
+import android.content.Context
+import android.content.pm.LauncherApps
+import android.content.pm.PackageManager
+import android.os.UserHandle
+import android.view.WindowManager
+import android.view.WindowManager.PROPERTY_SUPPORTS_MULTI_INSTANCE_SYSTEM_UI
+import com.android.internal.annotations.VisibleForTesting
+import com.android.wm.shell.R
+import com.android.wm.shell.protolog.ShellProtoLogGroup
+import com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL
+import com.android.wm.shell.util.KtProtoLog
+import java.util.Arrays
+
+/**
+ * Helper for multi-instance related checks.
+ */
+class MultiInstanceHelper @JvmOverloads constructor(
+ private val context: Context,
+ private val packageManager: PackageManager,
+ private val staticAppsSupportingMultiInstance: Array<String> = context.resources
+ .getStringArray(R.array.config_appsSupportMultiInstancesSplit)) {
+
+ /**
+ * Returns whether a specific component desires to be launched in multiple instances.
+ */
+ @VisibleForTesting
+ fun supportsMultiInstanceSplit(componentName: ComponentName?): Boolean {
+ if (componentName == null || componentName.packageName == null) {
+ // TODO(b/262864589): Handle empty component case
+ return false
+ }
+
+ // Check the pre-defined allow list
+ val packageName = componentName.packageName
+ for (pkg in staticAppsSupportingMultiInstance) {
+ if (pkg == packageName) {
+ KtProtoLog.v(WM_SHELL, "application=%s in allowlist supports multi-instance",
+ packageName)
+ return true
+ }
+ }
+
+ // Check the activity property first
+ try {
+ val activityProp = packageManager.getProperty(
+ PROPERTY_SUPPORTS_MULTI_INSTANCE_SYSTEM_UI, componentName)
+ // If the above call doesn't throw a NameNotFoundException, then the activity property
+ // should override the application property value
+ if (activityProp.isBoolean) {
+ KtProtoLog.v(WM_SHELL, "activity=%s supports multi-instance", componentName)
+ return activityProp.boolean
+ } else {
+ KtProtoLog.w(WM_SHELL, "Warning: property=%s for activity=%s has non-bool type=%d",
+ PROPERTY_SUPPORTS_MULTI_INSTANCE_SYSTEM_UI, packageName, activityProp.type)
+ }
+ } catch (nnfe: PackageManager.NameNotFoundException) {
+ // Not specified in the activity, fall through
+ }
+
+ // Check the application property otherwise
+ try {
+ val appProp = packageManager.getProperty(
+ PROPERTY_SUPPORTS_MULTI_INSTANCE_SYSTEM_UI, packageName)
+ if (appProp.isBoolean) {
+ KtProtoLog.v(WM_SHELL, "application=%s supports multi-instance", packageName)
+ return appProp.boolean
+ } else {
+ KtProtoLog.w(WM_SHELL,
+ "Warning: property=%s for application=%s has non-bool type=%d",
+ PROPERTY_SUPPORTS_MULTI_INSTANCE_SYSTEM_UI, packageName, appProp.type)
+ }
+ } catch (nnfe: PackageManager.NameNotFoundException) {
+ // Not specified in either application or activity
+ }
+ return false
+ }
+
+ companion object {
+ /** Returns the component from a PendingIntent */
+ @JvmStatic
+ fun getComponent(pendingIntent: PendingIntent?): ComponentName? {
+ return pendingIntent?.intent?.component
+ }
+
+ /** Returns the component from a shortcut */
+ @JvmStatic
+ fun getShortcutComponent(packageName: String, shortcutId: String,
+ user: UserHandle, launcherApps: LauncherApps): ComponentName? {
+ val query = LauncherApps.ShortcutQuery()
+ query.setPackage(packageName)
+ query.setShortcutIds(Arrays.asList(shortcutId))
+ query.setQueryFlags(LauncherApps.ShortcutQuery.FLAG_MATCH_ALL_KINDS_WITH_ALL_PINNED)
+ val shortcuts = launcherApps.getShortcuts(query, user)
+ val info = if (shortcuts != null && shortcuts.size > 0) shortcuts[0] else null
+ return info?.activity
+ }
+
+ /** Returns true if package names and user ids match. */
+ @JvmStatic
+ fun samePackage(packageName1: String?, packageName2: String?,
+ userId1: Int, userId2: Int): Boolean {
+ return (packageName1 != null && packageName1 == packageName2) && (userId1 == userId2)
+ }
+ }
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/IPip.aidl b/libs/WindowManager/Shell/src/com/android/wm/shell/common/pip/IPip.aidl
similarity index 96%
rename from libs/WindowManager/Shell/src/com/android/wm/shell/pip/IPip.aidl
rename to libs/WindowManager/Shell/src/com/android/wm/shell/common/pip/IPip.aidl
index 8b3de62..b5f25433f 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/IPip.aidl
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/pip/IPip.aidl
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.wm.shell.pip;
+package com.android.wm.shell.common.pip;
import android.app.PictureInPictureParams;
import android.view.SurfaceControl;
@@ -22,7 +22,7 @@
import android.content.pm.ActivityInfo;
import android.graphics.Rect;
-import com.android.wm.shell.pip.IPipAnimationListener;
+import com.android.wm.shell.common.pip.IPipAnimationListener;
/**
* Interface that is exposed to remote callers to manipulate the Pip feature.
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/IPipAnimationListener.aidl b/libs/WindowManager/Shell/src/com/android/wm/shell/common/pip/IPipAnimationListener.aidl
similarity index 96%
rename from libs/WindowManager/Shell/src/com/android/wm/shell/pip/IPipAnimationListener.aidl
rename to libs/WindowManager/Shell/src/com/android/wm/shell/common/pip/IPipAnimationListener.aidl
index 062e3ba..b8d1966 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/IPipAnimationListener.aidl
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/pip/IPipAnimationListener.aidl
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.wm.shell.pip;
+package com.android.wm.shell.common.pip;
/**
* Listener interface that Launcher attaches to SystemUI to get Pip animation callbacks.
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitScreenUtils.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitScreenUtils.java
index 662f325..f9259e7 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitScreenUtils.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitScreenUtils.java
@@ -99,12 +99,6 @@
return taskInfo != null ? taskInfo.userId : -1;
}
- /** Returns true if package names and user ids match. */
- public static boolean samePackage(String packageName1, String packageName2,
- int userId1, int userId2) {
- return (packageName1 != null && packageName1.equals(packageName2)) && (userId1 == userId2);
- }
-
/** Generates a common log message for split screen failures */
public static String splitFailureMessage(String caller, String reason) {
return "(" + caller + ") Splitscreen aborted: " + reason;
@@ -143,28 +137,4 @@
return isLandscape;
}
}
-
- /** Returns the component from a PendingIntent */
- @Nullable
- public static ComponentName getComponent(@Nullable PendingIntent pendingIntent) {
- if (pendingIntent == null || pendingIntent.getIntent() == null) {
- return null;
- }
- return pendingIntent.getIntent().getComponent();
- }
-
- /** Returns the component from a shortcut */
- @Nullable
- public static ComponentName getShortcutComponent(@NonNull String packageName, String shortcutId,
- @NonNull UserHandle user, @NonNull LauncherApps launcherApps) {
- LauncherApps.ShortcutQuery query = new LauncherApps.ShortcutQuery();
- query.setPackage(packageName);
- query.setShortcutIds(Arrays.asList(shortcutId));
- query.setQueryFlags(FLAG_MATCH_ALL_KINDS_WITH_ALL_PINNED);
- List<ShortcutInfo> shortcuts = launcherApps.getShortcuts(query, user);
- ShortcutInfo info = shortcuts != null && shortcuts.size() > 0
- ? shortcuts.get(0)
- : null;
- return info != null ? info.getActivity() : null;
- }
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/TvWMShellModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/TvWMShellModule.java
index d4ed017..216da07 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/TvWMShellModule.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/TvWMShellModule.java
@@ -26,6 +26,7 @@
import com.android.wm.shell.common.DisplayImeController;
import com.android.wm.shell.common.DisplayInsetsController;
import com.android.wm.shell.common.LaunchAdjacentController;
+import com.android.wm.shell.common.MultiInstanceHelper;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.SyncTransactionQueue;
import com.android.wm.shell.common.SystemWindows;
@@ -88,13 +89,14 @@
IconProvider iconProvider,
Optional<RecentTasksController> recentTasks,
LaunchAdjacentController launchAdjacentController,
+ MultiInstanceHelper multiInstanceHelper,
@ShellMainThread ShellExecutor mainExecutor,
Handler mainHandler,
SystemWindows systemWindows) {
return new TvSplitScreenController(context, shellInit, shellCommandHandler, shellController,
shellTaskOrganizer, syncQueue, rootTDAOrganizer, displayController,
displayImeController, displayInsetsController, transitions, transactionPool,
- iconProvider, recentTasks, launchAdjacentController, mainExecutor, mainHandler,
- systemWindows);
+ iconProvider, recentTasks, launchAdjacentController, multiInstanceHelper,
+ mainExecutor, mainHandler, systemWindows);
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java
index 63a912e..8b2ec0a 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java
@@ -50,6 +50,7 @@
import com.android.wm.shell.common.DockStateReader;
import com.android.wm.shell.common.FloatingContentCoordinator;
import com.android.wm.shell.common.LaunchAdjacentController;
+import com.android.wm.shell.common.MultiInstanceHelper;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.SyncTransactionQueue;
import com.android.wm.shell.common.SystemWindows;
@@ -322,6 +323,12 @@
return Optional.of(perfHintController.getHinter());
}
+ @WMSingleton
+ @Provides
+ static MultiInstanceHelper provideMultiInstanceHelper(Context context) {
+ return new MultiInstanceHelper(context, context.getPackageManager());
+ }
+
//
// Back animation
//
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
index bd9d89c..4fe79c1 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
@@ -47,6 +47,7 @@
import com.android.wm.shell.common.DisplayLayout;
import com.android.wm.shell.common.FloatingContentCoordinator;
import com.android.wm.shell.common.LaunchAdjacentController;
+import com.android.wm.shell.common.MultiInstanceHelper;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.SyncTransactionQueue;
import com.android.wm.shell.common.TaskStackListenerImpl;
@@ -347,12 +348,14 @@
LaunchAdjacentController launchAdjacentController,
Optional<WindowDecorViewModel> windowDecorViewModel,
Optional<DesktopTasksController> desktopTasksController,
+ MultiInstanceHelper multiInstanceHelper,
@ShellMainThread ShellExecutor mainExecutor) {
return new SplitScreenController(context, shellInit, shellCommandHandler, shellController,
shellTaskOrganizer, syncQueue, rootTaskDisplayAreaOrganizer, displayController,
displayImeController, displayInsetsController, dragAndDropController, transitions,
transactionPool, iconProvider, recentTasks, launchAdjacentController,
- windowDecorViewModel, desktopTasksController, mainExecutor);
+ windowDecorViewModel, desktopTasksController, null /* stageCoordinator */,
+ multiInstanceHelper, mainExecutor);
}
//
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt
index 837cb99..11304ec 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt
@@ -62,7 +62,7 @@
import com.android.wm.shell.recents.RecentsTransitionHandler
import com.android.wm.shell.recents.RecentsTransitionStateListener
import com.android.wm.shell.splitscreen.SplitScreenController
-import com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_ENTER_DESKTOP
+import com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_DESKTOP_MODE
import com.android.wm.shell.sysui.ShellCommandHandler
import com.android.wm.shell.sysui.ShellController
import com.android.wm.shell.sysui.ShellInit
@@ -355,7 +355,7 @@
splitScreenController.prepareExitSplitScreen(
wct,
splitScreenController.getStageOfTask(taskInfo.taskId),
- EXIT_REASON_ENTER_DESKTOP
+ EXIT_REASON_DESKTOP_MODE
)
getOtherSplitTask(taskInfo.taskId)?.let { otherTaskInfo ->
wct.removeTask(otherTaskInfo.token)
@@ -919,19 +919,13 @@
}
if (inputCoordinate.x <= transitionAreaWidth) {
releaseVisualIndicator()
- val wct = WindowContainerTransaction()
- addMoveToSplitChanges(wct, taskInfo)
- splitScreenController.requestEnterSplitSelect(taskInfo, wct,
- SPLIT_POSITION_TOP_OR_LEFT, taskBounds)
+ snapToHalfScreen(taskInfo, SnapPosition.LEFT)
return
}
if (inputCoordinate.x >= (displayController.getDisplayLayout(taskInfo.displayId)?.width()
?.minus(transitionAreaWidth) ?: return)) {
releaseVisualIndicator()
- val wct = WindowContainerTransaction()
- addMoveToSplitChanges(wct, taskInfo)
- splitScreenController.requestEnterSplitSelect(taskInfo, wct,
- SPLIT_POSITION_BOTTOM_OR_RIGHT, taskBounds)
+ snapToHalfScreen(taskInfo, SnapPosition.RIGHT)
return
}
// A freeform drag-move ended, remove the indicator immediately.
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java
index 05d4f53..4b12134 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java
@@ -75,6 +75,8 @@
import com.android.wm.shell.common.TabletopModeController;
import com.android.wm.shell.common.TaskStackListenerCallback;
import com.android.wm.shell.common.TaskStackListenerImpl;
+import com.android.wm.shell.common.pip.IPip;
+import com.android.wm.shell.common.pip.IPipAnimationListener;
import com.android.wm.shell.common.pip.PipAppOpsListener;
import com.android.wm.shell.common.pip.PipBoundsAlgorithm;
import com.android.wm.shell.common.pip.PipBoundsState;
@@ -85,8 +87,6 @@
import com.android.wm.shell.common.pip.PipUtils;
import com.android.wm.shell.onehanded.OneHandedController;
import com.android.wm.shell.onehanded.OneHandedTransitionCallback;
-import com.android.wm.shell.pip.IPip;
-import com.android.wm.shell.pip.IPipAnimationListener;
import com.android.wm.shell.pip.PinnedStackListenerForwarder;
import com.android.wm.shell.pip.Pip;
import com.android.wm.shell.pip.PipAnimationController;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/protolog/ShellProtoLogGroup.java b/libs/WindowManager/Shell/src/com/android/wm/shell/protolog/ShellProtoLogGroup.java
index 05e4af3..ad29d15 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/protolog/ShellProtoLogGroup.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/protolog/ShellProtoLogGroup.java
@@ -26,6 +26,8 @@
public enum ShellProtoLogGroup implements IProtoLogGroup {
// NOTE: Since we enable these from the same WM ShellCommand, these names should not conflict
// with those in the framework ProtoLogGroup
+ WM_SHELL(Consts.ENABLE_DEBUG, Consts.ENABLE_LOG_TO_PROTO_DEBUG, true,
+ Consts.TAG_WM_SHELL),
WM_SHELL_INIT(Consts.ENABLE_DEBUG, Consts.ENABLE_LOG_TO_PROTO_DEBUG, true,
Consts.TAG_WM_SHELL),
WM_SHELL_TASK_ORG(Consts.ENABLE_DEBUG, Consts.ENABLE_LOG_TO_PROTO_DEBUG, false,
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
index 1b124c2..53dd981 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
@@ -23,25 +23,22 @@
import static android.content.Intent.FLAG_ACTIVITY_NO_USER_ACTION;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.RemoteAnimationTarget.MODE_OPENING;
-import static android.view.WindowManager.PROPERTY_SUPPORTS_MULTI_INSTANCE_SYSTEM_UI;
import static com.android.wm.shell.common.ExecutorUtils.executeRemoteCallWithTaskPermission;
+import static com.android.wm.shell.common.MultiInstanceHelper.getComponent;
+import static com.android.wm.shell.common.MultiInstanceHelper.getShortcutComponent;
+import static com.android.wm.shell.common.MultiInstanceHelper.samePackage;
import static com.android.wm.shell.common.split.SplitScreenConstants.KEY_EXTRA_WIDGET_INTENT;
import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT;
import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT;
import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_UNDEFINED;
-import static com.android.wm.shell.common.split.SplitScreenUtils.getComponent;
-import static com.android.wm.shell.common.split.SplitScreenUtils.getShortcutComponent;
import static com.android.wm.shell.common.split.SplitScreenUtils.isValidToSplit;
import static com.android.wm.shell.common.split.SplitScreenUtils.reverseSplitPosition;
-import static com.android.wm.shell.common.split.SplitScreenUtils.samePackage;
import static com.android.wm.shell.common.split.SplitScreenUtils.splitFailureMessage;
import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_TYPE_UNDEFINED;
import static com.android.wm.shell.sysui.ShellSharedConstants.KEY_EXTRA_SHELL_SPLIT_SCREEN;
import static com.android.wm.shell.transition.Transitions.ENABLE_SHELL_TRANSITIONS;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.ActivityOptions;
import android.app.ActivityTaskManager;
@@ -51,7 +48,6 @@
import android.content.Context;
import android.content.Intent;
import android.content.pm.LauncherApps;
-import android.content.pm.PackageManager;
import android.content.pm.ShortcutInfo;
import android.graphics.Rect;
import android.os.Bundle;
@@ -73,6 +69,8 @@
import androidx.annotation.BinderThread;
import androidx.annotation.IntDef;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.InstanceId;
@@ -86,6 +84,7 @@
import com.android.wm.shell.common.DisplayInsetsController;
import com.android.wm.shell.common.ExternalInterfaceBinder;
import com.android.wm.shell.common.LaunchAdjacentController;
+import com.android.wm.shell.common.MultiInstanceHelper;
import com.android.wm.shell.common.RemoteCallable;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.SingleInstanceRemoteListener;
@@ -138,7 +137,7 @@
public static final int EXIT_REASON_CHILD_TASK_ENTER_PIP = 9;
public static final int EXIT_REASON_RECREATE_SPLIT = 10;
public static final int EXIT_REASON_FULLSCREEN_SHORTCUT = 11;
- public static final int EXIT_REASON_ENTER_DESKTOP = 12;
+ public static final int EXIT_REASON_DESKTOP_MODE = 12;
@IntDef(value = {
EXIT_REASON_UNKNOWN,
EXIT_REASON_APP_DOES_NOT_SUPPORT_MULTIWINDOW,
@@ -152,7 +151,7 @@
EXIT_REASON_CHILD_TASK_ENTER_PIP,
EXIT_REASON_RECREATE_SPLIT,
EXIT_REASON_FULLSCREEN_SHORTCUT,
- EXIT_REASON_ENTER_DESKTOP
+ EXIT_REASON_DESKTOP_MODE
})
@Retention(RetentionPolicy.SOURCE)
@interface ExitReason{}
@@ -176,7 +175,6 @@
private final ShellTaskOrganizer mTaskOrganizer;
private final SyncTransactionQueue mSyncQueue;
private final Context mContext;
- private final PackageManager mPackageManager;
private final LauncherApps mLauncherApps;
private final RootTaskDisplayAreaOrganizer mRootTDAOrganizer;
private final ShellExecutor mMainExecutor;
@@ -192,9 +190,8 @@
private final LaunchAdjacentController mLaunchAdjacentController;
private final Optional<WindowDecorViewModel> mWindowDecorViewModel;
private final Optional<DesktopTasksController> mDesktopTasksController;
+ private final MultiInstanceHelper mMultiInstanceHelpher;
private final SplitScreenShellCommandHandler mSplitScreenShellCommandHandler;
- // A static allow list of apps which support multi-instance
- private final String[] mAppsSupportingMultiInstance;
@VisibleForTesting
StageCoordinator mStageCoordinator;
@@ -204,6 +201,10 @@
private SurfaceControl mGoingToRecentsTasksLayer;
private SurfaceControl mStartingSplitTasksLayer;
+ /**
+ * @param stageCoordinator if null, a stage coordinator will be created when this controller is
+ * initialized. Can be non-null for testing purposes.
+ */
public SplitScreenController(Context context,
ShellInit shellInit,
ShellCommandHandler shellCommandHandler,
@@ -222,13 +223,14 @@
LaunchAdjacentController launchAdjacentController,
Optional<WindowDecorViewModel> windowDecorViewModel,
Optional<DesktopTasksController> desktopTasksController,
+ @Nullable StageCoordinator stageCoordinator,
+ MultiInstanceHelper multiInstanceHelper,
ShellExecutor mainExecutor) {
mShellCommandHandler = shellCommandHandler;
mShellController = shellController;
mTaskOrganizer = shellTaskOrganizer;
mSyncQueue = syncQueue;
mContext = context;
- mPackageManager = context.getPackageManager();
mLauncherApps = context.getSystemService(LauncherApps.class);
mRootTDAOrganizer = rootTDAOrganizer;
mMainExecutor = mainExecutor;
@@ -243,65 +245,14 @@
mLaunchAdjacentController = launchAdjacentController;
mWindowDecorViewModel = windowDecorViewModel;
mDesktopTasksController = desktopTasksController;
+ mStageCoordinator = stageCoordinator;
+ mMultiInstanceHelpher = multiInstanceHelper;
mSplitScreenShellCommandHandler = new SplitScreenShellCommandHandler(this);
// TODO(b/238217847): Temporarily add this check here until we can remove the dynamic
// override for this controller from the base module
if (ActivityTaskManager.supportsSplitScreenMultiWindow(context)) {
shellInit.addInitCallback(this::onInit, this);
}
-
- // TODO(255224696): Remove the config once having a way for client apps to opt-in
- // multi-instances split.
- mAppsSupportingMultiInstance = mContext.getResources()
- .getStringArray(R.array.config_appsSupportMultiInstancesSplit);
- }
-
- @VisibleForTesting
- SplitScreenController(Context context,
- ShellInit shellInit,
- ShellCommandHandler shellCommandHandler,
- ShellController shellController,
- ShellTaskOrganizer shellTaskOrganizer,
- SyncTransactionQueue syncQueue,
- RootTaskDisplayAreaOrganizer rootTDAOrganizer,
- DisplayController displayController,
- DisplayImeController displayImeController,
- DisplayInsetsController displayInsetsController,
- DragAndDropController dragAndDropController,
- Transitions transitions,
- TransactionPool transactionPool,
- IconProvider iconProvider,
- RecentTasksController recentTasks,
- LaunchAdjacentController launchAdjacentController,
- WindowDecorViewModel windowDecorViewModel,
- DesktopTasksController desktopTasksController,
- ShellExecutor mainExecutor,
- StageCoordinator stageCoordinator,
- String[] appsSupportingMultiInstance) {
- mShellCommandHandler = shellCommandHandler;
- mShellController = shellController;
- mTaskOrganizer = shellTaskOrganizer;
- mSyncQueue = syncQueue;
- mContext = context;
- mPackageManager = context.getPackageManager();
- mLauncherApps = context.getSystemService(LauncherApps.class);
- mRootTDAOrganizer = rootTDAOrganizer;
- mMainExecutor = mainExecutor;
- mDisplayController = displayController;
- mDisplayImeController = displayImeController;
- mDisplayInsetsController = displayInsetsController;
- mDragAndDropController = dragAndDropController;
- mTransitions = transitions;
- mTransactionPool = transactionPool;
- mIconProvider = iconProvider;
- mRecentTasksOptional = Optional.of(recentTasks);
- mLaunchAdjacentController = launchAdjacentController;
- mWindowDecorViewModel = Optional.of(windowDecorViewModel);
- mDesktopTasksController = Optional.of(desktopTasksController);
- mStageCoordinator = stageCoordinator;
- mSplitScreenShellCommandHandler = new SplitScreenShellCommandHandler(this);
- shellInit.addInitCallback(this::onInit, this);
- mAppsSupportingMultiInstance = appsSupportingMultiInstance;
}
public SplitScreen asSplitScreen() {
@@ -529,8 +480,8 @@
}
/** Move the specified task to fullscreen, regardless of focus state. */
- public void moveTaskToFullscreen(int taskId) {
- mStageCoordinator.moveTaskToFullscreen(taskId);
+ public void moveTaskToFullscreen(int taskId, int exitReason) {
+ mStageCoordinator.moveTaskToFullscreen(taskId, exitReason);
}
public boolean isLaunchToSplit(TaskInfo taskInfo) {
@@ -613,8 +564,8 @@
if (samePackage(packageName, getPackageName(reverseSplitPosition(position)),
user.getIdentifier(), getUserId(reverseSplitPosition(position)))) {
- if (supportsMultiInstanceSplit(getShortcutComponent(packageName, shortcutId, user,
- mLauncherApps))) {
+ if (mMultiInstanceHelpher.supportsMultiInstanceSplit(
+ getShortcutComponent(packageName, shortcutId, user, mLauncherApps))) {
activityOptions.setApplyMultipleTaskFlagForShortcut(true);
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_SPLIT_SCREEN, "Adding MULTIPLE_TASK");
} else if (isSplitScreenVisible()) {
@@ -647,7 +598,7 @@
final int userId1 = shortcutInfo.getUserId();
final int userId2 = SplitScreenUtils.getUserId(taskId, mTaskOrganizer);
if (samePackage(packageName1, packageName2, userId1, userId2)) {
- if (supportsMultiInstanceSplit(shortcutInfo.getActivity())) {
+ if (mMultiInstanceHelpher.supportsMultiInstanceSplit(shortcutInfo.getActivity())) {
activityOptions.setApplyMultipleTaskFlagForShortcut(true);
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_SPLIT_SCREEN, "Adding MULTIPLE_TASK");
} else {
@@ -679,7 +630,7 @@
final int userId1 = shortcutInfo.getUserId();
final int userId2 = SplitScreenUtils.getUserId(taskId, mTaskOrganizer);
if (samePackage(packageName1, packageName2, userId1, userId2)) {
- if (supportsMultiInstanceSplit(shortcutInfo.getActivity())) {
+ if (mMultiInstanceHelpher.supportsMultiInstanceSplit(shortcutInfo.getActivity())) {
activityOptions.setApplyMultipleTaskFlagForShortcut(true);
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_SPLIT_SCREEN, "Adding MULTIPLE_TASK");
} else {
@@ -718,7 +669,7 @@
final String packageName2 = SplitScreenUtils.getPackageName(taskId, mTaskOrganizer);
final int userId2 = SplitScreenUtils.getUserId(taskId, mTaskOrganizer);
if (samePackage(packageName1, packageName2, userId1, userId2)) {
- if (supportsMultiInstanceSplit(getComponent(pendingIntent))) {
+ if (mMultiInstanceHelpher.supportsMultiInstanceSplit(getComponent(pendingIntent))) {
fillInIntent = new Intent();
fillInIntent.addFlags(FLAG_ACTIVITY_MULTIPLE_TASK);
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_SPLIT_SCREEN, "Adding MULTIPLE_TASK");
@@ -748,7 +699,7 @@
final int userId2 = SplitScreenUtils.getUserId(taskId, mTaskOrganizer);
boolean setSecondIntentMultipleTask = false;
if (samePackage(packageName1, packageName2, userId1, userId2)) {
- if (supportsMultiInstanceSplit(getComponent(pendingIntent))) {
+ if (mMultiInstanceHelpher.supportsMultiInstanceSplit(getComponent(pendingIntent))) {
setSecondIntentMultipleTask = true;
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_SPLIT_SCREEN, "Adding MULTIPLE_TASK");
} else {
@@ -783,7 +734,7 @@
final String packageName1 = SplitScreenUtils.getPackageName(pendingIntent1);
final String packageName2 = SplitScreenUtils.getPackageName(pendingIntent2);
if (samePackage(packageName1, packageName2, userId1, userId2)) {
- if (supportsMultiInstanceSplit(getComponent(pendingIntent1))) {
+ if (mMultiInstanceHelpher.supportsMultiInstanceSplit(getComponent(pendingIntent1))) {
fillInIntent1 = new Intent();
fillInIntent1.addFlags(FLAG_ACTIVITY_MULTIPLE_TASK);
fillInIntent2 = new Intent();
@@ -820,7 +771,7 @@
? ActivityOptions.fromBundle(options2) : ActivityOptions.makeBasic();
boolean setSecondIntentMultipleTask = false;
if (samePackage(packageName1, packageName2, userId1, userId2)) {
- if (supportsMultiInstanceSplit(getComponent(pendingIntent1))) {
+ if (mMultiInstanceHelpher.supportsMultiInstanceSplit(getComponent(pendingIntent1))) {
fillInIntent1 = new Intent();
fillInIntent1.addFlags(FLAG_ACTIVITY_MULTIPLE_TASK);
setSecondIntentMultipleTask = true;
@@ -882,7 +833,7 @@
return;
}
if (samePackage(packageName1, packageName2, userId1, userId2)) {
- if (supportsMultiInstanceSplit(getComponent(intent))) {
+ if (mMultiInstanceHelpher.supportsMultiInstanceSplit(getComponent(intent))) {
// Flag with MULTIPLE_TASK if this is launching the same activity into both sides of
// the split and there is no reusable background task.
fillInIntent.addFlags(FLAG_ACTIVITY_MULTIPLE_TASK);
@@ -942,66 +893,6 @@
}
/**
- * Returns whether a specific component desires to be launched in multiple instances for
- * split screen.
- */
- @VisibleForTesting
- boolean supportsMultiInstanceSplit(@Nullable ComponentName componentName) {
- if (componentName == null || componentName.getPackageName() == null) {
- // TODO(b/262864589): Handle empty component case
- return false;
- }
-
- // Check the pre-defined allow list
- final String packageName = componentName.getPackageName();
- for (int i = 0; i < mAppsSupportingMultiInstance.length; i++) {
- if (mAppsSupportingMultiInstance[i].equals(packageName)) {
- ProtoLog.v(ShellProtoLogGroup.WM_SHELL_SPLIT_SCREEN,
- "application=%s in allowlist supports multi-instance", packageName);
- return true;
- }
- }
-
- // Check the activity property first
- try {
- final PackageManager.Property activityProp = mPackageManager.getProperty(
- PROPERTY_SUPPORTS_MULTI_INSTANCE_SYSTEM_UI, componentName);
- // If the above call doesn't throw a NameNotFoundException, then the activity property
- // should override the application property value
- if (activityProp.isBoolean()) {
- ProtoLog.v(ShellProtoLogGroup.WM_SHELL_SPLIT_SCREEN,
- "activity=%s supports multi-instance", componentName);
- return activityProp.getBoolean();
- } else {
- ProtoLog.w(ShellProtoLogGroup.WM_SHELL_SPLIT_SCREEN,
- "Warning: property=%s for activity=%s has non-bool type=%d",
- PROPERTY_SUPPORTS_MULTI_INSTANCE_SYSTEM_UI, packageName,
- activityProp.getType());
- }
- } catch (PackageManager.NameNotFoundException nnfe) {
- // Not specified in the activity, fall through
- }
-
- // Check the application property otherwise
- try {
- final PackageManager.Property appProp = mPackageManager.getProperty(
- PROPERTY_SUPPORTS_MULTI_INSTANCE_SYSTEM_UI, packageName);
- if (appProp.isBoolean()) {
- ProtoLog.v(ShellProtoLogGroup.WM_SHELL_SPLIT_SCREEN,
- "application=%s supports multi-instance", packageName);
- return appProp.getBoolean();
- } else {
- ProtoLog.w(ShellProtoLogGroup.WM_SHELL_SPLIT_SCREEN,
- "Warning: property=%s for application=%s has non-bool type=%d",
- PROPERTY_SUPPORTS_MULTI_INSTANCE_SYSTEM_UI, packageName, appProp.getType());
- }
- } catch (PackageManager.NameNotFoundException nnfe) {
- // Not specified in either application or activity
- }
- return false;
- }
-
- /**
* Determines whether the widgetIntent needs to be modified if multiple tasks of its
* corresponding package/app are supported. There are 4 possible paths:
* <li> We select a widget for second app which is the same as the first app </li>
@@ -1144,8 +1035,8 @@
return "CHILD_TASK_ENTER_PIP";
case EXIT_REASON_RECREATE_SPLIT:
return "RECREATE_SPLIT";
- case EXIT_REASON_ENTER_DESKTOP:
- return "ENTER_DESKTOP";
+ case EXIT_REASON_DESKTOP_MODE:
+ return "DESKTOP_MODE";
default:
return "unknown reason, reason int = " + exitReason;
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitscreenEventLogger.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitscreenEventLogger.java
index f4ab226..a0bf843 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitscreenEventLogger.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitscreenEventLogger.java
@@ -25,7 +25,7 @@
import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED__EXIT_REASON__DEVICE_FOLDED;
import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED__EXIT_REASON__DRAG_DIVIDER;
import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED__EXIT_REASON__FULLSCREEN_SHORTCUT;
-import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED__EXIT_REASON__ENTER_DESKTOP;
+import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED__EXIT_REASON__DESKTOP_MODE;
import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED__EXIT_REASON__RECREATE_SPLIT;
import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED__EXIT_REASON__RETURN_HOME;
import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED__EXIT_REASON__ROOT_TASK_VANISHED;
@@ -43,7 +43,7 @@
import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_CHILD_TASK_ENTER_PIP;
import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_DEVICE_FOLDED;
import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_DRAG_DIVIDER;
-import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_ENTER_DESKTOP;
+import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_DESKTOP_MODE;
import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_FULLSCREEN_SHORTCUT;
import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_RECREATE_SPLIT;
import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_RETURN_HOME;
@@ -194,8 +194,8 @@
return SPLITSCREEN_UICHANGED__EXIT_REASON__RECREATE_SPLIT;
case EXIT_REASON_FULLSCREEN_SHORTCUT:
return SPLITSCREEN_UICHANGED__EXIT_REASON__FULLSCREEN_SHORTCUT;
- case EXIT_REASON_ENTER_DESKTOP:
- return SPLITSCREEN_UICHANGED__EXIT_REASON__ENTER_DESKTOP;
+ case EXIT_REASON_DESKTOP_MODE:
+ return SPLITSCREEN_UICHANGED__EXIT_REASON__DESKTOP_MODE;
case EXIT_REASON_UNKNOWN:
// Fall through
default:
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
index 70b2f21..fa14b4c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
@@ -2973,7 +2973,7 @@
}
/** Move the specified task to fullscreen, regardless of focus state. */
- public void moveTaskToFullscreen(int taskId) {
+ public void moveTaskToFullscreen(int taskId, int exitReason) {
boolean leftOrTop;
if (mMainStage.containsTask(taskId)) {
leftOrTop = (mSideStagePosition == SPLIT_POSITION_TOP_OR_LEFT);
@@ -2982,7 +2982,7 @@
} else {
return;
}
- mSplitLayout.flingDividerToDismiss(!leftOrTop, EXIT_REASON_FULLSCREEN_SHORTCUT);
+ mSplitLayout.flingDividerToDismiss(!leftOrTop, exitReason);
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/tv/TvSplitScreenController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/tv/TvSplitScreenController.java
index aec4d11..e330f3a 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/tv/TvSplitScreenController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/tv/TvSplitScreenController.java
@@ -28,6 +28,7 @@
import com.android.wm.shell.common.DisplayImeController;
import com.android.wm.shell.common.DisplayInsetsController;
import com.android.wm.shell.common.LaunchAdjacentController;
+import com.android.wm.shell.common.MultiInstanceHelper;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.SyncTransactionQueue;
import com.android.wm.shell.common.SystemWindows;
@@ -79,6 +80,7 @@
IconProvider iconProvider,
Optional<RecentTasksController> recentTasks,
LaunchAdjacentController launchAdjacentController,
+ MultiInstanceHelper multiInstanceHelper,
ShellExecutor mainExecutor,
Handler mainHandler,
SystemWindows systemWindows) {
@@ -86,7 +88,7 @@
syncQueue, rootTDAOrganizer, displayController, displayImeController,
displayInsetsController, null, transitions, transactionPool,
iconProvider, recentTasks, launchAdjacentController, Optional.empty(),
- Optional.empty(), mainExecutor);
+ Optional.empty(), null /* stageCoordinator */, multiInstanceHelper, mainExecutor);
mTaskOrganizer = shellTaskOrganizer;
mSyncQueue = syncQueue;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java
index 7db3d38..c713a2e 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java
@@ -339,7 +339,8 @@
final int id = v.getId();
if (id == R.id.close_window) {
if (isTaskInSplitScreen(mTaskId)) {
- mSplitScreenController.moveTaskToFullscreen(getOtherSplitTask(mTaskId).taskId);
+ mSplitScreenController.moveTaskToFullscreen(getOtherSplitTask(mTaskId).taskId,
+ SplitScreenController.EXIT_REASON_DESKTOP_MODE);
} else {
mTaskOperations.closeTask(mTaskToken);
}
@@ -365,7 +366,8 @@
} else if (id == R.id.fullscreen_button) {
decoration.closeHandleMenu();
if (isTaskInSplitScreen(mTaskId)) {
- mSplitScreenController.moveTaskToFullscreen(mTaskId);
+ mSplitScreenController.moveTaskToFullscreen(mTaskId,
+ SplitScreenController.EXIT_REASON_DESKTOP_MODE);
} else {
mDesktopTasksController.ifPresent(c ->
c.moveToFullscreen(mTaskId));
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/VeiledResizeTaskPositioner.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/VeiledResizeTaskPositioner.java
index 7c6e69e..5c69d55 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/VeiledResizeTaskPositioner.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/VeiledResizeTaskPositioner.java
@@ -61,7 +61,6 @@
private int mCtrlType;
private boolean mIsResizingOrAnimatingResize;
@Surface.Rotation private int mRotation;
- private boolean mVeilIsVisible;
public VeiledResizeTaskPositioner(ShellTaskOrganizer taskOrganizer,
DesktopModeWindowDecoration windowDecoration,
@@ -119,10 +118,9 @@
if (isResizing() && DragPositioningCallbackUtility.changeBounds(mCtrlType,
mRepositionTaskBounds, mTaskBoundsAtDragStart, mStableBounds, delta,
mDisplayController, mDesktopWindowDecoration)) {
- mIsResizingOrAnimatingResize = true;
- if (!mVeilIsVisible) {
+ if (!mIsResizingOrAnimatingResize) {
mDesktopWindowDecoration.showResizeVeil(mRepositionTaskBounds);
- mVeilIsVisible = true;
+ mIsResizingOrAnimatingResize = true;
} else {
mDesktopWindowDecoration.updateResizeVeil(mRepositionTaskBounds);
}
@@ -148,11 +146,10 @@
final WindowContainerTransaction wct = new WindowContainerTransaction();
wct.setBounds(mDesktopWindowDecoration.mTaskInfo.token, mRepositionTaskBounds);
mTransitions.startTransition(TRANSIT_CHANGE, wct, this);
- } else if (mVeilIsVisible) {
+ } else {
// If bounds haven't changed, perform necessary veil reset here as startAnimation
// won't be called.
- mDesktopWindowDecoration.hideResizeVeil();
- mIsResizingOrAnimatingResize = false;
+ resetVeilIfVisible();
}
} else if (DragPositioningCallbackUtility.isBelowDisallowedArea(
mDisallowedAreaForEndBoundsHeight, mTaskBoundsAtDragStart, mRepositionStartPoint,
@@ -168,7 +165,6 @@
mCtrlType = CTRL_TYPE_UNDEFINED;
mTaskBoundsAtDragStart.setEmpty();
mRepositionStartPoint.set(0, 0);
- mVeilIsVisible = false;
return new Rect(mRepositionTaskBounds);
}
@@ -177,6 +173,13 @@
|| (mCtrlType & CTRL_TYPE_LEFT) != 0 || (mCtrlType & CTRL_TYPE_RIGHT) != 0;
}
+ private void resetVeilIfVisible() {
+ if (mIsResizingOrAnimatingResize) {
+ mDesktopWindowDecoration.hideResizeVeil();
+ mIsResizingOrAnimatingResize = false;
+ }
+ }
+
@Override
public boolean startAnimation(@NonNull IBinder transition, @NonNull TransitionInfo info,
@NonNull SurfaceControl.Transaction startTransaction,
@@ -192,7 +195,7 @@
}
startTransaction.apply();
- mDesktopWindowDecoration.hideResizeVeil();
+ resetVeilIfVisible();
mCtrlType = CTRL_TYPE_UNDEFINED;
finishCallback.onTransitionFinished(null);
mIsResizingOrAnimatingResize = false;
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/MultiInstanceHelperTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/MultiInstanceHelperTest.kt
new file mode 100644
index 0000000..2f5fe11
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/MultiInstanceHelperTest.kt
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.common
+
+import android.app.ActivityTaskManager
+import android.content.ComponentName
+import android.content.pm.LauncherApps
+import android.content.pm.PackageManager
+import android.content.pm.ShortcutInfo
+import android.os.UserHandle
+import android.view.WindowManager.PROPERTY_SUPPORTS_MULTI_INSTANCE_SYSTEM_UI
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.android.wm.shell.ShellTestCase
+import org.junit.Assert.assertEquals
+import org.junit.Assume.assumeTrue
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.ArgumentMatchers
+import org.mockito.ArgumentMatchers.eq
+import org.mockito.kotlin.doReturn
+import org.mockito.kotlin.doThrow
+import org.mockito.kotlin.mock
+import org.mockito.kotlin.whenever
+
+@RunWith(AndroidJUnit4::class)
+class MultiInstanceHelperTest : ShellTestCase() {
+
+ @Before
+ fun setup() {
+ assumeTrue(ActivityTaskManager.supportsSplitScreenMultiWindow(mContext))
+ }
+
+ @Test
+ fun getShortcutComponent_nullShortcuts() {
+ val launcherApps = mock<LauncherApps>()
+ whenever(launcherApps.getShortcuts(ArgumentMatchers.any(), ArgumentMatchers.any()))
+ .thenReturn(null)
+ assertEquals(null, MultiInstanceHelper.getShortcutComponent(TEST_PACKAGE,
+ TEST_SHORTCUT_ID, UserHandle.CURRENT, launcherApps))
+ }
+
+ @Test
+ fun getShortcutComponent_noShortcuts() {
+ val launcherApps = mock<LauncherApps>()
+ whenever(launcherApps.getShortcuts(ArgumentMatchers.any(), ArgumentMatchers.any()))
+ .thenReturn(ArrayList<ShortcutInfo>())
+ assertEquals(null, MultiInstanceHelper.getShortcutComponent(TEST_PACKAGE,
+ TEST_SHORTCUT_ID, UserHandle.CURRENT, launcherApps))
+ }
+
+ @Test
+ fun getShortcutComponent_validShortcut() {
+ val component = ComponentName(TEST_PACKAGE, TEST_ACTIVITY)
+ val shortcutInfo = ShortcutInfo.Builder(context, "id").setActivity(component).build()
+ val launcherApps = mock<LauncherApps>()
+ whenever(launcherApps.getShortcuts(ArgumentMatchers.any(), ArgumentMatchers.any()))
+ .thenReturn(arrayListOf(shortcutInfo))
+ assertEquals(component, MultiInstanceHelper.getShortcutComponent(TEST_PACKAGE,
+ TEST_SHORTCUT_ID, UserHandle.CURRENT, launcherApps))
+ }
+
+ @Test
+ fun supportsMultiInstanceSplit_inStaticAllowList() {
+ val allowList = arrayOf(TEST_PACKAGE)
+ val helper = MultiInstanceHelper(mContext, context.packageManager, allowList)
+ val component = ComponentName(TEST_PACKAGE, TEST_ACTIVITY)
+ assertEquals(true, helper.supportsMultiInstanceSplit(component))
+ }
+
+ @Test
+ fun supportsMultiInstanceSplit_notInStaticAllowList() {
+ val allowList = arrayOf(TEST_PACKAGE)
+ val helper = MultiInstanceHelper(mContext, context.packageManager, allowList)
+ val component = ComponentName(TEST_NOT_ALLOWED_PACKAGE, TEST_ACTIVITY)
+ assertEquals(false, helper.supportsMultiInstanceSplit(component))
+ }
+
+ @Test
+ @Throws(PackageManager.NameNotFoundException::class)
+ fun supportsMultiInstanceSplit_activityPropertyTrue() {
+ val component = ComponentName(TEST_PACKAGE, TEST_ACTIVITY)
+ val pm = mock<PackageManager>()
+ val activityProp = PackageManager.Property("", true, "", "")
+ whenever(pm.getProperty(eq(PROPERTY_SUPPORTS_MULTI_INSTANCE_SYSTEM_UI),
+ eq(component)))
+ .thenReturn(activityProp)
+ val appProp = PackageManager.Property("", false, "", "")
+ whenever(pm.getProperty(eq(PROPERTY_SUPPORTS_MULTI_INSTANCE_SYSTEM_UI),
+ eq(component.packageName)))
+ .thenReturn(appProp)
+
+ val helper = MultiInstanceHelper(mContext, pm, emptyArray())
+ // Expect activity property to override application property
+ assertEquals(true, helper.supportsMultiInstanceSplit(component))
+ }
+
+ @Test
+ @Throws(PackageManager.NameNotFoundException::class)
+ fun supportsMultiInstanceSplit_activityPropertyFalseApplicationPropertyTrue() {
+ val component = ComponentName(TEST_PACKAGE, TEST_ACTIVITY)
+ val pm = mock<PackageManager>()
+ val activityProp = PackageManager.Property("", false, "", "")
+ whenever(pm.getProperty(eq(PROPERTY_SUPPORTS_MULTI_INSTANCE_SYSTEM_UI),
+ eq(component)))
+ .thenReturn(activityProp)
+ val appProp = PackageManager.Property("", true, "", "")
+ whenever(pm.getProperty(eq(PROPERTY_SUPPORTS_MULTI_INSTANCE_SYSTEM_UI),
+ eq(component.packageName)))
+ .thenReturn(appProp)
+
+ val helper = MultiInstanceHelper(mContext, pm, emptyArray())
+ // Expect activity property to override application property
+ assertEquals(false, helper.supportsMultiInstanceSplit(component))
+ }
+
+ @Test
+ @Throws(PackageManager.NameNotFoundException::class)
+ fun supportsMultiInstanceSplit_noActivityPropertyApplicationPropertyTrue() {
+ val component = ComponentName(TEST_PACKAGE, TEST_ACTIVITY)
+ val pm = mock<PackageManager>()
+ whenever(pm.getProperty(eq(PROPERTY_SUPPORTS_MULTI_INSTANCE_SYSTEM_UI),
+ eq(component)))
+ .thenThrow(PackageManager.NameNotFoundException())
+ val appProp = PackageManager.Property("", true, "", "")
+ whenever(pm.getProperty(eq(PROPERTY_SUPPORTS_MULTI_INSTANCE_SYSTEM_UI),
+ eq(component.packageName)))
+ .thenReturn(appProp)
+
+ val helper = MultiInstanceHelper(mContext, pm, emptyArray())
+ // Expect fall through to app property
+ assertEquals(true, helper.supportsMultiInstanceSplit(component))
+ }
+
+ @Test
+ @Throws(PackageManager.NameNotFoundException::class)
+ fun supportsMultiInstanceSplit_noActivityOrAppProperty() {
+ val component = ComponentName(TEST_PACKAGE, TEST_ACTIVITY)
+ val pm = mock<PackageManager>()
+ whenever(pm.getProperty(eq(PROPERTY_SUPPORTS_MULTI_INSTANCE_SYSTEM_UI),
+ eq(component)))
+ .thenThrow(PackageManager.NameNotFoundException())
+ whenever(pm.getProperty(eq(PROPERTY_SUPPORTS_MULTI_INSTANCE_SYSTEM_UI),
+ eq(component.packageName)))
+ .thenThrow(PackageManager.NameNotFoundException())
+
+ val helper = MultiInstanceHelper(mContext, pm, emptyArray())
+ assertEquals(false, helper.supportsMultiInstanceSplit(component))
+ }
+
+ companion object {
+ val TEST_PACKAGE = "com.android.wm.shell.common"
+ val TEST_NOT_ALLOWED_PACKAGE = "com.android.wm.shell.common.fake";
+ val TEST_ACTIVITY = "TestActivity";
+ val TEST_SHORTCUT_ID = "test_shortcut_1"
+ }
+}
\ No newline at end of file
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitScreenUtilsTests.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitScreenUtilsTests.kt
deleted file mode 100644
index 955660c..0000000
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitScreenUtilsTests.kt
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.wm.shell.common.split
-
-import android.content.ComponentName
-import android.content.pm.LauncherApps
-import android.content.pm.ShortcutInfo
-import android.os.UserHandle
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import com.android.wm.shell.ShellTestCase
-import org.junit.Assert.assertEquals
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.mockito.ArgumentMatchers.any
-import org.mockito.Mockito.mock
-import org.mockito.Mockito.`when`
-
-@RunWith(AndroidJUnit4::class)
-class SplitScreenUtilsTests : ShellTestCase() {
-
- @Test
- fun getShortcutComponent_nullShortcuts() {
- val launcherApps = mock(LauncherApps::class.java).also {
- `when`(it.getShortcuts(any(), any())).thenReturn(null)
- }
- assertEquals(null, SplitScreenUtils.getShortcutComponent(TEST_PACKAGE,
- TEST_SHORTCUT_ID, UserHandle.CURRENT, launcherApps))
- }
-
- @Test
- fun getShortcutComponent_noShortcuts() {
- val launcherApps = mock(LauncherApps::class.java).also {
- `when`(it.getShortcuts(any(), any())).thenReturn(ArrayList<ShortcutInfo>())
- }
- assertEquals(null, SplitScreenUtils.getShortcutComponent(TEST_PACKAGE,
- TEST_SHORTCUT_ID, UserHandle.CURRENT, launcherApps))
- }
-
- @Test
- fun getShortcutComponent_validShortcut() {
- val component = ComponentName(TEST_PACKAGE, TEST_ACTIVITY)
- val shortcutInfo = ShortcutInfo.Builder(context, "id").setActivity(component).build()
- val launcherApps = mock(LauncherApps::class.java).also {
- `when`(it.getShortcuts(any(), any())).thenReturn(arrayListOf(shortcutInfo))
- }
- assertEquals(component, SplitScreenUtils.getShortcutComponent(TEST_PACKAGE,
- TEST_SHORTCUT_ID, UserHandle.CURRENT, launcherApps))
- }
-
- companion object {
- val TEST_PACKAGE = "com.android.wm.shell.common.split"
- val TEST_ACTIVITY = "TestActivity";
- val TEST_SHORTCUT_ID = "test_shortcut_1"
- }
-}
\ No newline at end of file
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt
index 79634e6..63618f4 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt
@@ -373,7 +373,7 @@
assertThat(wct.changes[task.token.asBinder()]?.windowingMode)
.isEqualTo(WINDOWING_MODE_FREEFORM)
verify(splitScreenController).prepareExitSplitScreen(any(), anyInt(),
- eq(SplitScreenController.EXIT_REASON_ENTER_DESKTOP)
+ eq(SplitScreenController.EXIT_REASON_DESKTOP_MODE)
)
}
@@ -385,7 +385,7 @@
assertThat(wct.changes[task.token.asBinder()]?.windowingMode)
.isEqualTo(WINDOWING_MODE_FREEFORM)
verify(splitScreenController, never()).prepareExitSplitScreen(any(), anyInt(),
- eq(SplitScreenController.EXIT_REASON_ENTER_DESKTOP)
+ eq(SplitScreenController.EXIT_REASON_DESKTOP_MODE)
)
}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitScreenControllerTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitScreenControllerTests.java
index 7f3bfbb..315d97e 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitScreenControllerTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitScreenControllerTests.java
@@ -22,7 +22,6 @@
import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
import static android.content.Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
import static android.content.Intent.FLAG_ACTIVITY_NO_USER_ACTION;
-import static android.view.WindowManager.PROPERTY_SUPPORTS_MULTI_INSTANCE_SYSTEM_UI;
import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT;
import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT;
@@ -37,8 +36,6 @@
import static org.mockito.ArgumentMatchers.isNull;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.doThrow;
-import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
@@ -49,10 +46,8 @@
import android.app.ActivityTaskManager;
import android.app.PendingIntent;
import android.content.ComponentName;
-import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
-import android.content.pm.PackageManager;
import android.os.Bundle;
import androidx.test.annotation.UiThreadTest;
@@ -60,7 +55,6 @@
import androidx.test.filters.SmallTest;
import com.android.launcher3.icons.IconProvider;
-import com.android.wm.shell.R;
import com.android.wm.shell.RootTaskDisplayAreaOrganizer;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.ShellTestCase;
@@ -69,6 +63,7 @@
import com.android.wm.shell.common.DisplayInsetsController;
import com.android.wm.shell.common.DisplayLayout;
import com.android.wm.shell.common.LaunchAdjacentController;
+import com.android.wm.shell.common.MultiInstanceHelper;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.SyncTransactionQueue;
import com.android.wm.shell.common.TransactionPool;
@@ -90,6 +85,8 @@
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import java.util.Optional;
+
/**
* Tests for {@link SplitScreenController}
*/
@@ -97,10 +94,6 @@
@RunWith(AndroidJUnit4.class)
public class SplitScreenControllerTests extends ShellTestCase {
- private static final String TEST_PACKAGE = "com.android.wm.shell.splitscreen";
- private static final String TEST_NOT_ALLOWED_PACKAGE = "com.android.wm.shell.splitscreen.fake";
- private static final String TEST_ACTIVITY = "TestActivity";
-
@Mock ShellInit mShellInit;
@Mock ShellCommandHandler mShellCommandHandler;
@Mock ShellTaskOrganizer mTaskOrganizer;
@@ -119,6 +112,7 @@
@Mock LaunchAdjacentController mLaunchAdjacentController;
@Mock WindowDecorViewModel mWindowDecorViewModel;
@Mock DesktopTasksController mDesktopTasksController;
+ @Mock MultiInstanceHelper mMultiInstanceHelper;
@Captor ArgumentCaptor<Intent> mIntentCaptor;
private ShellController mShellController;
@@ -128,17 +122,15 @@
public void setup() {
assumeTrue(ActivityTaskManager.supportsSplitScreenMultiWindow(mContext));
MockitoAnnotations.initMocks(this);
- String[] appsSupportingMultiInstance = mContext.getResources()
- .getStringArray(R.array.config_appsSupportMultiInstancesSplit);
mShellController = spy(new ShellController(mContext, mShellInit, mShellCommandHandler,
mMainExecutor));
mSplitScreenController = spy(new SplitScreenController(mContext, mShellInit,
mShellCommandHandler, mShellController, mTaskOrganizer, mSyncQueue,
mRootTDAOrganizer, mDisplayController, mDisplayImeController,
mDisplayInsetsController, mDragAndDropController, mTransitions, mTransactionPool,
- mIconProvider, mRecentTasks, mLaunchAdjacentController, mWindowDecorViewModel,
- mDesktopTasksController, mMainExecutor, mStageCoordinator,
- appsSupportingMultiInstance));
+ mIconProvider, Optional.of(mRecentTasks), mLaunchAdjacentController,
+ Optional.of(mWindowDecorViewModel), Optional.of(mDesktopTasksController),
+ mStageCoordinator, mMultiInstanceHelper, mMainExecutor));
}
@Test
@@ -213,7 +205,7 @@
@Test
public void startIntent_multiInstancesSupported_appendsMultipleTaskFag() {
- doReturn(true).when(mSplitScreenController).supportsMultiInstanceSplit(any());
+ doReturn(true).when(mMultiInstanceHelper).supportsMultiInstanceSplit(any());
Intent startIntent = createStartIntent("startActivity");
PendingIntent pendingIntent =
PendingIntent.getActivity(mContext, 0, startIntent, FLAG_IMMUTABLE);
@@ -250,13 +242,13 @@
verify(mStageCoordinator).startTask(anyInt(), eq(SPLIT_POSITION_TOP_OR_LEFT),
isNull());
- verify(mSplitScreenController, never()).supportsMultiInstanceSplit(any());
+ verify(mMultiInstanceHelper, never()).supportsMultiInstanceSplit(any());
verify(mStageCoordinator, never()).switchSplitPosition(any());
}
@Test
public void startIntent_multiInstancesSupported_startTaskInBackgroundAfterSplitActivated() {
- doReturn(true).when(mSplitScreenController).supportsMultiInstanceSplit(any());
+ doReturn(true).when(mMultiInstanceHelper).supportsMultiInstanceSplit(any());
doNothing().when(mSplitScreenController).startTask(anyInt(), anyInt(), any());
Intent startIntent = createStartIntent("startActivity");
PendingIntent pendingIntent =
@@ -273,14 +265,14 @@
mSplitScreenController.startIntent(pendingIntent, mContext.getUserId(), null,
SPLIT_POSITION_TOP_OR_LEFT, null);
- verify(mSplitScreenController, never()).supportsMultiInstanceSplit(any());
+ verify(mMultiInstanceHelper, never()).supportsMultiInstanceSplit(any());
verify(mStageCoordinator).startTask(anyInt(), eq(SPLIT_POSITION_TOP_OR_LEFT),
isNull());
}
@Test
public void startIntent_multiInstancesNotSupported_switchesPositionAfterSplitActivated() {
- doReturn(false).when(mSplitScreenController).supportsMultiInstanceSplit(any());
+ doReturn(false).when(mMultiInstanceHelper).supportsMultiInstanceSplit(any());
Intent startIntent = createStartIntent("startActivity");
PendingIntent pendingIntent =
PendingIntent.getActivity(mContext, 0, startIntent, FLAG_IMMUTABLE);
@@ -298,130 +290,6 @@
}
@Test
- public void supportsMultiInstanceSplit_inStaticAllowList() {
- String[] allowList = { TEST_PACKAGE };
- SplitScreenController controller = new SplitScreenController(mContext, mShellInit,
- mShellCommandHandler, mShellController, mTaskOrganizer, mSyncQueue,
- mRootTDAOrganizer, mDisplayController, mDisplayImeController,
- mDisplayInsetsController, mDragAndDropController, mTransitions, mTransactionPool,
- mIconProvider, mRecentTasks, mLaunchAdjacentController, mWindowDecorViewModel,
- mDesktopTasksController, mMainExecutor, mStageCoordinator,
- allowList);
- ComponentName component = new ComponentName(TEST_PACKAGE, TEST_ACTIVITY);
- assertEquals(true, controller.supportsMultiInstanceSplit(component));
- }
-
- @Test
- public void supportsMultiInstanceSplit_notInStaticAllowList() {
- String[] allowList = { TEST_PACKAGE };
- SplitScreenController controller = new SplitScreenController(mContext, mShellInit,
- mShellCommandHandler, mShellController, mTaskOrganizer, mSyncQueue,
- mRootTDAOrganizer, mDisplayController, mDisplayImeController,
- mDisplayInsetsController, mDragAndDropController, mTransitions, mTransactionPool,
- mIconProvider, mRecentTasks, mLaunchAdjacentController, mWindowDecorViewModel,
- mDesktopTasksController, mMainExecutor, mStageCoordinator,
- allowList);
- ComponentName component = new ComponentName(TEST_NOT_ALLOWED_PACKAGE, TEST_ACTIVITY);
- assertEquals(false, controller.supportsMultiInstanceSplit(component));
- }
-
- @Test
- public void supportsMultiInstanceSplit_activityPropertyTrue()
- throws PackageManager.NameNotFoundException {
- Context context = spy(mContext);
- ComponentName component = new ComponentName(TEST_PACKAGE, TEST_ACTIVITY);
- PackageManager pm = mock(PackageManager.class);
- doReturn(pm).when(context).getPackageManager();
- PackageManager.Property activityProp = new PackageManager.Property("", true, "", "");
- doReturn(activityProp).when(pm).getProperty(eq(PROPERTY_SUPPORTS_MULTI_INSTANCE_SYSTEM_UI),
- eq(component));
- PackageManager.Property appProp = new PackageManager.Property("", false, "", "");
- doReturn(appProp).when(pm).getProperty(eq(PROPERTY_SUPPORTS_MULTI_INSTANCE_SYSTEM_UI),
- eq(component.getPackageName()));
-
- SplitScreenController controller = new SplitScreenController(context, mShellInit,
- mShellCommandHandler, mShellController, mTaskOrganizer, mSyncQueue,
- mRootTDAOrganizer, mDisplayController, mDisplayImeController,
- mDisplayInsetsController, mDragAndDropController, mTransitions, mTransactionPool,
- mIconProvider, mRecentTasks, mLaunchAdjacentController, mWindowDecorViewModel,
- mDesktopTasksController, mMainExecutor, mStageCoordinator,
- new String[0]);
- // Expect activity property to override application property
- assertEquals(true, controller.supportsMultiInstanceSplit(component));
- }
-
- @Test
- public void supportsMultiInstanceSplit_activityPropertyFalseApplicationPropertyTrue()
- throws PackageManager.NameNotFoundException {
- Context context = spy(mContext);
- ComponentName component = new ComponentName(TEST_PACKAGE, TEST_ACTIVITY);
- PackageManager pm = mock(PackageManager.class);
- doReturn(pm).when(context).getPackageManager();
- PackageManager.Property activityProp = new PackageManager.Property("", false, "", "");
- doReturn(activityProp).when(pm).getProperty(eq(PROPERTY_SUPPORTS_MULTI_INSTANCE_SYSTEM_UI),
- eq(component));
- PackageManager.Property appProp = new PackageManager.Property("", true, "", "");
- doReturn(appProp).when(pm).getProperty(eq(PROPERTY_SUPPORTS_MULTI_INSTANCE_SYSTEM_UI),
- eq(component.getPackageName()));
-
- SplitScreenController controller = new SplitScreenController(context, mShellInit,
- mShellCommandHandler, mShellController, mTaskOrganizer, mSyncQueue,
- mRootTDAOrganizer, mDisplayController, mDisplayImeController,
- mDisplayInsetsController, mDragAndDropController, mTransitions, mTransactionPool,
- mIconProvider, mRecentTasks, mLaunchAdjacentController, mWindowDecorViewModel,
- mDesktopTasksController, mMainExecutor, mStageCoordinator,
- new String[0]);
- // Expect activity property to override application property
- assertEquals(false, controller.supportsMultiInstanceSplit(component));
- }
-
- @Test
- public void supportsMultiInstanceSplit_noActivityPropertyApplicationPropertyTrue()
- throws PackageManager.NameNotFoundException {
- Context context = spy(mContext);
- ComponentName component = new ComponentName(TEST_PACKAGE, TEST_ACTIVITY);
- PackageManager pm = mock(PackageManager.class);
- doReturn(pm).when(context).getPackageManager();
- doThrow(PackageManager.NameNotFoundException.class).when(pm).getProperty(
- eq(PROPERTY_SUPPORTS_MULTI_INSTANCE_SYSTEM_UI), eq(component));
- PackageManager.Property appProp = new PackageManager.Property("", true, "", "");
- doReturn(appProp).when(pm).getProperty(eq(PROPERTY_SUPPORTS_MULTI_INSTANCE_SYSTEM_UI),
- eq(component.getPackageName()));
-
- SplitScreenController controller = new SplitScreenController(context, mShellInit,
- mShellCommandHandler, mShellController, mTaskOrganizer, mSyncQueue,
- mRootTDAOrganizer, mDisplayController, mDisplayImeController,
- mDisplayInsetsController, mDragAndDropController, mTransitions, mTransactionPool,
- mIconProvider, mRecentTasks, mLaunchAdjacentController, mWindowDecorViewModel,
- mDesktopTasksController, mMainExecutor, mStageCoordinator,
- new String[0]);
- // Expect fall through to app property
- assertEquals(true, controller.supportsMultiInstanceSplit(component));
- }
-
- @Test
- public void supportsMultiInstanceSplit_noActivityOrAppProperty()
- throws PackageManager.NameNotFoundException {
- Context context = spy(mContext);
- ComponentName component = new ComponentName(TEST_PACKAGE, TEST_ACTIVITY);
- PackageManager pm = mock(PackageManager.class);
- doReturn(pm).when(context).getPackageManager();
- doThrow(PackageManager.NameNotFoundException.class).when(pm).getProperty(
- eq(PROPERTY_SUPPORTS_MULTI_INSTANCE_SYSTEM_UI), eq(component));
- doThrow(PackageManager.NameNotFoundException.class).when(pm).getProperty(
- eq(PROPERTY_SUPPORTS_MULTI_INSTANCE_SYSTEM_UI), eq(component.getPackageName()));
-
- SplitScreenController controller = new SplitScreenController(context, mShellInit,
- mShellCommandHandler, mShellController, mTaskOrganizer, mSyncQueue,
- mRootTDAOrganizer, mDisplayController, mDisplayImeController,
- mDisplayInsetsController, mDragAndDropController, mTransitions, mTransactionPool,
- mIconProvider, mRecentTasks, mLaunchAdjacentController, mWindowDecorViewModel,
- mDesktopTasksController, mMainExecutor, mStageCoordinator,
- new String[0]);
- assertEquals(false, controller.supportsMultiInstanceSplit(component));
- }
-
- @Test
public void testSwitchSplitPosition_checksIsSplitScreenVisible() {
final String reason = "test";
when(mSplitScreenController.isSplitScreenVisible()).thenReturn(true, false);
diff --git a/media/java/android/media/MediaRouter2.java b/media/java/android/media/MediaRouter2.java
index 144b01a..4d5a33d 100644
--- a/media/java/android/media/MediaRouter2.java
+++ b/media/java/android/media/MediaRouter2.java
@@ -20,6 +20,7 @@
import static com.android.media.flags.Flags.FLAG_ENABLE_BUILT_IN_SPEAKER_ROUTE_SUITABILITY_STATUSES;
import static com.android.media.flags.Flags.FLAG_ENABLE_CROSS_USER_ROUTING_IN_MEDIA_ROUTER2;
import static com.android.media.flags.Flags.FLAG_ENABLE_GET_TRANSFERABLE_ROUTES;
+import static com.android.media.flags.Flags.FLAG_ENABLE_PRIVILEGED_ROUTING_FOR_MEDIA_ROUTING_CONTROL;
import static com.android.media.flags.Flags.FLAG_ENABLE_RLP_CALLBACKS_IN_MEDIA_ROUTER2;
import static com.android.media.flags.Flags.FLAG_ENABLE_SCREEN_OFF_SCANNING;
@@ -989,17 +990,24 @@
}
/**
- * Requests a volume change for the route asynchronously.
- * It may have no effect if the route is currently not selected.
+ * Sets the volume for a specific route.
*
- * <p>This will be no-op for non-system media routers.
+ * <p>The call may have no effect if the route is currently not selected.
+ *
+ * <p>This method is only supported by {@link #getInstance(Context, String) proxy MediaRouter2
+ * instances}. Use {@link RoutingController#setVolume(int) RoutingController#setVolume(int)}
+ * instead for {@link #getInstance(Context) local MediaRouter2 instances}.</p>
*
* @param volume The new volume value between 0 and {@link MediaRoute2Info#getVolumeMax}.
- * @see #getInstance(Context, String)
- * @hide
+ * @throws UnsupportedOperationException If called on a {@link #getInstance(Context) local
+ * router instance}.
*/
- @SystemApi
- @RequiresPermission(Manifest.permission.MEDIA_CONTENT_CONTROL)
+ @FlaggedApi(FLAG_ENABLE_PRIVILEGED_ROUTING_FOR_MEDIA_ROUTING_CONTROL)
+ @RequiresPermission(
+ anyOf = {
+ Manifest.permission.MEDIA_CONTENT_CONTROL,
+ Manifest.permission.MEDIA_ROUTING_CONTROL
+ })
public void setRouteVolume(@NonNull MediaRoute2Info route, int volume) {
Objects.requireNonNull(route, "route must not be null");
@@ -3464,10 +3472,11 @@
return result;
}
- /** No-op. Local routers cannot modify the volume of specific routes. */
+ /** Local routers cannot modify the volume of specific routes. */
@Override
public void setRouteVolume(MediaRoute2Info route, int volume) {
- // Do nothing.
+ throw new UnsupportedOperationException(
+ "setRouteVolume is only supported by proxy routers. See javadoc.");
// If this API needs to be public, use IMediaRouterService#setRouteVolumeWithRouter2()
}
diff --git a/media/java/android/service/media/MediaBrowserService.java b/media/java/android/service/media/MediaBrowserService.java
index a8e9423..e92c7b3 100644
--- a/media/java/android/service/media/MediaBrowserService.java
+++ b/media/java/android/service/media/MediaBrowserService.java
@@ -211,51 +211,40 @@
}
private static class ServiceBinder extends IMediaBrowserService.Stub {
- private WeakReference<MediaBrowserService> mService;
+ private WeakReference<ServiceState> mServiceState;
- private ServiceBinder(MediaBrowserService service) {
- mService = new WeakReference(service);
+ private ServiceBinder(ServiceState serviceState) {
+ mServiceState = new WeakReference(serviceState);
}
@Override
public void connect(final String pkg, final Bundle rootHints,
final IMediaBrowserServiceCallbacks callbacks) {
- MediaBrowserService service = mService.get();
- if (service == null) {
+ ServiceState serviceState = mServiceState.get();
+ if (serviceState == null) {
return;
}
final int pid = Binder.getCallingPid();
final int uid = Binder.getCallingUid();
- if (!service.isValidPackage(pkg, uid)) {
+ if (!serviceState.isValidPackage(pkg, uid)) {
throw new IllegalArgumentException("Package/uid mismatch: uid=" + uid
+ " package=" + pkg);
}
- service.mHandler.post(
- () -> service.connectOnHandler(pkg, pid, uid, rootHints, callbacks));
+ serviceState.postOnHandler(
+ () -> serviceState.connectOnHandler(pkg, pid, uid, rootHints, callbacks));
}
@Override
public void disconnect(final IMediaBrowserServiceCallbacks callbacks) {
- MediaBrowserService service = mService.get();
- if (service == null) {
+ ServiceState serviceState = mServiceState.get();
+ if (serviceState == null) {
return;
}
- service.mHandler.post(new Runnable() {
- @Override
- public void run() {
- final IBinder b = callbacks.asBinder();
-
- // Clear out the old subscriptions. We are getting new ones.
- final ConnectionRecord old = service.mServiceState.mConnections.remove(b);
- if (old != null) {
- // TODO
- old.callbacks.asBinder().unlinkToDeath(old, 0);
- }
- }
- });
+ serviceState.postOnHandler(
+ () -> serviceState.removeConnectionRecordOnHandler(callbacks));
}
@Override
@@ -266,13 +255,13 @@
@Override
public void addSubscription(final String id, final IBinder token, final Bundle options,
final IMediaBrowserServiceCallbacks callbacks) {
- MediaBrowserService service = mService.get();
- if (service == null) {
+ ServiceState serviceState = mServiceState.get();
+ if (serviceState == null) {
return;
}
- service.mHandler.post(
- () -> service.addSubscriptionOnHandler(id, callbacks, token, options));
+ serviceState.postOnHandler(
+ () -> serviceState.addSubscriptionOnHandler(id, callbacks, token, options));
}
@Override
@@ -284,14 +273,14 @@
@Override
public void removeSubscription(final String id, final IBinder token,
final IMediaBrowserServiceCallbacks callbacks) {
- MediaBrowserService service = mService.get();
- if (service == null) {
+ ServiceState serviceState = mServiceState.get();
+ if (serviceState == null) {
return;
}
- service.mHandler.post(
+ serviceState.postOnHandler(
() -> {
- if (!service.removeSubscriptionOnHandler(id, callbacks, token)) {
+ if (!serviceState.removeSubscriptionOnHandler(id, callbacks, token)) {
Log.w(TAG, "removeSubscription for id with no subscription: " + id);
}
});
@@ -300,20 +289,20 @@
@Override
public void getMediaItem(final String mediaId, final ResultReceiver receiver,
final IMediaBrowserServiceCallbacks callbacks) {
- MediaBrowserService service = mService.get();
- if (service == null) {
+ ServiceState serviceState = mServiceState.get();
+ if (serviceState == null) {
return;
}
- service.mHandler.post(
- () -> service.performLoadItemOnHandler(mediaId, callbacks, receiver));
+ serviceState.postOnHandler(
+ () -> serviceState.performLoadItemOnHandler(mediaId, callbacks, receiver));
}
}
@Override
public void onCreate() {
super.onCreate();
- mServiceState.mBinder = new ServiceBinder(this);
+ mServiceState.mBinder = new ServiceBinder(mServiceState);
}
@Override
@@ -448,7 +437,7 @@
throw new IllegalStateException("The session token has already been set.");
}
mServiceState.mSession = token;
- mHandler.post(() -> notifySessionTokenInitializedOnHandler(token));
+ mHandler.post(() -> mServiceState.notifySessionTokenInitializedOnHandler(token));
}
/**
@@ -526,268 +515,7 @@
if (parentId == null) {
throw new IllegalArgumentException("parentId cannot be null in notifyChildrenChanged");
}
- mHandler.post(() -> notifyChildrenChangeOnHandler(parentId, options));
- }
-
- /**
- * Return whether the given package is one of the ones that is owned by the uid.
- */
- private boolean isValidPackage(String pkg, int uid) {
- if (pkg == null) {
- return false;
- }
- final PackageManager pm = getPackageManager();
- final String[] packages = pm.getPackagesForUid(uid);
- final int N = packages.length;
- for (int i = 0; i < N; i++) {
- if (packages[i].equals(pkg)) {
- return true;
- }
- }
- return false;
- }
-
- private void notifySessionTokenInitializedOnHandler(MediaSession.Token token) {
- Iterator<ConnectionRecord> iter = mServiceState.mConnections.values().iterator();
- while (iter.hasNext()) {
- ConnectionRecord connection = iter.next();
- try {
- connection.callbacks.onConnect(
- connection.root.getRootId(), token, connection.root.getExtras());
- } catch (RemoteException e) {
- Log.w(TAG, "Connection for " + connection.pkg + " is no longer valid.");
- iter.remove();
- }
- }
- }
-
- private void notifyChildrenChangeOnHandler(final String parentId, final Bundle options) {
- for (IBinder binder : mServiceState.mConnections.keySet()) {
- ConnectionRecord connection = mServiceState.mConnections.get(binder);
- List<Pair<IBinder, Bundle>> callbackList = connection.subscriptions.get(parentId);
- if (callbackList != null) {
- for (Pair<IBinder, Bundle> callback : callbackList) {
- if (MediaBrowserUtils.hasDuplicatedItems(options, callback.second)) {
- performLoadChildrenOnHandler(parentId, connection, callback.second);
- }
- }
- }
- }
- }
-
- /** Save the subscription and if it is a new subscription send the results. */
- private void addSubscriptionOnHandler(
- String id, IMediaBrowserServiceCallbacks callbacks, IBinder token, Bundle options) {
- IBinder b = callbacks.asBinder();
- // Get the record for the connection
- ConnectionRecord connection = mServiceState.mConnections.get(b);
- if (connection == null) {
- Log.w(TAG, "addSubscription for callback that isn't registered id=" + id);
- return;
- }
-
- // Save the subscription
- List<Pair<IBinder, Bundle>> callbackList = connection.subscriptions.get(id);
- if (callbackList == null) {
- callbackList = new ArrayList<>();
- }
- for (Pair<IBinder, Bundle> callback : callbackList) {
- if (token == callback.first
- && MediaBrowserUtils.areSameOptions(options, callback.second)) {
- return;
- }
- }
- callbackList.add(new Pair<>(token, options));
- connection.subscriptions.put(id, callbackList);
- // send the results
- performLoadChildrenOnHandler(id, connection, options);
- }
-
- private void connectOnHandler(
- String pkg,
- int pid,
- int uid,
- Bundle rootHints,
- IMediaBrowserServiceCallbacks callbacks) {
- IBinder b = callbacks.asBinder();
- // Clear out the old subscriptions. We are getting new ones.
- mServiceState.mConnections.remove(b);
-
- // Temporarily sets a placeholder ConnectionRecord to make getCurrentBrowserInfo() work in
- // onGetRoot().
- mServiceState.mCurConnection =
- new ConnectionRecord(
- /* service= */ this, pkg, pid, uid, rootHints, callbacks, /* root= */ null);
- BrowserRoot root = onGetRoot(pkg, uid, rootHints);
- mServiceState.mCurConnection = null;
-
- // If they didn't return something, don't allow this client.
- if (root == null) {
- Log.i(TAG, "No root for client " + pkg + " from service " + getClass().getName());
- try {
- callbacks.onConnectFailed();
- } catch (RemoteException ex) {
- Log.w(TAG, "Calling onConnectFailed() failed. Ignoring. pkg=" + pkg);
- }
- } else {
- try {
- ConnectionRecord connection =
- new ConnectionRecord(
- /* service= */ this, pkg, pid, uid, rootHints, callbacks, root);
- mServiceState.mConnections.put(b, connection);
- b.linkToDeath(connection, /* flags= */ 0);
- if (mServiceState.mSession != null) {
- callbacks.onConnect(
- connection.root.getRootId(),
- mServiceState.mSession,
- connection.root.getExtras());
- }
- } catch (RemoteException ex) {
- Log.w(TAG, "Calling onConnect() failed. Dropping client. pkg=" + pkg);
- mServiceState.mConnections.remove(b);
- }
- }
- }
-
- /** Remove the subscription. */
- private boolean removeSubscriptionOnHandler(
- String id, IMediaBrowserServiceCallbacks callbacks, IBinder token) {
- final IBinder b = callbacks.asBinder();
-
- ConnectionRecord connection = mServiceState.mConnections.get(b);
- if (connection == null) {
- Log.w(TAG, "removeSubscription for callback that isn't registered id=" + id);
- return true;
- }
-
- if (token == null) {
- return connection.subscriptions.remove(id) != null;
- }
- boolean removed = false;
- List<Pair<IBinder, Bundle>> callbackList = connection.subscriptions.get(id);
- if (callbackList != null) {
- Iterator<Pair<IBinder, Bundle>> iter = callbackList.iterator();
- while (iter.hasNext()) {
- if (token == iter.next().first) {
- removed = true;
- iter.remove();
- }
- }
- if (callbackList.isEmpty()) {
- connection.subscriptions.remove(id);
- }
- }
- return removed;
- }
-
- /**
- * Call onLoadChildren and then send the results back to the connection.
- *
- * <p>Callers must make sure that this connection is still connected.
- */
- private void performLoadChildrenOnHandler(
- final String parentId, final ConnectionRecord connection, final Bundle options) {
- final Result<List<MediaBrowser.MediaItem>> result =
- new Result<>(parentId) {
- @Override
- void onResultSent(List<MediaBrowser.MediaItem> list, @ResultFlags int flag) {
- if (mServiceState.mConnections.get(connection.callbacks.asBinder())
- != connection) {
- if (DBG) {
- Log.d(
- TAG,
- "Not sending onLoadChildren result for connection that has"
- + " been disconnected. pkg="
- + connection.pkg
- + " id="
- + parentId);
- }
- return;
- }
-
- List<MediaBrowser.MediaItem> filteredList =
- (flag & RESULT_FLAG_OPTION_NOT_HANDLED) != 0
- ? MediaBrowserUtils.applyPagingOptions(list, options)
- : list;
- ParceledListSlice<MediaBrowser.MediaItem> pls = null;
- if (filteredList != null) {
- pls = new ParceledListSlice<>(filteredList);
- // Limit the size of initial Parcel to prevent binder buffer overflow
- // as onLoadChildren is an async binder call.
- pls.setInlineCountLimit(1);
- }
- try {
- connection.callbacks.onLoadChildren(parentId, pls, options);
- } catch (RemoteException ex) {
- // The other side is in the process of crashing.
- Log.w(
- TAG,
- "Calling onLoadChildren() failed for id="
- + parentId
- + " package="
- + connection.pkg);
- }
- }
- };
-
- mServiceState.mCurConnection = connection;
- if (options == null) {
- onLoadChildren(parentId, result);
- } else {
- onLoadChildren(parentId, result, options);
- }
- mServiceState.mCurConnection = null;
-
- if (!result.isDone()) {
- throw new IllegalStateException("onLoadChildren must call detach() or sendResult()"
- + " before returning for package=" + connection.pkg + " id=" + parentId);
- }
- }
-
- private void performLoadItemOnHandler(
- String itemId, IMediaBrowserServiceCallbacks callbacks, final ResultReceiver receiver) {
- final IBinder b = callbacks.asBinder();
- ConnectionRecord connection = mServiceState.mConnections.get(b);
- if (connection == null) {
- Log.w(TAG, "getMediaItem for callback that isn't registered id=" + itemId);
- return;
- }
-
- final Result<MediaBrowser.MediaItem> result =
- new Result<>(itemId) {
- @Override
- void onResultSent(MediaBrowser.MediaItem item, @ResultFlags int flag) {
- if (mServiceState.mConnections.get(connection.callbacks.asBinder())
- != connection) {
- if (DBG) {
- Log.d(
- TAG,
- "Not sending onLoadItem result for connection that has"
- + " been disconnected. pkg="
- + connection.pkg
- + " id="
- + itemId);
- }
- return;
- }
- if ((flag & RESULT_FLAG_ON_LOAD_ITEM_NOT_IMPLEMENTED) != 0) {
- receiver.send(RESULT_ERROR, null);
- return;
- }
- Bundle bundle = new Bundle();
- bundle.putParcelable(KEY_MEDIA_ITEM, item);
- receiver.send(RESULT_OK, bundle);
- }
- };
-
- mServiceState.mCurConnection = connection;
- onLoadItem(itemId, result);
- mServiceState.mCurConnection = null;
-
- if (!result.isDone()) {
- throw new IllegalStateException("onLoadItem must call detach() or sendResult()"
- + " before returning for id=" + itemId);
- }
+ mHandler.post(() -> mServiceState.notifyChildrenChangeOnHandler(parentId, options));
}
/**
@@ -885,7 +613,7 @@
* service. This allows us to put the service in a valid state once the session is released
* (which is an irrecoverable invalid state). More details about this in b/185136506.
*/
- private static class ServiceState {
+ private class ServiceState {
// Fields accessed from any caller thread.
@Nullable private MediaSession.Token mSession;
@@ -894,5 +622,292 @@
// Fields accessed from mHandler only.
@NonNull private final ArrayMap<IBinder, ConnectionRecord> mConnections = new ArrayMap<>();
@Nullable private ConnectionRecord mCurConnection;
+
+ public void postOnHandler(Runnable runnable) {
+ mHandler.post(runnable);
+ }
+
+ public void removeConnectionRecordOnHandler(IMediaBrowserServiceCallbacks callbacks) {
+ IBinder b = callbacks.asBinder();
+ // Clear out the old subscriptions. We are getting new ones.
+ ConnectionRecord old = mConnections.remove(b);
+ if (old != null) {
+ old.callbacks.asBinder().unlinkToDeath(old, 0);
+ }
+ }
+
+ public void notifySessionTokenInitializedOnHandler(MediaSession.Token token) {
+ Iterator<ConnectionRecord> iter = mConnections.values().iterator();
+ while (iter.hasNext()) {
+ ConnectionRecord connection = iter.next();
+ try {
+ connection.callbacks.onConnect(
+ connection.root.getRootId(), token, connection.root.getExtras());
+ } catch (RemoteException e) {
+ Log.w(TAG, "Connection for " + connection.pkg + " is no longer valid.");
+ iter.remove();
+ }
+ }
+ }
+
+ public void notifyChildrenChangeOnHandler(String parentId, Bundle options) {
+ for (IBinder binder : mConnections.keySet()) {
+ ConnectionRecord connection = mConnections.get(binder);
+ List<Pair<IBinder, Bundle>> callbackList = connection.subscriptions.get(parentId);
+ if (callbackList != null) {
+ for (Pair<IBinder, Bundle> callback : callbackList) {
+ if (MediaBrowserUtils.hasDuplicatedItems(options, callback.second)) {
+ performLoadChildrenOnHandler(parentId, connection, callback.second);
+ }
+ }
+ }
+ }
+ }
+
+ /** Save the subscription and if it is a new subscription send the results. */
+ public void addSubscriptionOnHandler(
+ String id, IMediaBrowserServiceCallbacks callbacks, IBinder token, Bundle options) {
+ IBinder b = callbacks.asBinder();
+ // Get the record for the connection
+ ConnectionRecord connection = mConnections.get(b);
+ if (connection == null) {
+ Log.w(TAG, "addSubscription for callback that isn't registered id=" + id);
+ return;
+ }
+
+ // Save the subscription
+ List<Pair<IBinder, Bundle>> callbackList = connection.subscriptions.get(id);
+ if (callbackList == null) {
+ callbackList = new ArrayList<>();
+ }
+ for (Pair<IBinder, Bundle> callback : callbackList) {
+ if (token == callback.first
+ && MediaBrowserUtils.areSameOptions(options, callback.second)) {
+ return;
+ }
+ }
+ callbackList.add(new Pair<>(token, options));
+ connection.subscriptions.put(id, callbackList);
+ // send the results
+ performLoadChildrenOnHandler(id, connection, options);
+ }
+
+ public void connectOnHandler(
+ String pkg,
+ int pid,
+ int uid,
+ Bundle rootHints,
+ IMediaBrowserServiceCallbacks callbacks) {
+ IBinder b = callbacks.asBinder();
+ // Clear out the old subscriptions. We are getting new ones.
+ mConnections.remove(b);
+
+ // Temporarily sets a placeholder ConnectionRecord to make getCurrentBrowserInfo() work
+ // in onGetRoot().
+ mCurConnection =
+ new ConnectionRecord(
+ /* service= */ MediaBrowserService.this,
+ pkg,
+ pid,
+ uid,
+ rootHints,
+ callbacks,
+ /* root= */ null);
+ BrowserRoot root = onGetRoot(pkg, uid, rootHints);
+ mCurConnection = null;
+
+ // If they didn't return something, don't allow this client.
+ if (root == null) {
+ Log.i(TAG, "No root for client " + pkg + " from service " + getClass().getName());
+ try {
+ callbacks.onConnectFailed();
+ } catch (RemoteException ex) {
+ Log.w(TAG, "Calling onConnectFailed() failed. Ignoring. pkg=" + pkg);
+ }
+ } else {
+ try {
+ ConnectionRecord connection =
+ new ConnectionRecord(
+ /* service= */ MediaBrowserService.this,
+ pkg,
+ pid,
+ uid,
+ rootHints,
+ callbacks,
+ root);
+ mConnections.put(b, connection);
+ b.linkToDeath(connection, /* flags= */ 0);
+ if (mSession != null) {
+ callbacks.onConnect(
+ connection.root.getRootId(), mSession, connection.root.getExtras());
+ }
+ } catch (RemoteException ex) {
+ Log.w(TAG, "Calling onConnect() failed. Dropping client. pkg=" + pkg);
+ mConnections.remove(b);
+ }
+ }
+ }
+
+ /** Remove the subscription. */
+ public boolean removeSubscriptionOnHandler(
+ String id, IMediaBrowserServiceCallbacks callbacks, IBinder token) {
+ IBinder b = callbacks.asBinder();
+
+ ConnectionRecord connection = mConnections.get(b);
+ if (connection == null) {
+ Log.w(TAG, "removeSubscription for callback that isn't registered id=" + id);
+ return true;
+ }
+
+ if (token == null) {
+ return connection.subscriptions.remove(id) != null;
+ }
+ boolean removed = false;
+ List<Pair<IBinder, Bundle>> callbackList = connection.subscriptions.get(id);
+ if (callbackList != null) {
+ Iterator<Pair<IBinder, Bundle>> iter = callbackList.iterator();
+ while (iter.hasNext()) {
+ if (token == iter.next().first) {
+ removed = true;
+ iter.remove();
+ }
+ }
+ if (callbackList.isEmpty()) {
+ connection.subscriptions.remove(id);
+ }
+ }
+ return removed;
+ }
+
+ /**
+ * Call onLoadChildren and then send the results back to the connection.
+ *
+ * <p>Callers must make sure that this connection is still connected.
+ */
+ public void performLoadChildrenOnHandler(
+ String parentId, ConnectionRecord connection, Bundle options) {
+ Result<List<MediaBrowser.MediaItem>> result =
+ new Result<>(parentId) {
+ @Override
+ void onResultSent(
+ List<MediaBrowser.MediaItem> list, @ResultFlags int flag) {
+ if (mServiceState.mConnections.get(connection.callbacks.asBinder())
+ != connection) {
+ if (DBG) {
+ Log.d(
+ TAG,
+ "Not sending onLoadChildren result for connection that"
+ + " has been disconnected. pkg="
+ + connection.pkg
+ + " id="
+ + parentId);
+ }
+ return;
+ }
+
+ List<MediaBrowser.MediaItem> filteredList =
+ (flag & RESULT_FLAG_OPTION_NOT_HANDLED) != 0
+ ? MediaBrowserUtils.applyPagingOptions(list, options)
+ : list;
+ ParceledListSlice<MediaBrowser.MediaItem> pls = null;
+ if (filteredList != null) {
+ pls = new ParceledListSlice<>(filteredList);
+ // Limit the size of initial Parcel to prevent binder buffer
+ // overflow as onLoadChildren is an async binder call.
+ pls.setInlineCountLimit(1);
+ }
+ try {
+ connection.callbacks.onLoadChildren(parentId, pls, options);
+ } catch (RemoteException ex) {
+ // The other side is in the process of crashing.
+ Log.w(
+ TAG,
+ "Calling onLoadChildren() failed for id="
+ + parentId
+ + " package="
+ + connection.pkg);
+ }
+ }
+ };
+
+ mCurConnection = connection;
+ if (options == null) {
+ onLoadChildren(parentId, result);
+ } else {
+ onLoadChildren(parentId, result, options);
+ }
+ mCurConnection = null;
+
+ if (!result.isDone()) {
+ throw new IllegalStateException(
+ "onLoadChildren must call detach() or sendResult()"
+ + " before returning for package="
+ + connection.pkg
+ + " id="
+ + parentId);
+ }
+ }
+
+ public void performLoadItemOnHandler(
+ String itemId,
+ IMediaBrowserServiceCallbacks callbacks,
+ ResultReceiver receiver) {
+ IBinder b = callbacks.asBinder();
+ ConnectionRecord connection = mConnections.get(b);
+ if (connection == null) {
+ Log.w(TAG, "getMediaItem for callback that isn't registered id=" + itemId);
+ return;
+ }
+
+ Result<MediaBrowser.MediaItem> result =
+ new Result<>(itemId) {
+ @Override
+ void onResultSent(MediaBrowser.MediaItem item, @ResultFlags int flag) {
+ if (mConnections.get(connection.callbacks.asBinder()) != connection) {
+ if (DBG) {
+ Log.d(
+ TAG,
+ "Not sending onLoadItem result for connection that has"
+ + " been disconnected. pkg="
+ + connection.pkg
+ + " id="
+ + itemId);
+ }
+ return;
+ }
+ if ((flag & RESULT_FLAG_ON_LOAD_ITEM_NOT_IMPLEMENTED) != 0) {
+ receiver.send(RESULT_ERROR, null);
+ return;
+ }
+ Bundle bundle = new Bundle();
+ bundle.putParcelable(KEY_MEDIA_ITEM, item);
+ receiver.send(RESULT_OK, bundle);
+ }
+ };
+
+ mCurConnection = connection;
+ onLoadItem(itemId, result);
+ mCurConnection = null;
+
+ if (!result.isDone()) {
+ throw new IllegalStateException(
+ "onLoadItem must call detach() or sendResult() before returning for id="
+ + itemId);
+ }
+ }
+
+ /** Return whether the given package corresponds to the given uid. */
+ public boolean isValidPackage(String providedPackage, int uid) {
+ if (providedPackage == null) {
+ return false;
+ }
+ PackageManager pm = getPackageManager();
+ for (String packageForUid : pm.getPackagesForUid(uid)) {
+ if (packageForUid.equals(providedPackage)) {
+ return true;
+ }
+ }
+ return false;
+ }
}
}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/CameraTestUtils.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/CameraTestUtils.java
index 388a65d..00068bd 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/CameraTestUtils.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/CameraTestUtils.java
@@ -1709,7 +1709,7 @@
* <p>
* Two images are strongly equal if and only if the data, formats, sizes,
* and timestamps are same. For {@link ImageFormat#PRIVATE PRIVATE} format
- * images, the image data is not not accessible thus the data comparison is
+ * images, the image data is not accessible thus the data comparison is
* effectively skipped as the number of planes is zero.
* </p>
* <p>
@@ -2049,7 +2049,7 @@
}
} else {
// Case 2.
- collector.expectEquals("Exif orientaiton should match requested orientation",
+ collector.expectEquals("Exif orientation should match requested orientation",
requestedOrientation, getExifOrientationInDegree(exifOrientation,
collector));
}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/StaticMetadata.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/StaticMetadata.java
index ed70ab9..5dcd1cb 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/StaticMetadata.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/StaticMetadata.java
@@ -1127,8 +1127,8 @@
* Get aeAvailableModes and do the validation check.
*
* <p>Depending on the check level this class has, for WAR or COLLECT levels,
- * If the aeMode list is invalid, return an empty mode array. The the caller doesn't
- * have to abort the execution even the aeMode list is invalid.</p>
+ * If the aeMode list is invalid, return an empty mode array. The caller doesn't
+ * have to abort the execution even if the aeMode list is invalid.</p>
* @return AE available modes
*/
public int[] getAeAvailableModesChecked() {
diff --git a/native/android/libandroid.map.txt b/native/android/libandroid.map.txt
index 3302265..35e37b2 100644
--- a/native/android/libandroid.map.txt
+++ b/native/android/libandroid.map.txt
@@ -277,6 +277,7 @@
ASurfaceTransaction_setHdrMetadata_cta861_3; # introduced=29
ASurfaceTransaction_setHdrMetadata_smpte2086; # introduced=29
ASurfaceTransaction_setExtendedRangeBrightness; # introduced=UpsideDownCake
+ ASurfaceTransaction_setDesiredHdrHeadroom; # introduced=VanillaIceCream
ASurfaceTransaction_setOnComplete; # introduced=29
ASurfaceTransaction_setOnCommit; # introduced=31
ASurfaceTransaction_setPosition; # introduced=31
diff --git a/native/android/surface_control.cpp b/native/android/surface_control.cpp
index 4b63fbf..9b1330f 100644
--- a/native/android/surface_control.cpp
+++ b/native/android/surface_control.cpp
@@ -646,6 +646,24 @@
transaction->setExtendedRangeBrightness(surfaceControl, currentBufferRatio, desiredRatio);
}
+void ASurfaceTransaction_setDesiredHdrHeadroom(ASurfaceTransaction* aSurfaceTransaction,
+ ASurfaceControl* aSurfaceControl,
+ float desiredRatio) {
+ CHECK_NOT_NULL(aSurfaceTransaction);
+ CHECK_NOT_NULL(aSurfaceControl);
+
+ if (!isfinite(desiredRatio) || (desiredRatio < 1.0f && desiredRatio > 0.0f)) {
+ LOG_ALWAYS_FATAL("setDesiredHdrHeadroom, desiredRatio isn't finite && >= 1.0f or 0, got %f",
+ desiredRatio);
+ return;
+ }
+
+ sp<SurfaceControl> surfaceControl = ASurfaceControl_to_SurfaceControl(aSurfaceControl);
+ Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction);
+
+ transaction->setDesiredHdrHeadroom(surfaceControl, desiredRatio);
+}
+
void ASurfaceTransaction_setColor(ASurfaceTransaction* aSurfaceTransaction,
ASurfaceControl* aSurfaceControl,
float r, float g, float b, float alpha,
diff --git a/nfc/api/system-current.txt b/nfc/api/system-current.txt
index dd2e174..a72e539 100644
--- a/nfc/api/system-current.txt
+++ b/nfc/api/system-current.txt
@@ -26,6 +26,8 @@
method @FlaggedApi("android.nfc.nfc_vendor_cmd") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void unregisterNfcVendorNciCallback(@NonNull android.nfc.NfcAdapter.NfcVendorNciCallback);
method @FlaggedApi("android.nfc.enable_nfc_charging") public void unregisterWlcStateListener(@NonNull android.nfc.NfcAdapter.WlcStateListener);
field @FlaggedApi("android.nfc.enable_nfc_mainline") public static final String ACTION_REQUIRE_UNLOCK_FOR_NFC = "android.nfc.action.REQUIRE_UNLOCK_FOR_NFC";
+ field @FlaggedApi("android.nfc.enable_nfc_mainline") @RequiresPermission(android.Manifest.permission.SHOW_CUSTOMIZED_RESOLVER) public static final String ACTION_SHOW_NFC_RESOLVER = "android.nfc.action.SHOW_NFC_RESOLVER";
+ field @FlaggedApi("android.nfc.enable_nfc_mainline") public static final String EXTRA_RESOLVE_INFOS = "android.nfc.extra.RESOLVE_INFOS";
field @FlaggedApi("android.nfc.nfc_vendor_cmd") public static final int MESSAGE_TYPE_COMMAND = 1; // 0x1
field @FlaggedApi("android.nfc.nfc_vendor_cmd") public static final int SEND_VENDOR_NCI_STATUS_FAILED = 3; // 0x3
field @FlaggedApi("android.nfc.nfc_vendor_cmd") public static final int SEND_VENDOR_NCI_STATUS_MESSAGE_CORRUPTED = 2; // 0x2
diff --git a/nfc/java/android/nfc/NfcAdapter.java b/nfc/java/android/nfc/NfcAdapter.java
index 252f46f..c5b7582 100644
--- a/nfc/java/android/nfc/NfcAdapter.java
+++ b/nfc/java/android/nfc/NfcAdapter.java
@@ -16,6 +16,7 @@
package android.nfc;
+import android.Manifest;
import android.annotation.CallbackExecutor;
import android.annotation.FlaggedApi;
import android.annotation.IntDef;
@@ -35,6 +36,7 @@
import android.content.Context;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
import android.net.Uri;
import android.nfc.tech.MifareClassic;
import android.nfc.tech.Ndef;
@@ -485,6 +487,25 @@
"android.nfc.action.REQUIRE_UNLOCK_FOR_NFC";
/**
+ * Intent action to start a NFC resolver activity in a customized share session with list of
+ * {@link ResolveInfo}.
+ * @hide
+ */
+ @SystemApi
+ @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
+ @RequiresPermission(Manifest.permission.SHOW_CUSTOMIZED_RESOLVER)
+ public static final String ACTION_SHOW_NFC_RESOLVER = "android.nfc.action.SHOW_NFC_RESOLVER";
+
+ /**
+ * "Extras" key for an ArrayList of {@link ResolveInfo} records which are to be shown as the
+ * targets in the customized share session.
+ * @hide
+ */
+ @SystemApi
+ @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
+ public static final String EXTRA_RESOLVE_INFOS = "android.nfc.extra.RESOLVE_INFOS";
+
+ /**
* The requested app is correctly added to the Tag intent app preference.
*
* @see #setTagIntentAppPreferenceForUser(int userId, String pkg, boolean allow)
diff --git a/packages/SystemUI/aconfig/Android.bp b/packages/SystemUI/aconfig/Android.bp
index 03f9d74..5d0847c 100644
--- a/packages/SystemUI/aconfig/Android.bp
+++ b/packages/SystemUI/aconfig/Android.bp
@@ -25,6 +25,7 @@
"//frameworks/base/packages/SystemUI:__subpackages__",
"//frameworks/libs/systemui/tracinglib:__subpackages__",
"//platform_testing:__subpackages__",
+ "//vendor:__subpackages__",
"//cts:__subpackages__",
],
}
diff --git a/packages/SystemUI/aconfig/systemui.aconfig b/packages/SystemUI/aconfig/systemui.aconfig
index 6f34f05..2c285c8 100644
--- a/packages/SystemUI/aconfig/systemui.aconfig
+++ b/packages/SystemUI/aconfig/systemui.aconfig
@@ -301,6 +301,9 @@
" central place, instead of reading resources directly. This is to take into account display"
" cutouts and other special cases. "
bug: "317199366"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
}
flag {
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/ElementTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/ElementTest.kt
index c0de87a..c9b5b75 100644
--- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/ElementTest.kt
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/ElementTest.kt
@@ -44,6 +44,7 @@
import kotlinx.coroutines.launch
import kotlinx.coroutines.test.runTest
import org.junit.Assert.assertThrows
+import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
@@ -247,6 +248,7 @@
}
@Test
+ @Ignore
fun elementIsReusedInSameSceneAndBetweenScenes() {
var currentScene by mutableStateOf(TestScenes.SceneA)
var sceneCState by mutableStateOf(0)
diff --git a/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardPasswordViewControllerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardPasswordViewControllerTest.kt
index c6327ff..c385788 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardPasswordViewControllerTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardPasswordViewControllerTest.kt
@@ -17,6 +17,7 @@
package com.android.keyguard
import android.testing.TestableLooper
+import android.view.ViewGroup
import android.view.inputmethod.InputMethodManager
import android.widget.EditText
import android.widget.ImageView
@@ -51,10 +52,14 @@
@SmallTest
@RunWith(AndroidJUnit4::class)
-@TestableLooper.RunWithLooper
+// collectFlow in KeyguardPinBasedInputViewController.onViewAttached calls JavaAdapter.CollectFlow,
+// which calls View.onRepeatWhenAttached, which requires being run on main thread.
+@TestableLooper.RunWithLooper(setAsMainLooper = true)
class KeyguardPasswordViewControllerTest : SysuiTestCase() {
@Mock private lateinit var keyguardPasswordView: KeyguardPasswordView
@Mock private lateinit var passwordEntry: EditText
+ private var passwordEntryLayoutParams =
+ ViewGroup.LayoutParams(/* width = */ 0, /* height = */ 0)
@Mock lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor
@Mock lateinit var securityMode: KeyguardSecurityModel.SecurityMode
@Mock lateinit var lockPatternUtils: LockPatternUtils
@@ -92,7 +97,7 @@
whenever(keyguardPasswordView.findViewById<ImageView>(R.id.switch_ime_button))
.thenReturn(mock(ImageView::class.java))
`when`(keyguardPasswordView.resources).thenReturn(context.resources)
-
+ whenever(passwordEntry.layoutParams).thenReturn(passwordEntryLayoutParams)
val keyguardKeyboardInteractor = KeyguardKeyboardInteractor(FakeKeyboardRepository())
val fakeFeatureFlags = FakeFeatureFlags()
fakeFeatureFlags.set(Flags.LOCKSCREEN_ENABLE_LANDSCAPE, false)
diff --git a/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardPinBasedInputViewControllerTest.java b/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardPinBasedInputViewControllerTest.java
index f86342c..0054d13 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardPinBasedInputViewControllerTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardPinBasedInputViewControllerTest.java
@@ -24,6 +24,7 @@
import android.testing.TestableLooper.RunWithLooper;
import android.view.View;
+import android.view.ViewGroup;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
@@ -48,13 +49,17 @@
@SmallTest
@RunWith(AndroidJUnit4.class)
-@RunWithLooper
+// collectFlow in KeyguardPinBasedInputViewController.onViewAttached calls JavaAdapter.CollectFlow,
+// which calls View.onRepeatWhenAttached, which requires being run on main thread.
+@RunWithLooper(setAsMainLooper = true)
public class KeyguardPinBasedInputViewControllerTest extends SysuiTestCase {
@Mock
private KeyguardPinBasedInputView mPinBasedInputView;
@Mock
private PasswordTextView mPasswordEntry;
+ private final ViewGroup.LayoutParams mPasswordEntryLayoutParams =
+ new ViewGroup.LayoutParams(/* width= */ 0, /* height= */ 0);
@Mock
private BouncerKeyguardMessageArea mKeyguardMessageArea;
@Mock
@@ -103,6 +108,7 @@
.thenReturn(mOkButton);
when(mPinBasedInputView.getResources()).thenReturn(getContext().getResources());
+ when(mPasswordEntry.getLayoutParams()).thenReturn(mPasswordEntryLayoutParams);
KeyguardKeyboardInteractor keyguardKeyboardInteractor =
new KeyguardKeyboardInteractor(new FakeKeyboardRepository());
FakeFeatureFlags featureFlags = new FakeFeatureFlags();
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/data/repository/CommunalSettingsRepositoryImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/data/repository/CommunalSettingsRepositoryImplTest.kt
index 0aca16d..6b28319 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/data/repository/CommunalSettingsRepositoryImplTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/data/repository/CommunalSettingsRepositoryImplTest.kt
@@ -20,6 +20,7 @@
import android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_FEATURES_NONE
import android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_WIDGETS_ALL
import android.app.admin.devicePolicyManager
+import android.appwidget.AppWidgetProviderInfo
import android.content.Intent
import android.content.pm.UserInfo
import android.platform.test.annotations.DisableFlags
@@ -136,6 +137,29 @@
)
}
+ @EnableFlags(FLAG_COMMUNAL_HUB)
+ @Test
+ fun hubShowsWidgetCategoriesSetByUser() =
+ testScope.runTest {
+ kosmos.fakeSettings.putIntForUser(
+ CommunalSettingsRepositoryImpl.GLANCEABLE_HUB_CONTENT_SETTING,
+ AppWidgetProviderInfo.WIDGET_CATEGORY_HOME_SCREEN,
+ PRIMARY_USER.id
+ )
+ val setting by collectLastValue(underTest.getWidgetCategories(PRIMARY_USER))
+ assertThat(setting?.categories)
+ .isEqualTo(AppWidgetProviderInfo.WIDGET_CATEGORY_HOME_SCREEN)
+ }
+
+ @EnableFlags(FLAG_COMMUNAL_HUB)
+ @Test
+ fun hubShowsKeyguardWidgetsByDefault() =
+ testScope.runTest {
+ val setting by collectLastValue(underTest.getWidgetCategories(PRIMARY_USER))
+ assertThat(setting?.categories)
+ .isEqualTo(AppWidgetProviderInfo.WIDGET_CATEGORY_KEYGUARD)
+ }
+
private fun setKeyguardFeaturesDisabled(user: UserInfo, disabledFlags: Int) {
whenever(kosmos.devicePolicyManager.getKeyguardDisabledFeatures(nullable(), eq(user.id)))
.thenReturn(disabledFlags)
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/view/viewmodel/CommunalEditModeViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/view/viewmodel/CommunalEditModeViewModelTest.kt
index cf727cf..ddb8582 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/view/viewmodel/CommunalEditModeViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/view/viewmodel/CommunalEditModeViewModelTest.kt
@@ -30,6 +30,7 @@
import com.android.systemui.communal.data.repository.fakeCommunalTutorialRepository
import com.android.systemui.communal.data.repository.fakeCommunalWidgetRepository
import com.android.systemui.communal.domain.interactor.communalInteractor
+import com.android.systemui.communal.domain.interactor.communalSettingsInteractor
import com.android.systemui.communal.domain.model.CommunalContentModel
import com.android.systemui.communal.shared.log.CommunalUiEvent
import com.android.systemui.communal.shared.model.CommunalWidgetContentModel
@@ -81,6 +82,7 @@
underTest =
CommunalEditModeViewModel(
kosmos.communalInteractor,
+ kosmos.communalSettingsInteractor,
mediaHost,
uiEventLogger,
logcatLogBuffer("CommunalEditModeViewModelTest"),
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/DozeServiceHostTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/DozeServiceHostTest.java
index 7a78b36..9169938 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/DozeServiceHostTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/DozeServiceHostTest.java
@@ -36,6 +36,7 @@
import androidx.test.filters.SmallTest;
import com.android.keyguard.KeyguardUpdateMonitor;
+import com.android.keyguard.LockIconViewController;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.assist.AssistManager;
import com.android.systemui.biometrics.AuthController;
@@ -45,7 +46,7 @@
import com.android.systemui.keyguard.WakefulnessLifecycle;
import com.android.systemui.keyguard.domain.interactor.DozeInteractor;
import com.android.systemui.shade.NotificationShadeWindowViewController;
-import com.android.systemui.shade.ShadeViewController;
+import com.android.systemui.shade.ShadeLockscreenInteractor;
import com.android.systemui.statusbar.NotificationShadeWindowController;
import com.android.systemui.statusbar.PulseExpansionHandler;
import com.android.systemui.statusbar.StatusBarState;
@@ -91,7 +92,8 @@
@Mock private NotificationIconAreaController mNotificationIconAreaController;
@Mock private NotificationShadeWindowViewController mNotificationShadeWindowViewController;
@Mock private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
- @Mock private ShadeViewController mShadeViewController;
+ @Mock private ShadeLockscreenInteractor mShadeLockscreenInteractor;
+ @Mock private LockIconViewController mLockIconViewController;
@Mock private View mAmbientIndicationContainer;
@Mock private BiometricUnlockController mBiometricUnlockController;
@Mock private AuthController mAuthController;
@@ -109,13 +111,12 @@
() -> mBiometricUnlockController, () -> mAssistManager, mDozeScrimController,
mKeyguardUpdateMonitor, mPulseExpansionHandler, mNotificationShadeWindowController,
mNotificationWakeUpCoordinator, mAuthController, mNotificationIconAreaController,
- mDozeInteractor);
+ mShadeLockscreenInteractor, mDozeInteractor);
mDozeServiceHost.initialize(
mCentralSurfaces,
mStatusBarKeyguardViewManager,
mNotificationShadeWindowViewController,
- mShadeViewController,
mAmbientIndicationContainer);
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardViewController.java
index ce03072..c3c4239 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardViewController.java
@@ -24,7 +24,7 @@
import com.android.systemui.keyguard.KeyguardViewMediator;
import com.android.systemui.shade.ShadeExpansionStateManager;
-import com.android.systemui.shade.ShadeViewController;
+import com.android.systemui.shade.ShadeLockscreenInteractor;
import com.android.systemui.statusbar.phone.BiometricUnlockController;
import com.android.systemui.statusbar.phone.CentralSurfaces;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
@@ -186,7 +186,7 @@
* Registers the CentralSurfaces to which this Keyguard View is mounted.
*/
void registerCentralSurfaces(CentralSurfaces centralSurfaces,
- ShadeViewController shadeViewController,
+ ShadeLockscreenInteractor shadeLockscreenInteractor,
@Nullable ShadeExpansionStateManager shadeExpansionStateManager,
BiometricUnlockController biometricUnlockController,
View notificationContainer,
diff --git a/packages/SystemUI/src/com/android/systemui/communal/data/model/CommunalWidgetCategories.kt b/packages/SystemUI/src/com/android/systemui/communal/data/model/CommunalWidgetCategories.kt
new file mode 100644
index 0000000..03f54c8
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/communal/data/model/CommunalWidgetCategories.kt
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.communal.data.model
+
+import android.appwidget.AppWidgetProviderInfo
+
+/**
+ * The widget categories to display on communal hub (where categories is a bitfield with values that
+ * match those in {@link AppWidgetProviderInfo}).
+ */
+@JvmInline
+value class CommunalWidgetCategories(
+ // The default is keyguard widgets.
+ val categories: Int = AppWidgetProviderInfo.WIDGET_CATEGORY_KEYGUARD
+) {
+ fun contains(category: Int) = (categories and category) == category
+}
diff --git a/packages/SystemUI/src/com/android/systemui/communal/data/repository/CommunalSettingsRepository.kt b/packages/SystemUI/src/com/android/systemui/communal/data/repository/CommunalSettingsRepository.kt
index 201b049..7c65d21 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/data/repository/CommunalSettingsRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/data/repository/CommunalSettingsRepository.kt
@@ -18,11 +18,13 @@
import android.app.admin.DevicePolicyManager
import android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_WIDGETS_ALL
+import android.appwidget.AppWidgetProviderInfo
import android.content.IntentFilter
import android.content.pm.UserInfo
import com.android.systemui.Flags.communalHub
import com.android.systemui.broadcast.BroadcastDispatcher
import com.android.systemui.communal.data.model.CommunalEnabledState
+import com.android.systemui.communal.data.model.CommunalWidgetCategories
import com.android.systemui.communal.data.model.DisabledReason
import com.android.systemui.communal.data.model.DisabledReason.DISABLED_REASON_DEVICE_POLICY
import com.android.systemui.communal.data.model.DisabledReason.DISABLED_REASON_FLAG
@@ -48,6 +50,12 @@
interface CommunalSettingsRepository {
/** A [CommunalEnabledState] for the specified user. */
fun getEnabledState(user: UserInfo): Flow<CommunalEnabledState>
+
+ /**
+ * A flow that reports the widget categories to show on the hub as selected by the user in
+ * Settings.
+ */
+ fun getWidgetCategories(user: UserInfo): Flow<CommunalWidgetCategories>
}
@SysUISingleton
@@ -89,6 +97,23 @@
.flowOn(bgDispatcher)
}
+ override fun getWidgetCategories(user: UserInfo): Flow<CommunalWidgetCategories> =
+ secureSettings
+ .observerFlow(userId = user.id, names = arrayOf(GLANCEABLE_HUB_CONTENT_SETTING))
+ // Force an update
+ .onStart { emit(Unit) }
+ .map {
+ CommunalWidgetCategories(
+ // The default is to show only keyguard widgets.
+ secureSettings.getIntForUser(
+ GLANCEABLE_HUB_CONTENT_SETTING,
+ AppWidgetProviderInfo.WIDGET_CATEGORY_KEYGUARD,
+ user.id
+ )
+ )
+ }
+ .flowOn(bgDispatcher)
+
private fun getEnabledByUser(user: UserInfo): Flow<Boolean> =
secureSettings
.observerFlow(userId = user.id, names = arrayOf(GLANCEABLE_HUB_ENABLED))
@@ -114,6 +139,7 @@
companion object {
const val GLANCEABLE_HUB_ENABLED = "glanceable_hub_enabled"
+ const val GLANCEABLE_HUB_CONTENT_SETTING = "glanceable_hub_content_setting"
private const val ENABLED_SETTING_DEFAULT = 1
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalSettingsInteractor.kt b/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalSettingsInteractor.kt
index 0b096ce..20f60b7 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalSettingsInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalSettingsInteractor.kt
@@ -17,6 +17,7 @@
package com.android.systemui.communal.domain.interactor
import com.android.systemui.communal.data.model.CommunalEnabledState
+import com.android.systemui.communal.data.model.CommunalWidgetCategories
import com.android.systemui.communal.data.repository.CommunalSettingsRepository
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Background
@@ -55,4 +56,16 @@
.map { model -> model.enabled }
// Start this eagerly since the value is accessed synchronously in many places.
.stateIn(scope = bgScope, started = SharingStarted.Eagerly, initialValue = false)
+
+ /** What widget categories to show on the hub. */
+ val communalWidgetCategories: StateFlow<Int> =
+ userInteractor.selectedUserInfo
+ .flatMapLatest { user -> repository.getWidgetCategories(user) }
+ .map { categories -> categories.categories }
+ .stateIn(
+ scope = bgScope,
+ // Start this eagerly since the value can be accessed synchronously.
+ started = SharingStarted.Eagerly,
+ initialValue = CommunalWidgetCategories().categories
+ )
}
diff --git a/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalEditModeViewModel.kt b/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalEditModeViewModel.kt
index 0b355cc..efbb11e 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalEditModeViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalEditModeViewModel.kt
@@ -18,6 +18,7 @@
import com.android.internal.logging.UiEventLogger
import com.android.systemui.communal.domain.interactor.CommunalInteractor
+import com.android.systemui.communal.domain.interactor.CommunalSettingsInteractor
import com.android.systemui.communal.domain.model.CommunalContentModel
import com.android.systemui.communal.shared.log.CommunalUiEvent
import com.android.systemui.dagger.SysUISingleton
@@ -40,6 +41,7 @@
@Inject
constructor(
private val communalInteractor: CommunalInteractor,
+ private val communalSettingsInteractor: CommunalSettingsInteractor,
@Named(MediaModule.COMMUNAL_HUB) mediaHost: MediaHost,
private val uiEventLogger: UiEventLogger,
@CommunalLog logBuffer: LogBuffer,
@@ -84,6 +86,10 @@
uiEventLogger.log(CommunalUiEvent.COMMUNAL_HUB_REORDER_WIDGET_CANCEL)
}
+ /** Returns the widget categories to show on communal hub. */
+ val getCommunalWidgetCategories: Int
+ get() = communalSettingsInteractor.communalWidgetCategories.value
+
/** Sets whether edit mode is currently open */
fun setEditModeOpen(isOpen: Boolean) = communalInteractor.setEditModeOpen(isOpen)
}
diff --git a/packages/SystemUI/src/com/android/systemui/communal/widgets/EditWidgetsActivity.kt b/packages/SystemUI/src/com/android/systemui/communal/widgets/EditWidgetsActivity.kt
index 337a98a..a5a390d 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/widgets/EditWidgetsActivity.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/widgets/EditWidgetsActivity.kt
@@ -16,6 +16,7 @@
package com.android.systemui.communal.widgets
+import android.appwidget.AppWidgetManager
import android.content.Intent
import android.content.pm.PackageManager
import android.os.Bundle
@@ -137,6 +138,10 @@
R.dimen.communal_widget_picker_desired_height
)
)
+ putExtra(
+ AppWidgetManager.EXTRA_CATEGORY_FILTER,
+ communalViewModel.getCommunalWidgetCategories
+ )
}
)
} catch (e: Exception) {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 641b967..c6b9952 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -153,7 +153,7 @@
import com.android.systemui.settings.UserTracker;
import com.android.systemui.shade.ShadeController;
import com.android.systemui.shade.ShadeExpansionStateManager;
-import com.android.systemui.shade.ShadeViewController;
+import com.android.systemui.shade.ShadeLockscreenInteractor;
import com.android.systemui.shared.system.QuickStepContract;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.NotificationShadeDepthController;
@@ -3529,14 +3529,14 @@
* @return the View Controller for the Keyguard View this class is mediating.
*/
public KeyguardViewController registerCentralSurfaces(CentralSurfaces centralSurfaces,
- ShadeViewController panelView,
+ ShadeLockscreenInteractor shadeLockscreenInteractor,
@Nullable ShadeExpansionStateManager shadeExpansionStateManager,
BiometricUnlockController biometricUnlockController,
View notificationContainer, KeyguardBypassController bypassController) {
mCentralSurfaces = centralSurfaces;
mKeyguardViewControllerLazy.get().registerCentralSurfaces(
centralSurfaces,
- panelView,
+ shadeLockscreenInteractor,
shadeExpansionStateManager,
biometricUnlockController,
notificationContainer,
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/AodBurnInLayer.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/AodBurnInLayer.kt
index 67a20e5..dc2eeac 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/AodBurnInLayer.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/AodBurnInLayer.kt
@@ -18,9 +18,12 @@
import android.content.Context
import android.view.View
+import android.view.ViewTreeObserver.OnPreDrawListener
import androidx.constraintlayout.helper.widget.Layer
-class AodBurnInLayer(context: Context) : Layer(context) {
+class AodBurnInLayer(
+ context: Context,
+) : Layer(context) {
// For setScale in Layer class, it stores it in mScaleX/Y and directly apply scale to
// referenceViews instead of keeping the value in fields of View class
// when we try to clone ConstraintSet, it will call getScaleX from View class and return 1.0
@@ -28,13 +31,32 @@
// which cause the flicker from AOD to LS
private var _scaleX = 1F
private var _scaleY = 1F
+
// As described for _scaleX and _scaleY, we have similar issue with translation
- private var _translationX = 1F
- private var _translationY = 1F
+ private var _translationX = 0F
+ private var _translationY = 0F
+
+ private val _predrawListener = OnPreDrawListener {
+ super.setScaleX(_scaleX)
+ super.setScaleY(_scaleY)
+ super.setTranslationX(_translationX)
+ super.setTranslationY(_translationY)
+ true
+ }
+
// avoid adding views with same ids
override fun addView(view: View?) {
view?.let { if (it.id !in referencedIds) super.addView(view) }
}
+
+ fun registerListener(rootView: View) {
+ rootView.viewTreeObserver.addOnPreDrawListener(_predrawListener)
+ }
+
+ fun unregisterListener(rootView: View) {
+ rootView.viewTreeObserver.removeOnPreDrawListener(_predrawListener)
+ }
+
override fun setScaleX(scaleX: Float) {
_scaleX = scaleX
super.setScaleX(scaleX)
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/AodBurnInSection.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/AodBurnInSection.kt
index 282c495..98bebd0 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/AodBurnInSection.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/AodBurnInSection.kt
@@ -23,6 +23,7 @@
import androidx.constraintlayout.widget.ConstraintSet
import com.android.systemui.Flags.migrateClocksToBlueprint
import com.android.systemui.keyguard.shared.model.KeyguardSection
+import com.android.systemui.keyguard.ui.view.KeyguardRootView
import com.android.systemui.keyguard.ui.viewmodel.KeyguardClockViewModel
import com.android.systemui.res.R
import javax.inject.Inject
@@ -32,6 +33,7 @@
@Inject
constructor(
private val context: Context,
+ private val rootView: KeyguardRootView,
private val clockViewModel: KeyguardClockViewModel,
) : KeyguardSection() {
private lateinit var burnInLayer: AodBurnInLayer
@@ -46,6 +48,7 @@
burnInLayer =
AodBurnInLayer(context).apply {
id = R.id.burn_in_layer
+ registerListener(rootView)
addView(emptyView)
if (!migrateClocksToBlueprint()) {
val statusView =
@@ -70,6 +73,7 @@
}
override fun removeViews(constraintLayout: ConstraintLayout) {
+ burnInLayer.unregisterListener(rootView)
constraintLayout.removeView(R.id.burn_in_layer)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/ClockSection.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/ClockSection.kt
index 54a7ca4..a22671d 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/ClockSection.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/ClockSection.kt
@@ -205,7 +205,7 @@
fun getDimen(context: Context, name: String): Int {
val res = context.packageManager.getResourcesForApplication(context.packageName)
val id = res.getIdentifier(name, "dimen", context.packageName)
- return res.getDimensionPixelSize(id)
+ return if (id == 0) 0 else res.getDimensionPixelSize(id)
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/transitions/ClockSizeTransition.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/transitions/ClockSizeTransition.kt
index ab0d489..f65f376 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/transitions/ClockSizeTransition.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/transitions/ClockSizeTransition.kt
@@ -34,6 +34,7 @@
import com.android.systemui.keyguard.ui.viewmodel.KeyguardSmartspaceViewModel
import com.android.systemui.res.R
import com.android.systemui.shared.R as sharedR
+import com.google.android.material.math.MathUtils
import kotlin.math.abs
internal fun View.setRect(rect: Rect) =
@@ -59,15 +60,6 @@
override fun captureEndValues(transition: TransitionValues) = captureValues(transition)
override fun captureStartValues(transition: TransitionValues) = captureValues(transition)
override fun getTransitionProperties(): Array<String> = TRANSITION_PROPERTIES
- open fun mutateBounds(
- view: View,
- fromVis: Int,
- toVis: Int,
- fromBounds: Rect,
- toBounds: Rect,
- fromSSBounds: Rect?,
- toSSBounds: Rect?
- ) {}
private fun captureValues(transition: TransitionValues) {
val view = transition.view
@@ -81,6 +73,16 @@
transition.values[SMARTSPACE_BOUNDS] = Rect(ss.left, ss.top, ss.right, ss.bottom)
}
+ open fun mutateBounds(
+ view: View,
+ fromIsVis: Boolean,
+ toIsVis: Boolean,
+ fromBounds: Rect,
+ toBounds: Rect,
+ fromSSBounds: Rect?,
+ toSSBounds: Rect?
+ ) {}
+
override fun createAnimator(
sceenRoot: ViewGroup,
startValues: TransitionValues?,
@@ -88,7 +90,6 @@
): Animator? {
if (startValues == null || endValues == null) return null
- val fromView = startValues.view
var fromVis = startValues.values[PROP_VISIBILITY] as Int
var fromIsVis = fromVis == View.VISIBLE
var fromAlpha = startValues.values[PROP_ALPHA] as Float
@@ -111,7 +112,7 @@
fromVis = View.INVISIBLE
}
- mutateBounds(toView, fromVis, toVis, fromBounds, toBounds, fromSSBounds, toSSBounds)
+ mutateBounds(toView, fromIsVis, toIsVis, fromBounds, toBounds, fromSSBounds, toSSBounds)
if (fromIsVis == toIsVis && fromBounds.equals(toBounds)) {
if (DEBUG) {
Log.w(
@@ -127,7 +128,7 @@
val sendToBack = fromIsVis && !toIsVis
fun lerp(start: Int, end: Int, fract: Float): Int =
- (start * (1f - fract) + end * fract).toInt()
+ MathUtils.lerp(start.toFloat(), end.toFloat(), fract).toInt()
fun computeBounds(fract: Float): Rect =
Rect(
lerp(fromBounds.left, toBounds.left, fract),
@@ -136,9 +137,14 @@
lerp(fromBounds.bottom, toBounds.bottom, fract)
)
- fun assignAnimValues(src: String, alpha: Float, fract: Float, vis: Int? = null) {
+ fun assignAnimValues(src: String, fract: Float, vis: Int? = null) {
val bounds = computeBounds(fract)
- if (DEBUG) Log.i(TAG, "$src: $toView; alpha=$alpha; vis=$vis; bounds=$bounds;")
+ val alpha = MathUtils.lerp(fromAlpha, toAlpha, fract)
+ if (DEBUG)
+ Log.i(
+ TAG,
+ "$src: $toView; fract=$fract; alpha=$alpha; vis=$vis; bounds=$bounds;"
+ )
toView.setVisibility(vis ?: View.VISIBLE)
toView.setAlpha(alpha)
toView.setRect(bounds)
@@ -154,12 +160,12 @@
)
}
- return ValueAnimator.ofFloat(fromAlpha, toAlpha).also { anim ->
+ return ValueAnimator.ofFloat(0f, 1f).also { anim ->
// We enforce the animation parameters on the target view every frame using a
// predraw listener. This is suboptimal but prevents issues with layout passes
// overwriting the animation for individual frames.
val predrawCallback = OnPreDrawListener {
- assignAnimValues("predraw", anim.animatedValue as Float, anim.animatedFraction)
+ assignAnimValues("predraw", anim.animatedFraction)
return@OnPreDrawListener true
}
@@ -169,16 +175,18 @@
anim.addListener(
object : AnimatorListenerAdapter() {
override fun onAnimationStart(anim: Animator) {
- assignAnimValues("start", fromAlpha, 0f)
+ assignAnimValues("start", 0f, fromVis)
}
override fun onAnimationEnd(anim: Animator) {
- assignAnimValues("end", toAlpha, 1f, toVis)
+ assignAnimValues("end", 1f, toVis)
if (sendToBack) toView.translationZ = 0f
toView.viewTreeObserver.removeOnPreDrawListener(predrawCallback)
}
}
)
+
+ assignAnimValues("init", 0f, fromVis)
toView.viewTreeObserver.addOnPreDrawListener(predrawCallback)
}
}
@@ -216,13 +224,16 @@
override fun mutateBounds(
view: View,
- fromVis: Int,
- toVis: Int,
+ fromIsVis: Boolean,
+ toIsVis: Boolean,
fromBounds: Rect,
toBounds: Rect,
fromSSBounds: Rect?,
toSSBounds: Rect?
) {
+ // Move normally if clock is not changing visibility
+ if (fromIsVis == toIsVis) return
+
fromBounds.left = toBounds.left
fromBounds.right = toBounds.right
if (viewModel.useLargeClock) {
@@ -271,13 +282,16 @@
override fun mutateBounds(
view: View,
- fromVis: Int,
- toVis: Int,
+ fromIsVis: Boolean,
+ toIsVis: Boolean,
fromBounds: Rect,
toBounds: Rect,
fromSSBounds: Rect?,
toSSBounds: Rect?
) {
+ // Move normally if clock is not changing visibility
+ if (fromIsVis == toIsVis) return
+
toBounds.left = fromBounds.left
toBounds.right = fromBounds.right
if (!viewModel.useLargeClock) {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/transitions/DefaultClockSteppingTransition.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/transitions/DefaultClockSteppingTransition.kt
index 60ab40c..f601155 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/transitions/DefaultClockSteppingTransition.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/transitions/DefaultClockSteppingTransition.kt
@@ -78,8 +78,8 @@
}
companion object {
- private const val PROP_BOUNDS_LEFT = "splitShadeTransitionAdapter:boundsLeft"
- private const val PROP_X_IN_WINDOW = "splitShadeTransitionAdapter:xInWindow"
+ private const val PROP_BOUNDS_LEFT = "DefaultClockSteppingTransition:boundsLeft"
+ private const val PROP_X_IN_WINDOW = "DefaultClockSteppingTransition:xInWindow"
private val TRANSITION_PROPERTIES = arrayOf(PROP_BOUNDS_LEFT, PROP_X_IN_WINDOW)
private const val KEYGUARD_STATUS_VIEW_CUSTOM_CLOCK_MOVE_DURATION_MS = 1000L
}
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
index 9a03393..95d9bc4 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
@@ -122,6 +122,7 @@
import com.android.systemui.dagger.qualifiers.DisplayId;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.deviceentry.domain.interactor.DeviceEntryFaceAuthInteractor;
+import com.android.systemui.deviceentry.shared.DeviceEntryUdfpsRefactor;
import com.android.systemui.doze.DozeLog;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.dump.DumpsysTableLogger;
@@ -906,7 +907,6 @@
mKeyguardBypassController = bypassController;
mUpdateMonitor = keyguardUpdateMonitor;
mLockscreenShadeTransitionController = lockscreenShadeTransitionController;
- lockscreenShadeTransitionController.setShadeViewController(this);
shadeTransitionController.setShadeViewController(this);
dynamicPrivacyController.addListener(this::onDynamicPrivacyChanged);
quickSettingsController.setExpansionHeightListener(this::onQsSetExpansionHeightCalled);
@@ -1826,7 +1826,14 @@
/** Returns space between top of lock icon and bottom of NotificationStackScrollLayout. */
private float getLockIconPadding() {
float lockIconPadding = 0f;
- if (mLockIconViewController.getTop() != 0f) {
+ if (DeviceEntryUdfpsRefactor.isEnabled()) {
+ View deviceEntryIconView = mKeyguardViewConfigurator.getKeyguardRootView()
+ .findViewById(R.id.device_entry_icon_view);
+ if (deviceEntryIconView != null) {
+ lockIconPadding = mNotificationStackScrollLayoutController.getBottom()
+ - deviceEntryIconView.getTop();
+ }
+ } else if (mLockIconViewController.getTop() != 0f) {
lockIconPadding = mNotificationStackScrollLayoutController.getBottom()
- mLockIconViewController.getTop();
}
@@ -4156,8 +4163,7 @@
mFixedDuration = NO_FIXED_DURATION;
}
- @Override
- public boolean postToView(Runnable action) {
+ boolean postToView(Runnable action) {
return mView.post(action);
}
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeControllerImpl.java b/packages/SystemUI/src/com/android/systemui/shade/ShadeControllerImpl.java
index e8d9c35..ea41912 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ShadeControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeControllerImpl.java
@@ -66,7 +66,7 @@
private final StatusBarWindowController mStatusBarWindowController;
private final DeviceProvisionedController mDeviceProvisionedController;
- private final Lazy<ShadeViewController> mShadeViewControllerLazy;
+ private final Lazy<NotificationPanelViewController> mNpvc;
private final Lazy<AssistManager> mAssistManagerLazy;
private final Lazy<NotificationGutsManager> mGutsManager;
@@ -89,7 +89,7 @@
DeviceProvisionedController deviceProvisionedController,
NotificationShadeWindowController notificationShadeWindowController,
WindowManager windowManager,
- Lazy<ShadeViewController> shadeViewControllerLazy,
+ Lazy<NotificationPanelViewController> shadeViewControllerLazy,
Lazy<AssistManager> assistManagerLazy,
Lazy<NotificationGutsManager> gutsManager
) {
@@ -101,7 +101,7 @@
mCommandQueue = commandQueue;
mMainExecutor = mainExecutor;
mWindowRootViewVisibilityInteractor = windowRootViewVisibilityInteractor;
- mShadeViewControllerLazy = shadeViewControllerLazy;
+ mNpvc = shadeViewControllerLazy;
mStatusBarStateController = statusBarStateController;
mStatusBarWindowController = statusBarWindowController;
mDeviceProvisionedController = deviceProvisionedController;
@@ -122,7 +122,7 @@
public void instantExpandShade() {
// Make our window larger and the panel expanded.
makeExpandedVisible(true /* force */);
- getShadeViewController().expand(false /* animate */);
+ getNpvc().expand(false /* animate */);
getCommandQueue().recomputeDisableFlags(mDisplayId, false /* animate */);
}
@@ -134,29 +134,29 @@
return;
}
if (getNotificationShadeWindowView() != null
- && getShadeViewController().canBeCollapsed()
+ && getNpvc().canBeCollapsed()
&& (flags & CommandQueue.FLAG_EXCLUDE_NOTIFICATION_PANEL) == 0) {
// release focus immediately to kick off focus change transition
mNotificationShadeWindowController.setNotificationShadeFocusable(false);
mNotificationShadeWindowViewController.cancelExpandHelper();
- getShadeViewController().collapse(true, delayed, speedUpFactor);
+ getNpvc().collapse(true, delayed, speedUpFactor);
}
}
@Override
protected void expandToNotifications() {
- getShadeViewController().expandToNotifications();
+ getNpvc().expandToNotifications();
}
@Override
protected void expandToQs() {
- getShadeViewController().expandToQs();
+ getNpvc().expandToQs();
}
@Override
public boolean closeShadeIfOpen() {
- if (!getShadeViewController().isFullyCollapsed()) {
+ if (!getNpvc().isFullyCollapsed()) {
getCommandQueue().animateCollapsePanels(
CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL, true /* force */);
notifyVisibilityChanged(false);
@@ -167,12 +167,12 @@
@Override
public boolean isShadeFullyOpen() {
- return getShadeViewController().isShadeFullyExpanded();
+ return getNpvc().isShadeFullyExpanded();
}
@Override
public boolean isExpandingOrCollapsing() {
- return getShadeViewController().isExpandingOrCollapsing();
+ return getNpvc().isExpandingOrCollapsing();
}
@Override
public void postAnimateCollapseShade() {
@@ -191,13 +191,13 @@
@Override
public void postOnShadeExpanded(Runnable executable) {
- getShadeViewController().addOnGlobalLayoutListener(
+ getNpvc().addOnGlobalLayoutListener(
new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
if (getNotificationShadeWindowView().isVisibleToUser()) {
- getShadeViewController().removeOnGlobalLayoutListener(this);
- getShadeViewController().postToView(executable);
+ getNpvc().removeOnGlobalLayoutListener(this);
+ getNpvc().postToView(executable);
}
}
});
@@ -209,7 +209,7 @@
}
private boolean collapseShadeInternal() {
- if (!getShadeViewController().isFullyCollapsed()) {
+ if (!getNpvc().isFullyCollapsed()) {
// close the shade if it was open
animateCollapseShadeForcedDelayed();
notifyVisibilityChanged(false);
@@ -237,10 +237,10 @@
@Override
public void cancelExpansionAndCollapseShade() {
- if (getShadeViewController().isTracking()) {
+ if (getNpvc().isTracking()) {
mNotificationShadeWindowViewController.cancelCurrentTouch();
}
- if (getShadeViewController().isPanelExpanded()
+ if (getNpvc().isPanelExpanded()
&& mStatusBarStateController.getState() == StatusBarState.SHADE) {
animateCollapseShade();
}
@@ -266,7 +266,7 @@
@Override
public void instantCollapseShade() {
- getShadeViewController().instantCollapse();
+ getNpvc().instantCollapse();
runPostCollapseActions();
}
@@ -297,7 +297,7 @@
}
// Ensure the panel is fully collapsed (just in case; bug 6765842, 7260868)
- getShadeViewController().collapse(false, false, 1.0f);
+ getNpvc().collapse(false, false, 1.0f);
mExpandedVisible = false;
notifyVisibilityChanged(false);
@@ -319,7 +319,7 @@
notifyExpandedVisibleChanged(false);
getCommandQueue().recomputeDisableFlags(
mDisplayId,
- getShadeViewController().shouldHideStatusBarIconsWhenExpanded());
+ getNpvc().shouldHideStatusBarIconsWhenExpanded());
// Trimming will happen later if Keyguard is showing - doing it here might cause a jank in
// the bouncer appear animation.
@@ -368,15 +368,15 @@
return mNotificationShadeWindowViewController.getView();
}
- private ShadeViewController getShadeViewController() {
- return mShadeViewControllerLazy.get();
+ private NotificationPanelViewController getNpvc() {
+ return mNpvc.get();
}
@Override
public void start() {
super.start();
- getShadeViewController().setTrackingStartedListener(this::runPostCollapseActions);
- getShadeViewController().setOpenCloseListener(
+ getNpvc().setTrackingStartedListener(this::runPostCollapseActions);
+ getNpvc().setOpenCloseListener(
new OpenCloseListener() {
@Override
public void onClosingFinished() {
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeEmptyImplModule.kt b/packages/SystemUI/src/com/android/systemui/shade/ShadeEmptyImplModule.kt
index f89a9c70..d393f0d 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ShadeEmptyImplModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeEmptyImplModule.kt
@@ -40,6 +40,12 @@
@Binds
@SysUISingleton
+ abstract fun bindsShadeLockscreenInteractor(
+ slsi: ShadeViewControllerEmptyImpl
+ ): ShadeLockscreenInteractor
+
+ @Binds
+ @SysUISingleton
abstract fun bindsShadeController(sc: ShadeControllerEmptyImpl): ShadeController
@Binds
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeLockscreenInteractor.kt b/packages/SystemUI/src/com/android/systemui/shade/ShadeLockscreenInteractor.kt
new file mode 100644
index 0000000..a9ba6f9
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeLockscreenInteractor.kt
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.systemui.shade
+
+/** Allows the lockscreen to control the shade. */
+interface ShadeLockscreenInteractor {
+
+ /**
+ * Expand shade so that notifications are visible. Non-split shade: just expanding shade or
+ * collapsing QS when they're expanded. Split shade: only expanding shade, notifications are
+ * always visible
+ *
+ * Called when `adb shell cmd statusbar expand-notifications` is executed.
+ */
+ @Deprecated("Use ShadeInteractor instead") fun expandToNotifications()
+
+ /** Returns whether the shade is expanding or collapsing itself or quick settings. */
+ val isExpandingOrCollapsing: Boolean
+
+ /**
+ * Returns whether the shade height is greater than zero (i.e. partially or fully expanded),
+ * there is a HUN, the shade is animating, or the shade is instantly expanding.
+ */
+ @Deprecated("Use ShadeInteractor instead") val isExpanded: Boolean
+
+ /** Called before animating Keyguard dismissal, i.e. the animation dismissing the bouncer. */
+ fun startBouncerPreHideAnimation()
+
+ /** Called once every minute while dozing. */
+ fun dozeTimeTick()
+
+ /**
+ * Do not let the user drag the shade up and down for the current touch session. This is
+ * necessary to avoid shade expansion while/after the bouncer is dismissed.
+ */
+ @Deprecated("Not supported by scenes") fun blockExpansionForCurrentTouch()
+
+ /** Close guts, notification menus, and QS. Set scroll and overscroll to 0. */
+ fun resetViews(animate: Boolean)
+
+ /** Sets whether the screen has temporarily woken up to display notifications. */
+ @Deprecated("Not supported by scenes") fun setPulsing(pulsing: Boolean)
+
+ /** Animate to expanded shade after a delay in ms. Used for lockscreen to shade transition. */
+ fun transitionToExpandedShade(delay: Long)
+
+ /** @see ViewGroupFadeHelper.reset */
+ @Deprecated("Not supported by scenes") fun resetViewGroupFade()
+
+ /**
+ * Set the alpha and translationY of the keyguard elements which only show on the lockscreen,
+ * but not in shade locked / shade. This is used when dragging down to the full shade.
+ */
+ @Deprecated("Not supported by scenes")
+ fun setKeyguardTransitionProgress(keyguardAlpha: Float, keyguardTranslationY: Int)
+
+ /** Sets the overstretch amount in raw pixels when dragging down. */
+ @Deprecated("Not supported by scenes") fun setOverStretchAmount(amount: Float)
+
+ /**
+ * Sets the alpha value to be set on the keyguard status bar.
+ *
+ * @param alpha value between 0 and 1. -1 if the value is to be reset.
+ */
+ @Deprecated("TODO(b/325072511) delete this") fun setKeyguardStatusBarAlpha(alpha: Float)
+}
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeModule.kt b/packages/SystemUI/src/com/android/systemui/shade/ShadeModule.kt
index e4d5d22..86fdcee 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ShadeModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeModule.kt
@@ -30,6 +30,7 @@
import com.android.systemui.shade.domain.interactor.ShadeInteractorImpl
import com.android.systemui.shade.domain.interactor.ShadeInteractorLegacyImpl
import com.android.systemui.shade.domain.interactor.ShadeInteractorSceneContainerImpl
+import com.android.systemui.shade.domain.interactor.ShadeLockscreenInteractorImpl
import dagger.Binds
import dagger.Module
import dagger.Provides
@@ -94,6 +95,20 @@
sceneContainerOff.get()
}
}
+
+ @Provides
+ @SysUISingleton
+ fun provideShadeLockscreenInteractor(
+ sceneContainerFlags: SceneContainerFlags,
+ sceneContainerOn: Provider<ShadeLockscreenInteractorImpl>,
+ sceneContainerOff: Provider<NotificationPanelViewController>
+ ): ShadeLockscreenInteractor {
+ return if (sceneContainerFlags.isEnabled()) {
+ sceneContainerOn.get()
+ } else {
+ sceneContainerOff.get()
+ }
+ }
}
@Binds
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeSurface.kt b/packages/SystemUI/src/com/android/systemui/shade/ShadeSurface.kt
index 0befb61..941c6f3 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ShadeSurface.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeSurface.kt
@@ -26,7 +26,7 @@
* this class. If any method in this class is needed outside of CentralSurfacesImpl, it must be
* pulled up into ShadeViewController.
*/
-interface ShadeSurface : ShadeViewController, ShadeBackActionInteractor {
+interface ShadeSurface : ShadeViewController, ShadeBackActionInteractor, ShadeLockscreenInteractor {
/** Initialize objects instead of injecting to avoid circular dependencies. */
fun initDependencies(
centralSurfaces: CentralSurfaces,
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeViewController.kt b/packages/SystemUI/src/com/android/systemui/shade/ShadeViewController.kt
index 74035bd..44c6a82 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ShadeViewController.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeViewController.kt
@@ -37,25 +37,10 @@
/** Animates to an expanded shade with QS expanded. If the shade starts expanded, expands QS. */
fun expandToQs()
- /**
- * Expand shade so that notifications are visible. Non-split shade: just expanding shade or
- * collapsing QS when they're expanded. Split shade: only expanding shade, notifications are
- * always visible
- *
- * Called when `adb shell cmd statusbar expand-notifications` is executed.
- */
- fun expandToNotifications()
-
/** Returns whether the shade is expanding or collapsing itself or quick settings. */
val isExpandingOrCollapsing: Boolean
/**
- * Returns whether the shade height is greater than zero (i.e. partially or fully expanded),
- * there is a HUN, the shade is animating, or the shade is instantly expanding.
- */
- val isExpanded: Boolean
-
- /**
* Returns whether the shade height is greater than zero or the shade is expecting a synthesized
* down event.
*/
@@ -101,12 +86,6 @@
/** Returns whether status bar icons should be hidden when the shade is expanded. */
fun shouldHideStatusBarIconsWhenExpanded(): Boolean
- /**
- * Do not let the user drag the shade up and down for the current touch session. This is
- * necessary to avoid shade expansion while/after the bouncer is dismissed.
- */
- fun blockExpansionForCurrentTouch()
-
/** Sets a listener to be notified when touch tracking begins. */
fun setTrackingStartedListener(trackingStartedListener: TrackingStartedListener)
@@ -120,15 +99,6 @@
/** If the latency tracker is enabled, begins tracking expand latency. */
fun startExpandLatencyTracking()
- /** Called before animating Keyguard dismissal, i.e. the animation dismissing the bouncer. */
- fun startBouncerPreHideAnimation()
-
- /** Called once every minute while dozing. */
- fun dozeTimeTick()
-
- /** Close guts, notification menus, and QS. Set scroll and overscroll to 0. */
- fun resetViews(animate: Boolean)
-
/** Returns the StatusBarState. */
val barState: Int
@@ -145,9 +115,6 @@
*/
fun setAlphaChangeAnimationEndAction(r: Runnable)
- /** Sets whether the screen has temporarily woken up to display notifications. */
- fun setPulsing(pulsing: Boolean)
-
/** Sets Qs ScrimEnabled and updates QS state. */
fun setQsScrimEnabled(qsScrimEnabled: Boolean)
@@ -166,32 +133,6 @@
/** Removes a global layout listener. */
fun removeOnGlobalLayoutListener(listener: ViewTreeObserver.OnGlobalLayoutListener)
- /** Posts the given runnable to the view. */
- fun postToView(action: Runnable): Boolean
-
- // ******* Begin Keyguard Section *********
- /** Animate to expanded shade after a delay in ms. Used for lockscreen to shade transition. */
- fun transitionToExpandedShade(delay: Long)
-
- /** @see ViewGroupFadeHelper.reset */
- fun resetViewGroupFade()
-
- /**
- * Set the alpha and translationY of the keyguard elements which only show on the lockscreen,
- * but not in shade locked / shade. This is used when dragging down to the full shade.
- */
- fun setKeyguardTransitionProgress(keyguardAlpha: Float, keyguardTranslationY: Int)
-
- /** Sets the overstretch amount in raw pixels when dragging down. */
- fun setOverStretchAmount(amount: Float)
-
- /**
- * Sets the alpha value to be set on the keyguard status bar.
- *
- * @param alpha value between 0 and 1. -1 if the value is to be reset.
- */
- fun setKeyguardStatusBarAlpha(alpha: Float)
-
/**
* Reconfigures the shade to show the AOD UI (clock, smartspace, etc). This is called by the
* screen off animation controller in order to animate in AOD without "actually" fully switching
@@ -251,8 +192,6 @@
*/
fun performHapticFeedback(constant: Int)
- // ******* End Keyguard Section *********
-
/** Returns the ShadeHeadsUpTracker. */
val shadeHeadsUpTracker: ShadeHeadsUpTracker
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeViewControllerEmptyImpl.kt b/packages/SystemUI/src/com/android/systemui/shade/ShadeViewControllerEmptyImpl.kt
index 5d966ac..7a181f1 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ShadeViewControllerEmptyImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeViewControllerEmptyImpl.kt
@@ -27,7 +27,7 @@
/** Empty implementation of ShadeViewController for variants with no shade. */
class ShadeViewControllerEmptyImpl @Inject constructor() :
- ShadeViewController, ShadeBackActionInteractor {
+ ShadeViewController, ShadeBackActionInteractor, ShadeLockscreenInteractor {
override fun expand(animate: Boolean) {}
override fun expandToQs() {}
override fun expandToNotifications() {}
@@ -70,9 +70,6 @@
override fun updateTouchableRegion() {}
override fun addOnGlobalLayoutListener(listener: ViewTreeObserver.OnGlobalLayoutListener) {}
override fun removeOnGlobalLayoutListener(listener: ViewTreeObserver.OnGlobalLayoutListener) {}
- override fun postToView(action: Runnable): Boolean {
- return false
- }
override fun transitionToExpandedShade(delay: Long) {}
override fun resetViewGroupFade() {}
diff --git a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeLockscreenInteractorImpl.kt b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeLockscreenInteractorImpl.kt
new file mode 100644
index 0000000..21a782e
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeLockscreenInteractorImpl.kt
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.shade.domain.interactor
+
+import com.android.keyguard.LockIconViewController
+import com.android.systemui.dagger.qualifiers.Background
+import com.android.systemui.scene.domain.interactor.SceneInteractor
+import com.android.systemui.scene.shared.model.SceneKey
+import com.android.systemui.shade.ShadeLockscreenInteractor
+import javax.inject.Inject
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.delay
+import kotlinx.coroutines.launch
+
+class ShadeLockscreenInteractorImpl
+@Inject
+constructor(
+ @Background private val scope: CoroutineScope,
+ shadeInteractor: ShadeInteractor,
+ private val sceneInteractor: SceneInteractor,
+ private val lockIconViewController: LockIconViewController,
+) : ShadeLockscreenInteractor {
+ override fun expandToNotifications() {
+ changeToShadeScene()
+ }
+
+ override val isExpandingOrCollapsing = shadeInteractor.isUserInteracting.value
+
+ override val isExpanded = shadeInteractor.isAnyExpanded.value
+
+ override fun startBouncerPreHideAnimation() {
+ // TODO("b/324280998") Implement replacement or delete
+ }
+
+ override fun dozeTimeTick() {
+ lockIconViewController.dozeTimeTick()
+ }
+
+ override fun blockExpansionForCurrentTouch() {
+ // TODO("b/324280998") Implement replacement or delete
+ }
+
+ override fun resetViews(animate: Boolean) {
+ // The existing comment to the only call to this claims it only calls it to collapse QS
+ changeToShadeScene()
+ }
+
+ override fun setPulsing(pulsing: Boolean) {
+ // Now handled elsewhere. Do nothing.
+ }
+ override fun transitionToExpandedShade(delay: Long) {
+ scope.launch {
+ delay(delay)
+ changeToShadeScene()
+ }
+ }
+
+ override fun resetViewGroupFade() {
+ // Now handled elsewhere. Do nothing.
+ }
+
+ override fun setKeyguardTransitionProgress(keyguardAlpha: Float, keyguardTranslationY: Int) {
+ // Now handled elsewhere. Do nothing.
+ }
+
+ override fun setOverStretchAmount(amount: Float) {
+ // Now handled elsewhere. Do nothing.
+ }
+
+ override fun setKeyguardStatusBarAlpha(alpha: Float) {
+ // TODO(b/325072511) delete this
+ }
+
+ private fun changeToShadeScene() {
+ sceneInteractor.changeScene(
+ SceneKey.Shade,
+ "ShadeLockscreenInteractorImpl.expandToNotifications",
+ )
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeKeyguardTransitionController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeKeyguardTransitionController.kt
index 62c9980..0b470c1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeKeyguardTransitionController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeKeyguardTransitionController.kt
@@ -3,10 +3,10 @@
import android.content.Context
import android.util.IndentingPrintWriter
import android.util.MathUtils
-import com.android.systemui.res.R
import com.android.systemui.dump.DumpManager
import com.android.systemui.media.controls.ui.MediaHierarchyManager
-import com.android.systemui.shade.ShadeViewController
+import com.android.systemui.res.R
+import com.android.systemui.shade.ShadeLockscreenInteractor
import com.android.systemui.statusbar.policy.ConfigurationController
import com.android.systemui.statusbar.policy.SplitShadeStateController
import dagger.assisted.Assisted
@@ -18,7 +18,7 @@
@AssistedInject
constructor(
private val mediaHierarchyManager: MediaHierarchyManager,
- @Assisted private val notificationPanelController: ShadeViewController,
+ @Assisted private val shadeLockscreenInteractor: ShadeLockscreenInteractor,
context: Context,
configurationController: ConfigurationController,
dumpManager: DumpManager,
@@ -72,10 +72,10 @@
alphaProgress = MathUtils.saturate(dragDownAmount / alphaTransitionDistance)
alpha = 1f - alphaProgress
translationY = calculateKeyguardTranslationY(dragDownAmount)
- notificationPanelController.setKeyguardTransitionProgress(alpha, translationY)
+ shadeLockscreenInteractor.setKeyguardTransitionProgress(alpha, translationY)
statusBarAlpha = if (useSplitShade) alpha else -1f
- notificationPanelController.setKeyguardStatusBarAlpha(statusBarAlpha)
+ shadeLockscreenInteractor.setKeyguardStatusBarAlpha(statusBarAlpha)
}
private fun calculateKeyguardTranslationY(dragDownAmount: Float): Int {
@@ -117,7 +117,7 @@
@AssistedFactory
fun interface Factory {
fun create(
- notificationPanelController: ShadeViewController
+ shadeLockscreenInteractor: ShadeLockscreenInteractor
): LockscreenShadeKeyguardTransitionController
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt
index 2e71103..1dbd87e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt
@@ -31,9 +31,8 @@
import com.android.systemui.plugins.FalsingManager
import com.android.systemui.plugins.qs.QS
import com.android.systemui.plugins.statusbar.StatusBarStateController
-import com.android.systemui.power.domain.interactor.PowerInteractor
import com.android.systemui.res.R
-import com.android.systemui.shade.ShadeViewController
+import com.android.systemui.shade.ShadeLockscreenInteractor
import com.android.systemui.shade.data.repository.ShadeRepository
import com.android.systemui.shade.domain.interactor.ShadeInteractor
import com.android.systemui.statusbar.notification.collection.NotificationEntry
@@ -47,6 +46,7 @@
import com.android.systemui.statusbar.policy.ConfigurationController
import com.android.systemui.statusbar.policy.SplitShadeStateController
import com.android.wm.shell.animation.Interpolators
+import dagger.Lazy
import java.io.PrintWriter
import javax.inject.Inject
@@ -81,9 +81,9 @@
qsTransitionControllerFactory: LockscreenShadeQsTransitionController.Factory,
private val shadeRepository: ShadeRepository,
private val shadeInteractor: ShadeInteractor,
- private val powerInteractor: PowerInteractor,
private val splitShadeStateController: SplitShadeStateController,
- private val naturalScrollingSettingObserver: NaturalScrollingSettingObserver,
+ private val shadeLockscreenInteractorLazy: Lazy<ShadeLockscreenInteractor>,
+ naturalScrollingSettingObserver: NaturalScrollingSettingObserver,
) : Dumpable {
private var pulseHeight: Float = 0f
@@ -92,7 +92,6 @@
private set
private var useSplitShade: Boolean = false
private lateinit var nsslController: NotificationStackScrollLayoutController
- lateinit var shadeViewController: ShadeViewController
lateinit var centralSurfaces: CentralSurfaces
lateinit var qS: QS
@@ -165,7 +164,6 @@
val touchHelper =
DragDownHelper(
falsingManager,
- falsingCollector,
this,
naturalScrollingSettingObserver,
shadeRepository,
@@ -181,7 +179,7 @@
}
private val keyguardTransitionController by lazy {
- keyguardTransitionControllerFactory.create(shadeViewController)
+ keyguardTransitionControllerFactory.create(shadeLockscreenInteractorLazy.get())
}
private val qsTransitionController = qsTransitionControllerFactory.create { qS }
@@ -320,7 +318,7 @@
true /* drag down is always an open */
)
}
- shadeViewController.transitionToExpandedShade(delay)
+ shadeLockscreenInteractorLazy.get().transitionToExpandedShade(delay)
callbacks.forEach {
it.setTransitionToFullShadeAmount(0f, /* animated= */ true, delay)
}
@@ -538,7 +536,7 @@
} else {
// Let's only animate notifications
animationHandler = { delay: Long ->
- shadeViewController.transitionToExpandedShade(delay)
+ shadeLockscreenInteractorLazy.get().transitionToExpandedShade(delay)
}
}
goToLockedShadeInternal(expandedView, animationHandler, cancelAction = null)
@@ -661,7 +659,7 @@
*/
private fun performDefaultGoToFullShadeAnimation(delay: Long) {
logger.logDefaultGoToFullShadeAnimation(delay)
- shadeViewController.transitionToExpandedShade(delay)
+ shadeLockscreenInteractorLazy.get().transitionToExpandedShade(delay)
animateAppear(delay)
}
@@ -686,7 +684,7 @@
} else {
pulseHeight = height
val overflow = nsslController.setPulseHeight(height)
- shadeViewController.setOverStretchAmount(overflow)
+ shadeLockscreenInteractorLazy.get().setOverStretchAmount(overflow)
val transitionHeight = if (keyguardBypassController.bypassEnabled) height else 0.0f
transitionToShadeAmountCommon(transitionHeight)
}
@@ -760,7 +758,6 @@
*/
class DragDownHelper(
private val falsingManager: FalsingManager,
- private val falsingCollector: FalsingCollector,
private val dragDownCallback: LockscreenShadeTransitionController,
private val naturalScrollingSettingObserver: NaturalScrollingSettingObserver,
private val shadeRepository: ShadeRepository,
@@ -852,7 +849,6 @@
if (!isDraggingDown) {
return false
}
- val x = event.x
val y = event.y
when (event.actionMasked) {
MotionEvent.ACTION_MOVE -> {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
index b0fefdd..b772158 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
@@ -982,7 +982,6 @@
this,
mStatusBarKeyguardViewManager,
getNotificationShadeWindowViewController(),
- mShadeSurface,
mAmbientIndicationContainer);
updateLightRevealScrimVisibility();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java
index 45005cb..442e43a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java
@@ -41,7 +41,7 @@
import com.android.systemui.keyguard.WakefulnessLifecycle;
import com.android.systemui.keyguard.domain.interactor.DozeInteractor;
import com.android.systemui.shade.NotificationShadeWindowViewController;
-import com.android.systemui.shade.ShadeViewController;
+import com.android.systemui.shade.ShadeLockscreenInteractor;
import com.android.systemui.statusbar.NotificationShadeWindowController;
import com.android.systemui.statusbar.PulseExpansionHandler;
import com.android.systemui.statusbar.StatusBarState;
@@ -98,7 +98,7 @@
private final AuthController mAuthController;
private final NotificationIconAreaController mNotificationIconAreaController;
private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
- private ShadeViewController mNotificationPanel;
+ private final ShadeLockscreenInteractor mShadeLockscreenInteractor;
private View mAmbientIndicationContainer;
private CentralSurfaces mCentralSurfaces;
private boolean mAlwaysOnSuppressed;
@@ -121,6 +121,7 @@
NotificationWakeUpCoordinator notificationWakeUpCoordinator,
AuthController authController,
NotificationIconAreaController notificationIconAreaController,
+ ShadeLockscreenInteractor shadeLockscreenInteractor,
DozeInteractor dozeInteractor) {
super();
mDozeLog = dozeLog;
@@ -141,6 +142,7 @@
mNotificationWakeUpCoordinator = notificationWakeUpCoordinator;
mAuthController = authController;
mNotificationIconAreaController = notificationIconAreaController;
+ mShadeLockscreenInteractor = shadeLockscreenInteractor;
mHeadsUpManager.addListener(mOnHeadsUpChangedListener);
mDozeInteractor = dozeInteractor;
}
@@ -154,11 +156,9 @@
CentralSurfaces centralSurfaces,
StatusBarKeyguardViewManager statusBarKeyguardViewManager,
NotificationShadeWindowViewController notificationShadeWindowViewController,
- ShadeViewController notificationPanel,
View ambientIndicationContainer) {
mCentralSurfaces = centralSurfaces;
mStatusBarKeyguardViewManager = statusBarKeyguardViewManager;
- mNotificationPanel = notificationPanel;
mNotificationShadeWindowViewController = notificationShadeWindowViewController;
mAmbientIndicationContainer = ambientIndicationContainer;
}
@@ -290,7 +290,7 @@
private void setPulsing(boolean pulsing) {
mStatusBarKeyguardViewManager.setPulsing(pulsing);
- mNotificationPanel.setPulsing(pulsing);
+ mShadeLockscreenInteractor.setPulsing(pulsing);
mStatusBarStateController.setPulsing(pulsing);
mIgnoreTouchWhilePulsing = false;
if (mKeyguardUpdateMonitor != null && passiveAuthInterrupt) {
@@ -329,7 +329,7 @@
@Override
public void dozeTimeTick() {
mDozeInteractor.dozeTimeTick();
- mNotificationPanel.dozeTimeTick();
+ mShadeLockscreenInteractor.dozeTimeTick();
mAuthController.dozeTimeTick();
if (mAmbientIndicationContainer instanceof DozeReceiver) {
((DozeReceiver) mAmbientIndicationContainer).dozeTimeTick();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index 9d70f42..29fd225 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -86,10 +86,9 @@
import com.android.systemui.shade.ShadeExpansionChangeEvent;
import com.android.systemui.shade.ShadeExpansionListener;
import com.android.systemui.shade.ShadeExpansionStateManager;
-import com.android.systemui.shade.ShadeViewController;
+import com.android.systemui.shade.ShadeLockscreenInteractor;
import com.android.systemui.shared.system.QuickStepContract;
import com.android.systemui.shared.system.SysUiStatsLog;
-import com.android.systemui.statusbar.NotificationMediaManager;
import com.android.systemui.statusbar.NotificationShadeWindowController;
import com.android.systemui.statusbar.RemoteInputController;
import com.android.systemui.statusbar.StatusBarState;
@@ -269,7 +268,7 @@
protected LockPatternUtils mLockPatternUtils;
protected ViewMediatorCallback mViewMediatorCallback;
@Nullable protected CentralSurfaces mCentralSurfaces;
- private ShadeViewController mShadeViewController;
+ private ShadeLockscreenInteractor mShadeLockscreenInteractor;
private BiometricUnlockController mBiometricUnlockController;
private boolean mCentralSurfacesRegistered;
@@ -314,7 +313,6 @@
// Dismiss action to be launched when we stop dozing or the keyguard is gone.
private DismissWithActionRequest mPendingWakeupAction;
private final KeyguardStateController mKeyguardStateController;
- private final NotificationMediaManager mMediaManager;
private final SysuiStatusBarStateController mStatusBarStateController;
private final DockManager mDockManager;
private final KeyguardUpdateMonitor mKeyguardUpdateManager;
@@ -363,7 +361,6 @@
DockManager dockManager,
NotificationShadeWindowController notificationShadeWindowController,
KeyguardStateController keyguardStateController,
- NotificationMediaManager notificationMediaManager,
KeyguardMessageAreaController.Factory keyguardMessageAreaFactory,
Optional<SysUIUnfoldComponent> sysUIUnfoldComponent,
Lazy<ShadeController> shadeController,
@@ -391,7 +388,6 @@
mNotificationShadeWindowController = notificationShadeWindowController;
mDreamOverlayStateController = dreamOverlayStateController;
mKeyguardStateController = keyguardStateController;
- mMediaManager = notificationMediaManager;
mKeyguardUpdateManager = keyguardUpdateMonitor;
mStatusBarStateController = sysuiStatusBarStateController;
mDockManager = dockManager;
@@ -422,7 +418,7 @@
@Override
public void registerCentralSurfaces(CentralSurfaces centralSurfaces,
- ShadeViewController shadeViewController,
+ ShadeLockscreenInteractor shadeLockscreenInteractor,
ShadeExpansionStateManager shadeExpansionStateManager,
BiometricUnlockController biometricUnlockController,
View notificationContainer,
@@ -431,7 +427,7 @@
mBiometricUnlockController = biometricUnlockController;
mPrimaryBouncerCallbackInteractor.addBouncerExpansionCallback(mExpansionCallback);
- mShadeViewController = shadeViewController;
+ mShadeLockscreenInteractor = shadeLockscreenInteractor;
if (shadeExpansionStateManager != null) {
ShadeExpansionChangeEvent currentState =
shadeExpansionStateManager.addExpansionListener(this);
@@ -565,8 +561,8 @@
// Avoid having the shade and the bouncer open at the same time over a dream.
final boolean hideBouncerOverDream =
mDreamOverlayStateController.isOverlayActive()
- && (mShadeViewController.isExpanded()
- || mShadeViewController.isExpandingOrCollapsing());
+ && (mShadeLockscreenInteractor.isExpanded()
+ || mShadeLockscreenInteractor.isExpandingOrCollapsing());
final boolean isUserTrackingStarted =
event.getFraction() != EXPANSION_HIDDEN && event.getTracking();
@@ -834,7 +830,7 @@
if (mKeyguardStateController.isShowing() && !bouncerIsAnimatingAway()) {
final boolean isOccluded = mKeyguardStateController.isOccluded();
// Hide quick settings.
- mShadeViewController.resetViews(/* animate= */ !isOccluded);
+ mShadeLockscreenInteractor.resetViews(/* animate= */ !isOccluded);
// Hide bouncer and quick-quick settings.
if (isOccluded && !mDozing) {
mCentralSurfaces.hideKeyguard();
@@ -1008,7 +1004,7 @@
public void startPreHideAnimation(Runnable finishRunnable) {
if (primaryBouncerIsShowing()) {
mPrimaryBouncerInteractor.startDisappearAnimation(finishRunnable);
- mShadeViewController.startBouncerPreHideAnimation();
+ mShadeLockscreenInteractor.startBouncerPreHideAnimation();
// We update the state (which will show the keyguard) only if an animation will run on
// the keyguard. If there is no animation, we wait before updating the state so that we
@@ -1023,12 +1019,12 @@
} else if (finishRunnable != null) {
finishRunnable.run();
}
- mShadeViewController.blockExpansionForCurrentTouch();
+ mShadeLockscreenInteractor.blockExpansionForCurrentTouch();
}
@Override
public void blockPanelExpansionFromCurrentTouch() {
- mShadeViewController.blockExpansionForCurrentTouch();
+ mShadeLockscreenInteractor.blockExpansionForCurrentTouch();
}
@Override
@@ -1125,7 +1121,7 @@
public void onKeyguardFadedAway() {
mNotificationContainer.postDelayed(() -> mNotificationShadeWindowController
.setKeyguardFadingAway(false), 100);
- mShadeViewController.resetViewGroupFade();
+ mShadeLockscreenInteractor.resetViewGroupFade();
mCentralSurfaces.finishKeyguardFadingAway();
mBiometricUnlockController.finishKeyguardFadingAway();
}
@@ -1208,7 +1204,7 @@
if (hideImmediately) {
mStatusBarStateController.setLeaveOpenOnKeyguardHide(false);
} else {
- mShadeViewController.expandToNotifications();
+ mShadeLockscreenInteractor.expandToNotifications();
}
}
return;
diff --git a/packages/SystemUI/src/com/android/systemui/unfold/DisplaySwitchLatencyTracker.kt b/packages/SystemUI/src/com/android/systemui/unfold/DisplaySwitchLatencyTracker.kt
index 4dfd5a1..b3e60e3 100644
--- a/packages/SystemUI/src/com/android/systemui/unfold/DisplaySwitchLatencyTracker.kt
+++ b/packages/SystemUI/src/com/android/systemui/unfold/DisplaySwitchLatencyTracker.kt
@@ -29,25 +29,31 @@
import com.android.systemui.power.domain.interactor.PowerInteractor
import com.android.systemui.power.shared.model.ScreenPowerState
import com.android.systemui.power.shared.model.WakeSleepReason
+import com.android.systemui.power.shared.model.WakefulnessState
import com.android.systemui.shared.system.SysUiStatsLog
+import com.android.systemui.unfold.DisplaySwitchLatencyTracker.DisplaySwitchLatencyEvent
import com.android.systemui.unfold.dagger.UnfoldSingleThreadBg
import com.android.systemui.unfold.domain.interactor.UnfoldTransitionInteractor
import com.android.systemui.util.Compile
import com.android.systemui.util.Utils.isDeviceFoldable
import com.android.systemui.util.animation.data.repository.AnimationStatusRepository
import com.android.systemui.util.kotlin.pairwise
+import com.android.systemui.util.kotlin.race
import com.android.systemui.util.time.SystemClock
import com.android.systemui.util.time.measureTimeMillis
+import java.time.Duration
import java.util.concurrent.Executor
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.TimeoutCancellationException
import kotlinx.coroutines.asCoroutineDispatcher
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.launch
+import kotlinx.coroutines.withTimeout
/**
* [DisplaySwitchLatencyTracker] tracks latency and related fields for display switch of a foldable
@@ -70,6 +76,8 @@
) : CoreStartable {
private val backgroundDispatcher = singleThreadBgExecutor.asCoroutineDispatcher()
+ private val isAodEnabled: Boolean
+ get() = keyguardInteractor.isAodAvailable.value
@OptIn(ExperimentalCoroutinesApi::class)
override fun start() {
@@ -98,8 +106,14 @@
val displaySwitchTimeMs =
measureTimeMillis(systemClock) {
- traceAsync(TAG, "displaySwitch") {
- waitForDisplaySwitch(toFoldableDeviceState)
+ try {
+ withTimeout(SCREEN_EVENT_TIMEOUT) {
+ traceAsync(TAG, "displaySwitch") {
+ waitForDisplaySwitch(toFoldableDeviceState)
+ }
+ }
+ } catch (e: TimeoutCancellationException) {
+ Log.e(TAG, "Wait for display switch timed out")
}
}
@@ -129,19 +143,19 @@
val isTransitionEnabled =
unfoldTransitionInteractor.isAvailable &&
animationStatusRepository.areAnimationsEnabled().first()
- if (shouldWaitForScreenOn(toFoldableDeviceState, isTransitionEnabled)) {
- waitForScreenTurnedOn()
- } else {
+ if (shouldWaitForTransitionStart(toFoldableDeviceState, isTransitionEnabled)) {
traceAsync(TAG, "waitForTransitionStart()") {
unfoldTransitionInteractor.waitForTransitionStart()
}
+ } else {
+ race({ waitForScreenTurnedOn() }, { waitForGoToSleepWithScreenOff() })
}
}
- private fun shouldWaitForScreenOn(
+ private fun shouldWaitForTransitionStart(
toFoldableDeviceState: Int,
isTransitionEnabled: Boolean
- ): Boolean = (toFoldableDeviceState == FOLDABLE_DEVICE_STATE_CLOSED || !isTransitionEnabled)
+ ): Boolean = (toFoldableDeviceState != FOLDABLE_DEVICE_STATE_CLOSED && isTransitionEnabled)
private suspend fun waitForScreenTurnedOn() {
traceAsync(TAG, "waitForScreenTurnedOn()") {
@@ -149,19 +163,30 @@
}
}
+ private suspend fun waitForGoToSleepWithScreenOff() {
+ traceAsync(TAG, "waitForGoToSleepWithScreenOff()") {
+ powerInteractor.detailedWakefulness
+ .filter { it.internalWakefulnessState == WakefulnessState.ASLEEP && !isAodEnabled }
+ .first()
+ }
+ }
+
private fun getCurrentState(): Int =
when {
isStateAod() -> SysUiStatsLog.DISPLAY_SWITCH_LATENCY_TRACKED__TO_STATE__AOD
+ isStateScreenOff() -> SysUiStatsLog.DISPLAY_SWITCH_LATENCY_TRACKED__TO_STATE__SCREEN_OFF
else -> SysUiStatsLog.DISPLAY_SWITCH_LATENCY_TRACKED__TO_STATE__UNKNOWN
}
- private fun isStateAod(): Boolean {
+ private fun isStateAod(): Boolean = (isAsleepDueToFold() && isAodEnabled)
+
+ private fun isStateScreenOff(): Boolean = (isAsleepDueToFold() && !isAodEnabled)
+
+ private fun isAsleepDueToFold(): Boolean {
val lastWakefulnessEvent = powerInteractor.detailedWakefulness.value
- val isAodEnabled = keyguardInteractor.isAodAvailable.value
return (lastWakefulnessEvent.isAsleep() &&
- (lastWakefulnessEvent.lastSleepReason == WakeSleepReason.FOLD) &&
- isAodEnabled)
+ (lastWakefulnessEvent.lastSleepReason == WakeSleepReason.FOLD))
}
private inline fun log(msg: () -> String) {
@@ -232,6 +257,7 @@
private const val VALUE_UNKNOWN = -1
private const val TAG = "DisplaySwitchLatency"
private val DEBUG = Compile.IS_DEBUG && Log.isLoggable(TAG, Log.VERBOSE)
+ private val SCREEN_EVENT_TIMEOUT = Duration.ofMillis(15000).toMillis()
private const val FOLDABLE_DEVICE_STATE_UNKNOWN =
SysUiStatsLog.DISPLAY_SWITCH_LATENCY_TRACKED__FROM_FOLDABLE_DEVICE_STATE__STATE_UNKNOWN
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPinViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPinViewControllerTest.kt
index d048cbe..36d4d12 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPinViewControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPinViewControllerTest.kt
@@ -18,6 +18,7 @@
import android.testing.TestableLooper
import android.view.View
+import android.view.ViewGroup
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.constraintlayout.widget.ConstraintSet
import androidx.test.ext.junit.runners.AndroidJUnit4
@@ -59,7 +60,9 @@
@SmallTest
@RunWith(AndroidJUnit4::class)
-@TestableLooper.RunWithLooper
+// collectFlow in KeyguardPinBasedInputViewController.onViewAttached calls JavaAdapter.CollectFlow,
+// which calls View.onRepeatWhenAttached, which requires being run on main thread.
+@TestableLooper.RunWithLooper(setAsMainLooper = true)
class KeyguardPinViewControllerTest : SysuiTestCase() {
private lateinit var objectKeyguardPINView: KeyguardPINView
@@ -90,6 +93,8 @@
@Mock private val mEmergencyButtonController: EmergencyButtonController? = null
private val falsingCollector: FalsingCollector = FalsingCollectorFake()
private val keyguardKeyboardInteractor = KeyguardKeyboardInteractor(FakeKeyboardRepository())
+ private val passwordTextViewLayoutParams =
+ ViewGroup.LayoutParams(/* width= */ 0, /* height= */ 0)
@Mock lateinit var postureController: DevicePostureController
@Mock lateinit var mSelectedUserInteractor: SelectedUserInteractor
@@ -104,11 +109,9 @@
@Before
fun setup() {
MockitoAnnotations.initMocks(this)
- Mockito.`when`(mockKeyguardPinView.requireViewById<View>(R.id.bouncer_message_area))
+ `when`(mockKeyguardPinView.requireViewById<View>(R.id.bouncer_message_area))
.thenReturn(keyguardMessageArea)
- Mockito.`when`(
- keyguardMessageAreaControllerFactory.create(any(KeyguardMessageArea::class.java))
- )
+ `when`(keyguardMessageAreaControllerFactory.create(any(KeyguardMessageArea::class.java)))
.thenReturn(keyguardMessageAreaController)
`when`(mockKeyguardPinView.passwordTextViewId).thenReturn(R.id.pinEntry)
`when`(mockKeyguardPinView.findViewById<PasswordTextView>(R.id.pinEntry))
@@ -121,6 +124,7 @@
`when`(mockKeyguardPinView.buttons).thenReturn(arrayOf())
`when`(lockPatternUtils.getPinLength(anyInt())).thenReturn(6)
`when`(featureFlags.isEnabled(Flags.LOCKSCREEN_ENABLE_LANDSCAPE)).thenReturn(false)
+ `when`(passwordTextView.layoutParams).thenReturn(passwordTextViewLayoutParams)
objectKeyguardPINView =
View.inflate(mContext, R.layout.keyguard_pin_view, null)
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSimPinViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSimPinViewControllerTest.kt
index 4a2554e..9b5364e 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSimPinViewControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSimPinViewControllerTest.kt
@@ -49,7 +49,9 @@
@SmallTest
@RunWith(AndroidJUnit4::class)
-@TestableLooper.RunWithLooper
+// collectFlow in KeyguardPinBasedInputViewController.onViewAttached calls JavaAdapter.CollectFlow,
+// which calls View.onRepeatWhenAttached, which requires being run on main thread.
+@TestableLooper.RunWithLooper(setAsMainLooper = true)
class KeyguardSimPinViewControllerTest : SysuiTestCase() {
private lateinit var simPinView: KeyguardSimPinView
private lateinit var underTest: KeyguardSimPinViewController
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSimPukViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSimPukViewControllerTest.kt
index 4f46184..e71490c 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSimPukViewControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSimPukViewControllerTest.kt
@@ -43,7 +43,9 @@
@SmallTest
@RunWith(AndroidJUnit4::class)
-@TestableLooper.RunWithLooper
+// collectFlow in KeyguardPinBasedInputViewController.onViewAttached calls JavaAdapter.CollectFlow,
+// which calls View.onRepeatWhenAttached, which requires being run on main thread.
+@TestableLooper.RunWithLooper(setAsMainLooper = true)
class KeyguardSimPukViewControllerTest : SysuiTestCase() {
private lateinit var simPukView: KeyguardSimPukView
private lateinit var underTest: KeyguardSimPukViewController
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/sections/ClockSectionTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/sections/ClockSectionTest.kt
index 08d44c1..aa7f9a9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/sections/ClockSectionTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/sections/ClockSectionTest.kt
@@ -67,12 +67,15 @@
context.resources.getDimensionPixelSize(R.dimen.keyguard_clock_top_margin) +
Utils.getStatusBarHeaderHeightKeyguard(context)
- private val LARGE_CLOCK_TOP =
+ private val LARGE_CLOCK_TOP_WITHOUT_SMARTSPACE =
context.resources.getDimensionPixelSize(R.dimen.status_bar_height) +
context.resources.getDimensionPixelSize(
com.android.systemui.customization.R.dimen.small_clock_padding_top
) +
- context.resources.getDimensionPixelSize(R.dimen.keyguard_smartspace_top_offset) +
+ context.resources.getDimensionPixelSize(R.dimen.keyguard_smartspace_top_offset)
+
+ private val LARGE_CLOCK_TOP =
+ LARGE_CLOCK_TOP_WITHOUT_SMARTSPACE +
SMART_SPACE_DATE_WEATHER_HEIGHT +
ENHANCED_SMART_SPACE_HEIGHT
@@ -81,36 +84,30 @@
com.android.systemui.customization.R.dimen.small_clock_height
)
+ private var DIMENSION_BY_IDENTIFIER_NAME: List<Pair<String, Int>> = listOf()
+
@Before
fun setup() {
+ DIMENSION_BY_IDENTIFIER_NAME =
+ listOf(
+ "date_weather_view_height" to SMART_SPACE_DATE_WEATHER_HEIGHT,
+ "enhanced_smartspace_height" to ENHANCED_SMART_SPACE_HEIGHT,
+ )
+
MockitoAnnotations.initMocks(this)
val remoteResources = mock<Resources>()
- whenever(
- remoteResources.getIdentifier(
- anyString(),
- eq("dimen"),
- anyString(),
- )
- )
- .then { invocation ->
- val name = invocation.arguments[0] as String
- val index = DIMENSION_BY_IDENTIFIER_NAME.indexOfFirst { (key, _) -> key == name }
- if (index == -1) {
- error(
- "No entry for a dimension named \"$name\", please add it to the list above."
- )
- }
- index
- }
- whenever(
- remoteResources.getDimensionPixelSize(
- anyInt(),
- )
- )
- .then { invocation ->
- val id = invocation.arguments[0] as Int
- DIMENSION_BY_IDENTIFIER_NAME[id].second
- }
+ whenever(remoteResources.getIdentifier(anyString(), eq("dimen"), anyString())).then {
+ invocation ->
+ val name = invocation.arguments[0] as String
+ val index = DIMENSION_BY_IDENTIFIER_NAME.indexOfFirst { (key, _) -> key == name }
+ // increment index so that the not-found sentinel value lines up w/ what is
+ // returned by getIdentifier when a resource is not found
+ index + 1
+ }
+ whenever(remoteResources.getDimensionPixelSize(anyInt())).then { invocation ->
+ val id = invocation.arguments[0] as Int
+ DIMENSION_BY_IDENTIFIER_NAME[id - 1].second
+ }
val packageManager = mock<PackageManager>()
whenever(packageManager.getResourcesForApplication(anyString())).thenReturn(remoteResources)
mContext.setMockPackageManager(packageManager)
@@ -159,6 +156,36 @@
}
@Test
+ fun testApplyDefaultConstraints_LargeClock_MissingSmartspace_SplitShade() {
+ DIMENSION_BY_IDENTIFIER_NAME = listOf() // Remove Smartspace from mock
+ setLargeClock(true)
+ setSplitShade(true)
+ val cs = ConstraintSet()
+ underTest.applyDefaultConstraints(cs)
+
+ val expectedLargeClockTopMargin = LARGE_CLOCK_TOP_WITHOUT_SMARTSPACE
+ assertLargeClockTop(cs, expectedLargeClockTopMargin)
+
+ val expectedSmallClockTopMargin = SMALL_CLOCK_TOP_SPLIT_SHADE
+ assertSmallClockTop(cs, expectedSmallClockTopMargin)
+ }
+
+ @Test
+ fun testApplyDefaultConstraints_LargeClock_MissingSmartspace_NonSplitShade() {
+ DIMENSION_BY_IDENTIFIER_NAME = listOf() // Remove Smartspace from mock
+ setLargeClock(true)
+ setSplitShade(false)
+ val cs = ConstraintSet()
+ underTest.applyDefaultConstraints(cs)
+
+ val expectedLargeClockTopMargin = LARGE_CLOCK_TOP_WITHOUT_SMARTSPACE
+ assertLargeClockTop(cs, expectedLargeClockTopMargin)
+
+ val expectedSmallClockTopMargin = SMALL_CLOCK_TOP_NON_SPLIT_SHADE
+ assertSmallClockTop(cs, expectedSmallClockTopMargin)
+ }
+
+ @Test
fun testApplyDefaultConstraints_SmallClock_SplitShade() {
setLargeClock(false)
setSplitShade(true)
@@ -249,10 +276,5 @@
companion object {
private val SMART_SPACE_DATE_WEATHER_HEIGHT = 10
private val ENHANCED_SMART_SPACE_HEIGHT = 11
- private val DIMENSION_BY_IDENTIFIER_NAME =
- listOf(
- "date_weather_view_height" to SMART_SPACE_DATE_WEATHER_HEIGHT,
- "enhanced_smartspace_height" to ENHANCED_SMART_SPACE_HEIGHT,
- )
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java
index 44b8974..992658a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java
@@ -103,6 +103,7 @@
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractorFactory;
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor;
import com.android.systemui.keyguard.domain.interactor.NaturalScrollingSettingObserver;
+import com.android.systemui.keyguard.ui.view.KeyguardRootView;
import com.android.systemui.keyguard.ui.viewmodel.DreamingToLockscreenTransitionViewModel;
import com.android.systemui.keyguard.ui.viewmodel.GoneToDreamingLockscreenHostedTransitionViewModel;
import com.android.systemui.keyguard.ui.viewmodel.GoneToDreamingTransitionViewModel;
@@ -280,6 +281,8 @@
@Mock protected UiEventLogger mUiEventLogger;
@Mock protected LockIconViewController mLockIconViewController;
@Mock protected KeyguardViewConfigurator mKeyguardViewConfigurator;
+ @Mock protected KeyguardRootView mKeyguardRootView;
+ @Mock protected View mKeyguardRootViewChild;
@Mock protected KeyguardMediaController mKeyguardMediaController;
@Mock protected NavigationModeController mNavigationModeController;
@Mock protected NavigationBarController mNavigationBarController;
@@ -389,6 +392,7 @@
mSetFlagsRule.disableFlags(com.android.systemui.Flags.FLAG_KEYGUARD_BOTTOM_AREA_REFACTOR);
mSetFlagsRule.disableFlags(com.android.systemui.Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT);
+ mSetFlagsRule.disableFlags(com.android.systemui.Flags.FLAG_DEVICE_ENTRY_UDFPS_REFACTOR);
mMainDispatcher = getMainDispatcher();
KeyguardInteractorFactory.WithDependencies keyguardInteractorDeps =
@@ -835,13 +839,13 @@
when(mNotificationStackScrollLayoutController.getBottom()).thenReturn(stackBottom);
when(mLockIconViewController.getTop()).thenReturn((float) (stackBottom - lockIconPadding));
+ when(mKeyguardRootViewChild.getTop()).thenReturn((int) (stackBottom - lockIconPadding));
+ when(mKeyguardRootView.findViewById(anyInt())).thenReturn(mKeyguardRootViewChild);
+ when(mKeyguardViewConfigurator.getKeyguardRootView()).thenReturn(mKeyguardRootView);
+
when(mResources.getDimensionPixelSize(R.dimen.keyguard_indication_bottom_padding))
.thenReturn(indicationPadding);
mNotificationPanelViewController.loadDimens();
-
- mNotificationPanelViewController.setAmbientIndicationTop(
- /* ambientIndicationTop= */ stackBottom - ambientPadding,
- /* ambientTextVisible= */ true);
}
protected void triggerPositionClockAndNotifications() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java
index 059053c..d24fe1b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java
@@ -203,6 +203,10 @@
when(mNotificationStackScrollLayoutController.getShelfHeight()).thenReturn(5);
assertThat(mNotificationPanelViewController.getVerticalSpaceForLockscreenShelf())
.isEqualTo(5);
+
+ mSetFlagsRule.enableFlags(com.android.systemui.Flags.FLAG_DEVICE_ENTRY_UDFPS_REFACTOR);
+ assertThat(mNotificationPanelViewController.getVerticalSpaceForLockscreenShelf())
+ .isEqualTo(5);
}
@Test
@@ -216,6 +220,10 @@
when(mNotificationStackScrollLayoutController.getShelfHeight()).thenReturn(5);
assertThat(mNotificationPanelViewController.getVerticalSpaceForLockscreenShelf())
.isEqualTo(0);
+
+ mSetFlagsRule.enableFlags(com.android.systemui.Flags.FLAG_DEVICE_ENTRY_UDFPS_REFACTOR);
+ assertThat(mNotificationPanelViewController.getVerticalSpaceForLockscreenShelf())
+ .isEqualTo(0);
}
@Test
@@ -229,6 +237,10 @@
when(mNotificationStackScrollLayoutController.getShelfHeight()).thenReturn(5);
assertThat(mNotificationPanelViewController.getVerticalSpaceForLockscreenShelf())
.isEqualTo(0);
+
+ mSetFlagsRule.enableFlags(com.android.systemui.Flags.FLAG_DEVICE_ENTRY_UDFPS_REFACTOR);
+ assertThat(mNotificationPanelViewController.getVerticalSpaceForLockscreenShelf())
+ .isEqualTo(0);
}
@Test
@@ -242,6 +254,10 @@
when(mNotificationStackScrollLayoutController.getShelfHeight()).thenReturn(5);
assertThat(mNotificationPanelViewController.getVerticalSpaceForLockscreenShelf())
.isEqualTo(2);
+
+ mSetFlagsRule.enableFlags(com.android.systemui.Flags.FLAG_DEVICE_ENTRY_UDFPS_REFACTOR);
+ assertThat(mNotificationPanelViewController.getVerticalSpaceForLockscreenShelf())
+ .isEqualTo(2);
}
@Test
@@ -255,6 +271,10 @@
when(mNotificationStackScrollLayoutController.getShelfHeight()).thenReturn(5);
assertThat(mNotificationPanelViewController.getVerticalSpaceForLockscreenShelf())
.isEqualTo(0);
+
+ mSetFlagsRule.enableFlags(com.android.systemui.Flags.FLAG_DEVICE_ENTRY_UDFPS_REFACTOR);
+ assertThat(mNotificationPanelViewController.getVerticalSpaceForLockscreenShelf())
+ .isEqualTo(0);
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/ShadeControllerImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/ShadeControllerImplTest.kt
index cc79ca4..f489937 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/ShadeControllerImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/ShadeControllerImplTest.kt
@@ -80,7 +80,7 @@
@Mock private lateinit var windowManager: WindowManager
@Mock private lateinit var assistManager: AssistManager
@Mock private lateinit var gutsManager: NotificationGutsManager
- @Mock private lateinit var shadeViewController: ShadeViewController
+ @Mock private lateinit var npvc: NotificationPanelViewController
@Mock private lateinit var nswvc: NotificationShadeWindowViewController
@Mock private lateinit var display: Display
@Mock private lateinit var touchLog: LogBuffer
@@ -120,7 +120,7 @@
deviceProvisionedController,
notificationShadeWindowController,
windowManager,
- Lazy { shadeViewController },
+ Lazy { npvc },
Lazy { assistManager },
Lazy { gutsManager },
)
@@ -134,9 +134,9 @@
// Trying to open it does nothing.
shadeController.animateExpandShade()
- verify(shadeViewController, never()).expandToNotifications()
+ verify(npvc, never()).expandToNotifications()
shadeController.animateExpandQs()
- verify(shadeViewController, never()).expand(ArgumentMatchers.anyBoolean())
+ verify(npvc, never()).expand(ArgumentMatchers.anyBoolean())
}
@Test
@@ -145,15 +145,15 @@
// Can now be opened.
shadeController.animateExpandShade()
- verify(shadeViewController).expandToNotifications()
+ verify(npvc).expandToNotifications()
shadeController.animateExpandQs()
- verify(shadeViewController).expandToQs()
+ verify(npvc).expandToQs()
}
@Test
fun cancelExpansionAndCollapseShade_callsCancelCurrentTouch() {
// GIVEN the shade is tracking a touch
- whenever(shadeViewController.isTracking).thenReturn(true)
+ whenever(npvc.isTracking).thenReturn(true)
// WHEN cancelExpansionAndCollapseShade is called
shadeController.cancelExpansionAndCollapseShade()
@@ -165,7 +165,7 @@
@Test
fun cancelExpansionAndCollapseShade_doesNotCallAnimateCollapseShade_whenCollapsed() {
// GIVEN the shade is tracking a touch
- whenever(shadeViewController.isTracking).thenReturn(false)
+ whenever(npvc.isTracking).thenReturn(false)
// WHEN cancelExpansionAndCollapseShade is called
shadeController.cancelExpansionAndCollapseShade()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/DragDownHelperTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/DragDownHelperTest.kt
index ffde601..9ec9b69 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/DragDownHelperTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/DragDownHelperTest.kt
@@ -25,9 +25,9 @@
import com.android.systemui.classifier.FalsingCollector
import com.android.systemui.keyguard.domain.interactor.NaturalScrollingSettingObserver
import com.android.systemui.plugins.FalsingManager
+import com.android.systemui.shade.data.repository.FakeShadeRepository
import com.android.systemui.statusbar.notification.row.ExpandableView
import com.android.systemui.util.mockito.mock
-import com.android.systemui.shade.data.repository.FakeShadeRepository
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -58,12 +58,11 @@
whenever(naturalScrollingSettingObserver.isNaturalScrollingEnabled).thenReturn(true)
dragDownHelper = DragDownHelper(
- falsingManager,
- falsingCollector,
- dragDownloadCallback,
- naturalScrollingSettingObserver,
- FakeShadeRepository(),
- mContext,
+ falsingManager,
+ dragDownloadCallback,
+ naturalScrollingSettingObserver,
+ FakeShadeRepository(),
+ mContext,
).also {
it.expandCallback = expandCallback
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt
index 3efcf7b..0933425 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt
@@ -5,10 +5,10 @@
import android.testing.TestableLooper
import android.testing.TestableLooper.RunWithLooper
import androidx.test.filters.SmallTest
-import com.android.systemui.SysUITestModule
-import com.android.systemui.TestMocksModule
import com.android.systemui.ExpandHelper
+import com.android.systemui.SysUITestModule
import com.android.systemui.SysuiTestCase
+import com.android.systemui.TestMocksModule
import com.android.systemui.classifier.FalsingCollectorFake
import com.android.systemui.classifier.FalsingManagerFake
import com.android.systemui.dagger.SysUISingleton
@@ -19,7 +19,7 @@
import com.android.systemui.plugins.qs.QS
import com.android.systemui.power.domain.interactor.PowerInteractor
import com.android.systemui.res.R
-import com.android.systemui.shade.ShadeViewController
+import com.android.systemui.shade.ShadeLockscreenInteractor
import com.android.systemui.shade.data.repository.FakeShadeRepository
import com.android.systemui.shade.domain.interactor.ShadeInteractor
import com.android.systemui.statusbar.disableflags.data.model.DisableFlagsModel
@@ -60,8 +60,8 @@
import org.mockito.Mockito.never
import org.mockito.Mockito.verify
import org.mockito.Mockito.verifyZeroInteractions
-import org.mockito.Mockito.`when` as whenever
import org.mockito.junit.MockitoJUnit
+import org.mockito.Mockito.`when` as whenever
private fun <T> anyObject(): T {
return Mockito.anyObject<T>()
@@ -94,7 +94,7 @@
@Mock lateinit var qS: QS
@Mock lateinit var qsTransitionController: LockscreenShadeQsTransitionController
@Mock lateinit var scrimController: ScrimController
- @Mock lateinit var shadeViewController: ShadeViewController
+ @Mock lateinit var shadeLockscreenInteractor: ShadeLockscreenInteractor
@Mock lateinit var singleShadeOverScroller: SingleShadeLockScreenOverScroller
@Mock lateinit var splitShadeOverScroller: SplitShadeLockScreenOverScroller
@Mock lateinit var stackscroller: NotificationStackScrollLayout
@@ -167,7 +167,7 @@
keyguardTransitionControllerFactory = { notificationPanelController ->
LockscreenShadeKeyguardTransitionController(
mediaHierarchyManager = mediaHierarchyManager,
- notificationPanelController = notificationPanelController,
+ shadeLockscreenInteractor = notificationPanelController,
context = context,
configurationController = configurationController,
dumpManager = mock(),
@@ -186,13 +186,12 @@
qsTransitionControllerFactory = { qsTransitionController },
shadeRepository = testComponent.shadeRepository,
shadeInteractor = testComponent.shadeInteractor,
- powerInteractor = testComponent.powerInteractor,
splitShadeStateController = ResourcesSplitShadeStateController(),
+ shadeLockscreenInteractorLazy = {shadeLockscreenInteractor},
naturalScrollingSettingObserver = naturalScrollingSettingObserver,
)
transitionController.addCallback(transitionControllerCallback)
- transitionController.shadeViewController = shadeViewController
transitionController.centralSurfaces = centralSurfaces
transitionController.qS = qS
transitionController.setStackScroller(nsslController)
@@ -286,7 +285,7 @@
fun testGoToLockedShadeCreatesQSAnimation() {
transitionController.goToLockedShade(null)
verify(statusbarStateController).setState(StatusBarState.SHADE_LOCKED)
- verify(shadeViewController).transitionToExpandedShade(anyLong())
+ verify(shadeLockscreenInteractor).transitionToExpandedShade(anyLong())
assertNotNull(transitionController.dragDownAnimator)
}
@@ -294,7 +293,7 @@
fun testGoToLockedShadeDoesntCreateQSAnimation() {
transitionController.goToLockedShade(null, needsQSAnimation = false)
verify(statusbarStateController).setState(StatusBarState.SHADE_LOCKED)
- verify(shadeViewController).transitionToExpandedShade(anyLong())
+ verify(shadeLockscreenInteractor).transitionToExpandedShade(anyLong())
assertNull(transitionController.dragDownAnimator)
}
@@ -302,7 +301,7 @@
fun testGoToLockedShadeAlwaysCreatesQSAnimationInSplitShade() {
enableSplitShade()
transitionController.goToLockedShade(null, needsQSAnimation = true)
- verify(shadeViewController).transitionToExpandedShade(anyLong())
+ verify(shadeLockscreenInteractor).transitionToExpandedShade(anyLong())
assertNotNull(transitionController.dragDownAnimator)
}
@@ -358,7 +357,7 @@
fun setDragAmount_setsKeyguardTransitionProgress() {
transitionController.dragDownAmount = 10f
- verify(shadeViewController).setKeyguardTransitionProgress(anyFloat(), anyInt())
+ verify(shadeLockscreenInteractor).setKeyguardTransitionProgress(anyFloat(), anyInt())
}
@Test
@@ -370,7 +369,7 @@
transitionController.dragDownAmount = 10f
val expectedAlpha = 1 - 10f / alphaDistance
- verify(shadeViewController).setKeyguardTransitionProgress(eq(expectedAlpha), anyInt())
+ verify(shadeLockscreenInteractor).setKeyguardTransitionProgress(eq(expectedAlpha), anyInt())
}
@Test
@@ -383,7 +382,7 @@
transitionController.dragDownAmount = 10f
- verify(shadeViewController).setKeyguardTransitionProgress(anyFloat(), eq(0))
+ verify(shadeLockscreenInteractor).setKeyguardTransitionProgress(anyFloat(), eq(0))
}
@Test
@@ -396,7 +395,8 @@
transitionController.dragDownAmount = 10f
- verify(shadeViewController).setKeyguardTransitionProgress(anyFloat(), eq(mediaTranslationY))
+ verify(shadeLockscreenInteractor)
+ .setKeyguardTransitionProgress(anyFloat(), eq(mediaTranslationY))
}
@Test
@@ -416,7 +416,7 @@
R.dimen.lockscreen_shade_keyguard_transition_vertical_offset
)
val expectedTranslation = 10f / distance * offset
- verify(shadeViewController)
+ verify(shadeLockscreenInteractor)
.setKeyguardTransitionProgress(anyFloat(), eq(expectedTranslation.toInt()))
}
@@ -555,7 +555,7 @@
transitionController.dragDownAmount = dragDownAmount
val expectedAlpha = 1 - dragDownAmount / alphaDistance
- verify(shadeViewController).setKeyguardStatusBarAlpha(expectedAlpha)
+ verify(shadeLockscreenInteractor).setKeyguardStatusBarAlpha(expectedAlpha)
}
@Test
@@ -564,7 +564,7 @@
transitionController.dragDownAmount = 10f
- verify(shadeViewController).setKeyguardStatusBarAlpha(-1f)
+ verify(shadeLockscreenInteractor).setKeyguardStatusBarAlpha(-1f)
}
private fun enableSplitShade() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
index 4015361..bd7406a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
@@ -90,8 +90,7 @@
import com.android.systemui.shade.ShadeController;
import com.android.systemui.shade.ShadeExpansionChangeEvent;
import com.android.systemui.shade.ShadeExpansionStateManager;
-import com.android.systemui.shade.ShadeViewController;
-import com.android.systemui.statusbar.NotificationMediaManager;
+import com.android.systemui.shade.ShadeLockscreenInteractor;
import com.android.systemui.statusbar.NotificationShadeWindowController;
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.SysuiStatusBarStateController;
@@ -125,7 +124,7 @@
@Mock private LockPatternUtils mLockPatternUtils;
@Mock private CentralSurfaces mCentralSurfaces;
@Mock private ViewGroup mContainer;
- @Mock private ShadeViewController mShadeViewController;
+ @Mock private ShadeLockscreenInteractor mShadeLockscreenInteractor;
@Mock private BiometricUnlockController mBiometricUnlockController;
@Mock private SysuiStatusBarStateController mStatusBarStateController;
@Mock private KeyguardUpdateMonitor mKeyguardUpdateMonitor;
@@ -206,7 +205,6 @@
mock(DockManager.class),
mNotificationShadeWindowController,
mKeyguardStateController,
- mock(NotificationMediaManager.class),
mKeyguardMessageAreaFactory,
Optional.of(mSysUiUnfoldComponent),
() -> mShadeController,
@@ -234,7 +232,7 @@
.thenReturn(mOnBackInvokedDispatcher);
mStatusBarKeyguardViewManager.registerCentralSurfaces(
mCentralSurfaces,
- mShadeViewController,
+ mShadeLockscreenInteractor,
new ShadeExpansionStateManager(),
mBiometricUnlockController,
mNotificationContainer,
@@ -715,7 +713,6 @@
mock(DockManager.class),
mock(NotificationShadeWindowController.class),
mKeyguardStateController,
- mock(NotificationMediaManager.class),
mKeyguardMessageAreaFactory,
Optional.of(mSysUiUnfoldComponent),
() -> mShadeController,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/unfold/DisplaySwitchLatencyTrackerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/unfold/DisplaySwitchLatencyTrackerTest.kt
index ee2e5ad..28adbce 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/unfold/DisplaySwitchLatencyTrackerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/unfold/DisplaySwitchLatencyTrackerTest.kt
@@ -321,4 +321,38 @@
verify(displaySwitchLatencyLogger, never()).log(any())
}
}
+
+ @Test
+ fun foldToScreenOff_capturesToStateAsScreenOff() {
+ testScope.runTest {
+ areAnimationEnabled.emit(true)
+ deviceState.emit(DeviceState.UNFOLDED)
+ isAodAvailable.emit(false)
+
+ displaySwitchLatencyTracker.start()
+ deviceState.emit(DeviceState.HALF_FOLDED)
+ systemClock.advanceTime(50)
+ runCurrent()
+ deviceState.emit(DeviceState.FOLDED)
+ lastWakefulnessEvent.emit(
+ WakefulnessModel(
+ internalWakefulnessState = WakefulnessState.ASLEEP,
+ lastSleepReason = WakeSleepReason.FOLD
+ )
+ )
+ screenPowerState.emit(ScreenPowerState.SCREEN_OFF)
+ runCurrent()
+
+ verify(displaySwitchLatencyLogger).log(capture(loggerArgumentCaptor))
+ val loggedEvent = loggerArgumentCaptor.value
+ val expectedLoggedEvent =
+ DisplaySwitchLatencyEvent(
+ latencyMs = 0,
+ fromFoldableDeviceState = FOLDABLE_DEVICE_STATE_HALF_OPEN,
+ toFoldableDeviceState = FOLDABLE_DEVICE_STATE_CLOSED,
+ toState = SysUiStatsLog.DISPLAY_SWITCH_LATENCY_TRACKED__TO_STATE__SCREEN_OFF
+ )
+ assertThat(loggedEvent).isEqualTo(expectedLoggedEvent)
+ }
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/unfold/FoldAodAnimationControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/unfold/FoldAodAnimationControllerTest.kt
index f924134..10aab96 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/unfold/FoldAodAnimationControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/unfold/FoldAodAnimationControllerTest.kt
@@ -246,7 +246,7 @@
private fun sendFoldEvent(folded: Boolean) {
val state = if (folded) deviceStates.folded else deviceStates.unfolded
- foldStateListenerCaptor.value.onStateChanged(state)
+ foldStateListenerCaptor.value.onDeviceStateChanged(state)
}
companion object {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/unfold/UnfoldLatencyTrackerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/unfold/UnfoldLatencyTrackerTest.kt
index c7dc0ab..ba72716 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/unfold/UnfoldLatencyTrackerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/unfold/UnfoldLatencyTrackerTest.kt
@@ -174,7 +174,7 @@
private fun sendFoldEvent(folded: Boolean) {
val state = if (folded) deviceStates.folded else deviceStates.unfolded
- foldStateListenerCaptor.value.onStateChanged(state)
+ foldStateListenerCaptor.value.onDeviceStateChanged(state)
}
private fun sendScreenTurnedOnEvent() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/unfold/util/FoldableTestUtils.kt b/packages/SystemUI/tests/src/com/android/systemui/unfold/util/FoldableTestUtils.kt
index 01b5359..e499a3c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/unfold/util/FoldableTestUtils.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/unfold/util/FoldableTestUtils.kt
@@ -17,21 +17,29 @@
package com.android.systemui.unfold.util
import android.content.Context
+import android.hardware.devicestate.DeviceState
import org.junit.Assume.assumeTrue
object FoldableTestUtils {
/** Finds device state for folded and unfolded. */
fun findDeviceStates(context: Context): FoldableDeviceStates {
+ // TODO(b/325474477): Migrate clients to updated DeviceStateManager API's
val foldedDeviceStates: IntArray = context.resources.getIntArray(
com.android.internal.R.array.config_foldedDeviceStates)
assumeTrue("Test should be launched on a foldable device",
foldedDeviceStates.isNotEmpty())
- val folded = foldedDeviceStates.maxOrNull()!!
- val unfolded = folded + 1
+ val folded =
+ DeviceState(foldedDeviceStates.maxOrNull()!! /* identifier */,
+ "" /* name */,
+ emptySet() /* properties */)
+ val unfolded =
+ DeviceState(folded.identifier + 1 /* identifier */,
+ "" /* name */,
+ emptySet() /* properties */)
return FoldableDeviceStates(folded = folded, unfolded = unfolded)
}
}
-data class FoldableDeviceStates(val folded: Int, val unfolded: Int)
\ No newline at end of file
+data class FoldableDeviceStates(val folded: DeviceState, val unfolded: DeviceState)
\ No newline at end of file
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ShadeControllerKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ShadeControllerKosmos.kt
index 82e0b8e..f4acf4d 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ShadeControllerKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ShadeControllerKosmos.kt
@@ -73,7 +73,7 @@
deviceProvisionedController,
mock<NotificationShadeWindowController>(),
mock<WindowManager>(),
- { mock<ShadeViewController>() },
+ { mock<NotificationPanelViewController>() },
{ mock<AssistManager>() },
{ mock<NotificationGutsManager>() },
)
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/shade/domain/interactor/ShadeLockscreenInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/domain/interactor/ShadeLockscreenInteractorKosmos.kt
new file mode 100644
index 0000000..4221d06
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/domain/interactor/ShadeLockscreenInteractorKosmos.kt
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.shade.domain.interactor
+
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.testScope
+import com.android.systemui.scene.domain.interactor.sceneInteractor
+import com.android.systemui.util.mockito.mock
+
+val Kosmos.shadeLockscreenInteractor by
+ Kosmos.Fixture {
+ ShadeLockscreenInteractorImpl(
+ scope = testScope,
+ shadeInteractor = shadeInteractorImpl,
+ sceneInteractor = sceneInteractor,
+ lockIconViewController = mock(),
+ )
+ }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerKosmos.kt
index 1c6ce79..81888c484 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerKosmos.kt
@@ -26,9 +26,9 @@
import com.android.systemui.kosmos.Kosmos.Fixture
import com.android.systemui.media.controls.ui.mediaHierarchyManager
import com.android.systemui.plugins.activityStarter
-import com.android.systemui.power.domain.interactor.powerInteractor
import com.android.systemui.shade.data.repository.shadeRepository
import com.android.systemui.shade.domain.interactor.shadeInteractor
+import com.android.systemui.shade.domain.interactor.shadeLockscreenInteractor
import com.android.systemui.statusbar.notification.stack.ambientState
import com.android.systemui.statusbar.phone.keyguardBypassController
import com.android.systemui.statusbar.phone.lsShadeTransitionLogger
@@ -58,8 +58,8 @@
qsTransitionControllerFactory = lockscreenShadeQsTransitionControllerFactory,
shadeRepository = shadeRepository,
shadeInteractor = shadeInteractor,
- powerInteractor = powerInteractor,
splitShadeStateController = splitShadeStateController,
+ shadeLockscreenInteractorLazy = { shadeLockscreenInteractor },
naturalScrollingSettingObserver = naturalScrollingSettingObserver,
)
}
diff --git a/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodRuleImpl.java b/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodRuleImpl.java
index 7b5932b..1d5c79c 100644
--- a/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodRuleImpl.java
+++ b/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodRuleImpl.java
@@ -16,6 +16,8 @@
package android.platform.test.ravenwood;
+import static org.junit.Assert.assertFalse;
+
import android.app.ActivityManager;
import android.app.Instrumentation;
import android.os.Build;
@@ -28,12 +30,19 @@
import com.android.internal.os.RuntimeInit;
+import org.junit.After;
import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
import org.junit.runner.Description;
import org.junit.runner.RunWith;
import org.junit.runners.model.Statement;
import java.io.PrintStream;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.Executors;
@@ -183,6 +192,7 @@
public static void validate(Statement base, Description description,
boolean enableOptionalValidation) {
validateTestRunner(base, description, enableOptionalValidation);
+ validateTestAnnotations(base, description, enableOptionalValidation);
}
private static void validateTestRunner(Statement base, Description description,
@@ -206,4 +216,63 @@
}
}
}
+
+ private static void validateTestAnnotations(Statement base, Description description,
+ boolean enableOptionalValidation) {
+ final var testClass = description.getTestClass();
+
+ final var message = new StringBuilder();
+
+ boolean hasErrors = false;
+ for (Method m : collectMethods(testClass)) {
+ if (Modifier.isPublic(m.getModifiers()) && m.getName().startsWith("test")) {
+ if (m.getAnnotation(Test.class) == null) {
+ message.append("\nMethod " + m.getName() + "() doesn't have @Test");
+ hasErrors = true;
+ }
+ }
+ if ("setUp".equals(m.getName())) {
+ if (m.getAnnotation(Before.class) == null) {
+ message.append("\nMethod " + m.getName() + "() doesn't have @Before");
+ hasErrors = true;
+ }
+ if (!Modifier.isPublic(m.getModifiers())) {
+ message.append("\nMethod " + m.getName() + "() must be public");
+ hasErrors = true;
+ }
+ }
+ if ("tearDown".equals(m.getName())) {
+ if (m.getAnnotation(After.class) == null) {
+ message.append("\nMethod " + m.getName() + "() doesn't have @After");
+ hasErrors = true;
+ }
+ if (!Modifier.isPublic(m.getModifiers())) {
+ message.append("\nMethod " + m.getName() + "() must be public");
+ hasErrors = true;
+ }
+ }
+ }
+ assertFalse("Problem(s) detected in class " + testClass.getCanonicalName() + ":"
+ + message, hasErrors);
+ }
+
+ /**
+ * Collect all (public or private or any) methods in a class, including inherited methods.
+ */
+ private static List<Method> collectMethods(Class<?> clazz) {
+ var ret = new ArrayList<Method>();
+ collectMethods(clazz, ret);
+ return ret;
+ }
+
+ private static void collectMethods(Class<?> clazz, List<Method> result) {
+ // Class.getMethods() only return public methods, so we need to use getDeclaredMethods()
+ // instead, and recurse.
+ for (var m : clazz.getDeclaredMethods()) {
+ result.add(m);
+ }
+ if (clazz.getSuperclass() != null) {
+ collectMethods(clazz.getSuperclass(), result);
+ }
+ }
}
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
index 5407af7..18e11ba 100644
--- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
@@ -327,10 +327,13 @@
synchronized (mLock) {
// No need to enforce unlocked state when there is no caller. User can be in the
// stopping state or removed by the time the message is processed
+ Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "convert_state_to_bytes");
ensureGroupStateLoadedLocked(userId, false /* enforceUserUnlockingOrUnlocked */);
userIdToBytesMapping = saveStateToByteArrayLocked(userId);
+ Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
}
+ Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "byte_to_disk_io");
for (int i = 0; i < userIdToBytesMapping.size(); i++) {
int currentProfileId = userIdToBytesMapping.keyAt(i);
byte[] currentStateByteArray = userIdToBytesMapping.valueAt(i);
@@ -351,6 +354,7 @@
currentFile.failWrite(fileStream);
}
}
+ Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
return true;
}
@@ -4787,8 +4791,10 @@
synchronized (mLock) {
// No need to enforce unlocked state when there is no caller. User can be in the
// stopping state or removed by the time the message is processed
+ Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "convert_state_and_io");
ensureGroupStateLoadedLocked(mUserId, false /* enforceUserUnlockingOrUnlocked */ );
saveStateLocked(mUserId);
+ Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
}
}
}
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index 96c65565..d47245e 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -5108,12 +5108,13 @@
}
}
} else if (resultCode == FAILURE_CREDMAN_SELECTOR) {
- GetCredentialException exception = resultData.getParcelable(
- CredentialProviderService.EXTRA_GET_CREDENTIAL_EXCEPTION,
- GetCredentialException.class);
- Slog.d(TAG, "Credman bottom sheet from pinned "
- + "entry failed with: + " + exception.getType() + " , "
- + exception.getMessage());
+ String[] exception = resultData.getStringArray(
+ CredentialProviderService.EXTRA_GET_CREDENTIAL_EXCEPTION);
+ if (exception != null && exception.length >= 2) {
+ Slog.w(TAG, "Credman bottom sheet from pinned "
+ + "entry failed with: + " + exception[0] + " , "
+ + exception[1]);
+ }
} else {
Slog.d(TAG, "Unknown resultCode from credential "
+ "manager bottom sheet: " + resultCode);
diff --git a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
index b43f1a9..ba1f51b 100644
--- a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
+++ b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
@@ -40,6 +40,7 @@
import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage;
import static com.android.server.companion.AssociationStore.CHANGE_TYPE_UPDATED_ADDRESS_UNCHANGED;
import static com.android.server.companion.MetricUtils.logRemoveAssociation;
+import static com.android.server.companion.PackageUtils.isRestrictedSettingsAllowed;
import static com.android.server.companion.PackageUtils.enforceUsesCompanionDeviceFeature;
import static com.android.server.companion.PackageUtils.getPackageInfo;
import static com.android.server.companion.PermissionsUtils.checkCallerCanManageCompanionDevice;
@@ -871,13 +872,22 @@
@Override
public PendingIntent requestNotificationAccess(ComponentName component, int userId)
throws RemoteException {
- String callingPackage = component.getPackageName();
+ int callingUid = getCallingUid();
+ final String callingPackage = component.getPackageName();
+
checkCanCallNotificationApi(callingPackage, userId);
+
if (component.flattenToString().length() > MAX_CN_LENGTH) {
throw new IllegalArgumentException("Component name is too long.");
}
+
final long identity = Binder.clearCallingIdentity();
try {
+ if (!isRestrictedSettingsAllowed(getContext(), callingPackage, callingUid)) {
+ Slog.e(TAG, "Side loaded app must enable restricted "
+ + "setting before request the notification access");
+ return null;
+ }
return PendingIntent.getActivityAsUser(getContext(),
0 /* request code */,
NotificationAccessConfirmationActivityContract.launcherIntent(
diff --git a/services/companion/java/com/android/server/companion/PackageUtils.java b/services/companion/java/com/android/server/companion/PackageUtils.java
index 6c77018..3aae1ec 100644
--- a/services/companion/java/com/android/server/companion/PackageUtils.java
+++ b/services/companion/java/com/android/server/companion/PackageUtils.java
@@ -28,6 +28,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
+import android.app.AppOpsManager;
import android.companion.CompanionDeviceService;
import android.content.ComponentName;
import android.content.Context;
@@ -222,4 +223,15 @@
return requestingPackageSignatureAllowlisted;
}
+
+ /**
+ * Check if restricted settings is enabled for a side-loaded app.
+ */
+ public static boolean isRestrictedSettingsAllowed(
+ Context context, String packageName, int uid) {
+ final int mode = context.getSystemService(AppOpsManager.class).noteOpNoThrow(
+ AppOpsManager.OP_ACCESS_RESTRICTED_SETTINGS, uid,
+ packageName, /* attributionTag= */ null, /* message= */ null);
+ return mode == AppOpsManager.MODE_ALLOWED;
+ }
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerConstants.java b/services/core/java/com/android/server/am/ActivityManagerConstants.java
index d97731c..ff83797 100644
--- a/services/core/java/com/android/server/am/ActivityManagerConstants.java
+++ b/services/core/java/com/android/server/am/ActivityManagerConstants.java
@@ -243,7 +243,7 @@
/**
* The default value to {@link #KEY_ENABLE_NEW_OOMADJ}.
*/
- private static final boolean DEFAULT_ENABLE_NEW_OOM_ADJ = false;
+ private static final boolean DEFAULT_ENABLE_NEW_OOM_ADJ = Flags.oomadjusterCorrectnessRewrite();
/**
* Same as {@link TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_NOT_ALLOWED}
diff --git a/services/core/java/com/android/server/biometrics/AuthService.java b/services/core/java/com/android/server/biometrics/AuthService.java
index 3f3540e..48bf9f4 100644
--- a/services/core/java/com/android/server/biometrics/AuthService.java
+++ b/services/core/java/com/android/server/biometrics/AuthService.java
@@ -216,6 +216,13 @@
public String[] getFaceAidlInstances() {
return ServiceManager.getDeclaredInstances(IFace.DESCRIPTOR);
}
+
+ /**
+ * Allows to test with handlers.
+ */
+ public BiometricHandlerProvider getBiometricHandlerProvider() {
+ return BiometricHandlerProvider.getInstance();
+ }
}
private final class AuthServiceImpl extends IAuthService.Stub {
@@ -772,7 +779,6 @@
}
if (com.android.server.biometrics.Flags.deHidl()) {
- Slog.d(TAG, "deHidl flag is on.");
registerAuthenticators();
} else {
// Registers HIDL and AIDL authenticators, but only HIDL configs need to be provided.
@@ -783,10 +789,16 @@
}
private void registerAuthenticators() {
- registerFingerprintSensors(mInjector.getFingerprintAidlInstances(),
- mInjector.getFingerprintConfiguration(getContext()));
- registerFaceSensors(mInjector.getFaceAidlInstances(),
- mInjector.getFaceConfiguration(getContext()));
+ BiometricHandlerProvider handlerProvider = mInjector.getBiometricHandlerProvider();
+
+ handlerProvider.getFingerprintHandler().post(() ->
+ registerFingerprintSensors(mInjector.getFingerprintAidlInstances(),
+ mInjector.getFingerprintConfiguration(getContext()), getContext(),
+ mInjector.getFingerprintService()));
+ handlerProvider.getFaceHandler().post(() ->
+ registerFaceSensors(mInjector.getFaceAidlInstances(),
+ mInjector.getFaceConfiguration(getContext()), getContext(),
+ mInjector.getFaceService()));
registerIrisSensors(mInjector.getIrisConfiguration(getContext()));
}
@@ -837,15 +849,18 @@
}
}
- private void registerFaceSensors(final String[] faceAidlInstances,
- final String[] hidlConfigStrings) {
+ /**
+ * This method is invoked on {@link BiometricHandlerProvider.mFaceHandler}.
+ */
+ private static void registerFaceSensors(final String[] faceAidlInstances,
+ final String[] hidlConfigStrings, final Context context,
+ final IFaceService faceService) {
final FaceSensorConfigurations mFaceSensorConfigurations =
new FaceSensorConfigurations(hidlConfigStrings != null
&& hidlConfigStrings.length > 0);
if (hidlConfigStrings != null && hidlConfigStrings.length > 0) {
- mFaceSensorConfigurations.addHidlConfigs(
- hidlConfigStrings, getContext());
+ mFaceSensorConfigurations.addHidlConfigs(hidlConfigStrings, context);
}
if (faceAidlInstances != null && faceAidlInstances.length > 0) {
@@ -854,7 +869,6 @@
ServiceManager.waitForDeclaredService(name))));
}
- final IFaceService faceService = mInjector.getFaceService();
if (faceService != null) {
try {
faceService.registerAuthenticatorsLegacy(mFaceSensorConfigurations);
@@ -866,14 +880,18 @@
}
}
- private void registerFingerprintSensors(final String[] fingerprintAidlInstances,
- final String[] hidlConfigStrings) {
+ /**
+ * This method is invoked on {@link BiometricHandlerProvider.mFingerprintHandler}.
+ */
+ private static void registerFingerprintSensors(final String[] fingerprintAidlInstances,
+ final String[] hidlConfigStrings, final Context context,
+ final IFingerprintService fingerprintService) {
final FingerprintSensorConfigurations mFingerprintSensorConfigurations =
new FingerprintSensorConfigurations(!(hidlConfigStrings != null
&& hidlConfigStrings.length > 0));
if (hidlConfigStrings != null && hidlConfigStrings.length > 0) {
- mFingerprintSensorConfigurations.addHidlSensors(hidlConfigStrings, getContext());
+ mFingerprintSensorConfigurations.addHidlSensors(hidlConfigStrings, context);
}
if (fingerprintAidlInstances != null && fingerprintAidlInstances.length > 0) {
@@ -882,7 +900,6 @@
ServiceManager.waitForDeclaredService(name))));
}
- final IFingerprintService fingerprintService = mInjector.getFingerprintService();
if (fingerprintService != null) {
try {
fingerprintService.registerAuthenticatorsLegacy(mFingerprintSensorConfigurations);
diff --git a/services/core/java/com/android/server/biometrics/sensors/HalClientMonitor.java b/services/core/java/com/android/server/biometrics/sensors/HalClientMonitor.java
index b0649b9..0f01510 100644
--- a/services/core/java/com/android/server/biometrics/sensors/HalClientMonitor.java
+++ b/services/core/java/com/android/server/biometrics/sensors/HalClientMonitor.java
@@ -22,7 +22,6 @@
import android.hardware.biometrics.BiometricAuthenticator;
import android.os.IBinder;
-import com.android.server.biometrics.Flags;
import com.android.server.biometrics.log.BiometricContext;
import com.android.server.biometrics.log.BiometricLogger;
import com.android.server.biometrics.log.OperationContextExt;
@@ -94,9 +93,6 @@
}
protected OperationContextExt getOperationContext() {
- if (Flags.deHidl()) {
- return mOperationContext;
- }
return getBiometricContext().updateContext(mOperationContext, isCryptoOperation());
}
diff --git a/services/core/java/com/android/server/devicestate/DeviceStateManagerService.java b/services/core/java/com/android/server/devicestate/DeviceStateManagerService.java
index cd064ae..38051c1 100644
--- a/services/core/java/com/android/server/devicestate/DeviceStateManagerService.java
+++ b/services/core/java/com/android/server/devicestate/DeviceStateManagerService.java
@@ -21,8 +21,8 @@
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.hardware.devicestate.DeviceState.FLAG_CANCEL_OVERRIDE_REQUESTS;
import static android.hardware.devicestate.DeviceStateManager.INVALID_DEVICE_STATE;
-import static android.hardware.devicestate.DeviceStateManager.MAXIMUM_DEVICE_STATE;
-import static android.hardware.devicestate.DeviceStateManager.MINIMUM_DEVICE_STATE;
+import static android.hardware.devicestate.DeviceStateManager.MAXIMUM_DEVICE_STATE_IDENTIFIER;
+import static android.hardware.devicestate.DeviceStateManager.MINIMUM_DEVICE_STATE_IDENTIFIER;
import static com.android.server.devicestate.OverrideRequest.OVERRIDE_REQUEST_TYPE_BASE_STATE;
import static com.android.server.devicestate.OverrideRequest.OVERRIDE_REQUEST_TYPE_EMULATED_STATE;
@@ -1065,7 +1065,8 @@
}
private final class DeviceStateProviderListener implements DeviceStateProvider.Listener {
- @IntRange(from = MINIMUM_DEVICE_STATE, to = MAXIMUM_DEVICE_STATE) int mCurrentBaseState;
+ @IntRange(from = MINIMUM_DEVICE_STATE_IDENTIFIER, to = MAXIMUM_DEVICE_STATE_IDENTIFIER)
+ int mCurrentBaseState;
@Override
public void onSupportedDeviceStatesChanged(DeviceState[] newDeviceStates,
@@ -1078,8 +1079,10 @@
@Override
public void onStateChanged(
- @IntRange(from = MINIMUM_DEVICE_STATE, to = MAXIMUM_DEVICE_STATE) int identifier) {
- if (identifier < MINIMUM_DEVICE_STATE || identifier > MAXIMUM_DEVICE_STATE) {
+ @IntRange(from = MINIMUM_DEVICE_STATE_IDENTIFIER, to =
+ MAXIMUM_DEVICE_STATE_IDENTIFIER) int identifier) {
+ if (identifier < MINIMUM_DEVICE_STATE_IDENTIFIER
+ || identifier > MAXIMUM_DEVICE_STATE_IDENTIFIER) {
throw new IllegalArgumentException("Invalid identifier: " + identifier);
}
diff --git a/services/core/java/com/android/server/devicestate/DeviceStateProvider.java b/services/core/java/com/android/server/devicestate/DeviceStateProvider.java
index 65b393a..b865c1d9 100644
--- a/services/core/java/com/android/server/devicestate/DeviceStateProvider.java
+++ b/services/core/java/com/android/server/devicestate/DeviceStateProvider.java
@@ -16,8 +16,8 @@
package com.android.server.devicestate;
-import static android.hardware.devicestate.DeviceStateManager.MAXIMUM_DEVICE_STATE;
-import static android.hardware.devicestate.DeviceStateManager.MINIMUM_DEVICE_STATE;
+import static android.hardware.devicestate.DeviceStateManager.MAXIMUM_DEVICE_STATE_IDENTIFIER;
+import static android.hardware.devicestate.DeviceStateManager.MINIMUM_DEVICE_STATE_IDENTIFIER;
import android.annotation.IntDef;
import android.annotation.IntRange;
@@ -133,10 +133,12 @@
*
* @param identifier the identifier of the new device state.
*
- * @throws IllegalArgumentException if the state is less than {@link MINIMUM_DEVICE_STATE}
- * or greater than {@link MAXIMUM_DEVICE_STATE}.
+ * @throws IllegalArgumentException if the state is less than
+ * {@link MINIMUM_DEVICE_STATE_IDENTIFIER} or greater than
+ * {@link MAXIMUM_DEVICE_STATE_IDENTIFIER}.
*/
void onStateChanged(
- @IntRange(from = MINIMUM_DEVICE_STATE, to = MAXIMUM_DEVICE_STATE) int identifier);
+ @IntRange(from = MINIMUM_DEVICE_STATE_IDENTIFIER, to =
+ MAXIMUM_DEVICE_STATE_IDENTIFIER) int identifier);
}
}
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index b5c51af..796d8d7 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -340,6 +340,8 @@
static final String TAG = NetworkPolicyLogger.TAG;
private static final boolean LOGD = NetworkPolicyLogger.LOGD;
private static final boolean LOGV = NetworkPolicyLogger.LOGV;
+ // TODO: b/304347838 - Remove once the feature is in staging.
+ private static final boolean ALWAYS_RESTRICT_BACKGROUND_NETWORK = false;
/**
* No opportunistic quota could be calculated from user data plan or data settings.
@@ -1061,7 +1063,8 @@
}
// The flag is boot-stable.
- mBackgroundNetworkRestricted = Flags.networkBlockedForTopSleepingAndAbove();
+ mBackgroundNetworkRestricted = ALWAYS_RESTRICT_BACKGROUND_NETWORK
+ && Flags.networkBlockedForTopSleepingAndAbove();
if (mBackgroundNetworkRestricted) {
// Firewall rules and UidBlockedState will get updated in
// updateRulesForGlobalChangeAL below.
diff --git a/services/core/java/com/android/server/pm/PackageAbiHelperImpl.java b/services/core/java/com/android/server/pm/PackageAbiHelperImpl.java
index bbce26c..9db4d33 100644
--- a/services/core/java/com/android/server/pm/PackageAbiHelperImpl.java
+++ b/services/core/java/com/android/server/pm/PackageAbiHelperImpl.java
@@ -53,7 +53,8 @@
import java.io.File;
import java.io.IOException;
-import java.util.Set;
+import java.util.ArrayList;
+import java.util.List;
final class PackageAbiHelperImpl implements PackageAbiHelper {
@@ -314,7 +315,7 @@
@NonNull
private static String[] getNativelySupportedAbis(@NonNull String[] supportedAbis) {
- Set<String> nativelySupportedAbis = new ArraySet<>();
+ List<String> nativelySupportedAbis = new ArrayList<>();
for (int i = 0; i < supportedAbis.length; i++) {
final String currentAbi = supportedAbis[i];
// In presence of a native bridge this means the Abi is emulated.
diff --git a/services/core/java/com/android/server/pm/PackageInstallerHistoricalSession.java b/services/core/java/com/android/server/pm/PackageInstallerHistoricalSession.java
index 4b98e34..ea37d8e 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerHistoricalSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerHistoricalSession.java
@@ -78,6 +78,7 @@
private final int mSessionErrorCode;
private final String mSessionErrorMessage;
private final String mPreVerifiedDomains;
+ private final String mPackageName;
PackageInstallerHistoricalSession(int sessionId, int userId, int originalInstallerUid,
String originalInstallerPackageName, InstallSource installSource, int installerUid,
@@ -88,7 +89,8 @@
String finalMessage, SessionParams params, int parentSessionId,
int[] childSessionIds, boolean sessionApplied, boolean sessionFailed,
boolean sessionReady, int sessionErrorCode, String sessionErrorMessage,
- PreapprovalDetails preapprovalDetails, DomainSet preVerifiedDomains) {
+ PreapprovalDetails preapprovalDetails, DomainSet preVerifiedDomains,
+ String packageNameFromApk) {
this.sessionId = sessionId;
this.userId = userId;
this.mOriginalInstallerUid = originalInstallerUid;
@@ -135,6 +137,9 @@
} else {
this.mPreVerifiedDomains = null;
}
+
+ this.mPackageName = preapprovalDetails != null ? preapprovalDetails.getPackageName()
+ : packageNameFromApk != null ? packageNameFromApk : params.appPackageName;
}
void dump(IndentingPrintWriter pw) {
@@ -178,6 +183,7 @@
pw.printPair("mSessionErrorMessage", mSessionErrorMessage);
pw.printPair("mPreapprovalDetails", mPreapprovalDetails);
pw.printPair("mPreVerifiedDomains", mPreVerifiedDomains);
+ pw.printPair("mAppPackageName", mPackageName);
pw.println();
pw.decreaseIndent();
@@ -206,6 +212,7 @@
info.createdMillis = mCreatedMillis;
info.updatedMillis = mUpdatedMillis;
info.installerUid = mInstallerUid;
+ info.appPackageName = mPackageName;
return info;
}
}
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index c860b5a..5792d86 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -1242,7 +1242,7 @@
mStageDirInUse, mDestroyed, mFds.size(), mBridges.size(), mFinalStatus,
mFinalMessage, params, mParentSessionId, getChildSessionIdsLocked(),
mSessionApplied, mSessionFailed, mSessionReady, mSessionErrorCode,
- mSessionErrorMessage, mPreapprovalDetails, mPreVerifiedDomains);
+ mSessionErrorMessage, mPreapprovalDetails, mPreVerifiedDomains, mPackageName);
}
}
diff --git a/services/core/java/com/android/server/policy/DeviceStateProviderImpl.java b/services/core/java/com/android/server/policy/DeviceStateProviderImpl.java
index 76952b3..1b220a0 100644
--- a/services/core/java/com/android/server/policy/DeviceStateProviderImpl.java
+++ b/services/core/java/com/android/server/policy/DeviceStateProviderImpl.java
@@ -17,7 +17,7 @@
package com.android.server.policy;
import static android.hardware.devicestate.DeviceStateManager.INVALID_DEVICE_STATE;
-import static android.hardware.devicestate.DeviceStateManager.MINIMUM_DEVICE_STATE;
+import static android.hardware.devicestate.DeviceStateManager.MINIMUM_DEVICE_STATE_IDENTIFIER;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -94,7 +94,7 @@
private static final BooleanSupplier FALSE_BOOLEAN_SUPPLIER = () -> false;
@VisibleForTesting
- static final DeviceState DEFAULT_DEVICE_STATE = new DeviceState(MINIMUM_DEVICE_STATE,
+ static final DeviceState DEFAULT_DEVICE_STATE = new DeviceState(MINIMUM_DEVICE_STATE_IDENTIFIER,
"DEFAULT", 0 /* flags */);
private static final String VENDOR_CONFIG_FILE_PATH = "etc/devicestate/";
diff --git a/services/core/java/com/android/server/vcn/routeselection/IpSecPacketLossDetector.java b/services/core/java/com/android/server/vcn/routeselection/IpSecPacketLossDetector.java
index 5f4852f..a25d67a 100644
--- a/services/core/java/com/android/server/vcn/routeselection/IpSecPacketLossDetector.java
+++ b/services/core/java/com/android/server/vcn/routeselection/IpSecPacketLossDetector.java
@@ -252,7 +252,7 @@
}
getInboundTransformInternal()
- .getIpSecTransformState(
+ .requestIpSecTransformState(
new HandlerExecutor(mHandler), new IpSecTransformStateReceiver());
// Schedule for next poll
@@ -302,7 +302,8 @@
"packetLossRate: "
+ packetLossRate
+ "% in the past "
- + (state.getTimestamp() - mLastIpSecTransformState.getTimestamp())
+ + (state.getTimestampMillis()
+ - mLastIpSecTransformState.getTimestampMillis())
+ "ms";
mLastIpSecTransformState = state;
diff --git a/services/core/java/com/android/server/vcn/routeselection/NetworkMetricMonitor.java b/services/core/java/com/android/server/vcn/routeselection/NetworkMetricMonitor.java
index a79f188..1704aa1 100644
--- a/services/core/java/com/android/server/vcn/routeselection/NetworkMetricMonitor.java
+++ b/services/core/java/com/android/server/vcn/routeselection/NetworkMetricMonitor.java
@@ -138,10 +138,10 @@
}
/** Poll an IpSecTransformState */
- public void getIpSecTransformState(
+ public void requestIpSecTransformState(
@NonNull Executor executor,
@NonNull OutcomeReceiver<IpSecTransformState, RuntimeException> callback) {
- ipSecTransform.getIpSecTransformState(executor, callback);
+ ipSecTransform.requestIpSecTransformState(executor, callback);
}
/** Close this instance and release the underlying resources */
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 52fdfda..3637ab1 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -3524,10 +3524,13 @@
}
final long callingIdentity = Binder.clearCallingIdentity();
try {
- hasRestrictedWindow = displayContent.forAllWindows(windowState -> {
- return windowState.isOnScreen() && UserManager.isUserTypePrivateProfile(
- getUserManager().getProfileType(windowState.mShowUserId));
- }, true /* traverseTopToBottom */);
+ hasRestrictedWindow = displayContent.forAllWindows(
+ windowState -> windowState.isOnScreen() && (
+ UserManager.isUserTypePrivateProfile(
+ getUserManager().getProfileType(windowState.mShowUserId))
+ || hasUserRestriction(
+ UserManager.DISALLOW_ASSIST_CONTENT,
+ windowState.mShowUserId)), true /* traverseTopToBottom */);
} finally {
Binder.restoreCallingIdentity(callingIdentity);
}
diff --git a/services/core/java/com/android/server/wm/BackgroundActivityStartController.java b/services/core/java/com/android/server/wm/BackgroundActivityStartController.java
index 3bc5319..86ca1ea 100644
--- a/services/core/java/com/android/server/wm/BackgroundActivityStartController.java
+++ b/services/core/java/com/android/server/wm/BackgroundActivityStartController.java
@@ -726,9 +726,8 @@
// Allowed before V by creator
if (state.mBalAllowedByPiCreator.allowsBackgroundActivityStarts()) {
Slog.wtf(TAG, "With Android 15 BAL hardening this activity start may be blocked"
- + " if the PI creator upgrades target_sdk to 35+! "
- + " (missing opt in by PI creator)! "
- + state.dump());
+ + " if the PI creator upgrades target_sdk to 35+! "
+ + " (missing opt in by PI creator)!" + state.dump());
showBalRiskToast();
return allowBasedOnCaller(state);
}
@@ -737,17 +736,15 @@
// Allowed before U by sender
if (state.mBalAllowedByPiSender.allowsBackgroundActivityStarts()) {
Slog.wtf(TAG, "With Android 14 BAL hardening this activity start will be blocked"
- + " if the PI sender upgrades target_sdk to 34+! "
- + " (missing opt in by PI sender)! "
- + state.dump());
+ + " if the PI sender upgrades target_sdk to 34+! "
+ + " (missing opt in by PI sender)!" + state.dump());
showBalRiskToast();
return allowBasedOnRealCaller(state);
}
}
// caller or real caller could start the activity, but would need to explicitly opt in
if (callerCanAllow || realCallerCanAllow) {
- Slog.wtf(TAG, "Without BAL hardening this activity start would be allowed "
- + state.dump());
+ Slog.w(TAG, "Without BAL hardening this activity start would be allowed");
}
// neither the caller not the realCaller can allow or have explicitly opted out
return abortLaunch(state);
@@ -770,7 +767,7 @@
}
private BalVerdict abortLaunch(BalState state) {
- Slog.w(TAG, "Background activity launch blocked! "
+ Slog.wtf(TAG, "Background activity launch blocked! "
+ state.dump());
showBalBlockedToast();
return statsLog(BalVerdict.BLOCK, state);
diff --git a/services/core/java/com/android/server/wm/EmbeddedWindowController.java b/services/core/java/com/android/server/wm/EmbeddedWindowController.java
index 68bff43..fac62fc 100644
--- a/services/core/java/com/android/server/wm/EmbeddedWindowController.java
+++ b/services/core/java/com/android/server/wm/EmbeddedWindowController.java
@@ -178,8 +178,8 @@
return true;
}
- boolean transferToHost(InputTransferToken embeddedWindowToken,
- WindowState transferToHostWindowState) {
+ boolean transferToHost(@NonNull InputTransferToken embeddedWindowToken,
+ @NonNull WindowState transferToHostWindowState) {
EmbeddedWindow ew = getByInputTransferToken(embeddedWindowToken);
if (!isValidTouchGestureParams(transferToHostWindowState, ew)) {
return false;
@@ -188,7 +188,8 @@
transferToHostWindowState.mInputChannelToken);
}
- boolean transferToEmbedded(WindowState hostWindowState, InputTransferToken transferToToken) {
+ boolean transferToEmbedded(WindowState hostWindowState,
+ @NonNull InputTransferToken transferToToken) {
final EmbeddedWindowController.EmbeddedWindow ew = getByInputTransferToken(transferToToken);
if (!isValidTouchGestureParams(hostWindowState, ew)) {
return false;
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 3d6bd4f..e538f5d5 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -101,7 +101,6 @@
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ADD_REMOVE;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ANIM;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_BOOT;
-import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_EMBEDDED_WINDOWS;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_FOCUS;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_FOCUS_LIGHT;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_IME;
@@ -9057,14 +9056,10 @@
}
@Override
- public boolean transferTouchGesture(InputTransferToken transferFromToken,
- InputTransferToken transferToToken) {
- if (transferFromToken == null || transferToToken == null) {
- ProtoLog.e(WM_DEBUG_EMBEDDED_WINDOWS,
- "transferTouchGesture failed because args transferFromToken or "
- + "transferToToken is null");
- return false;
- }
+ public boolean transferTouchGesture(@NonNull InputTransferToken transferFromToken,
+ @NonNull InputTransferToken transferToToken) {
+ Objects.requireNonNull(transferFromToken);
+ Objects.requireNonNull(transferToToken);
final long identity = Binder.clearCallingIdentity();
boolean didTransfer;
diff --git a/services/credentials/java/com/android/server/credentials/GetCandidateRequestSession.java b/services/credentials/java/com/android/server/credentials/GetCandidateRequestSession.java
index adb1b72..d06d4d8 100644
--- a/services/credentials/java/com/android/server/credentials/GetCandidateRequestSession.java
+++ b/services/credentials/java/com/android/server/credentials/GetCandidateRequestSession.java
@@ -168,6 +168,9 @@
mRequestSessionMetric.collectFrameworkException(exception);
if (finalResponseReceiver != null) {
Bundle resultData = new Bundle();
+ resultData.putStringArray(
+ CredentialProviderService.EXTRA_GET_CREDENTIAL_EXCEPTION,
+ new String[] {exception, message});
finalResponseReceiver.send(Constants.FAILURE_CREDMAN_SELECTOR, resultData);
} else {
respondToClientWithErrorAndFinish(exception, message);
diff --git a/services/foldables/devicestateprovider/src/com/android/server/policy/FoldableDeviceStateProvider.java b/services/foldables/devicestateprovider/src/com/android/server/policy/FoldableDeviceStateProvider.java
index bf2619b..42e41d5 100644
--- a/services/foldables/devicestateprovider/src/com/android/server/policy/FoldableDeviceStateProvider.java
+++ b/services/foldables/devicestateprovider/src/com/android/server/policy/FoldableDeviceStateProvider.java
@@ -18,8 +18,8 @@
import static android.hardware.SensorManager.SENSOR_DELAY_FASTEST;
import static android.hardware.devicestate.DeviceStateManager.INVALID_DEVICE_STATE;
-import static android.hardware.devicestate.DeviceStateManager.MAXIMUM_DEVICE_STATE;
-import static android.hardware.devicestate.DeviceStateManager.MINIMUM_DEVICE_STATE;
+import static android.hardware.devicestate.DeviceStateManager.MAXIMUM_DEVICE_STATE_IDENTIFIER;
+import static android.hardware.devicestate.DeviceStateManager.MINIMUM_DEVICE_STATE_IDENTIFIER;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.TYPE_EXTERNAL;
@@ -478,7 +478,8 @@
}
public static DeviceStateConfiguration createConfig(
- @IntRange(from = MINIMUM_DEVICE_STATE, to = MAXIMUM_DEVICE_STATE) int identifier,
+ @IntRange(from = MINIMUM_DEVICE_STATE_IDENTIFIER, to =
+ MAXIMUM_DEVICE_STATE_IDENTIFIER) int identifier,
@NonNull String name,
@DeviceState.DeviceStateFlags int flags,
@NonNull Predicate<FoldableDeviceStateProvider> activeStatePredicate
@@ -488,7 +489,8 @@
}
public static DeviceStateConfiguration createConfig(
- @IntRange(from = MINIMUM_DEVICE_STATE, to = MAXIMUM_DEVICE_STATE) int identifier,
+ @IntRange(from = MINIMUM_DEVICE_STATE_IDENTIFIER, to =
+ MAXIMUM_DEVICE_STATE_IDENTIFIER) int identifier,
@NonNull String name,
@NonNull Predicate<FoldableDeviceStateProvider> activeStatePredicate
) {
@@ -498,7 +500,8 @@
/** Create a configuration with availability predicate **/
public static DeviceStateConfiguration createConfig(
- @IntRange(from = MINIMUM_DEVICE_STATE, to = MAXIMUM_DEVICE_STATE) int identifier,
+ @IntRange(from = MINIMUM_DEVICE_STATE_IDENTIFIER, to =
+ MAXIMUM_DEVICE_STATE_IDENTIFIER) int identifier,
@NonNull String name,
@DeviceState.DeviceStateFlags int flags,
@NonNull Predicate<FoldableDeviceStateProvider> activeStatePredicate,
@@ -543,7 +546,8 @@
* @return device state configuration
*/
public static DeviceStateConfiguration createTentModeClosedState(
- @IntRange(from = MINIMUM_DEVICE_STATE, to = MAXIMUM_DEVICE_STATE) int identifier,
+ @IntRange(from = MINIMUM_DEVICE_STATE_IDENTIFIER, to =
+ MAXIMUM_DEVICE_STATE_IDENTIFIER) int identifier,
@NonNull String name,
@DeviceState.DeviceStateFlags int flags,
int minClosedAngleDegrees,
diff --git a/services/permission/java/com/android/server/permission/access/permission/AppIdPermissionPolicy.kt b/services/permission/java/com/android/server/permission/access/permission/AppIdPermissionPolicy.kt
index cb3ee73..4b086b3 100644
--- a/services/permission/java/com/android/server/permission/access/permission/AppIdPermissionPolicy.kt
+++ b/services/permission/java/com/android/server/permission/access/permission/AppIdPermissionPolicy.kt
@@ -590,8 +590,13 @@
var areGidsPerUser = false
if (!parsedPermission.isTree && packageState.isSystem) {
newState.externalState.configPermissions[permissionName]?.let {
- gids = it.gids
- areGidsPerUser = it.perUser
+ // PermissionEntry.gids may return null when parsing legacy config trying
+ // to work around an issue about upgrading from L platfrm. We can just
+ // ignore such entries now.
+ if (it.gids != null) {
+ gids = it.gids
+ areGidsPerUser = it.perUser
+ }
}
}
newPermission = Permission(
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityWindowManagerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityWindowManagerTest.java
index b12d6da..89d146d 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityWindowManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityWindowManagerTest.java
@@ -41,12 +41,12 @@
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.annotation.Nullable;
import android.graphics.Region;
import android.os.IBinder;
import android.os.LocaleList;
import android.os.RemoteException;
import android.os.UserHandle;
-import android.text.TextUtils;
import android.util.SparseArray;
import android.view.Display;
import android.view.IWindow;
@@ -452,7 +452,9 @@
false, mockHostToken, USER_SYSTEM_ID);
final int embeddedWindowId = addAccessibilityInteractionConnection(Display.DEFAULT_DISPLAY,
false, mockEmbeddedToken, USER_SYSTEM_ID);
+
mA11yWindowManager.associateEmbeddedHierarchyLocked(mockHostToken, mockEmbeddedToken);
+
final int resolvedWindowId = mA11yWindowManager.resolveParentWindowIdLocked(
embeddedWindowId);
assertEquals(hostWindowId, resolvedWindowId);
@@ -467,10 +469,13 @@
false, mockHostToken, USER_SYSTEM_ID);
final int embeddedWindowId = addAccessibilityInteractionConnection(Display.DEFAULT_DISPLAY,
false, mockEmbeddedToken, USER_SYSTEM_ID);
+
mA11yWindowManager.associateEmbeddedHierarchyLocked(mockHostToken, mockEmbeddedToken);
mA11yWindowManager.disassociateEmbeddedHierarchyLocked(mockEmbeddedToken);
+
final int resolvedWindowId = mA11yWindowManager.resolveParentWindowIdLocked(
embeddedWindowId);
+ assertNotEquals(hostWindowId, resolvedWindowId);
assertEquals(embeddedWindowId, resolvedWindowId);
}
@@ -917,7 +922,7 @@
final AccessibilityWindowInfo a11yWindow = mA11yWindowManager.findA11yWindowInfoByIdLocked(
windowId);
- assertTrue(TextUtils.equals(layoutParams.accessibilityTitle, a11yWindow.getTitle()));
+ assertEquals(toString(layoutParams.accessibilityTitle), toString(a11yWindow.getTitle()));
}
@Test
@@ -1057,7 +1062,7 @@
when(mockWindowToken.asBinder()).thenReturn(mockWindowBinder);
when(mMockA11ySecurityPolicy.isCallerInteractingAcrossUsers(userId))
.thenReturn(bGlobal);
- when(mMockWindowManagerInternal.getDisplayIdForWindow(mockWindowToken.asBinder()))
+ when(mMockWindowManagerInternal.getDisplayIdForWindow(mockWindowBinder))
.thenReturn(displayId);
int windowId = mA11yWindowManager.addAccessibilityInteractionConnection(
@@ -1077,7 +1082,7 @@
when(mockWindowToken.asBinder()).thenReturn(mockWindowBinder);
when(mMockA11ySecurityPolicy.isCallerInteractingAcrossUsers(userId))
.thenReturn(bGlobal);
- when(mMockWindowManagerInternal.getDisplayIdForWindow(mockWindowToken.asBinder()))
+ when(mMockWindowManagerInternal.getDisplayIdForWindow(mockWindowBinder))
.thenReturn(displayId);
int windowId = mA11yWindowManager.addAccessibilityInteractionConnection(
@@ -1148,6 +1153,11 @@
}
}
+ @Nullable
+ private static String toString(@Nullable CharSequence cs) {
+ return cs == null ? null : cs.toString();
+ }
+
static class DisplayIdMatcher extends TypeSafeMatcher<AccessibilityEvent> {
private final int mDisplayId;
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationControllerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationControllerTest.java
index cd904eb..a0c4b5e 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationControllerTest.java
@@ -150,6 +150,9 @@
@Mock
private DisplayManagerInternal mDisplayManagerInternal;
+ @Mock
+ private Scroller mMockScroller;
+
// To mock package-private class
@Rule
public final DexmakerShareClassLoaderRule mDexmakerShareClassLoaderRule =
@@ -208,7 +211,7 @@
mScaleProvider,
() -> null,
ConcurrentUtils.DIRECT_EXECUTOR,
- () -> new Scroller(mContext),
+ () -> mMockScroller,
() -> mTimeAnimator));
mScreenMagnificationController.register(TEST_DISPLAY);
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/AuthServiceTest.java b/services/tests/servicestests/src/com/android/server/biometrics/AuthServiceTest.java
index 071db68..f0dc5f0 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/AuthServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/AuthServiceTest.java
@@ -60,8 +60,10 @@
import android.hardware.fingerprint.IFingerprintService;
import android.hardware.iris.IIrisService;
import android.os.Binder;
+import android.os.Handler;
import android.os.RemoteException;
import android.os.UserHandle;
+import android.os.test.TestLooper;
import android.platform.test.annotations.Presubmit;
import android.platform.test.annotations.RequiresFlagsDisabled;
import android.platform.test.annotations.RequiresFlagsEnabled;
@@ -127,6 +129,8 @@
AppOpsManager mAppOpsManager;
@Mock
private VirtualDeviceManagerInternal mVdmInternal;
+ @Mock
+ private BiometricHandlerProvider mBiometricHandlerProvider;
@Captor
private ArgumentCaptor<List<FingerprintSensorPropertiesInternal>> mFingerprintPropsCaptor;
@Captor
@@ -136,6 +140,9 @@
@Captor
private ArgumentCaptor<List<FaceSensorPropertiesInternal>> mFacePropsCaptor;
+ private final TestLooper mFingerprintLooper = new TestLooper();
+ private final TestLooper mFaceLooper = new TestLooper();
+
@Before
public void setUp() {
// Placeholder test config
@@ -167,6 +174,11 @@
when(mInjector.getIrisService()).thenReturn(mIrisService);
when(mInjector.getAppOps(any())).thenReturn(mAppOpsManager);
when(mInjector.isHidlDisabled(any())).thenReturn(false);
+ when(mInjector.getBiometricHandlerProvider()).thenReturn(mBiometricHandlerProvider);
+ when(mBiometricHandlerProvider.getFingerprintHandler()).thenReturn(
+ new Handler(mFingerprintLooper.getLooper()));
+ when(mBiometricHandlerProvider.getFaceHandler()).thenReturn(
+ new Handler(mFaceLooper.getLooper()));
setInternalAndTestBiometricPermissions(mContext, false /* hasPermission */);
}
@@ -250,6 +262,9 @@
mAuthService = new AuthService(mContext, mInjector);
mAuthService.onStart();
+ mFingerprintLooper.dispatchAll();
+ mFaceLooper.dispatchAll();
+
verify(mFingerprintService).registerAuthenticatorsLegacy(
mFingerprintSensorConfigurationsCaptor.capture());
diff --git a/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
index 5f2abc3..3492935 100644
--- a/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
@@ -205,6 +205,7 @@
import org.junit.After;
import org.junit.Assume;
import org.junit.Before;
+import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.MethodRule;
@@ -2217,6 +2218,7 @@
assertFalse(mService.isUidNetworkingBlocked(UID_B, false));
}
+ @Ignore("Temporarily disabled until the feature is enabled")
@Test
@RequiresFlagsEnabled(Flags.FLAG_NETWORK_BLOCKED_FOR_TOP_SLEEPING_AND_ABOVE)
public void testBackgroundChainOnTempAllowlistChange() throws Exception {
@@ -2246,6 +2248,7 @@
assertTrue(mService.isUidNetworkingBlocked(UID_A, false));
}
+ @Ignore("Temporarily disabled until the feature is enabled")
@Test
@RequiresFlagsEnabled(Flags.FLAG_NETWORK_BLOCKED_FOR_TOP_SLEEPING_AND_ABOVE)
public void testUidObserverFiltersProcStateChanges() throws Exception {
@@ -2308,6 +2311,7 @@
waitForUidEventHandlerIdle();
}
+ @Ignore("Temporarily disabled until the feature is enabled")
@Test
@RequiresFlagsEnabled(Flags.FLAG_NETWORK_BLOCKED_FOR_TOP_SLEEPING_AND_ABOVE)
public void testUidObserverFiltersStaleChanges() throws Exception {
@@ -2328,6 +2332,7 @@
waitForUidEventHandlerIdle();
}
+ @Ignore("Temporarily disabled until the feature is enabled")
@Test
@RequiresFlagsEnabled(Flags.FLAG_NETWORK_BLOCKED_FOR_TOP_SLEEPING_AND_ABOVE)
public void testUidObserverFiltersCapabilityChanges() throws Exception {
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeConfigTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeConfigTest.java
index 12f9e26..abfb95c 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeConfigTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeConfigTest.java
@@ -625,6 +625,21 @@
}
@Test
+ public void testRuleXml_customInterruptionFilter() throws Exception {
+ ZenModeConfig.ZenRule rule = new ZenModeConfig.ZenRule();
+ rule.zenMode = Settings.Global.ZEN_MODE_ALARMS;
+ rule.conditionId = Uri.parse("condition://android/blah");
+ assertThat(Condition.isValidId(rule.conditionId, ZenModeConfig.SYSTEM_AUTHORITY)).isTrue();
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ writeRuleXml(rule, baos);
+ ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
+ ZenModeConfig.ZenRule fromXml = readRuleXml(bais);
+
+ assertEquals(rule.zenMode, fromXml.zenMode);
+ }
+
+ @Test
public void testZenPolicyXml_allUnset() throws Exception {
ZenPolicy policy = new ZenPolicy.Builder().build();
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 697c8ec..d99abe8 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -3844,13 +3844,27 @@
* and if the 5G state changes to neither 'connected' not 'not_restricted_rrc_idle', the icon
* will change to reflect the true state.
*
+ * The value can be overridden by {@link #KEY_NR_ADVANCED_BANDS_SECONDARY_TIMER_SECONDS_INT}
* @hide
*/
public static final String KEY_5G_ICON_DISPLAY_SECONDARY_GRACE_PERIOD_STRING =
"5g_icon_display_secondary_grace_period_string";
/**
- * Whether device reset all of NR timers when device camped on a network that haven't 5G
+ * The secondary grace periods in seconds to use if NR advanced icon was shown due to connecting
+ * to bands specified in {@link #KEY_ADDITIONAL_NR_ADVANCED_BANDS_INT_ARRAY}.
+ *
+ * The default value is 0, meaning the original value in
+ * {@link #KEY_5G_ICON_DISPLAY_SECONDARY_GRACE_PERIOD_STRING} is used. Otherwise, it overrides
+ * the value in {@link #KEY_5G_ICON_DISPLAY_SECONDARY_GRACE_PERIOD_STRING}.
+ *
+ * @hide
+ */
+ public static final String KEY_NR_ADVANCED_BANDS_SECONDARY_TIMER_SECONDS_INT =
+ "nr_advanced_bands_secondary_timer_seconds_int";
+
+ /**
+ * Whether device resets all of NR timers when device camped on a network that haven't 5G
* capability and RRC currently in IDLE state.
*
* The default value is false;
@@ -3861,6 +3875,30 @@
"nr_timers_reset_if_non_endc_and_rrc_idle_bool";
/**
+ * Whether device resets all of NR timers when device is in a voice call and QOS is established.
+ * The default value is false;
+ *
+ * @see #KEY_5G_ICON_DISPLAY_GRACE_PERIOD_STRING
+ * @see #KEY_5G_ICON_DISPLAY_SECONDARY_GRACE_PERIOD_STRING
+ *
+ * @hide
+ */
+ public static final String KEY_NR_TIMERS_RESET_ON_VOICE_QOS_BOOL =
+ "nr_timers_reset_on_voice_qos_bool";
+
+ /**
+ * Whether device resets all of NR timers when the PLMN changes.
+ * The default value is false;
+ *
+ * @see #KEY_5G_ICON_DISPLAY_GRACE_PERIOD_STRING
+ * @see #KEY_5G_ICON_DISPLAY_SECONDARY_GRACE_PERIOD_STRING
+ *
+ * @hide
+ */
+ public static final String KEY_NR_TIMERS_RESET_ON_PLMN_CHANGE_BOOL =
+ "nr_timers_reset_on_plmn_change_bool";
+
+ /**
* A list of additional NR advanced band would map to
* {@link TelephonyDisplayInfo#OVERRIDE_NETWORK_TYPE_NR_ADVANCED} when the device is on that
* band.
@@ -10688,7 +10726,10 @@
+ "not_restricted_rrc_con:5G");
sDefaults.putString(KEY_5G_ICON_DISPLAY_GRACE_PERIOD_STRING, "");
sDefaults.putString(KEY_5G_ICON_DISPLAY_SECONDARY_GRACE_PERIOD_STRING, "");
+ sDefaults.putInt(KEY_NR_ADVANCED_BANDS_SECONDARY_TIMER_SECONDS_INT, 0);
sDefaults.putBoolean(KEY_NR_TIMERS_RESET_IF_NON_ENDC_AND_RRC_IDLE_BOOL, false);
+ sDefaults.putBoolean(KEY_NR_TIMERS_RESET_ON_VOICE_QOS_BOOL, false);
+ sDefaults.putBoolean(KEY_NR_TIMERS_RESET_ON_PLMN_CHANGE_BOOL, false);
/* Default value is 1 hour. */
sDefaults.putLong(KEY_5G_WATCHDOG_TIME_MS_LONG, 3600000);
sDefaults.putIntArray(KEY_ADDITIONAL_NR_ADVANCED_BANDS_INT_ARRAY, new int[0]);
diff --git a/tests/vcn/java/com/android/server/vcn/routeselection/IpSecPacketLossDetectorTest.java b/tests/vcn/java/com/android/server/vcn/routeselection/IpSecPacketLossDetectorTest.java
index 9daba6a..1d7be2f 100644
--- a/tests/vcn/java/com/android/server/vcn/routeselection/IpSecPacketLossDetectorTest.java
+++ b/tests/vcn/java/com/android/server/vcn/routeselection/IpSecPacketLossDetectorTest.java
@@ -144,7 +144,7 @@
mTestLooper.dispatchAll();
verify(mIpSecTransform)
- .getIpSecTransformState(any(), mTransformStateReceiverCaptor.capture());
+ .requestIpSecTransformState(any(), mTransformStateReceiverCaptor.capture());
return mTransformStateReceiverCaptor.getValue();
}
@@ -210,7 +210,7 @@
assertNull(mIpSecPacketLossDetector.getLastTransformState());
mTestLooper.moveTimeForward(POLL_IPSEC_STATE_INTERVAL_MS);
mTestLooper.dispatchAll();
- verify(newTransform).getIpSecTransformState(any(), any());
+ verify(newTransform).requestIpSecTransformState(any(), any());
}
@Test
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/SubclassFilter.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/SubclassFilter.kt
new file mode 100644
index 0000000..83e09bf
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/SubclassFilter.kt
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.hoststubgen.filters
+
+import com.android.hoststubgen.asm.ClassNodes
+import com.android.hoststubgen.asm.toJvmClassName
+
+/**
+ * Filter to apply a policy to classes extending or implementing a class,
+ * either directly or indirectly. (with a breadth first search.)
+ *
+ * The policy won't apply to the super class itself.
+ */
+class SubclassFilter(
+ private val classes: ClassNodes,
+ fallback: OutputFilter
+) : DelegatingFilter(fallback) {
+ private val mPolicies: MutableMap<String, FilterPolicyWithReason> = mutableMapOf()
+
+ /**
+ * Add a policy to all classes extending or implementing a class, either directly or indirectly.
+ */
+ fun addPolicy(superClassName: String, policy: FilterPolicyWithReason) {
+ mPolicies[superClassName.toJvmClassName()] = policy
+ }
+
+ override fun getPolicyForClass(className: String): FilterPolicyWithReason {
+ return findPolicyForClass(className) ?: super.getPolicyForClass(className)
+ }
+
+ /**
+ * Find a policy for a class with a breadth-first search.
+ */
+ private fun findPolicyForClass(className: String): FilterPolicyWithReason? {
+ val cn = classes.findClass(className) ?: return null
+
+ if (cn.superName == null) {
+ return null
+ }
+ // First, check the direct super class / interfaces.
+ mPolicies[cn.superName]?.let { policy ->
+ return policy
+ }
+ cn.interfaces?.forEach { iface ->
+ mPolicies[iface]?.let { policy ->
+ return policy
+ }
+ }
+
+ // Then recurse.
+ cn.superName?.let { superName ->
+ findPolicyForClass(superName)?.let { policy ->
+ return policy
+ }
+ }
+ cn.interfaces?.forEach { iface ->
+ findPolicyForClass(iface)?.let { policy ->
+ return policy
+ }
+ }
+ return null
+ }
+}
\ No newline at end of file
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/TextFileFilterPolicyParser.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/TextFileFilterPolicyParser.kt
index 6ad83fb..75b5fc8 100644
--- a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/TextFileFilterPolicyParser.kt
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/TextFileFilterPolicyParser.kt
@@ -58,7 +58,8 @@
): OutputFilter {
log.i("Loading offloaded annotations from $filename ...")
log.withIndent {
- val imf = InMemoryOutputFilter(classes, fallback)
+ val subclassFilter = SubclassFilter(classes, fallback)
+ val imf = InMemoryOutputFilter(classes, subclassFilter)
var lineNo = 0
@@ -94,6 +95,10 @@
}
className = fields[1]
+ // superClass is set when the class name starts with a "*".
+ val superClass = resolveExtendingClass(className)
+
+ // :aidl, etc?
val classType = resolveSpecialClass(className)
if (fields[2].startsWith("!")) {
@@ -124,8 +129,14 @@
when (classType) {
SpecialClass.NotSpecial -> {
// TODO: Duplicate check, etc
- imf.setPolicyForClass(
- className, policy.withReason(FILTER_REASON))
+ if (superClass == null) {
+ imf.setPolicyForClass(
+ className, policy.withReason(FILTER_REASON)
+ )
+ } else {
+ subclassFilter.addPolicy(superClass,
+ policy.withReason("extends $superClass"))
+ }
}
SpecialClass.Aidl -> {
if (aidlPolicy != null) {
@@ -243,6 +254,13 @@
throw ParseException("Invalid special class name \"$className\"")
}
+private fun resolveExtendingClass(className: String): String? {
+ if (!className.startsWith("*")) {
+ return null
+ }
+ return className.substring(1)
+}
+
private fun parsePolicy(s: String): FilterPolicy {
return when (s.lowercase()) {
"s", "stub" -> FilterPolicy.Stub
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/01-hoststubgen-test-tiny-framework-orig-dump.txt b/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/01-hoststubgen-test-tiny-framework-orig-dump.txt
index 70f56ae..78f277e 100644
--- a/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/01-hoststubgen-test-tiny-framework-orig-dump.txt
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/01-hoststubgen-test-tiny-framework-orig-dump.txt
@@ -2589,6 +2589,567 @@
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestWholeClassStub
+## Class: com/android/hoststubgen/test/tinyframework/subclasstest/C1.class
+ Compiled from "C1.java"
+public class com.android.hoststubgen.test.tinyframework.subclasstest.C1
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/C1
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 0, methods: 1, attributes: 1
+ public com.android.hoststubgen.test.tinyframework.subclasstest.C1();
+ descriptor: ()V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=1, locals=1, args_size=1
+ x: aload_0
+ x: invokespecial #x // Method java/lang/Object."<init>":()V
+ x: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/subclasstest/C1;
+}
+SourceFile: "C1.java"
+## Class: com/android/hoststubgen/test/tinyframework/subclasstest/C2.class
+ Compiled from "C2.java"
+public class com.android.hoststubgen.test.tinyframework.subclasstest.C2 extends com.android.hoststubgen.test.tinyframework.subclasstest.C1
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/C2
+ super_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/C1
+ interfaces: 0, fields: 0, methods: 1, attributes: 1
+ public com.android.hoststubgen.test.tinyframework.subclasstest.C2();
+ descriptor: ()V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=1, locals=1, args_size=1
+ x: aload_0
+ x: invokespecial #x // Method com/android/hoststubgen/test/tinyframework/subclasstest/C1."<init>":()V
+ x: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/subclasstest/C2;
+}
+SourceFile: "C2.java"
+## Class: com/android/hoststubgen/test/tinyframework/subclasstest/C3.class
+ Compiled from "C3.java"
+public class com.android.hoststubgen.test.tinyframework.subclasstest.C3 extends com.android.hoststubgen.test.tinyframework.subclasstest.C2
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/C3
+ super_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/C2
+ interfaces: 0, fields: 0, methods: 1, attributes: 1
+ public com.android.hoststubgen.test.tinyframework.subclasstest.C3();
+ descriptor: ()V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=1, locals=1, args_size=1
+ x: aload_0
+ x: invokespecial #x // Method com/android/hoststubgen/test/tinyframework/subclasstest/C2."<init>":()V
+ x: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/subclasstest/C3;
+}
+SourceFile: "C3.java"
+## Class: com/android/hoststubgen/test/tinyframework/subclasstest/CA.class
+ Compiled from "CA.java"
+public class com.android.hoststubgen.test.tinyframework.subclasstest.CA
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/CA
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 0, methods: 1, attributes: 1
+ public com.android.hoststubgen.test.tinyframework.subclasstest.CA();
+ descriptor: ()V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=1, locals=1, args_size=1
+ x: aload_0
+ x: invokespecial #x // Method java/lang/Object."<init>":()V
+ x: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/subclasstest/CA;
+}
+SourceFile: "CA.java"
+## Class: com/android/hoststubgen/test/tinyframework/subclasstest/CB.class
+ Compiled from "CB.java"
+public class com.android.hoststubgen.test.tinyframework.subclasstest.CB
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/CB
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 0, methods: 1, attributes: 1
+ public com.android.hoststubgen.test.tinyframework.subclasstest.CB();
+ descriptor: ()V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=1, locals=1, args_size=1
+ x: aload_0
+ x: invokespecial #x // Method java/lang/Object."<init>":()V
+ x: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/subclasstest/CB;
+}
+SourceFile: "CB.java"
+## Class: com/android/hoststubgen/test/tinyframework/subclasstest/Class_C1.class
+ Compiled from "Class_C1.java"
+public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_C1 extends com.android.hoststubgen.test.tinyframework.subclasstest.C1
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/Class_C1
+ super_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/C1
+ interfaces: 0, fields: 0, methods: 1, attributes: 1
+ public com.android.hoststubgen.test.tinyframework.subclasstest.Class_C1();
+ descriptor: ()V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=1, locals=1, args_size=1
+ x: aload_0
+ x: invokespecial #x // Method com/android/hoststubgen/test/tinyframework/subclasstest/C1."<init>":()V
+ x: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/subclasstest/Class_C1;
+}
+SourceFile: "Class_C1.java"
+## Class: com/android/hoststubgen/test/tinyframework/subclasstest/Class_C2.class
+ Compiled from "Class_C2.java"
+public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_C2 extends com.android.hoststubgen.test.tinyframework.subclasstest.C2
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/Class_C2
+ super_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/C2
+ interfaces: 0, fields: 0, methods: 1, attributes: 1
+ public com.android.hoststubgen.test.tinyframework.subclasstest.Class_C2();
+ descriptor: ()V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=1, locals=1, args_size=1
+ x: aload_0
+ x: invokespecial #x // Method com/android/hoststubgen/test/tinyframework/subclasstest/C2."<init>":()V
+ x: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/subclasstest/Class_C2;
+}
+SourceFile: "Class_C2.java"
+## Class: com/android/hoststubgen/test/tinyframework/subclasstest/Class_C3.class
+ Compiled from "Class_C3.java"
+public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_C3 extends com.android.hoststubgen.test.tinyframework.subclasstest.C3
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/Class_C3
+ super_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/C3
+ interfaces: 0, fields: 0, methods: 1, attributes: 1
+ public com.android.hoststubgen.test.tinyframework.subclasstest.Class_C3();
+ descriptor: ()V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=1, locals=1, args_size=1
+ x: aload_0
+ x: invokespecial #x // Method com/android/hoststubgen/test/tinyframework/subclasstest/C3."<init>":()V
+ x: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/subclasstest/Class_C3;
+}
+SourceFile: "Class_C3.java"
+## Class: com/android/hoststubgen/test/tinyframework/subclasstest/Class_CA.class
+ Compiled from "Class_CA.java"
+public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_CA extends com.android.hoststubgen.test.tinyframework.subclasstest.CA
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/Class_CA
+ super_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/CA
+ interfaces: 0, fields: 0, methods: 1, attributes: 1
+ public com.android.hoststubgen.test.tinyframework.subclasstest.Class_CA();
+ descriptor: ()V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=1, locals=1, args_size=1
+ x: aload_0
+ x: invokespecial #x // Method com/android/hoststubgen/test/tinyframework/subclasstest/CA."<init>":()V
+ x: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/subclasstest/Class_CA;
+}
+SourceFile: "Class_CA.java"
+## Class: com/android/hoststubgen/test/tinyframework/subclasstest/Class_CB.class
+ Compiled from "Class_CB.java"
+public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_CB extends com.android.hoststubgen.test.tinyframework.subclasstest.CB
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/Class_CB
+ super_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/CB
+ interfaces: 0, fields: 0, methods: 1, attributes: 1
+ public com.android.hoststubgen.test.tinyframework.subclasstest.Class_CB();
+ descriptor: ()V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=1, locals=1, args_size=1
+ x: aload_0
+ x: invokespecial #x // Method com/android/hoststubgen/test/tinyframework/subclasstest/CB."<init>":()V
+ x: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/subclasstest/Class_CB;
+}
+SourceFile: "Class_CB.java"
+## Class: com/android/hoststubgen/test/tinyframework/subclasstest/Class_CB_IA.class
+ Compiled from "Class_CB_IA.java"
+public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_CB_IA extends com.android.hoststubgen.test.tinyframework.subclasstest.CB implements com.android.hoststubgen.test.tinyframework.subclasstest.IA
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/Class_CB_IA
+ super_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/CB
+ interfaces: 1, fields: 0, methods: 1, attributes: 1
+ public com.android.hoststubgen.test.tinyframework.subclasstest.Class_CB_IA();
+ descriptor: ()V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=1, locals=1, args_size=1
+ x: aload_0
+ x: invokespecial #x // Method com/android/hoststubgen/test/tinyframework/subclasstest/CB."<init>":()V
+ x: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/subclasstest/Class_CB_IA;
+}
+SourceFile: "Class_CB_IA.java"
+## Class: com/android/hoststubgen/test/tinyframework/subclasstest/Class_I1.class
+ Compiled from "Class_I1.java"
+public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_I1 implements com.android.hoststubgen.test.tinyframework.subclasstest.I1
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/Class_I1
+ super_class: #x // java/lang/Object
+ interfaces: 1, fields: 0, methods: 1, attributes: 1
+ public com.android.hoststubgen.test.tinyframework.subclasstest.Class_I1();
+ descriptor: ()V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=1, locals=1, args_size=1
+ x: aload_0
+ x: invokespecial #x // Method java/lang/Object."<init>":()V
+ x: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/subclasstest/Class_I1;
+}
+SourceFile: "Class_I1.java"
+## Class: com/android/hoststubgen/test/tinyframework/subclasstest/Class_I1_IA.class
+ Compiled from "Class_I1_IA.java"
+public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_I1_IA implements com.android.hoststubgen.test.tinyframework.subclasstest.I1,com.android.hoststubgen.test.tinyframework.subclasstest.IA
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/Class_I1_IA
+ super_class: #x // java/lang/Object
+ interfaces: 2, fields: 0, methods: 1, attributes: 1
+ public com.android.hoststubgen.test.tinyframework.subclasstest.Class_I1_IA();
+ descriptor: ()V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=1, locals=1, args_size=1
+ x: aload_0
+ x: invokespecial #x // Method java/lang/Object."<init>":()V
+ x: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/subclasstest/Class_I1_IA;
+}
+SourceFile: "Class_I1_IA.java"
+## Class: com/android/hoststubgen/test/tinyframework/subclasstest/Class_I2.class
+ Compiled from "Class_I2.java"
+public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_I2 implements com.android.hoststubgen.test.tinyframework.subclasstest.I2
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/Class_I2
+ super_class: #x // java/lang/Object
+ interfaces: 1, fields: 0, methods: 1, attributes: 1
+ public com.android.hoststubgen.test.tinyframework.subclasstest.Class_I2();
+ descriptor: ()V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=1, locals=1, args_size=1
+ x: aload_0
+ x: invokespecial #x // Method java/lang/Object."<init>":()V
+ x: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/subclasstest/Class_I2;
+}
+SourceFile: "Class_I2.java"
+## Class: com/android/hoststubgen/test/tinyframework/subclasstest/Class_I3.class
+ Compiled from "Class_I3.java"
+public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_I3 implements com.android.hoststubgen.test.tinyframework.subclasstest.I3
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/Class_I3
+ super_class: #x // java/lang/Object
+ interfaces: 1, fields: 0, methods: 1, attributes: 1
+ public com.android.hoststubgen.test.tinyframework.subclasstest.Class_I3();
+ descriptor: ()V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=1, locals=1, args_size=1
+ x: aload_0
+ x: invokespecial #x // Method java/lang/Object."<init>":()V
+ x: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/subclasstest/Class_I3;
+}
+SourceFile: "Class_I3.java"
+## Class: com/android/hoststubgen/test/tinyframework/subclasstest/Class_I3_IA.class
+ Compiled from "Class_I3_IA.java"
+public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_I3_IA implements com.android.hoststubgen.test.tinyframework.subclasstest.I3,com.android.hoststubgen.test.tinyframework.subclasstest.IA
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/Class_I3_IA
+ super_class: #x // java/lang/Object
+ interfaces: 2, fields: 0, methods: 1, attributes: 1
+ public com.android.hoststubgen.test.tinyframework.subclasstest.Class_I3_IA();
+ descriptor: ()V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=1, locals=1, args_size=1
+ x: aload_0
+ x: invokespecial #x // Method java/lang/Object."<init>":()V
+ x: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/subclasstest/Class_I3_IA;
+}
+SourceFile: "Class_I3_IA.java"
+## Class: com/android/hoststubgen/test/tinyframework/subclasstest/Class_IA.class
+ Compiled from "Class_IA.java"
+public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_IA implements com.android.hoststubgen.test.tinyframework.subclasstest.IA
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/Class_IA
+ super_class: #x // java/lang/Object
+ interfaces: 1, fields: 0, methods: 1, attributes: 1
+ public com.android.hoststubgen.test.tinyframework.subclasstest.Class_IA();
+ descriptor: ()V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=1, locals=1, args_size=1
+ x: aload_0
+ x: invokespecial #x // Method java/lang/Object."<init>":()V
+ x: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/subclasstest/Class_IA;
+}
+SourceFile: "Class_IA.java"
+## Class: com/android/hoststubgen/test/tinyframework/subclasstest/Class_IA_I1.class
+ Compiled from "Class_IA_I1.java"
+public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_IA_I1 implements com.android.hoststubgen.test.tinyframework.subclasstest.IA,com.android.hoststubgen.test.tinyframework.subclasstest.I1
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/Class_IA_I1
+ super_class: #x // java/lang/Object
+ interfaces: 2, fields: 0, methods: 1, attributes: 1
+ public com.android.hoststubgen.test.tinyframework.subclasstest.Class_IA_I1();
+ descriptor: ()V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=1, locals=1, args_size=1
+ x: aload_0
+ x: invokespecial #x // Method java/lang/Object."<init>":()V
+ x: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/subclasstest/Class_IA_I1;
+}
+SourceFile: "Class_IA_I1.java"
+## Class: com/android/hoststubgen/test/tinyframework/subclasstest/Class_IA_I3.class
+ Compiled from "Class_IA_I3.java"
+public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_IA_I3 implements com.android.hoststubgen.test.tinyframework.subclasstest.IA,com.android.hoststubgen.test.tinyframework.subclasstest.I3
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/Class_IA_I3
+ super_class: #x // java/lang/Object
+ interfaces: 2, fields: 0, methods: 1, attributes: 1
+ public com.android.hoststubgen.test.tinyframework.subclasstest.Class_IA_I3();
+ descriptor: ()V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=1, locals=1, args_size=1
+ x: aload_0
+ x: invokespecial #x // Method java/lang/Object."<init>":()V
+ x: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/subclasstest/Class_IA_I3;
+}
+SourceFile: "Class_IA_I3.java"
+## Class: com/android/hoststubgen/test/tinyframework/subclasstest/Class_IB.class
+ Compiled from "Class_IB.java"
+public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_IB implements com.android.hoststubgen.test.tinyframework.subclasstest.IB
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/Class_IB
+ super_class: #x // java/lang/Object
+ interfaces: 1, fields: 0, methods: 1, attributes: 1
+ public com.android.hoststubgen.test.tinyframework.subclasstest.Class_IB();
+ descriptor: ()V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=1, locals=1, args_size=1
+ x: aload_0
+ x: invokespecial #x // Method java/lang/Object."<init>":()V
+ x: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/subclasstest/Class_IB;
+}
+SourceFile: "Class_IB.java"
+## Class: com/android/hoststubgen/test/tinyframework/subclasstest/Class_IB_IA.class
+ Compiled from "Class_IB_IA.java"
+public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_IB_IA implements com.android.hoststubgen.test.tinyframework.subclasstest.IB,com.android.hoststubgen.test.tinyframework.subclasstest.IA
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/Class_IB_IA
+ super_class: #x // java/lang/Object
+ interfaces: 2, fields: 0, methods: 1, attributes: 1
+ public com.android.hoststubgen.test.tinyframework.subclasstest.Class_IB_IA();
+ descriptor: ()V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=1, locals=1, args_size=1
+ x: aload_0
+ x: invokespecial #x // Method java/lang/Object."<init>":()V
+ x: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/subclasstest/Class_IB_IA;
+}
+SourceFile: "Class_IB_IA.java"
+## Class: com/android/hoststubgen/test/tinyframework/subclasstest/Class_None.class
+ Compiled from "Class_None.java"
+public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_None
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/Class_None
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 0, methods: 1, attributes: 1
+ public com.android.hoststubgen.test.tinyframework.subclasstest.Class_None();
+ descriptor: ()V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=1, locals=1, args_size=1
+ x: aload_0
+ x: invokespecial #x // Method java/lang/Object."<init>":()V
+ x: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/subclasstest/Class_None;
+}
+SourceFile: "Class_None.java"
+## Class: com/android/hoststubgen/test/tinyframework/subclasstest/I1.class
+ Compiled from "I1.java"
+public interface com.android.hoststubgen.test.tinyframework.subclasstest.I1
+ minor version: 0
+ major version: 61
+ flags: (0x0601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT
+ this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/I1
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 0, methods: 0, attributes: 1
+}
+SourceFile: "I1.java"
+## Class: com/android/hoststubgen/test/tinyframework/subclasstest/I2.class
+ Compiled from "I2.java"
+public interface com.android.hoststubgen.test.tinyframework.subclasstest.I2 extends com.android.hoststubgen.test.tinyframework.subclasstest.I1
+ minor version: 0
+ major version: 61
+ flags: (0x0601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT
+ this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/I2
+ super_class: #x // java/lang/Object
+ interfaces: 1, fields: 0, methods: 0, attributes: 1
+}
+SourceFile: "I2.java"
+## Class: com/android/hoststubgen/test/tinyframework/subclasstest/I3.class
+ Compiled from "I3.java"
+public interface com.android.hoststubgen.test.tinyframework.subclasstest.I3 extends com.android.hoststubgen.test.tinyframework.subclasstest.I2
+ minor version: 0
+ major version: 61
+ flags: (0x0601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT
+ this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/I3
+ super_class: #x // java/lang/Object
+ interfaces: 1, fields: 0, methods: 0, attributes: 1
+}
+SourceFile: "I3.java"
+## Class: com/android/hoststubgen/test/tinyframework/subclasstest/IA.class
+ Compiled from "IA.java"
+public interface com.android.hoststubgen.test.tinyframework.subclasstest.IA
+ minor version: 0
+ major version: 61
+ flags: (0x0601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT
+ this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/IA
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 0, methods: 0, attributes: 1
+}
+SourceFile: "IA.java"
+## Class: com/android/hoststubgen/test/tinyframework/subclasstest/IB.class
+ Compiled from "IB.java"
+public interface com.android.hoststubgen.test.tinyframework.subclasstest.IB
+ minor version: 0
+ major version: 61
+ flags: (0x0601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT
+ this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/IB
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 0, methods: 0, attributes: 1
+}
+SourceFile: "IB.java"
## Class: com/supported/UnsupportedClass.class
Compiled from "UnsupportedClass.java"
public class com.supported.UnsupportedClass
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/02-hoststubgen-test-tiny-framework-host-stub-dump.txt b/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/02-hoststubgen-test-tiny-framework-host-stub-dump.txt
index b0db483..406cb74 100644
--- a/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/02-hoststubgen-test-tiny-framework-host-stub-dump.txt
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/02-hoststubgen-test-tiny-framework-host-stub-dump.txt
@@ -2055,6 +2055,166 @@
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestWholeClassStub
+## Class: com/android/hoststubgen/test/tinyframework/subclasstest/C1.class
+ Compiled from "C1.java"
+public class com.android.hoststubgen.test.tinyframework.subclasstest.C1
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/C1
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 0, methods: 0, attributes: 2
+}
+SourceFile: "C1.java"
+RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+## Class: com/android/hoststubgen/test/tinyframework/subclasstest/C2.class
+ Compiled from "C2.java"
+public class com.android.hoststubgen.test.tinyframework.subclasstest.C2 extends com.android.hoststubgen.test.tinyframework.subclasstest.C1
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/C2
+ super_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/C1
+ interfaces: 0, fields: 0, methods: 0, attributes: 2
+}
+SourceFile: "C2.java"
+RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+## Class: com/android/hoststubgen/test/tinyframework/subclasstest/C3.class
+ Compiled from "C3.java"
+public class com.android.hoststubgen.test.tinyframework.subclasstest.C3 extends com.android.hoststubgen.test.tinyframework.subclasstest.C2
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/C3
+ super_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/C2
+ interfaces: 0, fields: 0, methods: 0, attributes: 2
+}
+SourceFile: "C3.java"
+RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+## Class: com/android/hoststubgen/test/tinyframework/subclasstest/CA.class
+ Compiled from "CA.java"
+public class com.android.hoststubgen.test.tinyframework.subclasstest.CA
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/CA
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 0, methods: 0, attributes: 2
+}
+SourceFile: "CA.java"
+RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+## Class: com/android/hoststubgen/test/tinyframework/subclasstest/CB.class
+ Compiled from "CB.java"
+public class com.android.hoststubgen.test.tinyframework.subclasstest.CB
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/CB
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 0, methods: 0, attributes: 2
+}
+SourceFile: "CB.java"
+RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+## Class: com/android/hoststubgen/test/tinyframework/subclasstest/I1.class
+ Compiled from "I1.java"
+public interface com.android.hoststubgen.test.tinyframework.subclasstest.I1
+ minor version: 0
+ major version: 61
+ flags: (0x0601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT
+ this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/I1
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 0, methods: 0, attributes: 2
+}
+SourceFile: "I1.java"
+RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+## Class: com/android/hoststubgen/test/tinyframework/subclasstest/I2.class
+ Compiled from "I2.java"
+public interface com.android.hoststubgen.test.tinyframework.subclasstest.I2 extends com.android.hoststubgen.test.tinyframework.subclasstest.I1
+ minor version: 0
+ major version: 61
+ flags: (0x0601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT
+ this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/I2
+ super_class: #x // java/lang/Object
+ interfaces: 1, fields: 0, methods: 0, attributes: 2
+}
+SourceFile: "I2.java"
+RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+## Class: com/android/hoststubgen/test/tinyframework/subclasstest/I3.class
+ Compiled from "I3.java"
+public interface com.android.hoststubgen.test.tinyframework.subclasstest.I3 extends com.android.hoststubgen.test.tinyframework.subclasstest.I2
+ minor version: 0
+ major version: 61
+ flags: (0x0601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT
+ this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/I3
+ super_class: #x // java/lang/Object
+ interfaces: 1, fields: 0, methods: 0, attributes: 2
+}
+SourceFile: "I3.java"
+RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+## Class: com/android/hoststubgen/test/tinyframework/subclasstest/IA.class
+ Compiled from "IA.java"
+public interface com.android.hoststubgen.test.tinyframework.subclasstest.IA
+ minor version: 0
+ major version: 61
+ flags: (0x0601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT
+ this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/IA
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 0, methods: 0, attributes: 2
+}
+SourceFile: "IA.java"
+RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+## Class: com/android/hoststubgen/test/tinyframework/subclasstest/IB.class
+ Compiled from "IB.java"
+public interface com.android.hoststubgen.test.tinyframework.subclasstest.IB
+ minor version: 0
+ major version: 61
+ flags: (0x0601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT
+ this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/IB
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 0, methods: 0, attributes: 2
+}
+SourceFile: "IB.java"
+RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
## Class: com/unsupported/UnsupportedClass.class
Compiled from "UnsupportedClass.java"
public class com.unsupported.UnsupportedClass
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/03-hoststubgen-test-tiny-framework-host-impl-dump.txt b/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/03-hoststubgen-test-tiny-framework-host-impl-dump.txt
index 112f69e..c673262 100644
--- a/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/03-hoststubgen-test-tiny-framework-host-impl-dump.txt
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/03-hoststubgen-test-tiny-framework-host-impl-dump.txt
@@ -3371,6 +3371,264 @@
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestWholeClassStub
+## Class: com/android/hoststubgen/test/tinyframework/subclasstest/C1.class
+ Compiled from "C1.java"
+public class com.android.hoststubgen.test.tinyframework.subclasstest.C1
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/C1
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 0, methods: 0, attributes: 2
+}
+SourceFile: "C1.java"
+RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+## Class: com/android/hoststubgen/test/tinyframework/subclasstest/C2.class
+ Compiled from "C2.java"
+public class com.android.hoststubgen.test.tinyframework.subclasstest.C2 extends com.android.hoststubgen.test.tinyframework.subclasstest.C1
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/C2
+ super_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/C1
+ interfaces: 0, fields: 0, methods: 0, attributes: 2
+}
+SourceFile: "C2.java"
+RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+## Class: com/android/hoststubgen/test/tinyframework/subclasstest/C3.class
+ Compiled from "C3.java"
+public class com.android.hoststubgen.test.tinyframework.subclasstest.C3 extends com.android.hoststubgen.test.tinyframework.subclasstest.C2
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/C3
+ super_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/C2
+ interfaces: 0, fields: 0, methods: 0, attributes: 2
+}
+SourceFile: "C3.java"
+RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+## Class: com/android/hoststubgen/test/tinyframework/subclasstest/CA.class
+ Compiled from "CA.java"
+public class com.android.hoststubgen.test.tinyframework.subclasstest.CA
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/CA
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 0, methods: 0, attributes: 2
+}
+SourceFile: "CA.java"
+RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+## Class: com/android/hoststubgen/test/tinyframework/subclasstest/CB.class
+ Compiled from "CB.java"
+public class com.android.hoststubgen.test.tinyframework.subclasstest.CB
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/CB
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 0, methods: 0, attributes: 2
+}
+SourceFile: "CB.java"
+RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+## Class: com/android/hoststubgen/test/tinyframework/subclasstest/Class_C1.class
+ Compiled from "Class_C1.java"
+public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_C1 extends com.android.hoststubgen.test.tinyframework.subclasstest.C1
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/Class_C1
+ super_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/C1
+ interfaces: 0, fields: 0, methods: 0, attributes: 2
+}
+SourceFile: "Class_C1.java"
+RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+## Class: com/android/hoststubgen/test/tinyframework/subclasstest/Class_C2.class
+ Compiled from "Class_C2.java"
+public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_C2 extends com.android.hoststubgen.test.tinyframework.subclasstest.C2
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/Class_C2
+ super_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/C2
+ interfaces: 0, fields: 0, methods: 0, attributes: 2
+}
+SourceFile: "Class_C2.java"
+RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+## Class: com/android/hoststubgen/test/tinyframework/subclasstest/Class_C3.class
+ Compiled from "Class_C3.java"
+public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_C3 extends com.android.hoststubgen.test.tinyframework.subclasstest.C3
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/Class_C3
+ super_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/C3
+ interfaces: 0, fields: 0, methods: 0, attributes: 2
+}
+SourceFile: "Class_C3.java"
+RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+## Class: com/android/hoststubgen/test/tinyframework/subclasstest/Class_I1.class
+ Compiled from "Class_I1.java"
+public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_I1 implements com.android.hoststubgen.test.tinyframework.subclasstest.I1
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/Class_I1
+ super_class: #x // java/lang/Object
+ interfaces: 1, fields: 0, methods: 0, attributes: 2
+}
+SourceFile: "Class_I1.java"
+RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+## Class: com/android/hoststubgen/test/tinyframework/subclasstest/Class_I1_IA.class
+ Compiled from "Class_I1_IA.java"
+public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_I1_IA implements com.android.hoststubgen.test.tinyframework.subclasstest.I1,com.android.hoststubgen.test.tinyframework.subclasstest.IA
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/Class_I1_IA
+ super_class: #x // java/lang/Object
+ interfaces: 2, fields: 0, methods: 0, attributes: 2
+}
+SourceFile: "Class_I1_IA.java"
+RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+## Class: com/android/hoststubgen/test/tinyframework/subclasstest/Class_I2.class
+ Compiled from "Class_I2.java"
+public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_I2 implements com.android.hoststubgen.test.tinyframework.subclasstest.I2
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/Class_I2
+ super_class: #x // java/lang/Object
+ interfaces: 1, fields: 0, methods: 0, attributes: 2
+}
+SourceFile: "Class_I2.java"
+RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+## Class: com/android/hoststubgen/test/tinyframework/subclasstest/Class_I3.class
+ Compiled from "Class_I3.java"
+public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_I3 implements com.android.hoststubgen.test.tinyframework.subclasstest.I3
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/Class_I3
+ super_class: #x // java/lang/Object
+ interfaces: 1, fields: 0, methods: 0, attributes: 2
+}
+SourceFile: "Class_I3.java"
+RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+## Class: com/android/hoststubgen/test/tinyframework/subclasstest/I1.class
+ Compiled from "I1.java"
+public interface com.android.hoststubgen.test.tinyframework.subclasstest.I1
+ minor version: 0
+ major version: 61
+ flags: (0x0601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT
+ this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/I1
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 0, methods: 0, attributes: 2
+}
+SourceFile: "I1.java"
+RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+## Class: com/android/hoststubgen/test/tinyframework/subclasstest/I2.class
+ Compiled from "I2.java"
+public interface com.android.hoststubgen.test.tinyframework.subclasstest.I2 extends com.android.hoststubgen.test.tinyframework.subclasstest.I1
+ minor version: 0
+ major version: 61
+ flags: (0x0601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT
+ this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/I2
+ super_class: #x // java/lang/Object
+ interfaces: 1, fields: 0, methods: 0, attributes: 2
+}
+SourceFile: "I2.java"
+RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+## Class: com/android/hoststubgen/test/tinyframework/subclasstest/I3.class
+ Compiled from "I3.java"
+public interface com.android.hoststubgen.test.tinyframework.subclasstest.I3 extends com.android.hoststubgen.test.tinyframework.subclasstest.I2
+ minor version: 0
+ major version: 61
+ flags: (0x0601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT
+ this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/I3
+ super_class: #x // java/lang/Object
+ interfaces: 1, fields: 0, methods: 0, attributes: 2
+}
+SourceFile: "I3.java"
+RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+## Class: com/android/hoststubgen/test/tinyframework/subclasstest/IA.class
+ Compiled from "IA.java"
+public interface com.android.hoststubgen.test.tinyframework.subclasstest.IA
+ minor version: 0
+ major version: 61
+ flags: (0x0601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT
+ this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/IA
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 0, methods: 0, attributes: 2
+}
+SourceFile: "IA.java"
+RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+## Class: com/android/hoststubgen/test/tinyframework/subclasstest/IB.class
+ Compiled from "IB.java"
+public interface com.android.hoststubgen.test.tinyframework.subclasstest.IB
+ minor version: 0
+ major version: 61
+ flags: (0x0601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT
+ this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/IB
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 0, methods: 0, attributes: 2
+}
+SourceFile: "IB.java"
+RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
## Class: com/supported/UnsupportedClass.class
Compiled from "UnsupportedClass.java"
public class com.supported.UnsupportedClass
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/12-hoststubgen-test-tiny-framework-host-ext-stub-dump.txt b/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/12-hoststubgen-test-tiny-framework-host-ext-stub-dump.txt
index b0db483..406cb74 100644
--- a/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/12-hoststubgen-test-tiny-framework-host-ext-stub-dump.txt
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/12-hoststubgen-test-tiny-framework-host-ext-stub-dump.txt
@@ -2055,6 +2055,166 @@
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestWholeClassStub
+## Class: com/android/hoststubgen/test/tinyframework/subclasstest/C1.class
+ Compiled from "C1.java"
+public class com.android.hoststubgen.test.tinyframework.subclasstest.C1
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/C1
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 0, methods: 0, attributes: 2
+}
+SourceFile: "C1.java"
+RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+## Class: com/android/hoststubgen/test/tinyframework/subclasstest/C2.class
+ Compiled from "C2.java"
+public class com.android.hoststubgen.test.tinyframework.subclasstest.C2 extends com.android.hoststubgen.test.tinyframework.subclasstest.C1
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/C2
+ super_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/C1
+ interfaces: 0, fields: 0, methods: 0, attributes: 2
+}
+SourceFile: "C2.java"
+RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+## Class: com/android/hoststubgen/test/tinyframework/subclasstest/C3.class
+ Compiled from "C3.java"
+public class com.android.hoststubgen.test.tinyframework.subclasstest.C3 extends com.android.hoststubgen.test.tinyframework.subclasstest.C2
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/C3
+ super_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/C2
+ interfaces: 0, fields: 0, methods: 0, attributes: 2
+}
+SourceFile: "C3.java"
+RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+## Class: com/android/hoststubgen/test/tinyframework/subclasstest/CA.class
+ Compiled from "CA.java"
+public class com.android.hoststubgen.test.tinyframework.subclasstest.CA
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/CA
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 0, methods: 0, attributes: 2
+}
+SourceFile: "CA.java"
+RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+## Class: com/android/hoststubgen/test/tinyframework/subclasstest/CB.class
+ Compiled from "CB.java"
+public class com.android.hoststubgen.test.tinyframework.subclasstest.CB
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/CB
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 0, methods: 0, attributes: 2
+}
+SourceFile: "CB.java"
+RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+## Class: com/android/hoststubgen/test/tinyframework/subclasstest/I1.class
+ Compiled from "I1.java"
+public interface com.android.hoststubgen.test.tinyframework.subclasstest.I1
+ minor version: 0
+ major version: 61
+ flags: (0x0601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT
+ this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/I1
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 0, methods: 0, attributes: 2
+}
+SourceFile: "I1.java"
+RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+## Class: com/android/hoststubgen/test/tinyframework/subclasstest/I2.class
+ Compiled from "I2.java"
+public interface com.android.hoststubgen.test.tinyframework.subclasstest.I2 extends com.android.hoststubgen.test.tinyframework.subclasstest.I1
+ minor version: 0
+ major version: 61
+ flags: (0x0601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT
+ this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/I2
+ super_class: #x // java/lang/Object
+ interfaces: 1, fields: 0, methods: 0, attributes: 2
+}
+SourceFile: "I2.java"
+RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+## Class: com/android/hoststubgen/test/tinyframework/subclasstest/I3.class
+ Compiled from "I3.java"
+public interface com.android.hoststubgen.test.tinyframework.subclasstest.I3 extends com.android.hoststubgen.test.tinyframework.subclasstest.I2
+ minor version: 0
+ major version: 61
+ flags: (0x0601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT
+ this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/I3
+ super_class: #x // java/lang/Object
+ interfaces: 1, fields: 0, methods: 0, attributes: 2
+}
+SourceFile: "I3.java"
+RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+## Class: com/android/hoststubgen/test/tinyframework/subclasstest/IA.class
+ Compiled from "IA.java"
+public interface com.android.hoststubgen.test.tinyframework.subclasstest.IA
+ minor version: 0
+ major version: 61
+ flags: (0x0601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT
+ this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/IA
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 0, methods: 0, attributes: 2
+}
+SourceFile: "IA.java"
+RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+## Class: com/android/hoststubgen/test/tinyframework/subclasstest/IB.class
+ Compiled from "IB.java"
+public interface com.android.hoststubgen.test.tinyframework.subclasstest.IB
+ minor version: 0
+ major version: 61
+ flags: (0x0601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT
+ this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/IB
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 0, methods: 0, attributes: 2
+}
+SourceFile: "IB.java"
+RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
## Class: com/unsupported/UnsupportedClass.class
Compiled from "UnsupportedClass.java"
public class com.unsupported.UnsupportedClass
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/13-hoststubgen-test-tiny-framework-host-ext-impl-dump.txt b/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/13-hoststubgen-test-tiny-framework-host-ext-impl-dump.txt
index 2357844..4fd5701 100644
--- a/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/13-hoststubgen-test-tiny-framework-host-ext-impl-dump.txt
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/13-hoststubgen-test-tiny-framework-host-ext-impl-dump.txt
@@ -4201,6 +4201,417 @@
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestWholeClassStub
+## Class: com/android/hoststubgen/test/tinyframework/subclasstest/C1.class
+ Compiled from "C1.java"
+public class com.android.hoststubgen.test.tinyframework.subclasstest.C1
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/C1
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 0, methods: 1, attributes: 2
+ private static {};
+ descriptor: ()V
+ flags: (0x000a) ACC_PRIVATE, ACC_STATIC
+ Code:
+ stack=2, locals=0, args_size=0
+ x: ldc #x // class com/android/hoststubgen/test/tinyframework/subclasstest/C1
+ x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
+ x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V
+ x: return
+}
+SourceFile: "C1.java"
+RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+## Class: com/android/hoststubgen/test/tinyframework/subclasstest/C2.class
+ Compiled from "C2.java"
+public class com.android.hoststubgen.test.tinyframework.subclasstest.C2 extends com.android.hoststubgen.test.tinyframework.subclasstest.C1
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/C2
+ super_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/C1
+ interfaces: 0, fields: 0, methods: 1, attributes: 2
+ private static {};
+ descriptor: ()V
+ flags: (0x000a) ACC_PRIVATE, ACC_STATIC
+ Code:
+ stack=2, locals=0, args_size=0
+ x: ldc #x // class com/android/hoststubgen/test/tinyframework/subclasstest/C2
+ x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
+ x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V
+ x: return
+}
+SourceFile: "C2.java"
+RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+## Class: com/android/hoststubgen/test/tinyframework/subclasstest/C3.class
+ Compiled from "C3.java"
+public class com.android.hoststubgen.test.tinyframework.subclasstest.C3 extends com.android.hoststubgen.test.tinyframework.subclasstest.C2
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/C3
+ super_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/C2
+ interfaces: 0, fields: 0, methods: 1, attributes: 2
+ private static {};
+ descriptor: ()V
+ flags: (0x000a) ACC_PRIVATE, ACC_STATIC
+ Code:
+ stack=2, locals=0, args_size=0
+ x: ldc #x // class com/android/hoststubgen/test/tinyframework/subclasstest/C3
+ x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
+ x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V
+ x: return
+}
+SourceFile: "C3.java"
+RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+## Class: com/android/hoststubgen/test/tinyframework/subclasstest/CA.class
+ Compiled from "CA.java"
+public class com.android.hoststubgen.test.tinyframework.subclasstest.CA
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/CA
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 0, methods: 1, attributes: 2
+ private static {};
+ descriptor: ()V
+ flags: (0x000a) ACC_PRIVATE, ACC_STATIC
+ Code:
+ stack=2, locals=0, args_size=0
+ x: ldc #x // class com/android/hoststubgen/test/tinyframework/subclasstest/CA
+ x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
+ x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V
+ x: return
+}
+SourceFile: "CA.java"
+RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+## Class: com/android/hoststubgen/test/tinyframework/subclasstest/CB.class
+ Compiled from "CB.java"
+public class com.android.hoststubgen.test.tinyframework.subclasstest.CB
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/CB
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 0, methods: 1, attributes: 2
+ private static {};
+ descriptor: ()V
+ flags: (0x000a) ACC_PRIVATE, ACC_STATIC
+ Code:
+ stack=2, locals=0, args_size=0
+ x: ldc #x // class com/android/hoststubgen/test/tinyframework/subclasstest/CB
+ x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
+ x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V
+ x: return
+}
+SourceFile: "CB.java"
+RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+## Class: com/android/hoststubgen/test/tinyframework/subclasstest/Class_C1.class
+ Compiled from "Class_C1.java"
+public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_C1 extends com.android.hoststubgen.test.tinyframework.subclasstest.C1
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/Class_C1
+ super_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/C1
+ interfaces: 0, fields: 0, methods: 1, attributes: 2
+ private static {};
+ descriptor: ()V
+ flags: (0x000a) ACC_PRIVATE, ACC_STATIC
+ Code:
+ stack=2, locals=0, args_size=0
+ x: ldc #x // class com/android/hoststubgen/test/tinyframework/subclasstest/Class_C1
+ x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
+ x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V
+ x: return
+}
+SourceFile: "Class_C1.java"
+RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+## Class: com/android/hoststubgen/test/tinyframework/subclasstest/Class_C2.class
+ Compiled from "Class_C2.java"
+public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_C2 extends com.android.hoststubgen.test.tinyframework.subclasstest.C2
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/Class_C2
+ super_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/C2
+ interfaces: 0, fields: 0, methods: 1, attributes: 2
+ private static {};
+ descriptor: ()V
+ flags: (0x000a) ACC_PRIVATE, ACC_STATIC
+ Code:
+ stack=2, locals=0, args_size=0
+ x: ldc #x // class com/android/hoststubgen/test/tinyframework/subclasstest/Class_C2
+ x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
+ x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V
+ x: return
+}
+SourceFile: "Class_C2.java"
+RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+## Class: com/android/hoststubgen/test/tinyframework/subclasstest/Class_C3.class
+ Compiled from "Class_C3.java"
+public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_C3 extends com.android.hoststubgen.test.tinyframework.subclasstest.C3
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/Class_C3
+ super_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/C3
+ interfaces: 0, fields: 0, methods: 1, attributes: 2
+ private static {};
+ descriptor: ()V
+ flags: (0x000a) ACC_PRIVATE, ACC_STATIC
+ Code:
+ stack=2, locals=0, args_size=0
+ x: ldc #x // class com/android/hoststubgen/test/tinyframework/subclasstest/Class_C3
+ x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
+ x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V
+ x: return
+}
+SourceFile: "Class_C3.java"
+RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+## Class: com/android/hoststubgen/test/tinyframework/subclasstest/Class_I1.class
+ Compiled from "Class_I1.java"
+public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_I1 implements com.android.hoststubgen.test.tinyframework.subclasstest.I1
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/Class_I1
+ super_class: #x // java/lang/Object
+ interfaces: 1, fields: 0, methods: 1, attributes: 2
+ private static {};
+ descriptor: ()V
+ flags: (0x000a) ACC_PRIVATE, ACC_STATIC
+ Code:
+ stack=2, locals=0, args_size=0
+ x: ldc #x // class com/android/hoststubgen/test/tinyframework/subclasstest/Class_I1
+ x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
+ x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V
+ x: return
+}
+SourceFile: "Class_I1.java"
+RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+## Class: com/android/hoststubgen/test/tinyframework/subclasstest/Class_I1_IA.class
+ Compiled from "Class_I1_IA.java"
+public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_I1_IA implements com.android.hoststubgen.test.tinyframework.subclasstest.I1,com.android.hoststubgen.test.tinyframework.subclasstest.IA
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/Class_I1_IA
+ super_class: #x // java/lang/Object
+ interfaces: 2, fields: 0, methods: 1, attributes: 2
+ private static {};
+ descriptor: ()V
+ flags: (0x000a) ACC_PRIVATE, ACC_STATIC
+ Code:
+ stack=2, locals=0, args_size=0
+ x: ldc #x // class com/android/hoststubgen/test/tinyframework/subclasstest/Class_I1_IA
+ x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
+ x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V
+ x: return
+}
+SourceFile: "Class_I1_IA.java"
+RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+## Class: com/android/hoststubgen/test/tinyframework/subclasstest/Class_I2.class
+ Compiled from "Class_I2.java"
+public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_I2 implements com.android.hoststubgen.test.tinyframework.subclasstest.I2
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/Class_I2
+ super_class: #x // java/lang/Object
+ interfaces: 1, fields: 0, methods: 1, attributes: 2
+ private static {};
+ descriptor: ()V
+ flags: (0x000a) ACC_PRIVATE, ACC_STATIC
+ Code:
+ stack=2, locals=0, args_size=0
+ x: ldc #x // class com/android/hoststubgen/test/tinyframework/subclasstest/Class_I2
+ x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
+ x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V
+ x: return
+}
+SourceFile: "Class_I2.java"
+RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+## Class: com/android/hoststubgen/test/tinyframework/subclasstest/Class_I3.class
+ Compiled from "Class_I3.java"
+public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_I3 implements com.android.hoststubgen.test.tinyframework.subclasstest.I3
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/Class_I3
+ super_class: #x // java/lang/Object
+ interfaces: 1, fields: 0, methods: 1, attributes: 2
+ private static {};
+ descriptor: ()V
+ flags: (0x000a) ACC_PRIVATE, ACC_STATIC
+ Code:
+ stack=2, locals=0, args_size=0
+ x: ldc #x // class com/android/hoststubgen/test/tinyframework/subclasstest/Class_I3
+ x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
+ x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V
+ x: return
+}
+SourceFile: "Class_I3.java"
+RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+## Class: com/android/hoststubgen/test/tinyframework/subclasstest/I1.class
+ Compiled from "I1.java"
+public interface com.android.hoststubgen.test.tinyframework.subclasstest.I1
+ minor version: 0
+ major version: 61
+ flags: (0x0601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT
+ this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/I1
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 0, methods: 1, attributes: 2
+ private static {};
+ descriptor: ()V
+ flags: (0x000a) ACC_PRIVATE, ACC_STATIC
+ Code:
+ stack=2, locals=0, args_size=0
+ x: ldc #x // class com/android/hoststubgen/test/tinyframework/subclasstest/I1
+ x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
+ x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V
+ x: return
+}
+SourceFile: "I1.java"
+RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+## Class: com/android/hoststubgen/test/tinyframework/subclasstest/I2.class
+ Compiled from "I2.java"
+public interface com.android.hoststubgen.test.tinyframework.subclasstest.I2 extends com.android.hoststubgen.test.tinyframework.subclasstest.I1
+ minor version: 0
+ major version: 61
+ flags: (0x0601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT
+ this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/I2
+ super_class: #x // java/lang/Object
+ interfaces: 1, fields: 0, methods: 1, attributes: 2
+ private static {};
+ descriptor: ()V
+ flags: (0x000a) ACC_PRIVATE, ACC_STATIC
+ Code:
+ stack=2, locals=0, args_size=0
+ x: ldc #x // class com/android/hoststubgen/test/tinyframework/subclasstest/I2
+ x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
+ x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V
+ x: return
+}
+SourceFile: "I2.java"
+RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+## Class: com/android/hoststubgen/test/tinyframework/subclasstest/I3.class
+ Compiled from "I3.java"
+public interface com.android.hoststubgen.test.tinyframework.subclasstest.I3 extends com.android.hoststubgen.test.tinyframework.subclasstest.I2
+ minor version: 0
+ major version: 61
+ flags: (0x0601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT
+ this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/I3
+ super_class: #x // java/lang/Object
+ interfaces: 1, fields: 0, methods: 1, attributes: 2
+ private static {};
+ descriptor: ()V
+ flags: (0x000a) ACC_PRIVATE, ACC_STATIC
+ Code:
+ stack=2, locals=0, args_size=0
+ x: ldc #x // class com/android/hoststubgen/test/tinyframework/subclasstest/I3
+ x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
+ x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V
+ x: return
+}
+SourceFile: "I3.java"
+RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+## Class: com/android/hoststubgen/test/tinyframework/subclasstest/IA.class
+ Compiled from "IA.java"
+public interface com.android.hoststubgen.test.tinyframework.subclasstest.IA
+ minor version: 0
+ major version: 61
+ flags: (0x0601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT
+ this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/IA
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 0, methods: 1, attributes: 2
+ private static {};
+ descriptor: ()V
+ flags: (0x000a) ACC_PRIVATE, ACC_STATIC
+ Code:
+ stack=2, locals=0, args_size=0
+ x: ldc #x // class com/android/hoststubgen/test/tinyframework/subclasstest/IA
+ x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
+ x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V
+ x: return
+}
+SourceFile: "IA.java"
+RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+## Class: com/android/hoststubgen/test/tinyframework/subclasstest/IB.class
+ Compiled from "IB.java"
+public interface com.android.hoststubgen.test.tinyframework.subclasstest.IB
+ minor version: 0
+ major version: 61
+ flags: (0x0601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT
+ this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/IB
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 0, methods: 1, attributes: 2
+ private static {};
+ descriptor: ()V
+ flags: (0x000a) ACC_PRIVATE, ACC_STATIC
+ Code:
+ stack=2, locals=0, args_size=0
+ x: ldc #x // class com/android/hoststubgen/test/tinyframework/subclasstest/IB
+ x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
+ x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V
+ x: return
+}
+SourceFile: "IB.java"
+RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
## Class: com/supported/UnsupportedClass.class
Compiled from "UnsupportedClass.java"
public class com.supported.UnsupportedClass
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/policy-override-tiny-framework.txt b/tools/hoststubgen/hoststubgen/test-tiny-framework/policy-override-tiny-framework.txt
index 9b6b6e4..d302084 100644
--- a/tools/hoststubgen/hoststubgen/test-tiny-framework/policy-override-tiny-framework.txt
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/policy-override-tiny-framework.txt
@@ -17,4 +17,23 @@
class com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy ~com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook.onClassLoaded
# Heuristics rule: Stub all the AIDL classes.
-class :aidl stubclass
\ No newline at end of file
+class :aidl stubclass
+
+# Default is "remove", so let's put all the base classes / interfaces in the stub first.
+class com.android.hoststubgen.test.tinyframework.subclasstest.C1 stub
+class com.android.hoststubgen.test.tinyframework.subclasstest.C2 stub
+class com.android.hoststubgen.test.tinyframework.subclasstest.C3 stub
+class com.android.hoststubgen.test.tinyframework.subclasstest.CA stub
+class com.android.hoststubgen.test.tinyframework.subclasstest.CB stub
+class com.android.hoststubgen.test.tinyframework.subclasstest.I1 stub
+class com.android.hoststubgen.test.tinyframework.subclasstest.I2 stub
+class com.android.hoststubgen.test.tinyframework.subclasstest.I3 stub
+class com.android.hoststubgen.test.tinyframework.subclasstest.IA stub
+class com.android.hoststubgen.test.tinyframework.subclasstest.IB stub
+
+# Then define inheritance based policies.
+class *com.android.hoststubgen.test.tinyframework.subclasstest.C1 keep
+class *com.android.hoststubgen.test.tinyframework.subclasstest.CA remove
+
+class *com.android.hoststubgen.test.tinyframework.subclasstest.I1 keep
+class *com.android.hoststubgen.test.tinyframework.subclasstest.IA remove
diff --git a/core/java/android/service/voice/HotwordTrainingAudio.aidl b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/subclasstest/C1.java
similarity index 79%
copy from core/java/android/service/voice/HotwordTrainingAudio.aidl
copy to tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/subclasstest/C1.java
index 4dd2289..03c9e2a 100644
--- a/core/java/android/service/voice/HotwordTrainingAudio.aidl
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/subclasstest/C1.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2023 The Android Open Source Project
+ * Copyright (C) 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+package com.android.hoststubgen.test.tinyframework.subclasstest;
-package android.service.voice;
-
-parcelable HotwordTrainingAudio;
\ No newline at end of file
+public class C1 {
+}
diff --git a/core/java/android/service/voice/HotwordTrainingAudio.aidl b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/subclasstest/C2.java
similarity index 78%
copy from core/java/android/service/voice/HotwordTrainingAudio.aidl
copy to tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/subclasstest/C2.java
index 4dd2289..3ca8f1f 100644
--- a/core/java/android/service/voice/HotwordTrainingAudio.aidl
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/subclasstest/C2.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2023 The Android Open Source Project
+ * Copyright (C) 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+package com.android.hoststubgen.test.tinyframework.subclasstest;
-package android.service.voice;
-
-parcelable HotwordTrainingAudio;
\ No newline at end of file
+public class C2 extends C1 {
+}
diff --git a/core/java/android/service/voice/HotwordTrainingAudio.aidl b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/subclasstest/C3.java
similarity index 78%
copy from core/java/android/service/voice/HotwordTrainingAudio.aidl
copy to tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/subclasstest/C3.java
index 4dd2289..a6c14f0 100644
--- a/core/java/android/service/voice/HotwordTrainingAudio.aidl
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/subclasstest/C3.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2023 The Android Open Source Project
+ * Copyright (C) 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+package com.android.hoststubgen.test.tinyframework.subclasstest;
-package android.service.voice;
-
-parcelable HotwordTrainingAudio;
\ No newline at end of file
+public class C3 extends C2 {
+}
diff --git a/core/java/android/service/voice/HotwordTrainingAudio.aidl b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/subclasstest/CA.java
similarity index 79%
copy from core/java/android/service/voice/HotwordTrainingAudio.aidl
copy to tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/subclasstest/CA.java
index 4dd2289..2e35370 100644
--- a/core/java/android/service/voice/HotwordTrainingAudio.aidl
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/subclasstest/CA.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2023 The Android Open Source Project
+ * Copyright (C) 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+package com.android.hoststubgen.test.tinyframework.subclasstest;
-package android.service.voice;
-
-parcelable HotwordTrainingAudio;
\ No newline at end of file
+public class CA {
+}
diff --git a/core/java/android/service/voice/HotwordTrainingAudio.aidl b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/subclasstest/CB.java
similarity index 79%
copy from core/java/android/service/voice/HotwordTrainingAudio.aidl
copy to tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/subclasstest/CB.java
index 4dd2289..fe4cee6 100644
--- a/core/java/android/service/voice/HotwordTrainingAudio.aidl
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/subclasstest/CB.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2023 The Android Open Source Project
+ * Copyright (C) 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+package com.android.hoststubgen.test.tinyframework.subclasstest;
-package android.service.voice;
-
-parcelable HotwordTrainingAudio;
\ No newline at end of file
+public class CB {
+}
diff --git a/core/java/android/service/voice/HotwordTrainingAudio.aidl b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/subclasstest/Class_C1.java
similarity index 77%
copy from core/java/android/service/voice/HotwordTrainingAudio.aidl
copy to tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/subclasstest/Class_C1.java
index 4dd2289..12012fc 100644
--- a/core/java/android/service/voice/HotwordTrainingAudio.aidl
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/subclasstest/Class_C1.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2023 The Android Open Source Project
+ * Copyright (C) 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+package com.android.hoststubgen.test.tinyframework.subclasstest;
-package android.service.voice;
-
-parcelable HotwordTrainingAudio;
\ No newline at end of file
+public class Class_C1 extends C1 {
+}
diff --git a/core/java/android/service/voice/HotwordTrainingAudio.aidl b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/subclasstest/Class_C2.java
similarity index 77%
copy from core/java/android/service/voice/HotwordTrainingAudio.aidl
copy to tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/subclasstest/Class_C2.java
index 4dd2289..8d48ee6 100644
--- a/core/java/android/service/voice/HotwordTrainingAudio.aidl
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/subclasstest/Class_C2.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2023 The Android Open Source Project
+ * Copyright (C) 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+package com.android.hoststubgen.test.tinyframework.subclasstest;
-package android.service.voice;
-
-parcelable HotwordTrainingAudio;
\ No newline at end of file
+public class Class_C2 extends C2 {
+}
diff --git a/core/java/android/service/voice/HotwordTrainingAudio.aidl b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/subclasstest/Class_C3.java
similarity index 77%
copy from core/java/android/service/voice/HotwordTrainingAudio.aidl
copy to tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/subclasstest/Class_C3.java
index 4dd2289..6748430 100644
--- a/core/java/android/service/voice/HotwordTrainingAudio.aidl
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/subclasstest/Class_C3.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2023 The Android Open Source Project
+ * Copyright (C) 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+package com.android.hoststubgen.test.tinyframework.subclasstest;
-package android.service.voice;
-
-parcelable HotwordTrainingAudio;
\ No newline at end of file
+public class Class_C3 extends C3 {
+}
diff --git a/core/java/android/service/voice/HotwordTrainingAudio.aidl b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/subclasstest/Class_CA.java
similarity index 77%
copy from core/java/android/service/voice/HotwordTrainingAudio.aidl
copy to tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/subclasstest/Class_CA.java
index 4dd2289..58aa5c3 100644
--- a/core/java/android/service/voice/HotwordTrainingAudio.aidl
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/subclasstest/Class_CA.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2023 The Android Open Source Project
+ * Copyright (C) 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+package com.android.hoststubgen.test.tinyframework.subclasstest;
-package android.service.voice;
-
-parcelable HotwordTrainingAudio;
\ No newline at end of file
+public class Class_CA extends CA {
+}
diff --git a/core/java/android/service/voice/HotwordTrainingAudio.aidl b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/subclasstest/Class_CB.java
similarity index 77%
copy from core/java/android/service/voice/HotwordTrainingAudio.aidl
copy to tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/subclasstest/Class_CB.java
index 4dd2289..c1c3d62 100644
--- a/core/java/android/service/voice/HotwordTrainingAudio.aidl
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/subclasstest/Class_CB.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2023 The Android Open Source Project
+ * Copyright (C) 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+package com.android.hoststubgen.test.tinyframework.subclasstest;
-package android.service.voice;
-
-parcelable HotwordTrainingAudio;
\ No newline at end of file
+public class Class_CB extends CB {
+}
diff --git a/core/java/android/service/voice/HotwordTrainingAudio.aidl b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/subclasstest/Class_CB_IA.java
similarity index 75%
copy from core/java/android/service/voice/HotwordTrainingAudio.aidl
copy to tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/subclasstest/Class_CB_IA.java
index 4dd2289..398b569 100644
--- a/core/java/android/service/voice/HotwordTrainingAudio.aidl
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/subclasstest/Class_CB_IA.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2023 The Android Open Source Project
+ * Copyright (C) 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+package com.android.hoststubgen.test.tinyframework.subclasstest;
-package android.service.voice;
-
-parcelable HotwordTrainingAudio;
\ No newline at end of file
+public class Class_CB_IA extends CB implements IA {
+}
diff --git a/core/java/android/service/voice/HotwordTrainingAudio.aidl b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/subclasstest/Class_I1.java
similarity index 77%
copy from core/java/android/service/voice/HotwordTrainingAudio.aidl
copy to tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/subclasstest/Class_I1.java
index 4dd2289..44cbd8f 100644
--- a/core/java/android/service/voice/HotwordTrainingAudio.aidl
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/subclasstest/Class_I1.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2023 The Android Open Source Project
+ * Copyright (C) 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+package com.android.hoststubgen.test.tinyframework.subclasstest;
-package android.service.voice;
-
-parcelable HotwordTrainingAudio;
\ No newline at end of file
+public class Class_I1 implements I1 {
+}
diff --git a/core/java/android/service/voice/HotwordTrainingAudio.aidl b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/subclasstest/Class_I1_IA.java
similarity index 76%
copy from core/java/android/service/voice/HotwordTrainingAudio.aidl
copy to tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/subclasstest/Class_I1_IA.java
index 4dd2289..42355a3 100644
--- a/core/java/android/service/voice/HotwordTrainingAudio.aidl
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/subclasstest/Class_I1_IA.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2023 The Android Open Source Project
+ * Copyright (C) 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+package com.android.hoststubgen.test.tinyframework.subclasstest;
-package android.service.voice;
-
-parcelable HotwordTrainingAudio;
\ No newline at end of file
+public class Class_I1_IA implements I1, IA {
+}
diff --git a/core/java/android/service/voice/HotwordTrainingAudio.aidl b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/subclasstest/Class_I2.java
similarity index 77%
copy from core/java/android/service/voice/HotwordTrainingAudio.aidl
copy to tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/subclasstest/Class_I2.java
index 4dd2289..09c8099 100644
--- a/core/java/android/service/voice/HotwordTrainingAudio.aidl
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/subclasstest/Class_I2.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2023 The Android Open Source Project
+ * Copyright (C) 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+package com.android.hoststubgen.test.tinyframework.subclasstest;
-package android.service.voice;
-
-parcelable HotwordTrainingAudio;
\ No newline at end of file
+public class Class_I2 implements I2 {
+}
diff --git a/core/java/android/service/voice/HotwordTrainingAudio.aidl b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/subclasstest/Class_I3.java
similarity index 77%
copy from core/java/android/service/voice/HotwordTrainingAudio.aidl
copy to tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/subclasstest/Class_I3.java
index 4dd2289..0806a47 100644
--- a/core/java/android/service/voice/HotwordTrainingAudio.aidl
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/subclasstest/Class_I3.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2023 The Android Open Source Project
+ * Copyright (C) 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+package com.android.hoststubgen.test.tinyframework.subclasstest;
-package android.service.voice;
-
-parcelable HotwordTrainingAudio;
\ No newline at end of file
+public class Class_I3 implements I3 {
+}
diff --git a/core/java/android/service/voice/HotwordTrainingAudio.aidl b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/subclasstest/Class_I3_IA.java
similarity index 76%
copy from core/java/android/service/voice/HotwordTrainingAudio.aidl
copy to tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/subclasstest/Class_I3_IA.java
index 4dd2289..eaa8528 100644
--- a/core/java/android/service/voice/HotwordTrainingAudio.aidl
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/subclasstest/Class_I3_IA.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2023 The Android Open Source Project
+ * Copyright (C) 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+package com.android.hoststubgen.test.tinyframework.subclasstest;
-package android.service.voice;
-
-parcelable HotwordTrainingAudio;
\ No newline at end of file
+public class Class_I3_IA implements I3, IA {
+}
diff --git a/core/java/android/service/voice/HotwordTrainingAudio.aidl b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/subclasstest/Class_IA.java
similarity index 77%
copy from core/java/android/service/voice/HotwordTrainingAudio.aidl
copy to tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/subclasstest/Class_IA.java
index 4dd2289..778c5aa 100644
--- a/core/java/android/service/voice/HotwordTrainingAudio.aidl
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/subclasstest/Class_IA.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2023 The Android Open Source Project
+ * Copyright (C) 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+package com.android.hoststubgen.test.tinyframework.subclasstest;
-package android.service.voice;
-
-parcelable HotwordTrainingAudio;
\ No newline at end of file
+public class Class_IA implements IA {
+}
diff --git a/core/java/android/service/voice/HotwordTrainingAudio.aidl b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/subclasstest/Class_IA_I1.java
similarity index 76%
copy from core/java/android/service/voice/HotwordTrainingAudio.aidl
copy to tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/subclasstest/Class_IA_I1.java
index 4dd2289..493f7c8 100644
--- a/core/java/android/service/voice/HotwordTrainingAudio.aidl
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/subclasstest/Class_IA_I1.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2023 The Android Open Source Project
+ * Copyright (C) 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+package com.android.hoststubgen.test.tinyframework.subclasstest;
-package android.service.voice;
-
-parcelable HotwordTrainingAudio;
\ No newline at end of file
+public class Class_IA_I1 implements IA, I1 {
+}
diff --git a/core/java/android/service/voice/HotwordTrainingAudio.aidl b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/subclasstest/Class_IA_I3.java
similarity index 76%
copy from core/java/android/service/voice/HotwordTrainingAudio.aidl
copy to tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/subclasstest/Class_IA_I3.java
index 4dd2289..2aa1de1 100644
--- a/core/java/android/service/voice/HotwordTrainingAudio.aidl
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/subclasstest/Class_IA_I3.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2023 The Android Open Source Project
+ * Copyright (C) 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+package com.android.hoststubgen.test.tinyframework.subclasstest;
-package android.service.voice;
-
-parcelable HotwordTrainingAudio;
\ No newline at end of file
+public class Class_IA_I3 implements IA, I3 {
+}
diff --git a/core/java/android/service/voice/HotwordTrainingAudio.aidl b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/subclasstest/Class_IB.java
similarity index 77%
copy from core/java/android/service/voice/HotwordTrainingAudio.aidl
copy to tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/subclasstest/Class_IB.java
index 4dd2289..d9eae09 100644
--- a/core/java/android/service/voice/HotwordTrainingAudio.aidl
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/subclasstest/Class_IB.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2023 The Android Open Source Project
+ * Copyright (C) 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+package com.android.hoststubgen.test.tinyframework.subclasstest;
-package android.service.voice;
-
-parcelable HotwordTrainingAudio;
\ No newline at end of file
+public class Class_IB implements IB {
+}
diff --git a/core/java/android/service/voice/HotwordTrainingAudio.aidl b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/subclasstest/Class_IB_IA.java
similarity index 76%
copy from core/java/android/service/voice/HotwordTrainingAudio.aidl
copy to tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/subclasstest/Class_IB_IA.java
index 4dd2289..9ee4283 100644
--- a/core/java/android/service/voice/HotwordTrainingAudio.aidl
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/subclasstest/Class_IB_IA.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2023 The Android Open Source Project
+ * Copyright (C) 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+package com.android.hoststubgen.test.tinyframework.subclasstest;
-package android.service.voice;
-
-parcelable HotwordTrainingAudio;
\ No newline at end of file
+public class Class_IB_IA implements IB, IA {
+}
diff --git a/core/java/android/service/voice/HotwordTrainingAudio.aidl b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/subclasstest/Class_None.java
similarity index 78%
copy from core/java/android/service/voice/HotwordTrainingAudio.aidl
copy to tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/subclasstest/Class_None.java
index 4dd2289..50ec2cb 100644
--- a/core/java/android/service/voice/HotwordTrainingAudio.aidl
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/subclasstest/Class_None.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2023 The Android Open Source Project
+ * Copyright (C) 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+package com.android.hoststubgen.test.tinyframework.subclasstest;
-package android.service.voice;
-
-parcelable HotwordTrainingAudio;
\ No newline at end of file
+public class Class_None {
+}
diff --git a/core/java/android/service/voice/HotwordTrainingAudio.aidl b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/subclasstest/I1.java
similarity index 79%
rename from core/java/android/service/voice/HotwordTrainingAudio.aidl
rename to tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/subclasstest/I1.java
index 4dd2289..3f36596 100644
--- a/core/java/android/service/voice/HotwordTrainingAudio.aidl
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/subclasstest/I1.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2023 The Android Open Source Project
+ * Copyright (C) 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+package com.android.hoststubgen.test.tinyframework.subclasstest;
-package android.service.voice;
-
-parcelable HotwordTrainingAudio;
\ No newline at end of file
+public interface I1 {
+}
diff --git a/core/java/android/service/voice/HotwordTrainingAudio.aidl b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/subclasstest/I2.java
similarity index 77%
copy from core/java/android/service/voice/HotwordTrainingAudio.aidl
copy to tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/subclasstest/I2.java
index 4dd2289..960060c 100644
--- a/core/java/android/service/voice/HotwordTrainingAudio.aidl
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/subclasstest/I2.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2023 The Android Open Source Project
+ * Copyright (C) 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+package com.android.hoststubgen.test.tinyframework.subclasstest;
-package android.service.voice;
-
-parcelable HotwordTrainingAudio;
\ No newline at end of file
+public interface I2 extends I1 {
+}
diff --git a/core/java/android/service/voice/HotwordTrainingAudio.aidl b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/subclasstest/I3.java
similarity index 77%
copy from core/java/android/service/voice/HotwordTrainingAudio.aidl
copy to tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/subclasstest/I3.java
index 4dd2289..c678eaa 100644
--- a/core/java/android/service/voice/HotwordTrainingAudio.aidl
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/subclasstest/I3.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2023 The Android Open Source Project
+ * Copyright (C) 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+package com.android.hoststubgen.test.tinyframework.subclasstest;
-package android.service.voice;
-
-parcelable HotwordTrainingAudio;
\ No newline at end of file
+public interface I3 extends I2 {
+}
diff --git a/core/java/android/service/voice/HotwordTrainingAudio.aidl b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/subclasstest/IA.java
similarity index 79%
copy from core/java/android/service/voice/HotwordTrainingAudio.aidl
copy to tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/subclasstest/IA.java
index 4dd2289..1cff484 100644
--- a/core/java/android/service/voice/HotwordTrainingAudio.aidl
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/subclasstest/IA.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2023 The Android Open Source Project
+ * Copyright (C) 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+package com.android.hoststubgen.test.tinyframework.subclasstest;
-package android.service.voice;
-
-parcelable HotwordTrainingAudio;
\ No newline at end of file
+public interface IA {
+}
diff --git a/core/java/android/service/voice/HotwordTrainingAudio.aidl b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/subclasstest/IB.java
similarity index 79%
copy from core/java/android/service/voice/HotwordTrainingAudio.aidl
copy to tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/subclasstest/IB.java
index 4dd2289..84e7173 100644
--- a/core/java/android/service/voice/HotwordTrainingAudio.aidl
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/subclasstest/IB.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2023 The Android Open Source Project
+ * Copyright (C) 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+package com.android.hoststubgen.test.tinyframework.subclasstest;
-package android.service.voice;
-
-parcelable HotwordTrainingAudio;
\ No newline at end of file
+public interface IB {
+}